1
2
3
4
5
6
7
8
9
10
11#include <linux/videodev2.h>
12#include <linux/slab.h>
13#include <linux/i2c.h>
14#include <linux/delay.h>
15#include <linux/log2.h>
16#include <linux/module.h>
17
18#include <media/soc_camera.h>
19#include <media/soc_mediabus.h>
20#include <media/v4l2-subdev.h>
21#include <media/v4l2-chip-ident.h>
22#include <media/v4l2-ctrls.h>
23
24
25
26
27
28
29
30static char *sensor_type;
31module_param(sensor_type, charp, S_IRUGO);
32MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
33
34
35#define MT9V022_CHIP_VERSION 0x00
36#define MT9V022_COLUMN_START 0x01
37#define MT9V022_ROW_START 0x02
38#define MT9V022_WINDOW_HEIGHT 0x03
39#define MT9V022_WINDOW_WIDTH 0x04
40#define MT9V022_HORIZONTAL_BLANKING 0x05
41#define MT9V022_VERTICAL_BLANKING 0x06
42#define MT9V022_CHIP_CONTROL 0x07
43#define MT9V022_SHUTTER_WIDTH1 0x08
44#define MT9V022_SHUTTER_WIDTH2 0x09
45#define MT9V022_SHUTTER_WIDTH_CTRL 0x0a
46#define MT9V022_TOTAL_SHUTTER_WIDTH 0x0b
47#define MT9V022_RESET 0x0c
48#define MT9V022_READ_MODE 0x0d
49#define MT9V022_MONITOR_MODE 0x0e
50#define MT9V022_PIXEL_OPERATION_MODE 0x0f
51#define MT9V022_LED_OUT_CONTROL 0x1b
52#define MT9V022_ADC_MODE_CONTROL 0x1c
53#define MT9V022_ANALOG_GAIN 0x35
54#define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47
55#define MT9V022_PIXCLK_FV_LV 0x74
56#define MT9V022_DIGITAL_TEST_PATTERN 0x7f
57#define MT9V022_AEC_AGC_ENABLE 0xAF
58#define MT9V022_MAX_TOTAL_SHUTTER_WIDTH 0xBD
59
60
61#define MT9V024_PIXCLK_FV_LV 0x72
62#define MT9V024_MAX_TOTAL_SHUTTER_WIDTH 0xAD
63
64
65#define MT9V022_CHIP_CONTROL_DEFAULT 0x188
66
67#define MT9V022_MAX_WIDTH 752
68#define MT9V022_MAX_HEIGHT 480
69#define MT9V022_MIN_WIDTH 48
70#define MT9V022_MIN_HEIGHT 32
71#define MT9V022_COLUMN_SKIP 1
72#define MT9V022_ROW_SKIP 4
73
74#define is_mt9v024(id) (id == 0x1324)
75
76
77struct mt9v022_datafmt {
78 enum v4l2_mbus_pixelcode code;
79 enum v4l2_colorspace colorspace;
80};
81
82
83static const struct mt9v022_datafmt *mt9v022_find_datafmt(
84 enum v4l2_mbus_pixelcode code, const struct mt9v022_datafmt *fmt,
85 int n)
86{
87 int i;
88 for (i = 0; i < n; i++)
89 if (fmt[i].code == code)
90 return fmt + i;
91
92 return NULL;
93}
94
95static const struct mt9v022_datafmt mt9v022_colour_fmts[] = {
96
97
98
99
100 {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
101 {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
102};
103
104static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = {
105
106 {V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
107 {V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
108};
109
110
111struct mt9v02x_register {
112 u8 max_total_shutter_width;
113 u8 pixclk_fv_lv;
114};
115
116static const struct mt9v02x_register mt9v022_register = {
117 .max_total_shutter_width = MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
118 .pixclk_fv_lv = MT9V022_PIXCLK_FV_LV,
119};
120
121static const struct mt9v02x_register mt9v024_register = {
122 .max_total_shutter_width = MT9V024_MAX_TOTAL_SHUTTER_WIDTH,
123 .pixclk_fv_lv = MT9V024_PIXCLK_FV_LV,
124};
125
126struct mt9v022 {
127 struct v4l2_subdev subdev;
128 struct v4l2_ctrl_handler hdl;
129 struct {
130
131 struct v4l2_ctrl *autoexposure;
132 struct v4l2_ctrl *exposure;
133 };
134 struct {
135
136 struct v4l2_ctrl *autogain;
137 struct v4l2_ctrl *gain;
138 };
139 struct v4l2_rect rect;
140 const struct mt9v022_datafmt *fmt;
141 const struct mt9v022_datafmt *fmts;
142 const struct mt9v02x_register *reg;
143 int num_fmts;
144 int model;
145 u16 chip_control;
146 unsigned short y_skip_top;
147};
148
149static struct mt9v022 *to_mt9v022(const struct i2c_client *client)
150{
151 return container_of(i2c_get_clientdata(client), struct mt9v022, subdev);
152}
153
154static int reg_read(struct i2c_client *client, const u8 reg)
155{
156 return i2c_smbus_read_word_swapped(client, reg);
157}
158
159static int reg_write(struct i2c_client *client, const u8 reg,
160 const u16 data)
161{
162 return i2c_smbus_write_word_swapped(client, reg, data);
163}
164
165static int reg_set(struct i2c_client *client, const u8 reg,
166 const u16 data)
167{
168 int ret;
169
170 ret = reg_read(client, reg);
171 if (ret < 0)
172 return ret;
173 return reg_write(client, reg, ret | data);
174}
175
176static int reg_clear(struct i2c_client *client, const u8 reg,
177 const u16 data)
178{
179 int ret;
180
181 ret = reg_read(client, reg);
182 if (ret < 0)
183 return ret;
184 return reg_write(client, reg, ret & ~data);
185}
186
187static int mt9v022_init(struct i2c_client *client)
188{
189 struct mt9v022 *mt9v022 = to_mt9v022(client);
190 int ret;
191
192
193
194
195
196
197 mt9v022->chip_control |= 0x10;
198 ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
199 if (!ret)
200 ret = reg_write(client, MT9V022_READ_MODE, 0x300);
201
202
203 if (!ret)
204
205 ret = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x3);
206 if (!ret)
207 ret = reg_write(client, MT9V022_ANALOG_GAIN, 16);
208 if (!ret)
209 ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, 480);
210 if (!ret)
211 ret = reg_write(client, mt9v022->reg->max_total_shutter_width, 480);
212 if (!ret)
213
214 ret = reg_clear(client, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
215 if (!ret)
216 ret = reg_write(client, MT9V022_DIGITAL_TEST_PATTERN, 0);
217 if (!ret)
218 return v4l2_ctrl_handler_setup(&mt9v022->hdl);
219
220 return ret;
221}
222
223static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable)
224{
225 struct i2c_client *client = v4l2_get_subdevdata(sd);
226 struct mt9v022 *mt9v022 = to_mt9v022(client);
227
228 if (enable)
229
230 mt9v022->chip_control &= ~0x10;
231 else
232
233 mt9v022->chip_control |= 0x10;
234
235 if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0)
236 return -EIO;
237 return 0;
238}
239
240static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
241{
242 struct i2c_client *client = v4l2_get_subdevdata(sd);
243 struct mt9v022 *mt9v022 = to_mt9v022(client);
244 struct v4l2_rect rect = a->c;
245 int ret;
246
247
248 if (mt9v022->fmts == mt9v022_colour_fmts) {
249 rect.width = ALIGN(rect.width, 2);
250 rect.height = ALIGN(rect.height, 2);
251
252 }
253
254 soc_camera_limit_side(&rect.left, &rect.width,
255 MT9V022_COLUMN_SKIP, MT9V022_MIN_WIDTH, MT9V022_MAX_WIDTH);
256
257 soc_camera_limit_side(&rect.top, &rect.height,
258 MT9V022_ROW_SKIP, MT9V022_MIN_HEIGHT, MT9V022_MAX_HEIGHT);
259
260
261 ret = reg_read(client, MT9V022_AEC_AGC_ENABLE);
262 if (ret >= 0) {
263 if (ret & 1)
264 ret = reg_write(client, mt9v022->reg->max_total_shutter_width,
265 rect.height + mt9v022->y_skip_top + 43);
266
267
268
269
270
271
272
273
274 }
275
276 if (!ret)
277 ret = reg_write(client, MT9V022_COLUMN_START, rect.left);
278 if (!ret)
279 ret = reg_write(client, MT9V022_ROW_START, rect.top);
280 if (!ret)
281
282
283
284
285 ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING,
286 rect.width > 660 - 43 ? 43 :
287 660 - rect.width);
288 if (!ret)
289 ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45);
290 if (!ret)
291 ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width);
292 if (!ret)
293 ret = reg_write(client, MT9V022_WINDOW_HEIGHT,
294 rect.height + mt9v022->y_skip_top);
295
296 if (ret < 0)
297 return ret;
298
299 dev_dbg(&client->dev, "Frame %dx%d pixel\n", rect.width, rect.height);
300
301 mt9v022->rect = rect;
302
303 return 0;
304}
305
306static int mt9v022_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
307{
308 struct i2c_client *client = v4l2_get_subdevdata(sd);
309 struct mt9v022 *mt9v022 = to_mt9v022(client);
310
311 a->c = mt9v022->rect;
312 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
313
314 return 0;
315}
316
317static int mt9v022_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
318{
319 a->bounds.left = MT9V022_COLUMN_SKIP;
320 a->bounds.top = MT9V022_ROW_SKIP;
321 a->bounds.width = MT9V022_MAX_WIDTH;
322 a->bounds.height = MT9V022_MAX_HEIGHT;
323 a->defrect = a->bounds;
324 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
325 a->pixelaspect.numerator = 1;
326 a->pixelaspect.denominator = 1;
327
328 return 0;
329}
330
331static int mt9v022_g_fmt(struct v4l2_subdev *sd,
332 struct v4l2_mbus_framefmt *mf)
333{
334 struct i2c_client *client = v4l2_get_subdevdata(sd);
335 struct mt9v022 *mt9v022 = to_mt9v022(client);
336
337 mf->width = mt9v022->rect.width;
338 mf->height = mt9v022->rect.height;
339 mf->code = mt9v022->fmt->code;
340 mf->colorspace = mt9v022->fmt->colorspace;
341 mf->field = V4L2_FIELD_NONE;
342
343 return 0;
344}
345
346static int mt9v022_s_fmt(struct v4l2_subdev *sd,
347 struct v4l2_mbus_framefmt *mf)
348{
349 struct i2c_client *client = v4l2_get_subdevdata(sd);
350 struct mt9v022 *mt9v022 = to_mt9v022(client);
351 struct v4l2_crop a = {
352 .c = {
353 .left = mt9v022->rect.left,
354 .top = mt9v022->rect.top,
355 .width = mf->width,
356 .height = mf->height,
357 },
358 };
359 int ret;
360
361
362
363
364
365 switch (mf->code) {
366 case V4L2_MBUS_FMT_Y8_1X8:
367 case V4L2_MBUS_FMT_Y10_1X10:
368 if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM)
369 return -EINVAL;
370 break;
371 case V4L2_MBUS_FMT_SBGGR8_1X8:
372 case V4L2_MBUS_FMT_SBGGR10_1X10:
373 if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
374 return -EINVAL;
375 break;
376 default:
377 return -EINVAL;
378 }
379
380
381 ret = mt9v022_s_crop(sd, &a);
382 if (!ret) {
383 mf->width = mt9v022->rect.width;
384 mf->height = mt9v022->rect.height;
385 mt9v022->fmt = mt9v022_find_datafmt(mf->code,
386 mt9v022->fmts, mt9v022->num_fmts);
387 mf->colorspace = mt9v022->fmt->colorspace;
388 }
389
390 return ret;
391}
392
393static int mt9v022_try_fmt(struct v4l2_subdev *sd,
394 struct v4l2_mbus_framefmt *mf)
395{
396 struct i2c_client *client = v4l2_get_subdevdata(sd);
397 struct mt9v022 *mt9v022 = to_mt9v022(client);
398 const struct mt9v022_datafmt *fmt;
399 int align = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
400 mf->code == V4L2_MBUS_FMT_SBGGR10_1X10;
401
402 v4l_bound_align_image(&mf->width, MT9V022_MIN_WIDTH,
403 MT9V022_MAX_WIDTH, align,
404 &mf->height, MT9V022_MIN_HEIGHT + mt9v022->y_skip_top,
405 MT9V022_MAX_HEIGHT + mt9v022->y_skip_top, align, 0);
406
407 fmt = mt9v022_find_datafmt(mf->code, mt9v022->fmts,
408 mt9v022->num_fmts);
409 if (!fmt) {
410 fmt = mt9v022->fmt;
411 mf->code = fmt->code;
412 }
413
414 mf->colorspace = fmt->colorspace;
415
416 return 0;
417}
418
419static int mt9v022_g_chip_ident(struct v4l2_subdev *sd,
420 struct v4l2_dbg_chip_ident *id)
421{
422 struct i2c_client *client = v4l2_get_subdevdata(sd);
423 struct mt9v022 *mt9v022 = to_mt9v022(client);
424
425 if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
426 return -EINVAL;
427
428 if (id->match.addr != client->addr)
429 return -ENODEV;
430
431 id->ident = mt9v022->model;
432 id->revision = 0;
433
434 return 0;
435}
436
437#ifdef CONFIG_VIDEO_ADV_DEBUG
438static int mt9v022_g_register(struct v4l2_subdev *sd,
439 struct v4l2_dbg_register *reg)
440{
441 struct i2c_client *client = v4l2_get_subdevdata(sd);
442
443 if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
444 return -EINVAL;
445
446 if (reg->match.addr != client->addr)
447 return -ENODEV;
448
449 reg->size = 2;
450 reg->val = reg_read(client, reg->reg);
451
452 if (reg->val > 0xffff)
453 return -EIO;
454
455 return 0;
456}
457
458static int mt9v022_s_register(struct v4l2_subdev *sd,
459 struct v4l2_dbg_register *reg)
460{
461 struct i2c_client *client = v4l2_get_subdevdata(sd);
462
463 if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
464 return -EINVAL;
465
466 if (reg->match.addr != client->addr)
467 return -ENODEV;
468
469 if (reg_write(client, reg->reg, reg->val) < 0)
470 return -EIO;
471
472 return 0;
473}
474#endif
475
476static int mt9v022_s_power(struct v4l2_subdev *sd, int on)
477{
478 struct i2c_client *client = v4l2_get_subdevdata(sd);
479 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
480
481 return soc_camera_set_power(&client->dev, icl, on);
482}
483
484static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
485{
486 struct mt9v022 *mt9v022 = container_of(ctrl->handler,
487 struct mt9v022, hdl);
488 struct v4l2_subdev *sd = &mt9v022->subdev;
489 struct i2c_client *client = v4l2_get_subdevdata(sd);
490 struct v4l2_ctrl *gain = mt9v022->gain;
491 struct v4l2_ctrl *exp = mt9v022->exposure;
492 unsigned long range;
493 int data;
494
495 switch (ctrl->id) {
496 case V4L2_CID_AUTOGAIN:
497 data = reg_read(client, MT9V022_ANALOG_GAIN);
498 if (data < 0)
499 return -EIO;
500
501 range = gain->maximum - gain->minimum;
502 gain->val = ((data - 16) * range + 24) / 48 + gain->minimum;
503 return 0;
504 case V4L2_CID_EXPOSURE_AUTO:
505 data = reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH);
506 if (data < 0)
507 return -EIO;
508
509 range = exp->maximum - exp->minimum;
510 exp->val = ((data - 1) * range + 239) / 479 + exp->minimum;
511 return 0;
512 }
513 return -EINVAL;
514}
515
516static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
517{
518 struct mt9v022 *mt9v022 = container_of(ctrl->handler,
519 struct mt9v022, hdl);
520 struct v4l2_subdev *sd = &mt9v022->subdev;
521 struct i2c_client *client = v4l2_get_subdevdata(sd);
522 int data;
523
524 switch (ctrl->id) {
525 case V4L2_CID_VFLIP:
526 if (ctrl->val)
527 data = reg_set(client, MT9V022_READ_MODE, 0x10);
528 else
529 data = reg_clear(client, MT9V022_READ_MODE, 0x10);
530 if (data < 0)
531 return -EIO;
532 return 0;
533 case V4L2_CID_HFLIP:
534 if (ctrl->val)
535 data = reg_set(client, MT9V022_READ_MODE, 0x20);
536 else
537 data = reg_clear(client, MT9V022_READ_MODE, 0x20);
538 if (data < 0)
539 return -EIO;
540 return 0;
541 case V4L2_CID_AUTOGAIN:
542 if (ctrl->val) {
543 if (reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
544 return -EIO;
545 } else {
546 struct v4l2_ctrl *gain = mt9v022->gain;
547
548 unsigned long range = gain->maximum - gain->minimum;
549
550 unsigned long gain_val = ((gain->val - gain->minimum) *
551 48 + range / 2) / range + 16;
552
553 if (gain_val >= 32)
554 gain_val &= ~1;
555
556
557
558
559
560 if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
561 return -EIO;
562
563 dev_dbg(&client->dev, "Setting gain from %d to %lu\n",
564 reg_read(client, MT9V022_ANALOG_GAIN), gain_val);
565 if (reg_write(client, MT9V022_ANALOG_GAIN, gain_val) < 0)
566 return -EIO;
567 }
568 return 0;
569 case V4L2_CID_EXPOSURE_AUTO:
570 if (ctrl->val == V4L2_EXPOSURE_AUTO) {
571 data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x1);
572 } else {
573 struct v4l2_ctrl *exp = mt9v022->exposure;
574 unsigned long range = exp->maximum - exp->minimum;
575 unsigned long shutter = ((exp->val - exp->minimum) *
576 479 + range / 2) / range + 1;
577
578
579
580
581
582 data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1);
583 if (data < 0)
584 return -EIO;
585 dev_dbg(&client->dev, "Shutter width from %d to %lu\n",
586 reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH),
587 shutter);
588 if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
589 shutter) < 0)
590 return -EIO;
591 }
592 return 0;
593 }
594 return -EINVAL;
595}
596
597
598
599
600
601static int mt9v022_video_probe(struct i2c_client *client)
602{
603 struct mt9v022 *mt9v022 = to_mt9v022(client);
604 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
605 s32 data;
606 int ret;
607 unsigned long flags;
608
609 ret = mt9v022_s_power(&mt9v022->subdev, 1);
610 if (ret < 0)
611 return ret;
612
613
614 data = reg_read(client, MT9V022_CHIP_VERSION);
615
616
617 if (data != 0x1311 && data != 0x1313 && data != 0x1324) {
618 ret = -ENODEV;
619 dev_info(&client->dev, "No MT9V022 found, ID register 0x%x\n",
620 data);
621 goto ei2c;
622 }
623
624 mt9v022->reg = is_mt9v024(data) ? &mt9v024_register :
625 &mt9v022_register;
626
627
628 ret = reg_write(client, MT9V022_RESET, 1);
629 if (ret < 0)
630 goto ei2c;
631
632 udelay(200);
633 if (reg_read(client, MT9V022_RESET)) {
634 dev_err(&client->dev, "Resetting MT9V022 failed!\n");
635 if (ret > 0)
636 ret = -EIO;
637 goto ei2c;
638 }
639
640
641 if (sensor_type && (!strcmp("colour", sensor_type) ||
642 !strcmp("color", sensor_type))) {
643 ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
644 mt9v022->model = V4L2_IDENT_MT9V022IX7ATC;
645 mt9v022->fmts = mt9v022_colour_fmts;
646 } else {
647 ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11);
648 mt9v022->model = V4L2_IDENT_MT9V022IX7ATM;
649 mt9v022->fmts = mt9v022_monochrome_fmts;
650 }
651
652 if (ret < 0)
653 goto ei2c;
654
655 mt9v022->num_fmts = 0;
656
657
658
659
660
661
662 if (icl->query_bus_param)
663 flags = icl->query_bus_param(icl);
664 else
665 flags = SOCAM_DATAWIDTH_10;
666
667 if (flags & SOCAM_DATAWIDTH_10)
668 mt9v022->num_fmts++;
669 else
670 mt9v022->fmts++;
671
672 if (flags & SOCAM_DATAWIDTH_8)
673 mt9v022->num_fmts++;
674
675 mt9v022->fmt = &mt9v022->fmts[0];
676
677 dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
678 data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
679 "monochrome" : "colour");
680
681 ret = mt9v022_init(client);
682 if (ret < 0)
683 dev_err(&client->dev, "Failed to initialise the camera\n");
684
685ei2c:
686 mt9v022_s_power(&mt9v022->subdev, 0);
687 return ret;
688}
689
690static int mt9v022_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines)
691{
692 struct i2c_client *client = v4l2_get_subdevdata(sd);
693 struct mt9v022 *mt9v022 = to_mt9v022(client);
694
695 *lines = mt9v022->y_skip_top;
696
697 return 0;
698}
699
700static const struct v4l2_ctrl_ops mt9v022_ctrl_ops = {
701 .g_volatile_ctrl = mt9v022_g_volatile_ctrl,
702 .s_ctrl = mt9v022_s_ctrl,
703};
704
705static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = {
706 .g_chip_ident = mt9v022_g_chip_ident,
707#ifdef CONFIG_VIDEO_ADV_DEBUG
708 .g_register = mt9v022_g_register,
709 .s_register = mt9v022_s_register,
710#endif
711 .s_power = mt9v022_s_power,
712};
713
714static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
715 enum v4l2_mbus_pixelcode *code)
716{
717 struct i2c_client *client = v4l2_get_subdevdata(sd);
718 struct mt9v022 *mt9v022 = to_mt9v022(client);
719
720 if (index >= mt9v022->num_fmts)
721 return -EINVAL;
722
723 *code = mt9v022->fmts[index].code;
724 return 0;
725}
726
727static int mt9v022_g_mbus_config(struct v4l2_subdev *sd,
728 struct v4l2_mbus_config *cfg)
729{
730 struct i2c_client *client = v4l2_get_subdevdata(sd);
731 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
732
733 cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE |
734 V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING |
735 V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW |
736 V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW |
737 V4L2_MBUS_DATA_ACTIVE_HIGH;
738 cfg->type = V4L2_MBUS_PARALLEL;
739 cfg->flags = soc_camera_apply_board_flags(icl, cfg);
740
741 return 0;
742}
743
744static int mt9v022_s_mbus_config(struct v4l2_subdev *sd,
745 const struct v4l2_mbus_config *cfg)
746{
747 struct i2c_client *client = v4l2_get_subdevdata(sd);
748 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
749 struct mt9v022 *mt9v022 = to_mt9v022(client);
750 unsigned long flags = soc_camera_apply_board_flags(icl, cfg);
751 unsigned int bps = soc_mbus_get_fmtdesc(mt9v022->fmt->code)->bits_per_sample;
752 int ret;
753 u16 pixclk = 0;
754
755 if (icl->set_bus_param) {
756 ret = icl->set_bus_param(icl, 1 << (bps - 1));
757 if (ret)
758 return ret;
759 } else if (bps != 10) {
760
761
762
763
764 return -EINVAL;
765 }
766
767 if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
768 pixclk |= 0x10;
769
770 if (!(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH))
771 pixclk |= 0x1;
772
773 if (!(flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH))
774 pixclk |= 0x2;
775
776 ret = reg_write(client, mt9v022->reg->pixclk_fv_lv, pixclk);
777 if (ret < 0)
778 return ret;
779
780 if (!(flags & V4L2_MBUS_MASTER))
781 mt9v022->chip_control &= ~0x8;
782
783 ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
784 if (ret < 0)
785 return ret;
786
787 dev_dbg(&client->dev, "Calculated pixclk 0x%x, chip control 0x%x\n",
788 pixclk, mt9v022->chip_control);
789
790 return 0;
791}
792
793static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = {
794 .s_stream = mt9v022_s_stream,
795 .s_mbus_fmt = mt9v022_s_fmt,
796 .g_mbus_fmt = mt9v022_g_fmt,
797 .try_mbus_fmt = mt9v022_try_fmt,
798 .s_crop = mt9v022_s_crop,
799 .g_crop = mt9v022_g_crop,
800 .cropcap = mt9v022_cropcap,
801 .enum_mbus_fmt = mt9v022_enum_fmt,
802 .g_mbus_config = mt9v022_g_mbus_config,
803 .s_mbus_config = mt9v022_s_mbus_config,
804};
805
806static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = {
807 .g_skip_top_lines = mt9v022_g_skip_top_lines,
808};
809
810static struct v4l2_subdev_ops mt9v022_subdev_ops = {
811 .core = &mt9v022_subdev_core_ops,
812 .video = &mt9v022_subdev_video_ops,
813 .sensor = &mt9v022_subdev_sensor_ops,
814};
815
816static int mt9v022_probe(struct i2c_client *client,
817 const struct i2c_device_id *did)
818{
819 struct mt9v022 *mt9v022;
820 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
821 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
822 int ret;
823
824 if (!icl) {
825 dev_err(&client->dev, "MT9V022 driver needs platform data\n");
826 return -EINVAL;
827 }
828
829 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
830 dev_warn(&adapter->dev,
831 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
832 return -EIO;
833 }
834
835 mt9v022 = kzalloc(sizeof(struct mt9v022), GFP_KERNEL);
836 if (!mt9v022)
837 return -ENOMEM;
838
839 v4l2_i2c_subdev_init(&mt9v022->subdev, client, &mt9v022_subdev_ops);
840 v4l2_ctrl_handler_init(&mt9v022->hdl, 6);
841 v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
842 V4L2_CID_VFLIP, 0, 1, 1, 0);
843 v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
844 V4L2_CID_HFLIP, 0, 1, 1, 0);
845 mt9v022->autogain = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
846 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
847 mt9v022->gain = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
848 V4L2_CID_GAIN, 0, 127, 1, 64);
849
850
851
852
853
854 mt9v022->autoexposure = v4l2_ctrl_new_std_menu(&mt9v022->hdl,
855 &mt9v022_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
856 V4L2_EXPOSURE_AUTO);
857 mt9v022->exposure = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
858 V4L2_CID_EXPOSURE, 1, 255, 1, 255);
859
860 mt9v022->subdev.ctrl_handler = &mt9v022->hdl;
861 if (mt9v022->hdl.error) {
862 int err = mt9v022->hdl.error;
863
864 kfree(mt9v022);
865 return err;
866 }
867 v4l2_ctrl_auto_cluster(2, &mt9v022->autoexposure,
868 V4L2_EXPOSURE_MANUAL, true);
869 v4l2_ctrl_auto_cluster(2, &mt9v022->autogain, 0, true);
870
871 mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
872
873
874
875
876
877 mt9v022->y_skip_top = 1;
878 mt9v022->rect.left = MT9V022_COLUMN_SKIP;
879 mt9v022->rect.top = MT9V022_ROW_SKIP;
880 mt9v022->rect.width = MT9V022_MAX_WIDTH;
881 mt9v022->rect.height = MT9V022_MAX_HEIGHT;
882
883 ret = mt9v022_video_probe(client);
884 if (ret) {
885 v4l2_ctrl_handler_free(&mt9v022->hdl);
886 kfree(mt9v022);
887 }
888
889 return ret;
890}
891
892static int mt9v022_remove(struct i2c_client *client)
893{
894 struct mt9v022 *mt9v022 = to_mt9v022(client);
895 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
896
897 v4l2_device_unregister_subdev(&mt9v022->subdev);
898 if (icl->free_bus)
899 icl->free_bus(icl);
900 v4l2_ctrl_handler_free(&mt9v022->hdl);
901 kfree(mt9v022);
902
903 return 0;
904}
905static const struct i2c_device_id mt9v022_id[] = {
906 { "mt9v022", 0 },
907 { }
908};
909MODULE_DEVICE_TABLE(i2c, mt9v022_id);
910
911static struct i2c_driver mt9v022_i2c_driver = {
912 .driver = {
913 .name = "mt9v022",
914 },
915 .probe = mt9v022_probe,
916 .remove = mt9v022_remove,
917 .id_table = mt9v022_id,
918};
919
920module_i2c_driver(mt9v022_i2c_driver);
921
922MODULE_DESCRIPTION("Micron MT9V022 Camera driver");
923MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
924MODULE_LICENSE("GPL");
925