GNU Linux-libre 4.4.288-gnu1
[releases.git] / drivers / media / i2c / vs6624.c
1 /*
2  * vs6624.c ST VS6624 CMOS image sensor driver
3  *
4  * Copyright (c) 2011 Analog Devices Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 #include <linux/delay.h>
21 #include <linux/errno.h>
22 #include <linux/gpio.h>
23 #include <linux/i2c.h>
24 #include <linux/init.h>
25 #include <linux/module.h>
26 #include <linux/slab.h>
27 #include <linux/types.h>
28 #include <linux/videodev2.h>
29
30 #include <media/v4l2-ctrls.h>
31 #include <media/v4l2-device.h>
32 #include <media/v4l2-mediabus.h>
33 #include <media/v4l2-image-sizes.h>
34
35 #include "vs6624_regs.h"
36
37 #define MAX_FRAME_RATE  30
38
39 struct vs6624 {
40         struct v4l2_subdev sd;
41         struct v4l2_ctrl_handler hdl;
42         struct v4l2_fract frame_rate;
43         struct v4l2_mbus_framefmt fmt;
44         unsigned ce_pin;
45 };
46
47 static const struct vs6624_format {
48         u32 mbus_code;
49         enum v4l2_colorspace colorspace;
50 } vs6624_formats[] = {
51         {
52                 .mbus_code      = MEDIA_BUS_FMT_UYVY8_2X8,
53                 .colorspace     = V4L2_COLORSPACE_JPEG,
54         },
55         {
56                 .mbus_code      = MEDIA_BUS_FMT_YUYV8_2X8,
57                 .colorspace     = V4L2_COLORSPACE_JPEG,
58         },
59         {
60                 .mbus_code      = MEDIA_BUS_FMT_RGB565_2X8_LE,
61                 .colorspace     = V4L2_COLORSPACE_SRGB,
62         },
63 };
64
65 static struct v4l2_mbus_framefmt vs6624_default_fmt = {
66         .width = VGA_WIDTH,
67         .height = VGA_HEIGHT,
68         .code = MEDIA_BUS_FMT_UYVY8_2X8,
69         .field = V4L2_FIELD_NONE,
70         .colorspace = V4L2_COLORSPACE_JPEG,
71 };
72
73 /*(DEBLOBBED)*/
74
75 static const u16 vs6624_p2[] = {
76         0x806f, 0x01,
77         0x058c, 0x01,
78         0x0000, 0x00,
79 };
80
81 static const u16 vs6624_run_setup[] = {
82         0x1d18, 0x00,                           /* Enableconstrainedwhitebalance */
83         VS6624_PEAK_MIN_OUT_G_MSB, 0x3c,        /* Damper PeakGain Output MSB */
84         VS6624_PEAK_MIN_OUT_G_LSB, 0x66,        /* Damper PeakGain Output LSB */
85         VS6624_CM_LOW_THR_MSB, 0x65,            /* Damper Low MSB */
86         VS6624_CM_LOW_THR_LSB, 0xd1,            /* Damper Low LSB */
87         VS6624_CM_HIGH_THR_MSB, 0x66,           /* Damper High MSB */
88         VS6624_CM_HIGH_THR_LSB, 0x62,           /* Damper High LSB */
89         VS6624_CM_MIN_OUT_MSB, 0x00,            /* Damper Min output MSB */
90         VS6624_CM_MIN_OUT_LSB, 0x00,            /* Damper Min output LSB */
91         VS6624_NORA_DISABLE, 0x00,              /* Nora fDisable */
92         VS6624_NORA_USAGE, 0x04,                /* Nora usage */
93         VS6624_NORA_LOW_THR_MSB, 0x63,          /* Damper Low MSB Changed 0x63 to 0x65 */
94         VS6624_NORA_LOW_THR_LSB, 0xd1,          /* Damper Low LSB */
95         VS6624_NORA_HIGH_THR_MSB, 0x68,         /* Damper High MSB */
96         VS6624_NORA_HIGH_THR_LSB, 0xdd,         /* Damper High LSB */
97         VS6624_NORA_MIN_OUT_MSB, 0x3a,          /* Damper Min output MSB */
98         VS6624_NORA_MIN_OUT_LSB, 0x00,          /* Damper Min output LSB */
99         VS6624_F2B_DISABLE, 0x00,               /* Disable */
100         0x1d8a, 0x30,                           /* MAXWeightHigh */
101         0x1d91, 0x62,                           /* fpDamperLowThresholdHigh MSB */
102         0x1d92, 0x4a,                           /* fpDamperLowThresholdHigh LSB */
103         0x1d95, 0x65,                           /* fpDamperHighThresholdHigh MSB */
104         0x1d96, 0x0e,                           /* fpDamperHighThresholdHigh LSB */
105         0x1da1, 0x3a,                           /* fpMinimumDamperOutputLow MSB */
106         0x1da2, 0xb8,                           /* fpMinimumDamperOutputLow LSB */
107         0x1e08, 0x06,                           /* MAXWeightLow */
108         0x1e0a, 0x0a,                           /* MAXWeightHigh */
109         0x1601, 0x3a,                           /* Red A MSB */
110         0x1602, 0x14,                           /* Red A LSB */
111         0x1605, 0x3b,                           /* Blue A MSB */
112         0x1606, 0x85,                           /* BLue A LSB */
113         0x1609, 0x3b,                           /* RED B MSB */
114         0x160a, 0x85,                           /* RED B LSB */
115         0x160d, 0x3a,                           /* Blue B MSB */
116         0x160e, 0x14,                           /* Blue B LSB */
117         0x1611, 0x30,                           /* Max Distance from Locus MSB */
118         0x1612, 0x8f,                           /* Max Distance from Locus MSB */
119         0x1614, 0x01,                           /* Enable constrainer */
120         0x0000, 0x00,
121 };
122
123 static const u16 vs6624_default[] = {
124         VS6624_CONTRAST0, 0x84,
125         VS6624_SATURATION0, 0x75,
126         VS6624_GAMMA0, 0x11,
127         VS6624_CONTRAST1, 0x84,
128         VS6624_SATURATION1, 0x75,
129         VS6624_GAMMA1, 0x11,
130         VS6624_MAN_RG, 0x80,
131         VS6624_MAN_GG, 0x80,
132         VS6624_MAN_BG, 0x80,
133         VS6624_WB_MODE, 0x1,
134         VS6624_EXPO_COMPENSATION, 0xfe,
135         VS6624_EXPO_METER, 0x0,
136         VS6624_LIGHT_FREQ, 0x64,
137         VS6624_PEAK_GAIN, 0xe,
138         VS6624_PEAK_LOW_THR, 0x28,
139         VS6624_HMIRROR0, 0x0,
140         VS6624_VFLIP0, 0x0,
141         VS6624_ZOOM_HSTEP0_MSB, 0x0,
142         VS6624_ZOOM_HSTEP0_LSB, 0x1,
143         VS6624_ZOOM_VSTEP0_MSB, 0x0,
144         VS6624_ZOOM_VSTEP0_LSB, 0x1,
145         VS6624_PAN_HSTEP0_MSB, 0x0,
146         VS6624_PAN_HSTEP0_LSB, 0xf,
147         VS6624_PAN_VSTEP0_MSB, 0x0,
148         VS6624_PAN_VSTEP0_LSB, 0xf,
149         VS6624_SENSOR_MODE, 0x1,
150         VS6624_SYNC_CODE_SETUP, 0x21,
151         VS6624_DISABLE_FR_DAMPER, 0x0,
152         VS6624_FR_DEN, 0x1,
153         VS6624_FR_NUM_LSB, 0xf,
154         VS6624_INIT_PIPE_SETUP, 0x0,
155         VS6624_IMG_FMT0, 0x0,
156         VS6624_YUV_SETUP, 0x1,
157         VS6624_IMAGE_SIZE0, 0x2,
158         0x0000, 0x00,
159 };
160
161 static inline struct vs6624 *to_vs6624(struct v4l2_subdev *sd)
162 {
163         return container_of(sd, struct vs6624, sd);
164 }
165 static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
166 {
167         return &container_of(ctrl->handler, struct vs6624, hdl)->sd;
168 }
169
170 #ifdef CONFIG_VIDEO_ADV_DEBUG
171 static int vs6624_read(struct v4l2_subdev *sd, u16 index)
172 {
173         struct i2c_client *client = v4l2_get_subdevdata(sd);
174         u8 buf[2];
175
176         buf[0] = index >> 8;
177         buf[1] = index;
178         i2c_master_send(client, buf, 2);
179         i2c_master_recv(client, buf, 1);
180
181         return buf[0];
182 }
183 #endif
184
185 static int vs6624_write(struct v4l2_subdev *sd, u16 index,
186                                 u8 value)
187 {
188         struct i2c_client *client = v4l2_get_subdevdata(sd);
189         u8 buf[3];
190
191         buf[0] = index >> 8;
192         buf[1] = index;
193         buf[2] = value;
194
195         return i2c_master_send(client, buf, 3);
196 }
197
198 static int vs6624_writeregs(struct v4l2_subdev *sd, const u16 *regs)
199 {
200         u16 reg;
201         u8 data;
202
203         while (*regs != 0x00) {
204                 reg = *regs++;
205                 data = *regs++;
206
207                 vs6624_write(sd, reg, data);
208         }
209         return 0;
210 }
211
212 static int vs6624_s_ctrl(struct v4l2_ctrl *ctrl)
213 {
214         struct v4l2_subdev *sd = to_sd(ctrl);
215
216         switch (ctrl->id) {
217         case V4L2_CID_CONTRAST:
218                 vs6624_write(sd, VS6624_CONTRAST0, ctrl->val);
219                 break;
220         case V4L2_CID_SATURATION:
221                 vs6624_write(sd, VS6624_SATURATION0, ctrl->val);
222                 break;
223         case V4L2_CID_HFLIP:
224                 vs6624_write(sd, VS6624_HMIRROR0, ctrl->val);
225                 break;
226         case V4L2_CID_VFLIP:
227                 vs6624_write(sd, VS6624_VFLIP0, ctrl->val);
228                 break;
229         default:
230                 return -EINVAL;
231         }
232
233         return 0;
234 }
235
236 static int vs6624_enum_mbus_code(struct v4l2_subdev *sd,
237                 struct v4l2_subdev_pad_config *cfg,
238                 struct v4l2_subdev_mbus_code_enum *code)
239 {
240         if (code->pad || code->index >= ARRAY_SIZE(vs6624_formats))
241                 return -EINVAL;
242
243         code->code = vs6624_formats[code->index].mbus_code;
244         return 0;
245 }
246
247 static int vs6624_set_fmt(struct v4l2_subdev *sd,
248                 struct v4l2_subdev_pad_config *cfg,
249                 struct v4l2_subdev_format *format)
250 {
251         struct v4l2_mbus_framefmt *fmt = &format->format;
252         struct vs6624 *sensor = to_vs6624(sd);
253         int index;
254
255         if (format->pad)
256                 return -EINVAL;
257
258         for (index = 0; index < ARRAY_SIZE(vs6624_formats); index++)
259                 if (vs6624_formats[index].mbus_code == fmt->code)
260                         break;
261         if (index >= ARRAY_SIZE(vs6624_formats)) {
262                 /* default to first format */
263                 index = 0;
264                 fmt->code = vs6624_formats[0].mbus_code;
265         }
266
267         /* sensor mode is VGA */
268         if (fmt->width > VGA_WIDTH)
269                 fmt->width = VGA_WIDTH;
270         if (fmt->height > VGA_HEIGHT)
271                 fmt->height = VGA_HEIGHT;
272         fmt->width = fmt->width & (~3);
273         fmt->height = fmt->height & (~3);
274         fmt->field = V4L2_FIELD_NONE;
275         fmt->colorspace = vs6624_formats[index].colorspace;
276
277         if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
278                 cfg->try_fmt = *fmt;
279                 return 0;
280         }
281
282         /* set image format */
283         switch (fmt->code) {
284         case MEDIA_BUS_FMT_UYVY8_2X8:
285                 vs6624_write(sd, VS6624_IMG_FMT0, 0x0);
286                 vs6624_write(sd, VS6624_YUV_SETUP, 0x1);
287                 break;
288         case MEDIA_BUS_FMT_YUYV8_2X8:
289                 vs6624_write(sd, VS6624_IMG_FMT0, 0x0);
290                 vs6624_write(sd, VS6624_YUV_SETUP, 0x3);
291                 break;
292         case MEDIA_BUS_FMT_RGB565_2X8_LE:
293                 vs6624_write(sd, VS6624_IMG_FMT0, 0x4);
294                 vs6624_write(sd, VS6624_RGB_SETUP, 0x0);
295                 break;
296         default:
297                 return -EINVAL;
298         }
299
300         /* set image size */
301         if ((fmt->width == VGA_WIDTH) && (fmt->height == VGA_HEIGHT))
302                 vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x2);
303         else if ((fmt->width == QVGA_WIDTH) && (fmt->height == QVGA_HEIGHT))
304                 vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x4);
305         else if ((fmt->width == QQVGA_WIDTH) && (fmt->height == QQVGA_HEIGHT))
306                 vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x6);
307         else if ((fmt->width == CIF_WIDTH) && (fmt->height == CIF_HEIGHT))
308                 vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x3);
309         else if ((fmt->width == QCIF_WIDTH) && (fmt->height == QCIF_HEIGHT))
310                 vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x5);
311         else if ((fmt->width == QQCIF_WIDTH) && (fmt->height == QQCIF_HEIGHT))
312                 vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x7);
313         else {
314                 vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x8);
315                 vs6624_write(sd, VS6624_MAN_HSIZE0_MSB, fmt->width >> 8);
316                 vs6624_write(sd, VS6624_MAN_HSIZE0_LSB, fmt->width & 0xFF);
317                 vs6624_write(sd, VS6624_MAN_VSIZE0_MSB, fmt->height >> 8);
318                 vs6624_write(sd, VS6624_MAN_VSIZE0_LSB, fmt->height & 0xFF);
319                 vs6624_write(sd, VS6624_CROP_CTRL0, 0x1);
320         }
321
322         sensor->fmt = *fmt;
323
324         return 0;
325 }
326
327 static int vs6624_get_fmt(struct v4l2_subdev *sd,
328                 struct v4l2_subdev_pad_config *cfg,
329                 struct v4l2_subdev_format *format)
330 {
331         struct vs6624 *sensor = to_vs6624(sd);
332
333         if (format->pad)
334                 return -EINVAL;
335
336         format->format = sensor->fmt;
337         return 0;
338 }
339
340 static int vs6624_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
341 {
342         struct vs6624 *sensor = to_vs6624(sd);
343         struct v4l2_captureparm *cp = &parms->parm.capture;
344
345         if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
346                 return -EINVAL;
347
348         memset(cp, 0, sizeof(*cp));
349         cp->capability = V4L2_CAP_TIMEPERFRAME;
350         cp->timeperframe.numerator = sensor->frame_rate.denominator;
351         cp->timeperframe.denominator = sensor->frame_rate.numerator;
352         return 0;
353 }
354
355 static int vs6624_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
356 {
357         struct vs6624 *sensor = to_vs6624(sd);
358         struct v4l2_captureparm *cp = &parms->parm.capture;
359         struct v4l2_fract *tpf = &cp->timeperframe;
360
361         if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
362                 return -EINVAL;
363         if (cp->extendedmode != 0)
364                 return -EINVAL;
365
366         if (tpf->numerator == 0 || tpf->denominator == 0
367                 || (tpf->denominator > tpf->numerator * MAX_FRAME_RATE)) {
368                 /* reset to max frame rate */
369                 tpf->numerator = 1;
370                 tpf->denominator = MAX_FRAME_RATE;
371         }
372         sensor->frame_rate.numerator = tpf->denominator;
373         sensor->frame_rate.denominator = tpf->numerator;
374         vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0);
375         vs6624_write(sd, VS6624_FR_NUM_MSB,
376                         sensor->frame_rate.numerator >> 8);
377         vs6624_write(sd, VS6624_FR_NUM_LSB,
378                         sensor->frame_rate.numerator & 0xFF);
379         vs6624_write(sd, VS6624_FR_DEN,
380                         sensor->frame_rate.denominator & 0xFF);
381         return 0;
382 }
383
384 static int vs6624_s_stream(struct v4l2_subdev *sd, int enable)
385 {
386         if (enable)
387                 vs6624_write(sd, VS6624_USER_CMD, 0x2);
388         else
389                 vs6624_write(sd, VS6624_USER_CMD, 0x4);
390         udelay(100);
391         return 0;
392 }
393
394 #ifdef CONFIG_VIDEO_ADV_DEBUG
395 static int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
396 {
397         reg->val = vs6624_read(sd, reg->reg & 0xffff);
398         reg->size = 1;
399         return 0;
400 }
401
402 static int vs6624_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
403 {
404         vs6624_write(sd, reg->reg & 0xffff, reg->val & 0xff);
405         return 0;
406 }
407 #endif
408
409 static const struct v4l2_ctrl_ops vs6624_ctrl_ops = {
410         .s_ctrl = vs6624_s_ctrl,
411 };
412
413 static const struct v4l2_subdev_core_ops vs6624_core_ops = {
414 #ifdef CONFIG_VIDEO_ADV_DEBUG
415         .g_register = vs6624_g_register,
416         .s_register = vs6624_s_register,
417 #endif
418 };
419
420 static const struct v4l2_subdev_video_ops vs6624_video_ops = {
421         .s_parm = vs6624_s_parm,
422         .g_parm = vs6624_g_parm,
423         .s_stream = vs6624_s_stream,
424 };
425
426 static const struct v4l2_subdev_pad_ops vs6624_pad_ops = {
427         .enum_mbus_code = vs6624_enum_mbus_code,
428         .get_fmt = vs6624_get_fmt,
429         .set_fmt = vs6624_set_fmt,
430 };
431
432 static const struct v4l2_subdev_ops vs6624_ops = {
433         .core = &vs6624_core_ops,
434         .video = &vs6624_video_ops,
435         .pad = &vs6624_pad_ops,
436 };
437
438 static int vs6624_probe(struct i2c_client *client,
439                         const struct i2c_device_id *id)
440 {
441         struct vs6624 *sensor;
442         struct v4l2_subdev *sd;
443         struct v4l2_ctrl_handler *hdl;
444         const unsigned *ce;
445         int ret;
446
447         /* Check if the adapter supports the needed features */
448         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
449                 return -EIO;
450
451         ce = client->dev.platform_data;
452         if (ce == NULL)
453                 return -EINVAL;
454
455         ret = devm_gpio_request_one(&client->dev, *ce, GPIOF_OUT_INIT_HIGH,
456                                     "VS6624 Chip Enable");
457         if (ret) {
458                 v4l_err(client, "failed to request GPIO %d\n", *ce);
459                 return ret;
460         }
461         /* wait 100ms before any further i2c writes are performed */
462         mdelay(100);
463
464         sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);
465         if (sensor == NULL)
466                 return -ENOMEM;
467
468         sd = &sensor->sd;
469         v4l2_i2c_subdev_init(sd, client, &vs6624_ops);
470
471         /*(DEBLOBBED)*/
472         vs6624_write(sd, VS6624_MICRO_EN, 0x2);
473         vs6624_write(sd, VS6624_DIO_EN, 0x1);
474         mdelay(10);
475         vs6624_writeregs(sd, vs6624_p2);
476
477         vs6624_writeregs(sd, vs6624_default);
478         vs6624_write(sd, VS6624_HSYNC_SETUP, 0xF);
479         vs6624_writeregs(sd, vs6624_run_setup);
480
481         /* set frame rate */
482         sensor->frame_rate.numerator = MAX_FRAME_RATE;
483         sensor->frame_rate.denominator = 1;
484         vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0);
485         vs6624_write(sd, VS6624_FR_NUM_MSB,
486                         sensor->frame_rate.numerator >> 8);
487         vs6624_write(sd, VS6624_FR_NUM_LSB,
488                         sensor->frame_rate.numerator & 0xFF);
489         vs6624_write(sd, VS6624_FR_DEN,
490                         sensor->frame_rate.denominator & 0xFF);
491
492         sensor->fmt = vs6624_default_fmt;
493         sensor->ce_pin = *ce;
494
495         v4l_info(client, "chip found @ 0x%02x (%s)\n",
496                         client->addr << 1, client->adapter->name);
497
498         hdl = &sensor->hdl;
499         v4l2_ctrl_handler_init(hdl, 4);
500         v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
501                         V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x87);
502         v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
503                         V4L2_CID_SATURATION, 0, 0xFF, 1, 0x78);
504         v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
505                         V4L2_CID_HFLIP, 0, 1, 1, 0);
506         v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
507                         V4L2_CID_VFLIP, 0, 1, 1, 0);
508         /* hook the control handler into the driver */
509         sd->ctrl_handler = hdl;
510         if (hdl->error) {
511                 int err = hdl->error;
512
513                 v4l2_ctrl_handler_free(hdl);
514                 return err;
515         }
516
517         /* initialize the hardware to the default control values */
518         ret = v4l2_ctrl_handler_setup(hdl);
519         if (ret)
520                 v4l2_ctrl_handler_free(hdl);
521         return ret;
522 }
523
524 static int vs6624_remove(struct i2c_client *client)
525 {
526         struct v4l2_subdev *sd = i2c_get_clientdata(client);
527
528         v4l2_device_unregister_subdev(sd);
529         v4l2_ctrl_handler_free(sd->ctrl_handler);
530         return 0;
531 }
532
533 static const struct i2c_device_id vs6624_id[] = {
534         {"vs6624", 0},
535         {},
536 };
537
538 MODULE_DEVICE_TABLE(i2c, vs6624_id);
539
540 static struct i2c_driver vs6624_driver = {
541         .driver = {
542                 .owner  = THIS_MODULE,
543                 .name   = "vs6624",
544         },
545         .probe          = vs6624_probe,
546         .remove         = vs6624_remove,
547         .id_table       = vs6624_id,
548 };
549
550 module_i2c_driver(vs6624_driver);
551
552 MODULE_DESCRIPTION("VS6624 sensor driver");
553 MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
554 MODULE_LICENSE("GPL v2");