2 * Samsung S5K6A3 image sensor driver
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/clk.h>
13 #include <linux/delay.h>
14 #include <linux/device.h>
15 #include <linux/errno.h>
16 #include <linux/gpio.h>
17 #include <linux/i2c.h>
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/of_gpio.h>
21 #include <linux/pm_runtime.h>
22 #include <linux/regulator/consumer.h>
23 #include <linux/slab.h>
24 #include <linux/videodev2.h>
25 #include <media/v4l2-async.h>
26 #include <media/v4l2-subdev.h>
28 #define S5K6A3_SENSOR_MAX_WIDTH 1412
29 #define S5K6A3_SENSOR_MAX_HEIGHT 1412
30 #define S5K6A3_SENSOR_MIN_WIDTH 32
31 #define S5K6A3_SENSOR_MIN_HEIGHT 32
33 #define S5K6A3_DEFAULT_WIDTH 1296
34 #define S5K6A3_DEFAULT_HEIGHT 732
36 #define S5K6A3_DRV_NAME "S5K6A3"
37 #define S5K6A3_CLK_NAME "extclk"
38 #define S5K6A3_DEFAULT_CLK_FREQ 24000000U
48 * struct s5k6a3 - fimc-is sensor data structure
49 * @dev: pointer to this I2C client device structure
50 * @subdev: the image sensor's v4l2 subdev
51 * @pad: subdev media source pad
52 * @supplies: image sensor's voltage regulator supplies
53 * @gpio_reset: GPIO connected to the sensor's reset pin
54 * @lock: mutex protecting the structure's members below
55 * @format: media bus format at the sensor's source pad
59 struct v4l2_subdev subdev
;
61 struct regulator_bulk_data supplies
[S5K6A3_NUM_SUPPLIES
];
64 struct v4l2_mbus_framefmt format
;
70 static const char * const s5k6a3_supply_names
[] = {
71 [S5K6A3_SUPP_VDDA
] = "svdda",
72 [S5K6A3_SUPP_VDDIO
] = "svddio",
73 [S5K6A3_SUPP_AFVDD
] = "afvdd",
76 static inline struct s5k6a3
*sd_to_s5k6a3(struct v4l2_subdev
*sd
)
78 return container_of(sd
, struct s5k6a3
, subdev
);
81 static const struct v4l2_mbus_framefmt s5k6a3_formats
[] = {
83 .code
= MEDIA_BUS_FMT_SGRBG10_1X10
,
84 .colorspace
= V4L2_COLORSPACE_SRGB
,
85 .field
= V4L2_FIELD_NONE
,
89 static const struct v4l2_mbus_framefmt
*find_sensor_format(
90 struct v4l2_mbus_framefmt
*mf
)
94 for (i
= 0; i
< ARRAY_SIZE(s5k6a3_formats
); i
++)
95 if (mf
->code
== s5k6a3_formats
[i
].code
)
96 return &s5k6a3_formats
[i
];
98 return &s5k6a3_formats
[0];
101 static int s5k6a3_enum_mbus_code(struct v4l2_subdev
*sd
,
102 struct v4l2_subdev_pad_config
*cfg
,
103 struct v4l2_subdev_mbus_code_enum
*code
)
105 if (code
->index
>= ARRAY_SIZE(s5k6a3_formats
))
108 code
->code
= s5k6a3_formats
[code
->index
].code
;
112 static void s5k6a3_try_format(struct v4l2_mbus_framefmt
*mf
)
114 const struct v4l2_mbus_framefmt
*fmt
;
116 fmt
= find_sensor_format(mf
);
117 mf
->code
= fmt
->code
;
118 mf
->field
= V4L2_FIELD_NONE
;
119 v4l_bound_align_image(&mf
->width
, S5K6A3_SENSOR_MIN_WIDTH
,
120 S5K6A3_SENSOR_MAX_WIDTH
, 0,
121 &mf
->height
, S5K6A3_SENSOR_MIN_HEIGHT
,
122 S5K6A3_SENSOR_MAX_HEIGHT
, 0, 0);
125 static struct v4l2_mbus_framefmt
*__s5k6a3_get_format(
126 struct s5k6a3
*sensor
, struct v4l2_subdev_pad_config
*cfg
,
127 u32 pad
, enum v4l2_subdev_format_whence which
)
129 if (which
== V4L2_SUBDEV_FORMAT_TRY
)
130 return cfg
? v4l2_subdev_get_try_format(&sensor
->subdev
, cfg
, pad
) : NULL
;
132 return &sensor
->format
;
135 static int s5k6a3_set_fmt(struct v4l2_subdev
*sd
,
136 struct v4l2_subdev_pad_config
*cfg
,
137 struct v4l2_subdev_format
*fmt
)
139 struct s5k6a3
*sensor
= sd_to_s5k6a3(sd
);
140 struct v4l2_mbus_framefmt
*mf
;
142 s5k6a3_try_format(&fmt
->format
);
144 mf
= __s5k6a3_get_format(sensor
, cfg
, fmt
->pad
, fmt
->which
);
146 mutex_lock(&sensor
->lock
);
147 if (fmt
->which
== V4L2_SUBDEV_FORMAT_ACTIVE
)
149 mutex_unlock(&sensor
->lock
);
154 static int s5k6a3_get_fmt(struct v4l2_subdev
*sd
,
155 struct v4l2_subdev_pad_config
*cfg
,
156 struct v4l2_subdev_format
*fmt
)
158 struct s5k6a3
*sensor
= sd_to_s5k6a3(sd
);
159 struct v4l2_mbus_framefmt
*mf
;
161 mf
= __s5k6a3_get_format(sensor
, cfg
, fmt
->pad
, fmt
->which
);
163 mutex_lock(&sensor
->lock
);
165 mutex_unlock(&sensor
->lock
);
169 static struct v4l2_subdev_pad_ops s5k6a3_pad_ops
= {
170 .enum_mbus_code
= s5k6a3_enum_mbus_code
,
171 .get_fmt
= s5k6a3_get_fmt
,
172 .set_fmt
= s5k6a3_set_fmt
,
175 static int s5k6a3_open(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
)
177 struct v4l2_mbus_framefmt
*format
= v4l2_subdev_get_try_format(sd
, fh
->pad
, 0);
179 *format
= s5k6a3_formats
[0];
180 format
->width
= S5K6A3_DEFAULT_WIDTH
;
181 format
->height
= S5K6A3_DEFAULT_HEIGHT
;
186 static const struct v4l2_subdev_internal_ops s5k6a3_sd_internal_ops
= {
190 static int __s5k6a3_power_on(struct s5k6a3
*sensor
)
192 int i
= S5K6A3_SUPP_VDDA
;
195 ret
= clk_set_rate(sensor
->clock
, sensor
->clock_frequency
);
199 ret
= pm_runtime_get(sensor
->dev
);
203 ret
= regulator_enable(sensor
->supplies
[i
].consumer
);
207 ret
= clk_prepare_enable(sensor
->clock
);
211 for (i
++; i
< S5K6A3_NUM_SUPPLIES
; i
++) {
212 ret
= regulator_enable(sensor
->supplies
[i
].consumer
);
217 gpio_set_value(sensor
->gpio_reset
, 1);
218 usleep_range(600, 800);
219 gpio_set_value(sensor
->gpio_reset
, 0);
220 usleep_range(600, 800);
221 gpio_set_value(sensor
->gpio_reset
, 1);
223 /* Delay needed for the sensor initialization */
228 for (--i
; i
>= 0; --i
)
229 regulator_disable(sensor
->supplies
[i
].consumer
);
231 pm_runtime_put(sensor
->dev
);
235 static int __s5k6a3_power_off(struct s5k6a3
*sensor
)
239 gpio_set_value(sensor
->gpio_reset
, 0);
241 for (i
= S5K6A3_NUM_SUPPLIES
- 1; i
>= 0; i
--)
242 regulator_disable(sensor
->supplies
[i
].consumer
);
244 clk_disable_unprepare(sensor
->clock
);
245 pm_runtime_put(sensor
->dev
);
249 static int s5k6a3_s_power(struct v4l2_subdev
*sd
, int on
)
251 struct s5k6a3
*sensor
= sd_to_s5k6a3(sd
);
254 mutex_lock(&sensor
->lock
);
256 if (sensor
->power_count
== !on
) {
258 ret
= __s5k6a3_power_on(sensor
);
260 ret
= __s5k6a3_power_off(sensor
);
263 sensor
->power_count
+= on
? 1 : -1;
266 mutex_unlock(&sensor
->lock
);
270 static struct v4l2_subdev_core_ops s5k6a3_core_ops
= {
271 .s_power
= s5k6a3_s_power
,
274 static struct v4l2_subdev_ops s5k6a3_subdev_ops
= {
275 .core
= &s5k6a3_core_ops
,
276 .pad
= &s5k6a3_pad_ops
,
279 static int s5k6a3_probe(struct i2c_client
*client
,
280 const struct i2c_device_id
*id
)
282 struct device
*dev
= &client
->dev
;
283 struct s5k6a3
*sensor
;
284 struct v4l2_subdev
*sd
;
287 sensor
= devm_kzalloc(dev
, sizeof(*sensor
), GFP_KERNEL
);
291 mutex_init(&sensor
->lock
);
292 sensor
->gpio_reset
= -EINVAL
;
293 sensor
->clock
= ERR_PTR(-EINVAL
);
296 sensor
->clock
= devm_clk_get(sensor
->dev
, S5K6A3_CLK_NAME
);
297 if (IS_ERR(sensor
->clock
))
298 return PTR_ERR(sensor
->clock
);
300 gpio
= of_get_gpio_flags(dev
->of_node
, 0, NULL
);
301 if (!gpio_is_valid(gpio
))
304 ret
= devm_gpio_request_one(dev
, gpio
, GPIOF_OUT_INIT_LOW
,
309 sensor
->gpio_reset
= gpio
;
311 if (of_property_read_u32(dev
->of_node
, "clock-frequency",
312 &sensor
->clock_frequency
)) {
313 sensor
->clock_frequency
= S5K6A3_DEFAULT_CLK_FREQ
;
314 dev_info(dev
, "using default %u Hz clock frequency\n",
315 sensor
->clock_frequency
);
318 for (i
= 0; i
< S5K6A3_NUM_SUPPLIES
; i
++)
319 sensor
->supplies
[i
].supply
= s5k6a3_supply_names
[i
];
321 ret
= devm_regulator_bulk_get(&client
->dev
, S5K6A3_NUM_SUPPLIES
,
326 sd
= &sensor
->subdev
;
327 v4l2_i2c_subdev_init(sd
, client
, &s5k6a3_subdev_ops
);
328 sensor
->subdev
.flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
329 sd
->internal_ops
= &s5k6a3_sd_internal_ops
;
331 sensor
->format
.code
= s5k6a3_formats
[0].code
;
332 sensor
->format
.width
= S5K6A3_DEFAULT_WIDTH
;
333 sensor
->format
.height
= S5K6A3_DEFAULT_HEIGHT
;
335 sensor
->pad
.flags
= MEDIA_PAD_FL_SOURCE
;
336 ret
= media_entity_init(&sd
->entity
, 1, &sensor
->pad
, 0);
340 pm_runtime_no_callbacks(dev
);
341 pm_runtime_enable(dev
);
343 ret
= v4l2_async_register_subdev(sd
);
346 pm_runtime_disable(&client
->dev
);
347 media_entity_cleanup(&sd
->entity
);
353 static int s5k6a3_remove(struct i2c_client
*client
)
355 struct v4l2_subdev
*sd
= i2c_get_clientdata(client
);
357 pm_runtime_disable(&client
->dev
);
358 v4l2_async_unregister_subdev(sd
);
359 media_entity_cleanup(&sd
->entity
);
363 static const struct i2c_device_id s5k6a3_ids
[] = {
366 MODULE_DEVICE_TABLE(i2c
, s5k6a3_ids
);
369 static const struct of_device_id s5k6a3_of_match
[] = {
370 { .compatible
= "samsung,s5k6a3" },
373 MODULE_DEVICE_TABLE(of
, s5k6a3_of_match
);
376 static struct i2c_driver s5k6a3_driver
= {
378 .of_match_table
= of_match_ptr(s5k6a3_of_match
),
379 .name
= S5K6A3_DRV_NAME
,
380 .owner
= THIS_MODULE
,
382 .probe
= s5k6a3_probe
,
383 .remove
= s5k6a3_remove
,
384 .id_table
= s5k6a3_ids
,
387 module_i2c_driver(s5k6a3_driver
);
389 MODULE_DESCRIPTION("S5K6A3 image sensor subdev driver");
390 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
391 MODULE_LICENSE("GPL v2");