Skip to content

Commit d265d9a

Browse files
Sylwester Nawrockimchehab
authored andcommitted
[media] exynos4-is: Use external s5k6a3 sensor driver
This patch removes the common fimc-is-sensor driver for image sensors that are normally controlled by the FIMC-IS firmware. The FIMC-IS driver now contains only a table of properties specific to each sensor. The sensor properties required for the ISP's firmware are parsed from device tree and retrieved from the internal table, which is selected based on the compatible property of an image sensor. To use the Exynos4x12 internal ISP the S5K6A3 sensor driver (drivers/ media/i2c/s5k6a3.c) is now required. Signed-off-by: Sylwester Nawrocki <[email protected]> Acked-by: Kyungmin Park <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent bce6744 commit d265d9a

File tree

5 files changed

+57
-380
lines changed

5 files changed

+57
-380
lines changed

drivers/media/platform/exynos4-is/fimc-is-regs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ void fimc_is_hw_set_sensor_num(struct fimc_is *is)
112112
mcuctl_write(IH_REPLY_DONE, is, MCUCTL_REG_ISSR(0));
113113
mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
114114
mcuctl_write(IHC_GET_SENSOR_NUM, is, MCUCTL_REG_ISSR(2));
115-
mcuctl_write(FIMC_IS_SENSOR_NUM, is, MCUCTL_REG_ISSR(3));
115+
mcuctl_write(FIMC_IS_SENSORS_NUM, is, MCUCTL_REG_ISSR(3));
116116
}
117117

118118
void fimc_is_hw_close_sensor(struct fimc_is *is, unsigned int index)

drivers/media/platform/exynos4-is/fimc-is-sensor.c

Lines changed: 7 additions & 278 deletions
Original file line numberDiff line numberDiff line change
@@ -2,304 +2,33 @@
22
* Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
33
*
44
* Copyright (C) 2013 Samsung Electronics Co., Ltd.
5-
*
65
* Author: Sylwester Nawrocki <[email protected]>
76
*
87
* This program is free software; you can redistribute it and/or modify
98
* it under the terms of the GNU General Public License version 2 as
109
* published by the Free Software Foundation.
1110
*/
12-
#include <linux/delay.h>
13-
#include <linux/device.h>
14-
#include <linux/errno.h>
15-
#include <linux/gpio.h>
16-
#include <linux/i2c.h>
17-
#include <linux/kernel.h>
18-
#include <linux/module.h>
19-
#include <linux/of_gpio.h>
20-
#include <linux/pm_runtime.h>
21-
#include <linux/regulator/consumer.h>
22-
#include <linux/slab.h>
23-
#include <media/v4l2-subdev.h>
2411

25-
#include "fimc-is.h"
2612
#include "fimc-is-sensor.h"
2713

