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
);
148 mutex_unlock(&sensor
->lock
);
153 static int s5k6a3_get_fmt(struct v4l2_subdev
*sd
,
154 struct v4l2_subdev_pad_config
*cfg
,
155 struct v4l2_subdev_format
*fmt
)
157 struct s5k6a3
*sensor
= sd_to_s5k6a3(sd
);
158 struct v4l2_mbus_framefmt
*mf
;
160 mf
= __s5k6a3_get_format(sensor
, cfg
, fmt
->pad
, fmt
->which
);
162 mutex_lock(&sensor
->lock
);
164 mutex_unlock(&sensor
->lock
);
168 static struct v4l2_subdev_pad_ops s5k6a3_pad_ops
= {
169 .enum_mbus_code
= s5k6a3_enum_mbus_code
,
170 .get_fmt
= s5k6a3_get_fmt
,
171 .set_fmt
= s5k6a3_set_fmt
,
174 static int s5k6a3_open(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
)
176 struct v4l2_mbus_framefmt
*format
= v4l2_subdev_get_try_format(sd
, fh
->pad
, 0);
178 *format
= s5k6a3_formats
[0];
179 format
->width
= S5K6A3_DEFAULT_WIDTH
;
180 format
->height
= S5K6A3_DEFAULT_HEIGHT
;
185 static const struct v4l2_subdev_internal_ops s5k6a3_sd_internal_ops
= {
189 static int __s5k6a3_power_on(struct s5k6a3
*sensor
)
191 int i
= S5K6A3_SUPP_VDDA
;
194 ret
= clk_set_rate(sensor
->clock
, sensor
->clock_frequency
);
198 ret
= pm_runtime_get(sensor
->dev
);
202 ret
= regulator_enable(sensor
->supplies
[i
].consumer
);
206 ret
= clk_prepare_enable(sensor
->clock
);
210 for (i
++; i
< S5K6A3_NUM_SUPPLIES
; i
++) {
211 ret
= regulator_enable(sensor
->supplies
[i
].consumer
);
216 gpio_set_value(sensor
->gpio_reset
, 1);
217 usleep_range(600, 800);
218 gpio_set_value(sensor
->gpio_reset
, 0);
219 usleep_range(600, 800);
220 gpio_set_value(sensor
->gpio_reset
, 1);
222 /* Delay needed for the sensor initialization */
227 for (--i
; i
>= 0; --i
)
228 regulator_disable(sensor
->supplies
[i
].consumer
);
230 pm_runtime_put(sensor
->dev
);
234 static int __s5k6a3_power_off(struct s5k6a3
*sensor
)
238 gpio_set_value(sensor
->gpio_reset
, 0);
240 for (i
= S5K6A3_NUM_SUPPLIES
- 1; i
>= 0; i
--)
241 regulator_disable(sensor
->supplies
[i
].consumer
);
243 clk_disable_unprepare(sensor
->clock
);
244 pm_runtime_put(sensor
->dev
);
248 static int s5k6a3_s_power(struct v4l2_subdev
*sd
, int on
)
250 struct s5k6a3
*sensor
= sd_to_s5k6a3(sd
);
253 mutex_lock(&sensor
->lock
);
255 if (sensor
->power_count
== !on
) {
257 ret
= __s5k6a3_power_on(sensor
);
259 ret
= __s5k6a3_power_off(sensor
);
262 sensor
->power_count
+= on
? 1 : -1;
265 mutex_unlock(&sensor
->lock
);
269 static struct v4l2_subdev_core_ops s5k6a3_core_ops
= {
270 .s_power
= s5k6a3_s_power
,
273 static struct v4l2_subdev_ops s5k6a3_subdev_ops
= {
274 .core
= &s5k6a3_core_ops
,
275 .pad
= &s5k6a3_pad_ops
,
278 static int s5k6a3_probe(struct i2c_client
*client
,
279 const struct i2c_device_id
*id
)
281 struct device
*dev
= &client
->dev
;
282 struct s5k6a3
*sensor
;
283 struct v4l2_subdev
*sd
;
286 sensor
= devm_kzalloc(dev
, sizeof(*sensor
), GFP_KERNEL
);
290 mutex_init(&sensor
->lock
);
291 sensor
->gpio_reset
= -EINVAL
;
292 sensor
->clock
= ERR_PTR(-EINVAL
);
295 sensor
->clock
= devm_clk_get(sensor
->dev
, S5K6A3_CLK_NAME
);
296 if (IS_ERR(sensor
->clock
))
297 return PTR_ERR(sensor
->clock
);
299 gpio
= of_get_gpio_flags(dev
->of_node
, 0, NULL
);
300 if (!gpio_is_valid(gpio
))
303 ret
= devm_gpio_request_one(dev
, gpio
, GPIOF_OUT_INIT_LOW
,
308 sensor
->gpio_reset
= gpio
;
310 if (of_property_read_u32(dev
->of_node
, "clock-frequency",
311 &sensor
->clock_frequency
)) {
312 sensor
->clock_frequency
= S5K6A3_DEFAULT_CLK_FREQ
;
313 dev_info(dev
, "using default %u Hz clock frequency\n",
314 sensor
->clock_frequency
);
317 for (i
= 0; i
< S5K6A3_NUM_SUPPLIES
; i
++)
318 sensor
->supplies
[i
].supply
= s5k6a3_supply_names
[i
];
320 ret
= devm_regulator_bulk_get(&client
->dev
, S5K6A3_NUM_SUPPLIES
,
325 sd
= &sensor
->subdev
;
326 v4l2_i2c_subdev_init(sd
, client
, &s5k6a3_subdev_ops
);
327 sensor
->subdev
.flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
328 sd
->internal_ops
= &s5k6a3_sd_internal_ops
;
330 sensor
->format
.code
= s5k6a3_formats
[0].code
;
331 sensor
->format
.width
= S5K6A3_DEFAULT_WIDTH
;
332 sensor
->format
.height
= S5K6A3_DEFAULT_HEIGHT
;
334 sd
->entity
.function
= MEDIA_ENT_F_CAM_SENSOR
;
335 sensor
->pad
.flags
= MEDIA_PAD_FL_SOURCE
;
336 ret
= media_entity_pads_init(&sd
->entity
, 1, &sensor
->pad
);
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
,
381 .probe
= s5k6a3_probe
,
382 .remove
= s5k6a3_remove
,
383 .id_table
= s5k6a3_ids
,
386 module_i2c_driver(s5k6a3_driver
);
388 MODULE_DESCRIPTION("S5K6A3 image sensor subdev driver");
389 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
390 MODULE_LICENSE("GPL v2");