2 * Driver for MT9V032 CMOS Image Sensor from Micron
4 * Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
6 * Based on the MT9M001 driver,
8 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
15 #include <linux/clk.h>
16 #include <linux/delay.h>
17 #include <linux/i2c.h>
18 #include <linux/log2.h>
19 #include <linux/mutex.h>
20 #include <linux/slab.h>
21 #include <linux/videodev2.h>
22 #include <linux/v4l2-mediabus.h>
23 #include <linux/module.h>
25 #include <media/mt9v032.h>
26 #include <media/v4l2-ctrls.h>
27 #include <media/v4l2-device.h>
28 #include <media/v4l2-subdev.h>
30 /* The first four rows are black rows. The active area spans 753x481 pixels. */
31 #define MT9V032_PIXEL_ARRAY_HEIGHT 485
32 #define MT9V032_PIXEL_ARRAY_WIDTH 753
34 #define MT9V032_SYSCLK_FREQ_DEF 26600000
36 #define MT9V032_CHIP_VERSION 0x00
37 #define MT9V032_CHIP_ID_REV1 0x1311
38 #define MT9V032_CHIP_ID_REV3 0x1313
39 #define MT9V032_COLUMN_START 0x01
40 #define MT9V032_COLUMN_START_MIN 1
41 #define MT9V032_COLUMN_START_DEF 1
42 #define MT9V032_COLUMN_START_MAX 752
43 #define MT9V032_ROW_START 0x02
44 #define MT9V032_ROW_START_MIN 4
45 #define MT9V032_ROW_START_DEF 5
46 #define MT9V032_ROW_START_MAX 482
47 #define MT9V032_WINDOW_HEIGHT 0x03
48 #define MT9V032_WINDOW_HEIGHT_MIN 1
49 #define MT9V032_WINDOW_HEIGHT_DEF 480
50 #define MT9V032_WINDOW_HEIGHT_MAX 480
51 #define MT9V032_WINDOW_WIDTH 0x04
52 #define MT9V032_WINDOW_WIDTH_MIN 1
53 #define MT9V032_WINDOW_WIDTH_DEF 752
54 #define MT9V032_WINDOW_WIDTH_MAX 752
55 #define MT9V032_HORIZONTAL_BLANKING 0x05
56 #define MT9V032_HORIZONTAL_BLANKING_MIN 43
57 #define MT9V032_HORIZONTAL_BLANKING_DEF 94
58 #define MT9V032_HORIZONTAL_BLANKING_MAX 1023
59 #define MT9V032_VERTICAL_BLANKING 0x06
60 #define MT9V032_VERTICAL_BLANKING_MIN 4
61 #define MT9V032_VERTICAL_BLANKING_DEF 45
62 #define MT9V032_VERTICAL_BLANKING_MAX 3000
63 #define MT9V032_CHIP_CONTROL 0x07
64 #define MT9V032_CHIP_CONTROL_MASTER_MODE (1 << 3)
65 #define MT9V032_CHIP_CONTROL_DOUT_ENABLE (1 << 7)
66 #define MT9V032_CHIP_CONTROL_SEQUENTIAL (1 << 8)
67 #define MT9V032_SHUTTER_WIDTH1 0x08
68 #define MT9V032_SHUTTER_WIDTH2 0x09
69 #define MT9V032_SHUTTER_WIDTH_CONTROL 0x0a
70 #define MT9V032_TOTAL_SHUTTER_WIDTH 0x0b
71 #define MT9V032_TOTAL_SHUTTER_WIDTH_MIN 1
72 #define MT9V032_TOTAL_SHUTTER_WIDTH_DEF 480
73 #define MT9V032_TOTAL_SHUTTER_WIDTH_MAX 32767
74 #define MT9V032_RESET 0x0c
75 #define MT9V032_READ_MODE 0x0d
76 #define MT9V032_READ_MODE_ROW_BIN_MASK (3 << 0)
77 #define MT9V032_READ_MODE_ROW_BIN_SHIFT 0
78 #define MT9V032_READ_MODE_COLUMN_BIN_MASK (3 << 2)
79 #define MT9V032_READ_MODE_COLUMN_BIN_SHIFT 2
80 #define MT9V032_READ_MODE_ROW_FLIP (1 << 4)
81 #define MT9V032_READ_MODE_COLUMN_FLIP (1 << 5)
82 #define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6)
83 #define MT9V032_READ_MODE_DARK_ROWS (1 << 7)
84 #define MT9V032_PIXEL_OPERATION_MODE 0x0f
85 #define MT9V032_PIXEL_OPERATION_MODE_COLOR (1 << 2)
86 #define MT9V032_PIXEL_OPERATION_MODE_HDR (1 << 6)
87 #define MT9V032_ANALOG_GAIN 0x35
88 #define MT9V032_ANALOG_GAIN_MIN 16
89 #define MT9V032_ANALOG_GAIN_DEF 16
90 #define MT9V032_ANALOG_GAIN_MAX 64
91 #define MT9V032_MAX_ANALOG_GAIN 0x36
92 #define MT9V032_MAX_ANALOG_GAIN_MAX 127
93 #define MT9V032_FRAME_DARK_AVERAGE 0x42
94 #define MT9V032_DARK_AVG_THRESH 0x46
95 #define MT9V032_DARK_AVG_LOW_THRESH_MASK (255 << 0)
96 #define MT9V032_DARK_AVG_LOW_THRESH_SHIFT 0
97 #define MT9V032_DARK_AVG_HIGH_THRESH_MASK (255 << 8)
98 #define MT9V032_DARK_AVG_HIGH_THRESH_SHIFT 8
99 #define MT9V032_ROW_NOISE_CORR_CONTROL 0x70
100 #define MT9V032_ROW_NOISE_CORR_ENABLE (1 << 5)
101 #define MT9V032_ROW_NOISE_CORR_USE_BLK_AVG (1 << 7)
102 #define MT9V032_PIXEL_CLOCK 0x74
103 #define MT9V032_PIXEL_CLOCK_INV_LINE (1 << 0)
104 #define MT9V032_PIXEL_CLOCK_INV_FRAME (1 << 1)
105 #define MT9V032_PIXEL_CLOCK_XOR_LINE (1 << 2)
106 #define MT9V032_PIXEL_CLOCK_CONT_LINE (1 << 3)
107 #define MT9V032_PIXEL_CLOCK_INV_PXL_CLK (1 << 4)
108 #define MT9V032_TEST_PATTERN 0x7f
109 #define MT9V032_TEST_PATTERN_DATA_MASK (1023 << 0)
110 #define MT9V032_TEST_PATTERN_DATA_SHIFT 0
111 #define MT9V032_TEST_PATTERN_USE_DATA (1 << 10)
112 #define MT9V032_TEST_PATTERN_GRAY_MASK (3 << 11)
113 #define MT9V032_TEST_PATTERN_GRAY_NONE (0 << 11)
114 #define MT9V032_TEST_PATTERN_GRAY_VERTICAL (1 << 11)
115 #define MT9V032_TEST_PATTERN_GRAY_HORIZONTAL (2 << 11)
116 #define MT9V032_TEST_PATTERN_GRAY_DIAGONAL (3 << 11)
117 #define MT9V032_TEST_PATTERN_ENABLE (1 << 13)
118 #define MT9V032_TEST_PATTERN_FLIP (1 << 14)
119 #define MT9V032_AEC_AGC_ENABLE 0xaf
120 #define MT9V032_AEC_ENABLE (1 << 0)
121 #define MT9V032_AGC_ENABLE (1 << 1)
122 #define MT9V032_THERMAL_INFO 0xc1
125 struct v4l2_subdev subdev;
126 struct media_pad pad;
128 struct v4l2_mbus_framefmt format;
129 struct v4l2_rect crop;
133 struct v4l2_ctrl_handler ctrls;
135 struct v4l2_ctrl *link_freq;
136 struct v4l2_ctrl *pixel_rate;
139 struct mutex power_lock;
144 struct mt9v032_platform_data *pdata;
151 struct v4l2_ctrl *test_pattern;
152 struct v4l2_ctrl *test_pattern_color;
156 static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
158 return container_of(sd, struct mt9v032, subdev);
161 static int mt9v032_read(struct i2c_client *client, const u8 reg)
163 s32 data = i2c_smbus_read_word_swapped(client, reg);
164 dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__,
169 static int mt9v032_write(struct i2c_client *client, const u8 reg,
172 dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__,
174 return i2c_smbus_write_word_swapped(client, reg, data);
177 static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set)
179 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
180 u16 value = (mt9v032->chip_control & ~clear) | set;
183 ret = mt9v032_write(client, MT9V032_CHIP_CONTROL, value);
187 mt9v032->chip_control = value;
192 mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
194 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
195 u16 value = mt9v032->aec_agc;
203 ret = mt9v032_write(client, MT9V032_AEC_AGC_ENABLE, value);
207 mt9v032->aec_agc = value;
212 mt9v032_update_hblank(struct mt9v032 *mt9v032)
214 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
215 struct v4l2_rect *crop = &mt9v032->crop;
217 return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING,
218 max_t(s32, mt9v032->hblank, 660 - crop->width));
221 static int mt9v032_power_on(struct mt9v032 *mt9v032)
223 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
226 clk_set_rate(mt9v032->clk, mt9v032->sysclk);
227 clk_prepare_enable(mt9v032->clk);
230 /* Reset the chip and stop data read out */
231 ret = mt9v032_write(client, MT9V032_RESET, 1);
235 ret = mt9v032_write(client, MT9V032_RESET, 0);
239 return mt9v032_write(client, MT9V032_CHIP_CONTROL, 0);
242 static void mt9v032_power_off(struct mt9v032 *mt9v032)
244 clk_disable_unprepare(mt9v032->clk);
247 static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
249 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
253 mt9v032_power_off(mt9v032);
257 ret = mt9v032_power_on(mt9v032);
261 /* Configure the pixel clock polarity */
262 if (mt9v032->pdata && mt9v032->pdata->clk_pol) {
263 ret = mt9v032_write(client, MT9V032_PIXEL_CLOCK,
264 MT9V032_PIXEL_CLOCK_INV_PXL_CLK);
269 /* Disable the noise correction algorithm and restore the controls. */
270 ret = mt9v032_write(client, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
274 return v4l2_ctrl_handler_setup(&mt9v032->ctrls);
277 /* -----------------------------------------------------------------------------
278 * V4L2 subdev video operations
281 static struct v4l2_mbus_framefmt *
282 __mt9v032_get_pad_format(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh,
283 unsigned int pad, enum v4l2_subdev_format_whence which)
286 case V4L2_SUBDEV_FORMAT_TRY:
287 return v4l2_subdev_get_try_format(fh, pad);
288 case V4L2_SUBDEV_FORMAT_ACTIVE:
289 return &mt9v032->format;
295 static struct v4l2_rect *
296 __mt9v032_get_pad_crop(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh,
297 unsigned int pad, enum v4l2_subdev_format_whence which)
300 case V4L2_SUBDEV_FORMAT_TRY:
301 return v4l2_subdev_get_try_crop(fh, pad);
302 case V4L2_SUBDEV_FORMAT_ACTIVE:
303 return &mt9v032->crop;
309 static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
311 const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE
312 | MT9V032_CHIP_CONTROL_DOUT_ENABLE
313 | MT9V032_CHIP_CONTROL_SEQUENTIAL;
314 struct i2c_client *client = v4l2_get_subdevdata(subdev);
315 struct mt9v032 *mt9v032 = to_mt9v032(subdev);
316 struct v4l2_rect *crop = &mt9v032->crop;
322 return mt9v032_set_chip_control(mt9v032, mode, 0);
324 /* Configure the window size and row/column bin */
325 hbin = fls(mt9v032->hratio) - 1;
326 vbin = fls(mt9v032->vratio) - 1;
327 ret = mt9v032_write(client, MT9V032_READ_MODE,
328 hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT |
329 vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT);
333 ret = mt9v032_write(client, MT9V032_COLUMN_START, crop->left);
337 ret = mt9v032_write(client, MT9V032_ROW_START, crop->top);
341 ret = mt9v032_write(client, MT9V032_WINDOW_WIDTH, crop->width);
345 ret = mt9v032_write(client, MT9V032_WINDOW_HEIGHT, crop->height);
349 ret = mt9v032_update_hblank(mt9v032);
353 /* Switch to master "normal" mode */
354 return mt9v032_set_chip_control(mt9v032, 0, mode);
357 static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev,
358 struct v4l2_subdev_fh *fh,
359 struct v4l2_subdev_mbus_code_enum *code)
364 code->code = V4L2_MBUS_FMT_SGRBG10_1X10;
368 static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev,
369 struct v4l2_subdev_fh *fh,
370 struct v4l2_subdev_frame_size_enum *fse)
372 if (fse->index >= 3 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10)
375 fse->min_width = MT9V032_WINDOW_WIDTH_DEF / (1 << fse->index);
376 fse->max_width = fse->min_width;
377 fse->min_height = MT9V032_WINDOW_HEIGHT_DEF / (1 << fse->index);
378 fse->max_height = fse->min_height;
383 static int mt9v032_get_format(struct v4l2_subdev *subdev,
384 struct v4l2_subdev_fh *fh,
385 struct v4l2_subdev_format *format)
387 struct mt9v032 *mt9v032 = to_mt9v032(subdev);
389 format->format = *__mt9v032_get_pad_format(mt9v032, fh, format->pad,
394 static void mt9v032_configure_pixel_rate(struct mt9v032 *mt9v032)
396 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
399 ret = v4l2_ctrl_s_ctrl_int64(mt9v032->pixel_rate,
400 mt9v032->sysclk / mt9v032->hratio);
402 dev_warn(&client->dev, "failed to set pixel rate (%d)\n", ret);
405 static unsigned int mt9v032_calc_ratio(unsigned int input, unsigned int output)
407 /* Compute the power-of-two binning factor closest to the input size to
408 * output size ratio. Given that the output size is bounded by input/4
409 * and input, a generic implementation would be an ineffective luxury.
411 if (output * 3 > input * 2)
413 if (output * 3 > input)
418 static int mt9v032_set_format(struct v4l2_subdev *subdev,
419 struct v4l2_subdev_fh *fh,
420 struct v4l2_subdev_format *format)
422 struct mt9v032 *mt9v032 = to_mt9v032(subdev);
423 struct v4l2_mbus_framefmt *__format;
424 struct v4l2_rect *__crop;
430 __crop = __mt9v032_get_pad_crop(mt9v032, fh, format->pad,
433 /* Clamp the width and height to avoid dividing by zero. */
434 width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
435 max(__crop->width / 4, MT9V032_WINDOW_WIDTH_MIN),
437 height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
438 max(__crop->height / 4, MT9V032_WINDOW_HEIGHT_MIN),
441 hratio = mt9v032_calc_ratio(__crop->width, width);
442 vratio = mt9v032_calc_ratio(__crop->height, height);
444 __format = __mt9v032_get_pad_format(mt9v032, fh, format->pad,
446 __format->width = __crop->width / hratio;
447 __format->height = __crop->height / vratio;
449 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
450 mt9v032->hratio = hratio;
451 mt9v032->vratio = vratio;
452 mt9v032_configure_pixel_rate(mt9v032);
455 format->format = *__format;
460 static int mt9v032_get_crop(struct v4l2_subdev *subdev,
461 struct v4l2_subdev_fh *fh,
462 struct v4l2_subdev_crop *crop)
464 struct mt9v032 *mt9v032 = to_mt9v032(subdev);
466 crop->rect = *__mt9v032_get_pad_crop(mt9v032, fh, crop->pad,
471 static int mt9v032_set_crop(struct v4l2_subdev *subdev,
472 struct v4l2_subdev_fh *fh,
473 struct v4l2_subdev_crop *crop)
475 struct mt9v032 *mt9v032 = to_mt9v032(subdev);
476 struct v4l2_mbus_framefmt *__format;
477 struct v4l2_rect *__crop;
478 struct v4l2_rect rect;
480 /* Clamp the crop rectangle boundaries and align them to a non multiple
481 * of 2 pixels to ensure a GRBG Bayer pattern.
483 rect.left = clamp(ALIGN(crop->rect.left + 1, 2) - 1,
484 MT9V032_COLUMN_START_MIN,
485 MT9V032_COLUMN_START_MAX);
486 rect.top = clamp(ALIGN(crop->rect.top + 1, 2) - 1,
487 MT9V032_ROW_START_MIN,
488 MT9V032_ROW_START_MAX);
489 rect.width = clamp(ALIGN(crop->rect.width, 2),
490 MT9V032_WINDOW_WIDTH_MIN,
491 MT9V032_WINDOW_WIDTH_MAX);
492 rect.height = clamp(ALIGN(crop->rect.height, 2),
493 MT9V032_WINDOW_HEIGHT_MIN,
494 MT9V032_WINDOW_HEIGHT_MAX);
496 rect.width = min(rect.width, MT9V032_PIXEL_ARRAY_WIDTH - rect.left);
497 rect.height = min(rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top);
499 __crop = __mt9v032_get_pad_crop(mt9v032, fh, crop->pad, crop->which);
501 if (rect.width != __crop->width || rect.height != __crop->height) {
502 /* Reset the output image size if the crop rectangle size has
505 __format = __mt9v032_get_pad_format(mt9v032, fh, crop->pad,
507 __format->width = rect.width;
508 __format->height = rect.height;
509 if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
512 mt9v032_configure_pixel_rate(mt9v032);
522 /* -----------------------------------------------------------------------------
523 * V4L2 subdev control operations
526 #define V4L2_CID_TEST_PATTERN_COLOR (V4L2_CID_USER_BASE | 0x1001)
528 static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
530 struct mt9v032 *mt9v032 =
531 container_of(ctrl->handler, struct mt9v032, ctrls);
532 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
537 case V4L2_CID_AUTOGAIN:
538 return mt9v032_update_aec_agc(mt9v032, MT9V032_AGC_ENABLE,
542 return mt9v032_write(client, MT9V032_ANALOG_GAIN, ctrl->val);
544 case V4L2_CID_EXPOSURE_AUTO:
545 return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE,
548 case V4L2_CID_EXPOSURE:
549 return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH,
552 case V4L2_CID_HBLANK:
553 mt9v032->hblank = ctrl->val;
554 return mt9v032_update_hblank(mt9v032);
556 case V4L2_CID_VBLANK:
557 return mt9v032_write(client, MT9V032_VERTICAL_BLANKING,
560 case V4L2_CID_PIXEL_RATE:
561 case V4L2_CID_LINK_FREQ:
562 if (mt9v032->link_freq == NULL)
565 freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val];
566 mt9v032->pixel_rate->val64 = freq;
567 mt9v032->sysclk = freq;
570 case V4L2_CID_TEST_PATTERN:
571 switch (mt9v032->test_pattern->val) {
576 data = MT9V032_TEST_PATTERN_GRAY_VERTICAL
577 | MT9V032_TEST_PATTERN_ENABLE;
580 data = MT9V032_TEST_PATTERN_GRAY_HORIZONTAL
581 | MT9V032_TEST_PATTERN_ENABLE;
584 data = MT9V032_TEST_PATTERN_GRAY_DIAGONAL
585 | MT9V032_TEST_PATTERN_ENABLE;
588 data = (mt9v032->test_pattern_color->val <<
589 MT9V032_TEST_PATTERN_DATA_SHIFT)
590 | MT9V032_TEST_PATTERN_USE_DATA
591 | MT9V032_TEST_PATTERN_ENABLE
592 | MT9V032_TEST_PATTERN_FLIP;
595 return mt9v032_write(client, MT9V032_TEST_PATTERN, data);
601 static struct v4l2_ctrl_ops mt9v032_ctrl_ops = {
602 .s_ctrl = mt9v032_s_ctrl,
605 static const char * const mt9v032_test_pattern_menu[] = {
607 "Gray Vertical Shade",
608 "Gray Horizontal Shade",
609 "Gray Diagonal Shade",
613 static const struct v4l2_ctrl_config mt9v032_test_pattern_color = {
614 .ops = &mt9v032_ctrl_ops,
615 .id = V4L2_CID_TEST_PATTERN_COLOR,
616 .type = V4L2_CTRL_TYPE_INTEGER,
617 .name = "Test Pattern Color",
625 /* -----------------------------------------------------------------------------
626 * V4L2 subdev core operations
629 static int mt9v032_set_power(struct v4l2_subdev *subdev, int on)
631 struct mt9v032 *mt9v032 = to_mt9v032(subdev);
634 mutex_lock(&mt9v032->power_lock);
636 /* If the power count is modified from 0 to != 0 or from != 0 to 0,
637 * update the power state.
639 if (mt9v032->power_count == !on) {
640 ret = __mt9v032_set_power(mt9v032, !!on);
645 /* Update the power count. */
646 mt9v032->power_count += on ? 1 : -1;
647 WARN_ON(mt9v032->power_count < 0);
650 mutex_unlock(&mt9v032->power_lock);
654 /* -----------------------------------------------------------------------------
655 * V4L2 subdev internal operations
658 static int mt9v032_registered(struct v4l2_subdev *subdev)
660 struct i2c_client *client = v4l2_get_subdevdata(subdev);
661 struct mt9v032 *mt9v032 = to_mt9v032(subdev);
665 dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n",
668 ret = mt9v032_power_on(mt9v032);
670 dev_err(&client->dev, "MT9V032 power up failed\n");
674 /* Read and check the sensor version */
675 data = mt9v032_read(client, MT9V032_CHIP_VERSION);
676 if (data != MT9V032_CHIP_ID_REV1 && data != MT9V032_CHIP_ID_REV3) {
677 dev_err(&client->dev, "MT9V032 not detected, wrong version "
682 mt9v032_power_off(mt9v032);
684 dev_info(&client->dev, "MT9V032 detected at address 0x%02x\n",
687 mt9v032_configure_pixel_rate(mt9v032);
692 static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
694 struct v4l2_mbus_framefmt *format;
695 struct v4l2_rect *crop;
697 crop = v4l2_subdev_get_try_crop(fh, 0);
698 crop->left = MT9V032_COLUMN_START_DEF;
699 crop->top = MT9V032_ROW_START_DEF;
700 crop->width = MT9V032_WINDOW_WIDTH_DEF;
701 crop->height = MT9V032_WINDOW_HEIGHT_DEF;
703 format = v4l2_subdev_get_try_format(fh, 0);
704 format->code = V4L2_MBUS_FMT_SGRBG10_1X10;
705 format->width = MT9V032_WINDOW_WIDTH_DEF;
706 format->height = MT9V032_WINDOW_HEIGHT_DEF;
707 format->field = V4L2_FIELD_NONE;
708 format->colorspace = V4L2_COLORSPACE_SRGB;
710 return mt9v032_set_power(subdev, 1);
713 static int mt9v032_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
715 return mt9v032_set_power(subdev, 0);
718 static struct v4l2_subdev_core_ops mt9v032_subdev_core_ops = {
719 .s_power = mt9v032_set_power,
722 static struct v4l2_subdev_video_ops mt9v032_subdev_video_ops = {
723 .s_stream = mt9v032_s_stream,
726 static struct v4l2_subdev_pad_ops mt9v032_subdev_pad_ops = {
727 .enum_mbus_code = mt9v032_enum_mbus_code,
728 .enum_frame_size = mt9v032_enum_frame_size,
729 .get_fmt = mt9v032_get_format,
730 .set_fmt = mt9v032_set_format,
731 .get_crop = mt9v032_get_crop,
732 .set_crop = mt9v032_set_crop,
735 static struct v4l2_subdev_ops mt9v032_subdev_ops = {
736 .core = &mt9v032_subdev_core_ops,
737 .video = &mt9v032_subdev_video_ops,
738 .pad = &mt9v032_subdev_pad_ops,
741 static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = {
742 .registered = mt9v032_registered,
743 .open = mt9v032_open,
744 .close = mt9v032_close,
747 /* -----------------------------------------------------------------------------
748 * Driver initialization and probing
751 static int mt9v032_probe(struct i2c_client *client,
752 const struct i2c_device_id *did)
754 struct mt9v032_platform_data *pdata = client->dev.platform_data;
755 struct mt9v032 *mt9v032;
759 if (!i2c_check_functionality(client->adapter,
760 I2C_FUNC_SMBUS_WORD_DATA)) {
761 dev_warn(&client->adapter->dev,
762 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
766 mt9v032 = devm_kzalloc(&client->dev, sizeof(*mt9v032), GFP_KERNEL);
770 mt9v032->clk = devm_clk_get(&client->dev, NULL);
771 if (IS_ERR(mt9v032->clk))
772 return PTR_ERR(mt9v032->clk);
774 mutex_init(&mt9v032->power_lock);
775 mt9v032->pdata = pdata;
777 v4l2_ctrl_handler_init(&mt9v032->ctrls, 10);
779 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
780 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
781 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
782 V4L2_CID_GAIN, MT9V032_ANALOG_GAIN_MIN,
783 MT9V032_ANALOG_GAIN_MAX, 1, MT9V032_ANALOG_GAIN_DEF);
784 v4l2_ctrl_new_std_menu(&mt9v032->ctrls, &mt9v032_ctrl_ops,
785 V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL, 0,
787 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
788 V4L2_CID_EXPOSURE, MT9V032_TOTAL_SHUTTER_WIDTH_MIN,
789 MT9V032_TOTAL_SHUTTER_WIDTH_MAX, 1,
790 MT9V032_TOTAL_SHUTTER_WIDTH_DEF);
791 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
792 V4L2_CID_HBLANK, MT9V032_HORIZONTAL_BLANKING_MIN,
793 MT9V032_HORIZONTAL_BLANKING_MAX, 1,
794 MT9V032_HORIZONTAL_BLANKING_DEF);
795 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
796 V4L2_CID_VBLANK, MT9V032_VERTICAL_BLANKING_MIN,
797 MT9V032_VERTICAL_BLANKING_MAX, 1,
798 MT9V032_VERTICAL_BLANKING_DEF);
799 mt9v032->test_pattern = v4l2_ctrl_new_std_menu_items(&mt9v032->ctrls,
800 &mt9v032_ctrl_ops, V4L2_CID_TEST_PATTERN,
801 ARRAY_SIZE(mt9v032_test_pattern_menu) - 1, 0, 0,
802 mt9v032_test_pattern_menu);
803 mt9v032->test_pattern_color = v4l2_ctrl_new_custom(&mt9v032->ctrls,
804 &mt9v032_test_pattern_color, NULL);
806 v4l2_ctrl_cluster(2, &mt9v032->test_pattern);
808 mt9v032->pixel_rate =
809 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
810 V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
812 if (pdata && pdata->link_freqs) {
813 unsigned int def = 0;
815 for (i = 0; pdata->link_freqs[i]; ++i) {
816 if (pdata->link_freqs[i] == pdata->link_def_freq)
821 v4l2_ctrl_new_int_menu(&mt9v032->ctrls,
823 V4L2_CID_LINK_FREQ, i - 1, def,
825 v4l2_ctrl_cluster(2, &mt9v032->link_freq);
829 mt9v032->subdev.ctrl_handler = &mt9v032->ctrls;
831 if (mt9v032->ctrls.error)
832 printk(KERN_INFO "%s: control initialization error %d\n",
833 __func__, mt9v032->ctrls.error);
835 mt9v032->crop.left = MT9V032_COLUMN_START_DEF;
836 mt9v032->crop.top = MT9V032_ROW_START_DEF;
837 mt9v032->crop.width = MT9V032_WINDOW_WIDTH_DEF;
838 mt9v032->crop.height = MT9V032_WINDOW_HEIGHT_DEF;
840 mt9v032->format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
841 mt9v032->format.width = MT9V032_WINDOW_WIDTH_DEF;
842 mt9v032->format.height = MT9V032_WINDOW_HEIGHT_DEF;
843 mt9v032->format.field = V4L2_FIELD_NONE;
844 mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB;
849 mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE;
850 mt9v032->hblank = MT9V032_HORIZONTAL_BLANKING_DEF;
851 mt9v032->sysclk = MT9V032_SYSCLK_FREQ_DEF;
853 v4l2_i2c_subdev_init(&mt9v032->subdev, client, &mt9v032_subdev_ops);
854 mt9v032->subdev.internal_ops = &mt9v032_subdev_internal_ops;
855 mt9v032->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
857 mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE;
858 ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0);
861 v4l2_ctrl_handler_free(&mt9v032->ctrls);
866 static int mt9v032_remove(struct i2c_client *client)
868 struct v4l2_subdev *subdev = i2c_get_clientdata(client);
869 struct mt9v032 *mt9v032 = to_mt9v032(subdev);
871 v4l2_ctrl_handler_free(&mt9v032->ctrls);
872 v4l2_device_unregister_subdev(subdev);
873 media_entity_cleanup(&subdev->entity);
878 static const struct i2c_device_id mt9v032_id[] = {
882 MODULE_DEVICE_TABLE(i2c, mt9v032_id);
884 static struct i2c_driver mt9v032_driver = {
888 .probe = mt9v032_probe,
889 .remove = mt9v032_remove,
890 .id_table = mt9v032_id,
893 module_i2c_driver(mt9v032_driver);
895 MODULE_DESCRIPTION("Aptina MT9V032 Camera driver");
896 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
897 MODULE_LICENSE("GPL");