28-
#define DRIVER_NAME "FIMC-IS-SENSOR"
29-
30-
static const char * const sensor_supply_names[] = {
31-
"svdda",
32-
"svddio",
33-
};
34-
35-
static const struct v4l2_mbus_framefmt fimc_is_sensor_formats[] = {
36-
{
37-
.code = V4L2_MBUS_FMT_SGRBG10_1X10,
38-
.colorspace = V4L2_COLORSPACE_SRGB,
39-
.field = V4L2_FIELD_NONE,
40-
}
41-
};
42-
43-
static const struct v4l2_mbus_framefmt *find_sensor_format(
44-
struct v4l2_mbus_framefmt *mf)
45-
{
46-
int i;
47-
48-
for (i = 0; i < ARRAY_SIZE(fimc_is_sensor_formats); i++)
49-
if (mf->code == fimc_is_sensor_formats[i].code)
50-
return &fimc_is_sensor_formats[i];
51-
52-
return &fimc_is_sensor_formats[0];
53-
}
54-
55-
static int fimc_is_sensor_enum_mbus_code(struct v4l2_subdev *sd,
56-
struct v4l2_subdev_fh *fh,
57-
struct v4l2_subdev_mbus_code_enum *code)
58-
{
59-
if (code->index >= ARRAY_SIZE(fimc_is_sensor_formats))
60-
return -EINVAL;
61-
62-
code->code = fimc_is_sensor_formats[code->index].code;
63-
return 0;
64-
}
65-
66-
static void fimc_is_sensor_try_format(struct fimc_is_sensor *sensor,
67-
struct v4l2_mbus_framefmt *mf)
68-
{
69-
const struct sensor_drv_data *dd = sensor->drvdata;
70-
const struct v4l2_mbus_framefmt *fmt;
71-
72-
fmt = find_sensor_format(mf);
73-
mf->code = fmt->code;
74-
v4l_bound_align_image(&mf->width, 16 + 8, dd->width, 0,
75-
&mf->height, 12 + 8, dd->height, 0, 0);
76-
}
77-
78-
static struct v4l2_mbus_framefmt *__fimc_is_sensor_get_format(
79-
struct fimc_is_sensor *sensor, struct v4l2_subdev_fh *fh,
80-
u32 pad, enum v4l2_subdev_format_whence which)
81-
{
82-
if (which == V4L2_SUBDEV_FORMAT_TRY)
83-
return fh ? v4l2_subdev_get_try_format(fh, pad) : NULL;
84-
85-
return &sensor->format;
86-
}
87-
88-
static int fimc_is_sensor_set_fmt(struct v4l2_subdev *sd,
89-
struct v4l2_subdev_fh *fh,
90-
struct v4l2_subdev_format *fmt)
91-
{
92-
struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
93-
struct v4l2_mbus_framefmt *mf;
94-
95-
fimc_is_sensor_try_format(sensor, &fmt->format);
96-
97-
mf = __fimc_is_sensor_get_format(sensor, fh, fmt->pad, fmt->which);
98-
if (mf) {
99-
mutex_lock(&sensor->lock);
100-
if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
101-
*mf = fmt->format;
102-
mutex_unlock(&sensor->lock);
103-
}
104-
return 0;
105-
}
106-
107-
static int fimc_is_sensor_get_fmt(struct v4l2_subdev *sd,
108-
struct v4l2_subdev_fh *fh,
109-
struct v4l2_subdev_format *fmt)
110-
{
111-
struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
112-
struct v4l2_mbus_framefmt *mf;
113-
114-
mf = __fimc_is_sensor_get_format(sensor, fh, fmt->pad, fmt->which);
115-
116-
mutex_lock(&sensor->lock);
117-
fmt->format = *mf;
118-
mutex_unlock(&sensor->lock);
119-
return 0;
120-
}
121-
122-
static struct v4l2_subdev_pad_ops fimc_is_sensor_pad_ops = {
123-
.enum_mbus_code = fimc_is_sensor_enum_mbus_code,
124-
.get_fmt = fimc_is_sensor_get_fmt,
125-
.set_fmt = fimc_is_sensor_set_fmt,
126-
};
127-
128-
static int fimc_is_sensor_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
129-
{
130-
struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
131-
132-
*format = fimc_is_sensor_formats[0];
133-
format->width = FIMC_IS_SENSOR_DEF_PIX_WIDTH;
134-
format->height = FIMC_IS_SENSOR_DEF_PIX_HEIGHT;
135-
136-
return 0;
137-
}
138-
139-
static const struct v4l2_subdev_internal_ops fimc_is_sensor_sd_internal_ops = {
140-
.open = fimc_is_sensor_open,
141-
};
142-
143-
static int fimc_is_sensor_s_power(struct v4l2_subdev *sd, int on)
144-
{
145-
struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
146-
int gpio = sensor->gpio_reset;
147-
int ret;
148-
149-
if (on) {
150-
ret = pm_runtime_get(sensor->dev);
151-
if (ret < 0)
152-
return ret;
153-
154-
ret = regulator_bulk_enable(SENSOR_NUM_SUPPLIES,
155-
sensor->supplies);
156-
if (ret < 0) {
157-
pm_runtime_put(sensor->dev);
158-
return ret;
159-
}
160-
if (gpio_is_valid(gpio)) {
161-
gpio_set_value(gpio, 1);
162-
usleep_range(600, 800);
163-
gpio_set_value(gpio, 0);
164-
usleep_range(10000, 11000);
165-
gpio_set_value(gpio, 1);
166-
}
167-
168-
/* A delay needed for the sensor initialization. */
169-
msleep(20);
170-
} else {
171-
if (gpio_is_valid(gpio))
172-
gpio_set_value(gpio, 0);
173-
174-
ret = regulator_bulk_disable(SENSOR_NUM_SUPPLIES,
175-
sensor->supplies);
176-
if (!ret)
177-
pm_runtime_put(sensor->dev);
178-
}
179-
180-
pr_info("%s:%d: on: %d, ret: %d\n", __func__, __LINE__, on, ret);
181-
182-
return ret;
183-
}
184-
185-
static struct v4l2_subdev_core_ops fimc_is_sensor_core_ops = {
186-
.s_power = fimc_is_sensor_s_power,
187-
};
188-
189-
static struct v4l2_subdev_ops fimc_is_sensor_subdev_ops = {
190-
.core = &fimc_is_sensor_core_ops,
191-
.pad = &fimc_is_sensor_pad_ops,
192-
};
193-
194-
static const struct of_device_id fimc_is_sensor_of_match[];
195-
196-
static int fimc_is_sensor_probe(struct i2c_client *client,
197-
const struct i2c_device_id *id)
198-
{
199-
struct device *dev = &client->dev;
200-
struct fimc_is_sensor *sensor;
201-
const struct of_device_id *of_id;
202-
struct v4l2_subdev *sd;
203-
int gpio, i, ret;
204-
205-
sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
206-
if (!sensor)
207-
return -ENOMEM;
208-
209-
mutex_init(&sensor->lock);
210-
sensor->gpio_reset = -EINVAL;
211-
212-
gpio = of_get_gpio_flags(dev->of_node, 0, NULL);
213-
if (gpio_is_valid(gpio)) {
214-
ret = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_LOW,
215-
DRIVER_NAME);
216-
if (ret < 0)
217-
return ret;
218-
}
219-
sensor->gpio_reset = gpio;
220-
221-
for (i = 0; i < SENSOR_NUM_SUPPLIES; i++)
222-
sensor->supplies[i].supply = sensor_supply_names[i];
223-
224-
ret = devm_regulator_bulk_get(&client->dev, SENSOR_NUM_SUPPLIES,
225-
sensor->supplies);
226-
if (ret < 0)
227-
return ret;
228-
229-
of_id = of_match_node(fimc_is_sensor_of_match, dev->of_node);
230-
if (!of_id)
231-
return -ENODEV;
232-
233-
sensor->drvdata = of_id->data;
234-
sensor->dev = dev;
235-
236-
sd = &sensor->subdev;
237-
v4l2_i2c_subdev_init(sd, client, &fimc_is_sensor_subdev_ops);
238-
snprintf(sd->name, sizeof(sd->name), sensor->drvdata->subdev_name);
239-
sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
240-
241-
sensor->format.code = fimc_is_sensor_formats[0].code;
242-
sensor->format.width = FIMC_IS_SENSOR_DEF_PIX_WIDTH;
243-
sensor->format.height = FIMC_IS_SENSOR_DEF_PIX_HEIGHT;
244-
245-
sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
246-
ret = media_entity_init(&sd->entity, 1, &sensor->pad, 0);
247-
if (ret < 0)
248-
return ret;
249-
250-
pm_runtime_no_callbacks(dev);
251-
pm_runtime_enable(dev);
252-
253-
return ret;
254-
}
255-
256-
static int fimc_is_sensor_remove(struct i2c_client *client)
257-
{
258-
struct v4l2_subdev *sd = i2c_get_clientdata(client);
259-
media_entity_cleanup(&sd->entity);
260-
return 0;
261-
}
262-
263-
static const struct i2c_device_id fimc_is_sensor_ids[] = {
264-
{ }
265-
};
266-
26714
static const struct sensor_drv_data s5k6a3_drvdata = {
26815
.id = FIMC_IS_SENSOR_ID_S5K6A3,
269-
.subdev_name = "S5K6A3",
270-
.width = S5K6A3_SENSOR_WIDTH,
271-
.height = S5K6A3_SENSOR_HEIGHT,
16+
.open_timeout = S5K6A3_OPEN_TIMEOUT,
27217
};
27318

