Merge tag 'firewire-updates' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee139...
[firefly-linux-kernel-4.4.55.git] / drivers / media / platform / exynos4-is / fimc-is-sensor.c
1 /*
2  * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3  *
4  * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5  *
6  * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
7  *
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.
11  */
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>
24
25 #include "fimc-is.h"
26 #include "fimc-is-sensor.h"
27
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
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,
272 };
273
274 static const struct of_device_id fimc_is_sensor_of_match[] = {
275         {
276                 .compatible     = "samsung,s5k6a3",
277                 .data           = &s5k6a3_drvdata,
278         },
279         {  }
280 };
281
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)
294 {
295         return i2c_add_driver(&fimc_is_sensor_driver);
296 }
297
298 void fimc_is_unregister_sensor_driver(void)
299 {
300         i2c_del_driver(&fimc_is_sensor_driver);
301 }
302
303 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
304 MODULE_DESCRIPTION("Exynos4x12 FIMC-IS image sensor subdev driver");
305 MODULE_LICENSE("GPL");