2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
6 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
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>
26 #include "fimc-is-sensor.h"
28 #define DRIVER_NAME "FIMC-IS-SENSOR"
30 static const char * const sensor_supply_names
[] = {
35 static const struct v4l2_mbus_framefmt fimc_is_sensor_formats
[] = {
37 .code
= V4L2_MBUS_FMT_SGRBG10_1X10
,
38 .colorspace
= V4L2_COLORSPACE_SRGB
,
39 .field
= V4L2_FIELD_NONE
,
43 static const struct v4l2_mbus_framefmt
*find_sensor_format(
44 struct v4l2_mbus_framefmt
*mf
)
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
];
52 return &fimc_is_sensor_formats
[0];
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
)
59 if (code
->index
>= ARRAY_SIZE(fimc_is_sensor_formats
))
62 code
->code
= fimc_is_sensor_formats
[code
->index
].code
;
66 static void fimc_is_sensor_try_format(struct fimc_is_sensor
*sensor
,
67 struct v4l2_mbus_framefmt
*mf
)
69 const struct sensor_drv_data
*dd
= sensor
->drvdata
;
70 const struct v4l2_mbus_framefmt
*fmt
;
72 fmt
= find_sensor_format(mf
);
74 v4l_bound_align_image(&mf
->width
, 16 + 8, dd
->width
, 0,
75 &mf
->height
, 12 + 8, dd
->height
, 0, 0);
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
)
82 if (which
== V4L2_SUBDEV_FORMAT_TRY
)
83 return fh
? v4l2_subdev_get_try_format(fh
, pad
) : NULL
;
85 return &sensor
->format
;
88 static int fimc_is_sensor_set_fmt(struct v4l2_subdev
*sd
,
89 struct v4l2_subdev_fh
*fh
,
90 struct v4l2_subdev_format
*fmt
)
92 struct fimc_is_sensor
*sensor
= sd_to_fimc_is_sensor(sd
);
93 struct v4l2_mbus_framefmt
*mf
;
95 fimc_is_sensor_try_format(sensor
, &fmt
->format
);
97 mf
= __fimc_is_sensor_get_format(sensor
, fh
, fmt
->pad
, fmt
->which
);
99 mutex_lock(&sensor
->lock
);
100 if (fmt
->which
== V4L2_SUBDEV_FORMAT_ACTIVE
)
102 mutex_unlock(&sensor
->lock
);
107 static int fimc_is_sensor_get_fmt(struct v4l2_subdev
*sd
,
108 struct v4l2_subdev_fh
*fh
,
109 struct v4l2_subdev_format
*fmt
)
111 struct fimc_is_sensor
*sensor
= sd_to_fimc_is_sensor(sd
);
112 struct v4l2_mbus_framefmt
*mf
;
114 mf
= __fimc_is_sensor_get_format(sensor
, fh
, fmt
->pad
, fmt
->which
);
116 mutex_lock(&sensor
->lock
);
118 mutex_unlock(&sensor
->lock
);
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
,
128 static int fimc_is_sensor_open(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
)
130 struct v4l2_mbus_framefmt
*format
= v4l2_subdev_get_try_format(fh
, 0);
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
;
139 static const struct v4l2_subdev_internal_ops fimc_is_sensor_sd_internal_ops
= {
140 .open
= fimc_is_sensor_open
,
143 static int fimc_is_sensor_s_power(struct v4l2_subdev
*sd
, int on
)
145 struct fimc_is_sensor
*sensor
= sd_to_fimc_is_sensor(sd
);
146 int gpio
= sensor
->gpio_reset
;
150 ret
= pm_runtime_get(sensor
->dev
);
154 ret
= regulator_bulk_enable(SENSOR_NUM_SUPPLIES
,
157 pm_runtime_put(sensor
->dev
);
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);
168 /* A delay needed for the sensor initialization. */
171 if (gpio_is_valid(gpio
))
172 gpio_set_value(gpio
, 0);
174 ret
= regulator_bulk_disable(SENSOR_NUM_SUPPLIES
,
177 pm_runtime_put(sensor
->dev
);
180 pr_info("%s:%d: on: %d, ret: %d\n", __func__
, __LINE__
, on
, ret
);
185 static struct v4l2_subdev_core_ops fimc_is_sensor_core_ops
= {
186 .s_power
= fimc_is_sensor_s_power
,
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
,
194 static const struct of_device_id fimc_is_sensor_of_match
[];
196 static int fimc_is_sensor_probe(struct i2c_client
*client
,
197 const struct i2c_device_id
*id
)
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
;
205 sensor
= devm_kzalloc(dev
, sizeof(*sensor
), GFP_KERNEL
);
209 mutex_init(&sensor
->lock
);
210 sensor
->gpio_reset
= -EINVAL
;
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
,
219 sensor
->gpio_reset
= gpio
;
221 for (i
= 0; i
< SENSOR_NUM_SUPPLIES
; i
++)
222 sensor
->supplies
[i
].supply
= sensor_supply_names
[i
];
224 ret
= devm_regulator_bulk_get(&client
->dev
, SENSOR_NUM_SUPPLIES
,
229 of_id
= of_match_node(fimc_is_sensor_of_match
, dev
->of_node
);
233 sensor
->drvdata
= of_id
->data
;
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
;
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
;
245 sensor
->pad
.flags
= MEDIA_PAD_FL_SOURCE
;
246 ret
= media_entity_init(&sd
->entity
, 1, &sensor
->pad
, 0);
250 pm_runtime_no_callbacks(dev
);
251 pm_runtime_enable(dev
);
256 static int fimc_is_sensor_remove(struct i2c_client
*client
)
258 struct v4l2_subdev
*sd
= i2c_get_clientdata(client
);
259 media_entity_cleanup(&sd
->entity
);
263 static const struct i2c_device_id fimc_is_sensor_ids
[] = {
267 static const struct sensor_drv_data s5k6a3_drvdata
= {
268 .id
= FIMC_IS_SENSOR_ID_S5K6A3
,
269 .subdev_name
= "S5K6A3",
270 .width
= S5K6A3_SENSOR_WIDTH
,
271 .height
= S5K6A3_SENSOR_HEIGHT
,
274 static const struct of_device_id fimc_is_sensor_of_match
[] = {
276 .compatible
= "samsung,s5k6a3",
277 .data
= &s5k6a3_drvdata
,
282 static struct i2c_driver fimc_is_sensor_driver
= {
284 .of_match_table
= fimc_is_sensor_of_match
,
286 .owner
= THIS_MODULE
,
288 .probe
= fimc_is_sensor_probe
,
289 .remove
= fimc_is_sensor_remove
,
290 .id_table
= fimc_is_sensor_ids
,
293 int fimc_is_register_sensor_driver(void)
295 return i2c_add_driver(&fimc_is_sensor_driver
);
298 void fimc_is_unregister_sensor_driver(void)
300 i2c_del_driver(&fimc_is_sensor_driver
);
303 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
304 MODULE_DESCRIPTION("Exynos4x12 FIMC-IS image sensor subdev driver");
305 MODULE_LICENSE("GPL");