274-
static const struct of_device_id fimc_is_sensor_of_match[] = {
19+
static const struct of_device_id fimc_is_sensor_of_ids[] = {
27520
{
27621
.compatible = "samsung,s5k6a3",
27722
.data = &s5k6a3_drvdata,
27823
},
27924
{ }
28025
};
28126

282-
static struct i2c_driver fimc_is_sensor_driver = {
283-
.driver = {
284-
.of_match_table = fimc_is_sensor_of_match,
285-
.name = DRIVER_NAME,
286-
.owner = THIS_MODULE,
287-
},
288-
.probe = fimc_is_sensor_probe,
289-
.remove = fimc_is_sensor_remove,
290-
.id_table = fimc_is_sensor_ids,
291-
};
292-
293-
int fimc_is_register_sensor_driver(void)
27+
const struct sensor_drv_data *fimc_is_sensor_get_drvdata(
28+
struct device_node *node)
29429
{
295-
return i2c_add_driver(&fimc_is_sensor_driver);
296-
}
30+
const struct of_device_id *of_id;
29731

298-
void fimc_is_unregister_sensor_driver(void)
299-
{
300-
i2c_del_driver(&fimc_is_sensor_driver);
32+
of_id = of_match_node(fimc_is_sensor_of_ids, node);
33+
return of_id ? of_id->data : NULL;
30134
}
302-
303-
MODULE_AUTHOR("Sylwester Nawrocki <[email protected]>");
304-
MODULE_DESCRIPTION("Exynos4x12 FIMC-IS image sensor subdev driver");
305-
MODULE_LICENSE("GPL");

drivers/media/platform/exynos4-is/fimc-is-sensor.h

Lines changed: 8 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,13 @@
1313
#ifndef FIMC_IS_SENSOR_H_
1414
#define FIMC_IS_SENSOR_H_
1515

16-
#include <linux/clk.h>
17-
#include <linux/device.h>
18-
#include <linux/kernel.h>
19-
#include <linux/platform_device.h>
20-
#include <linux/regulator/consumer.h>
21-
#include <linux/videodev2.h>
22-
#include <media/v4l2-subdev.h>
23-
24-
#define FIMC_IS_SENSOR_OPEN_TIMEOUT 2000 /* ms */
25-
26-
#define FIMC_IS_SENSOR_DEF_PIX_WIDTH 1296
27-
#define FIMC_IS_SENSOR_DEF_PIX_HEIGHT 732
16+
#include <linux/of.h>
17+
#include <linux/types.h>
2818

19+
#define S5K6A3_OPEN_TIMEOUT 2000 /* ms */
2920
#define S5K6A3_SENSOR_WIDTH 1392
3021
#define S5K6A3_SENSOR_HEIGHT 1392
3122

32-
#define SENSOR_NUM_SUPPLIES 2
33-
3423
enum fimc_is_sensor_id {
3524
FIMC_IS_SENSOR_ID_S5K3H2 = 1,
3625
FIMC_IS_SENSOR_ID_S5K6A3,
@@ -45,45 +34,23 @@ enum fimc_is_sensor_id {
4534

4635
struct sensor_drv_data {
4736
enum fimc_is_sensor_id id;
48-
const char * const subdev_name;
49-
unsigned int width;
50-
unsigned int height;
37+
/* sensor open timeout in ms */
38+
unsigned short open_timeout;
5139
};
5240

5341
/**
5442
* struct fimc_is_sensor - fimc-is sensor data structure
55-
* @dev: pointer to this I2C client device structure
56-
* @subdev: the image sensor's v4l2 subdev
57-
* @pad: subdev media source pad
58-
* @supplies: image sensor's voltage regulator supplies
59-
* @gpio_reset: GPIO connected to the sensor's reset pin
6043
* @drvdata: a pointer to the sensor's parameters data structure
6144
* @i2c_bus: ISP I2C bus index (0...1)
6245
* @test_pattern: true to enable video test pattern
63-
* @lock: mutex protecting the structure's members below
64-
* @format: media bus format at the sensor's source pad
6546
*/
6647
struct fimc_is_sensor {
67-
struct device *dev;
68-
struct v4l2_subdev subdev;
69-
struct media_pad pad;
70-
struct regulator_bulk_data supplies[SENSOR_NUM_SUPPLIES];
71-
int gpio_reset;
7248
const struct sensor_drv_data *drvdata;
7349
unsigned int i2c_bus;
74-
bool test_pattern;
75-
76-
struct mutex lock;
77-
struct v4l2_mbus_framefmt format;
50+
u8 test_pattern;
7851
};
7952

80-
static inline
81-
struct fimc_is_sensor *sd_to_fimc_is_sensor(struct v4l2_subdev *sd)
82-
{
83-
return container_of(sd, struct fimc_is_sensor, subdev);
84-
}
85-
86-
int fimc_is_register_sensor_driver(void);
87-
void fimc_is_unregister_sensor_driver(void);
53+
const struct sensor_drv_data *fimc_is_sensor_get_drvdata(
54+
struct device_node *node);
8855

8956
#endif /* FIMC_IS_SENSOR_H_ */

0 commit comments

Comments
 (0)