aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/i2c/mt9v032.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/i2c/mt9v032.c')
-rw-r--r--drivers/media/i2c/mt9v032.c264
1 files changed, 205 insertions, 59 deletions
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c
index 2c50effaa334..36c504b78f2c 100644
--- a/drivers/media/i2c/mt9v032.c
+++ b/drivers/media/i2c/mt9v032.c
@@ -27,14 +27,16 @@
27#include <media/v4l2-device.h> 27#include <media/v4l2-device.h>
28#include <media/v4l2-subdev.h> 28#include <media/v4l2-subdev.h>
29 29
30#define MT9V032_PIXEL_ARRAY_HEIGHT 492 30/* The first four rows are black rows. The active area spans 753x481 pixels. */
31#define MT9V032_PIXEL_ARRAY_WIDTH 782 31#define MT9V032_PIXEL_ARRAY_HEIGHT 485
32#define MT9V032_PIXEL_ARRAY_WIDTH 753
32 33
33#define MT9V032_SYSCLK_FREQ_DEF 26600000 34#define MT9V032_SYSCLK_FREQ_DEF 26600000
34 35
35#define MT9V032_CHIP_VERSION 0x00 36#define MT9V032_CHIP_VERSION 0x00
36#define MT9V032_CHIP_ID_REV1 0x1311 37#define MT9V032_CHIP_ID_REV1 0x1311
37#define MT9V032_CHIP_ID_REV3 0x1313 38#define MT9V032_CHIP_ID_REV3 0x1313
39#define MT9V034_CHIP_ID_REV1 0X1324
38#define MT9V032_COLUMN_START 0x01 40#define MT9V032_COLUMN_START 0x01
39#define MT9V032_COLUMN_START_MIN 1 41#define MT9V032_COLUMN_START_MIN 1
40#define MT9V032_COLUMN_START_DEF 1 42#define MT9V032_COLUMN_START_DEF 1
@@ -53,12 +55,15 @@
53#define MT9V032_WINDOW_WIDTH_MAX 752 55#define MT9V032_WINDOW_WIDTH_MAX 752
54#define MT9V032_HORIZONTAL_BLANKING 0x05 56#define MT9V032_HORIZONTAL_BLANKING 0x05
55#define MT9V032_HORIZONTAL_BLANKING_MIN 43 57#define MT9V032_HORIZONTAL_BLANKING_MIN 43
58#define MT9V034_HORIZONTAL_BLANKING_MIN 61
56#define MT9V032_HORIZONTAL_BLANKING_DEF 94 59#define MT9V032_HORIZONTAL_BLANKING_DEF 94
57#define MT9V032_HORIZONTAL_BLANKING_MAX 1023 60#define MT9V032_HORIZONTAL_BLANKING_MAX 1023
58#define MT9V032_VERTICAL_BLANKING 0x06 61#define MT9V032_VERTICAL_BLANKING 0x06
59#define MT9V032_VERTICAL_BLANKING_MIN 4 62#define MT9V032_VERTICAL_BLANKING_MIN 4
63#define MT9V034_VERTICAL_BLANKING_MIN 2
60#define MT9V032_VERTICAL_BLANKING_DEF 45 64#define MT9V032_VERTICAL_BLANKING_DEF 45
61#define MT9V032_VERTICAL_BLANKING_MAX 3000 65#define MT9V032_VERTICAL_BLANKING_MAX 3000
66#define MT9V034_VERTICAL_BLANKING_MAX 32288
62#define MT9V032_CHIP_CONTROL 0x07 67#define MT9V032_CHIP_CONTROL 0x07
63#define MT9V032_CHIP_CONTROL_MASTER_MODE (1 << 3) 68#define MT9V032_CHIP_CONTROL_MASTER_MODE (1 << 3)
64#define MT9V032_CHIP_CONTROL_DOUT_ENABLE (1 << 7) 69#define MT9V032_CHIP_CONTROL_DOUT_ENABLE (1 << 7)
@@ -68,8 +73,10 @@
68#define MT9V032_SHUTTER_WIDTH_CONTROL 0x0a 73#define MT9V032_SHUTTER_WIDTH_CONTROL 0x0a
69#define MT9V032_TOTAL_SHUTTER_WIDTH 0x0b 74#define MT9V032_TOTAL_SHUTTER_WIDTH 0x0b
70#define MT9V032_TOTAL_SHUTTER_WIDTH_MIN 1 75#define MT9V032_TOTAL_SHUTTER_WIDTH_MIN 1
76#define MT9V034_TOTAL_SHUTTER_WIDTH_MIN 0
71#define MT9V032_TOTAL_SHUTTER_WIDTH_DEF 480 77#define MT9V032_TOTAL_SHUTTER_WIDTH_DEF 480
72#define MT9V032_TOTAL_SHUTTER_WIDTH_MAX 32767 78#define MT9V032_TOTAL_SHUTTER_WIDTH_MAX 32767
79#define MT9V034_TOTAL_SHUTTER_WIDTH_MAX 32765
73#define MT9V032_RESET 0x0c 80#define MT9V032_RESET 0x0c
74#define MT9V032_READ_MODE 0x0d 81#define MT9V032_READ_MODE 0x0d
75#define MT9V032_READ_MODE_ROW_BIN_MASK (3 << 0) 82#define MT9V032_READ_MODE_ROW_BIN_MASK (3 << 0)
@@ -81,6 +88,8 @@
81#define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6) 88#define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6)
82#define MT9V032_READ_MODE_DARK_ROWS (1 << 7) 89#define MT9V032_READ_MODE_DARK_ROWS (1 << 7)
83#define MT9V032_PIXEL_OPERATION_MODE 0x0f 90#define MT9V032_PIXEL_OPERATION_MODE 0x0f
91#define MT9V034_PIXEL_OPERATION_MODE_HDR (1 << 0)
92#define MT9V034_PIXEL_OPERATION_MODE_COLOR (1 << 1)
84#define MT9V032_PIXEL_OPERATION_MODE_COLOR (1 << 2) 93#define MT9V032_PIXEL_OPERATION_MODE_COLOR (1 << 2)
85#define MT9V032_PIXEL_OPERATION_MODE_HDR (1 << 6) 94#define MT9V032_PIXEL_OPERATION_MODE_HDR (1 << 6)
86#define MT9V032_ANALOG_GAIN 0x35 95#define MT9V032_ANALOG_GAIN 0x35
@@ -96,9 +105,12 @@
96#define MT9V032_DARK_AVG_HIGH_THRESH_MASK (255 << 8) 105#define MT9V032_DARK_AVG_HIGH_THRESH_MASK (255 << 8)
97#define MT9V032_DARK_AVG_HIGH_THRESH_SHIFT 8 106#define MT9V032_DARK_AVG_HIGH_THRESH_SHIFT 8
98#define MT9V032_ROW_NOISE_CORR_CONTROL 0x70 107#define MT9V032_ROW_NOISE_CORR_CONTROL 0x70
108#define MT9V034_ROW_NOISE_CORR_ENABLE (1 << 0)
109#define MT9V034_ROW_NOISE_CORR_USE_BLK_AVG (1 << 1)
99#define MT9V032_ROW_NOISE_CORR_ENABLE (1 << 5) 110#define MT9V032_ROW_NOISE_CORR_ENABLE (1 << 5)
100#define MT9V032_ROW_NOISE_CORR_USE_BLK_AVG (1 << 7) 111#define MT9V032_ROW_NOISE_CORR_USE_BLK_AVG (1 << 7)
101#define MT9V032_PIXEL_CLOCK 0x74 112#define MT9V032_PIXEL_CLOCK 0x74
113#define MT9V034_PIXEL_CLOCK 0x72
102#define MT9V032_PIXEL_CLOCK_INV_LINE (1 << 0) 114#define MT9V032_PIXEL_CLOCK_INV_LINE (1 << 0)
103#define MT9V032_PIXEL_CLOCK_INV_FRAME (1 << 1) 115#define MT9V032_PIXEL_CLOCK_INV_FRAME (1 << 1)
104#define MT9V032_PIXEL_CLOCK_XOR_LINE (1 << 2) 116#define MT9V032_PIXEL_CLOCK_XOR_LINE (1 << 2)
@@ -120,12 +132,88 @@
120#define MT9V032_AGC_ENABLE (1 << 1) 132#define MT9V032_AGC_ENABLE (1 << 1)
121#define MT9V032_THERMAL_INFO 0xc1 133#define MT9V032_THERMAL_INFO 0xc1
122 134
135enum mt9v032_model {
136 MT9V032_MODEL_V032_COLOR,
137 MT9V032_MODEL_V032_MONO,
138 MT9V032_MODEL_V034_COLOR,
139 MT9V032_MODEL_V034_MONO,
140};
141
142struct mt9v032_model_version {
143 unsigned int version;
144 const char *name;
145};
146
147struct mt9v032_model_data {
148 unsigned int min_row_time;
149 unsigned int min_hblank;
150 unsigned int min_vblank;
151 unsigned int max_vblank;
152 unsigned int min_shutter;
153 unsigned int max_shutter;
154 unsigned int pclk_reg;
155};
156
157struct mt9v032_model_info {
158 const struct mt9v032_model_data *data;
159 bool color;
160};
161
162static const struct mt9v032_model_version mt9v032_versions[] = {
163 { MT9V032_CHIP_ID_REV1, "MT9V032 rev1/2" },
164 { MT9V032_CHIP_ID_REV3, "MT9V032 rev3" },
165 { MT9V034_CHIP_ID_REV1, "MT9V034 rev1" },
166};
167
168static const struct mt9v032_model_data mt9v032_model_data[] = {
169 {
170 /* MT9V032 revisions 1/2/3 */
171 .min_row_time = 660,
172 .min_hblank = MT9V032_HORIZONTAL_BLANKING_MIN,
173 .min_vblank = MT9V032_VERTICAL_BLANKING_MIN,
174 .max_vblank = MT9V032_VERTICAL_BLANKING_MAX,
175 .min_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MIN,
176 .max_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MAX,
177 .pclk_reg = MT9V032_PIXEL_CLOCK,
178 }, {
179 /* MT9V034 */
180 .min_row_time = 690,
181 .min_hblank = MT9V034_HORIZONTAL_BLANKING_MIN,
182 .min_vblank = MT9V034_VERTICAL_BLANKING_MIN,
183 .max_vblank = MT9V034_VERTICAL_BLANKING_MAX,
184 .min_shutter = MT9V034_TOTAL_SHUTTER_WIDTH_MIN,
185 .max_shutter = MT9V034_TOTAL_SHUTTER_WIDTH_MAX,
186 .pclk_reg = MT9V034_PIXEL_CLOCK,
187 },
188};
189
190static const struct mt9v032_model_info mt9v032_models[] = {
191 [MT9V032_MODEL_V032_COLOR] = {
192 .data = &mt9v032_model_data[0],
193 .color = true,
194 },
195 [MT9V032_MODEL_V032_MONO] = {
196 .data = &mt9v032_model_data[0],
197 .color = false,
198 },
199 [MT9V032_MODEL_V034_COLOR] = {
200 .data = &mt9v032_model_data[1],
201 .color = true,
202 },
203 [MT9V032_MODEL_V034_MONO] = {
204 .data = &mt9v032_model_data[1],
205 .color = false,
206 },
207};
208
123struct mt9v032 { 209struct mt9v032 {
124 struct v4l2_subdev subdev; 210 struct v4l2_subdev subdev;
125 struct media_pad pad; 211 struct media_pad pad;
126 212
127 struct v4l2_mbus_framefmt format; 213 struct v4l2_mbus_framefmt format;
128 struct v4l2_rect crop; 214 struct v4l2_rect crop;
215 unsigned int hratio;
216 unsigned int vratio;
129 217
130 struct v4l2_ctrl_handler ctrls; 218 struct v4l2_ctrl_handler ctrls;
131 struct { 219 struct {
@@ -139,6 +227,8 @@ struct mt9v032 {
139 struct clk *clk; 227 struct clk *clk;
140 228
141 struct mt9v032_platform_data *pdata; 229 struct mt9v032_platform_data *pdata;
230 const struct mt9v032_model_info *model;
231 const struct mt9v032_model_version *version;
142 232
143 u32 sysclk; 233 u32 sysclk;
144 u16 chip_control; 234 u16 chip_control;
@@ -210,12 +300,17 @@ mt9v032_update_hblank(struct mt9v032 *mt9v032)
210{ 300{
211 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); 301 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
212 struct v4l2_rect *crop = &mt9v032->crop; 302 struct v4l2_rect *crop = &mt9v032->crop;
303 unsigned int min_hblank = mt9v032->model->data->min_hblank;
304 unsigned int hblank;
213 305
214 return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, 306 if (mt9v032->version->version == MT9V034_CHIP_ID_REV1)
215 max_t(s32, mt9v032->hblank, 660 - crop->width)); 307 min_hblank += (mt9v032->hratio - 1) * 10;
216} 308 min_hblank = max_t(unsigned int, (int)mt9v032->model->data->min_row_time - crop->width,
309 (int)min_hblank);
310 hblank = max_t(unsigned int, mt9v032->hblank, min_hblank);
217 311
218#define EXT_CLK 25000000 312 return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, hblank);
313}
219 314
220static int mt9v032_power_on(struct mt9v032 *mt9v032) 315static int mt9v032_power_on(struct mt9v032 *mt9v032)
221{ 316{
@@ -259,7 +354,7 @@ static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
259 354
260 /* Configure the pixel clock polarity */ 355 /* Configure the pixel clock polarity */
261 if (mt9v032->pdata && mt9v032->pdata->clk_pol) { 356 if (mt9v032->pdata && mt9v032->pdata->clk_pol) {
262 ret = mt9v032_write(client, MT9V032_PIXEL_CLOCK, 357 ret = mt9v032_write(client, mt9v032->model->data->pclk_reg,
263 MT9V032_PIXEL_CLOCK_INV_PXL_CLK); 358 MT9V032_PIXEL_CLOCK_INV_PXL_CLK);
264 if (ret < 0) 359 if (ret < 0)
265 return ret; 360 return ret;
@@ -312,22 +407,20 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
312 | MT9V032_CHIP_CONTROL_SEQUENTIAL; 407 | MT9V032_CHIP_CONTROL_SEQUENTIAL;
313 struct i2c_client *client = v4l2_get_subdevdata(subdev); 408 struct i2c_client *client = v4l2_get_subdevdata(subdev);
314 struct mt9v032 *mt9v032 = to_mt9v032(subdev); 409 struct mt9v032 *mt9v032 = to_mt9v032(subdev);
315 struct v4l2_mbus_framefmt *format = &mt9v032->format;
316 struct v4l2_rect *crop = &mt9v032->crop; 410 struct v4l2_rect *crop = &mt9v032->crop;
317 unsigned int hratio; 411 unsigned int hbin;
318 unsigned int vratio; 412 unsigned int vbin;
319 int ret; 413 int ret;
320 414
321 if (!enable) 415 if (!enable)
322 return mt9v032_set_chip_control(mt9v032, mode, 0); 416 return mt9v032_set_chip_control(mt9v032, mode, 0);
323 417
324 /* Configure the window size and row/column bin */ 418 /* Configure the window size and row/column bin */
325 hratio = DIV_ROUND_CLOSEST(crop->width, format->width); 419 hbin = fls(mt9v032->hratio) - 1;
326 vratio = DIV_ROUND_CLOSEST(crop->height, format->height); 420 vbin = fls(mt9v032->vratio) - 1;
327
328 ret = mt9v032_write(client, MT9V032_READ_MODE, 421 ret = mt9v032_write(client, MT9V032_READ_MODE,
329 (hratio - 1) << MT9V032_READ_MODE_ROW_BIN_SHIFT | 422 hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT |
330 (vratio - 1) << MT9V032_READ_MODE_COLUMN_BIN_SHIFT); 423 vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT);
331 if (ret < 0) 424 if (ret < 0)
332 return ret; 425 return ret;
333 426
@@ -370,12 +463,12 @@ static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev,
370 struct v4l2_subdev_fh *fh, 463 struct v4l2_subdev_fh *fh,
371 struct v4l2_subdev_frame_size_enum *fse) 464 struct v4l2_subdev_frame_size_enum *fse)
372{ 465{
373 if (fse->index >= 8 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10) 466 if (fse->index >= 3 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10)
374 return -EINVAL; 467 return -EINVAL;
375 468
376 fse->min_width = MT9V032_WINDOW_WIDTH_DEF / fse->index; 469 fse->min_width = MT9V032_WINDOW_WIDTH_DEF / (1 << fse->index);
377 fse->max_width = fse->min_width; 470 fse->max_width = fse->min_width;
378 fse->min_height = MT9V032_WINDOW_HEIGHT_DEF / fse->index; 471 fse->min_height = MT9V032_WINDOW_HEIGHT_DEF / (1 << fse->index);
379 fse->max_height = fse->min_height; 472 fse->max_height = fse->min_height;
380 473
381 return 0; 474 return 0;
@@ -392,18 +485,30 @@ static int mt9v032_get_format(struct v4l2_subdev *subdev,
392 return 0; 485 return 0;
393} 486}
394 487
395static void mt9v032_configure_pixel_rate(struct mt9v032 *mt9v032, 488static void mt9v032_configure_pixel_rate(struct mt9v032 *mt9v032)
396 unsigned int hratio)
397{ 489{
398 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); 490 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
399 int ret; 491 int ret;
400 492
401 ret = v4l2_ctrl_s_ctrl_int64(mt9v032->pixel_rate, 493 ret = v4l2_ctrl_s_ctrl_int64(mt9v032->pixel_rate,
402 mt9v032->sysclk / hratio); 494 mt9v032->sysclk / mt9v032->hratio);
403 if (ret < 0) 495 if (ret < 0)
404 dev_warn(&client->dev, "failed to set pixel rate (%d)\n", ret); 496 dev_warn(&client->dev, "failed to set pixel rate (%d)\n", ret);
405} 497}
406 498
499static unsigned int mt9v032_calc_ratio(unsigned int input, unsigned int output)
500{
501 /* Compute the power-of-two binning factor closest to the input size to
502 * output size ratio. Given that the output size is bounded by input/4
503 * and input, a generic implementation would be an ineffective luxury.
504 */
505 if (output * 3 > input * 2)
506 return 1;
507 if (output * 3 > input)
508 return 2;
509 return 4;
510}
511
407static int mt9v032_set_format(struct v4l2_subdev *subdev, 512static int mt9v032_set_format(struct v4l2_subdev *subdev,
408 struct v4l2_subdev_fh *fh, 513 struct v4l2_subdev_fh *fh,
409 struct v4l2_subdev_format *format) 514 struct v4l2_subdev_format *format)
@@ -420,22 +525,28 @@ static int mt9v032_set_format(struct v4l2_subdev *subdev,
420 format->which); 525 format->which);
421 526
422 /* Clamp the width and height to avoid dividing by zero. */ 527 /* Clamp the width and height to avoid dividing by zero. */
423 width = clamp_t(unsigned int, ALIGN(format->format.width, 2), 528 width = clamp(ALIGN(format->format.width, 2),
424 max(__crop->width / 8, MT9V032_WINDOW_WIDTH_MIN), 529 max_t(unsigned int, __crop->width / 4,
425 __crop->width); 530 MT9V032_WINDOW_WIDTH_MIN),
426 height = clamp_t(unsigned int, ALIGN(format->format.height, 2), 531 __crop->width);
427 max(__crop->height / 8, MT9V032_WINDOW_HEIGHT_MIN), 532 height = clamp(ALIGN(format->format.height, 2),
428 __crop->height); 533 max_t(unsigned int, __crop->height / 4,
429 534 MT9V032_WINDOW_HEIGHT_MIN),
430 hratio = DIV_ROUND_CLOSEST(__crop->width, width); 535 __crop->height);
431 vratio = DIV_ROUND_CLOSEST(__crop->height, height); 536
537 hratio = mt9v032_calc_ratio(__crop->width, width);
538 vratio = mt9v032_calc_ratio(__crop->height, height);
432 539
433 __format = __mt9v032_get_pad_format(mt9v032, fh, format->pad, 540 __format = __mt9v032_get_pad_format(mt9v032, fh, format->pad,
434 format->which); 541 format->which);
435 __format->width = __crop->width / hratio; 542 __format->width = __crop->width / hratio;
436 __format->height = __crop->height / vratio; 543 __format->height = __crop->height / vratio;
437 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) 544
438 mt9v032_configure_pixel_rate(mt9v032, hratio); 545 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
546 mt9v032->hratio = hratio;
547 mt9v032->vratio = vratio;
548 mt9v032_configure_pixel_rate(mt9v032);
549 }
439 550
440 format->format = *__format; 551 format->format = *__format;
441 552
@@ -471,15 +582,17 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev,
471 rect.top = clamp(ALIGN(crop->rect.top + 1, 2) - 1, 582 rect.top = clamp(ALIGN(crop->rect.top + 1, 2) - 1,
472 MT9V032_ROW_START_MIN, 583 MT9V032_ROW_START_MIN,
473 MT9V032_ROW_START_MAX); 584 MT9V032_ROW_START_MAX);
474 rect.width = clamp(ALIGN(crop->rect.width, 2), 585 rect.width = clamp_t(unsigned int, ALIGN(crop->rect.width, 2),
475 MT9V032_WINDOW_WIDTH_MIN, 586 MT9V032_WINDOW_WIDTH_MIN,
476 MT9V032_WINDOW_WIDTH_MAX); 587 MT9V032_WINDOW_WIDTH_MAX);
477 rect.height = clamp(ALIGN(crop->rect.height, 2), 588 rect.height = clamp_t(unsigned int, ALIGN(crop->rect.height, 2),
478 MT9V032_WINDOW_HEIGHT_MIN, 589 MT9V032_WINDOW_HEIGHT_MIN,
479 MT9V032_WINDOW_HEIGHT_MAX); 590 MT9V032_WINDOW_HEIGHT_MAX);
480 591
481 rect.width = min(rect.width, MT9V032_PIXEL_ARRAY_WIDTH - rect.left); 592 rect.width = min_t(unsigned int,
482 rect.height = min(rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top); 593 rect.width, MT9V032_PIXEL_ARRAY_WIDTH - rect.left);
594 rect.height = min_t(unsigned int,
595 rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top);
483 596
484 __crop = __mt9v032_get_pad_crop(mt9v032, fh, crop->pad, crop->which); 597 __crop = __mt9v032_get_pad_crop(mt9v032, fh, crop->pad, crop->which);
485 598
@@ -491,8 +604,11 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev,
491 crop->which); 604 crop->which);
492 __format->width = rect.width; 605 __format->width = rect.width;
493 __format->height = rect.height; 606 __format->height = rect.height;
494 if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) 607 if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
495 mt9v032_configure_pixel_rate(mt9v032, 1); 608 mt9v032->hratio = 1;
609 mt9v032->vratio = 1;
610 mt9v032_configure_pixel_rate(mt9v032);
611 }
496 } 612 }
497 613
498 *__crop = rect; 614 *__crop = rect;
@@ -641,7 +757,8 @@ static int mt9v032_registered(struct v4l2_subdev *subdev)
641{ 757{
642 struct i2c_client *client = v4l2_get_subdevdata(subdev); 758 struct i2c_client *client = v4l2_get_subdevdata(subdev);
643 struct mt9v032 *mt9v032 = to_mt9v032(subdev); 759 struct mt9v032 *mt9v032 = to_mt9v032(subdev);
644 s32 data; 760 unsigned int i;
761 s32 version;
645 int ret; 762 int ret;
646 763
647 dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n", 764 dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n",
@@ -654,25 +771,38 @@ static int mt9v032_registered(struct v4l2_subdev *subdev)
654 } 771 }
655 772
656 /* Read and check the sensor version */ 773 /* Read and check the sensor version */
657 data = mt9v032_read(client, MT9V032_CHIP_VERSION); 774 version = mt9v032_read(client, MT9V032_CHIP_VERSION);
658 if (data != MT9V032_CHIP_ID_REV1 && data != MT9V032_CHIP_ID_REV3) { 775 if (version < 0) {
659 dev_err(&client->dev, "MT9V032 not detected, wrong version " 776 dev_err(&client->dev, "Failed reading chip version\n");
660 "0x%04x\n", data); 777 return version;
778 }
779
780 for (i = 0; i < ARRAY_SIZE(mt9v032_versions); ++i) {
781 if (mt9v032_versions[i].version == version) {
782 mt9v032->version = &mt9v032_versions[i];
783 break;
784 }
785 }
786
787 if (mt9v032->version == NULL) {
788 dev_err(&client->dev, "Unsupported chip version 0x%04x\n",
789 version);
661 return -ENODEV; 790 return -ENODEV;
662 } 791 }
663 792
664 mt9v032_power_off(mt9v032); 793 mt9v032_power_off(mt9v032);
665 794
666 dev_info(&client->dev, "MT9V032 detected at address 0x%02x\n", 795 dev_info(&client->dev, "%s detected at address 0x%02x\n",
667 client->addr); 796 mt9v032->version->name, client->addr);
668 797
669 mt9v032_configure_pixel_rate(mt9v032, 1); 798 mt9v032_configure_pixel_rate(mt9v032);
670 799
671 return ret; 800 return ret;
672} 801}
673 802
674static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) 803static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
675{ 804{
805 struct mt9v032 *mt9v032 = to_mt9v032(subdev);
676 struct v4l2_mbus_framefmt *format; 806 struct v4l2_mbus_framefmt *format;
677 struct v4l2_rect *crop; 807 struct v4l2_rect *crop;
678 808
@@ -683,7 +813,12 @@ static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
683 crop->height = MT9V032_WINDOW_HEIGHT_DEF; 813 crop->height = MT9V032_WINDOW_HEIGHT_DEF;
684 814
685 format = v4l2_subdev_get_try_format(fh, 0); 815 format = v4l2_subdev_get_try_format(fh, 0);
686 format->code = V4L2_MBUS_FMT_SGRBG10_1X10; 816
817 if (mt9v032->model->color)
818 format->code = V4L2_MBUS_FMT_SGRBG10_1X10;
819 else
820 format->code = V4L2_MBUS_FMT_Y10_1X10;
821
687 format->width = MT9V032_WINDOW_WIDTH_DEF; 822 format->width = MT9V032_WINDOW_WIDTH_DEF;
688 format->height = MT9V032_WINDOW_HEIGHT_DEF; 823 format->height = MT9V032_WINDOW_HEIGHT_DEF;
689 format->field = V4L2_FIELD_NONE; 824 format->field = V4L2_FIELD_NONE;
@@ -755,6 +890,7 @@ static int mt9v032_probe(struct i2c_client *client,
755 890
756 mutex_init(&mt9v032->power_lock); 891 mutex_init(&mt9v032->power_lock);
757 mt9v032->pdata = pdata; 892 mt9v032->pdata = pdata;
893 mt9v032->model = (const void *)did->driver_data;
758 894
759 v4l2_ctrl_handler_init(&mt9v032->ctrls, 10); 895 v4l2_ctrl_handler_init(&mt9v032->ctrls, 10);
760 896
@@ -767,16 +903,16 @@ static int mt9v032_probe(struct i2c_client *client,
767 V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL, 0, 903 V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL, 0,
768 V4L2_EXPOSURE_AUTO); 904 V4L2_EXPOSURE_AUTO);
769 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, 905 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
770 V4L2_CID_EXPOSURE, MT9V032_TOTAL_SHUTTER_WIDTH_MIN, 906 V4L2_CID_EXPOSURE, mt9v032->model->data->min_shutter,
771 MT9V032_TOTAL_SHUTTER_WIDTH_MAX, 1, 907 mt9v032->model->data->max_shutter, 1,
772 MT9V032_TOTAL_SHUTTER_WIDTH_DEF); 908 MT9V032_TOTAL_SHUTTER_WIDTH_DEF);
773 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, 909 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
774 V4L2_CID_HBLANK, MT9V032_HORIZONTAL_BLANKING_MIN, 910 V4L2_CID_HBLANK, mt9v032->model->data->min_hblank,
775 MT9V032_HORIZONTAL_BLANKING_MAX, 1, 911 MT9V032_HORIZONTAL_BLANKING_MAX, 1,
776 MT9V032_HORIZONTAL_BLANKING_DEF); 912 MT9V032_HORIZONTAL_BLANKING_DEF);
777 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, 913 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
778 V4L2_CID_VBLANK, MT9V032_VERTICAL_BLANKING_MIN, 914 V4L2_CID_VBLANK, mt9v032->model->data->min_vblank,
779 MT9V032_VERTICAL_BLANKING_MAX, 1, 915 mt9v032->model->data->max_vblank, 1,
780 MT9V032_VERTICAL_BLANKING_DEF); 916 MT9V032_VERTICAL_BLANKING_DEF);
781 mt9v032->test_pattern = v4l2_ctrl_new_std_menu_items(&mt9v032->ctrls, 917 mt9v032->test_pattern = v4l2_ctrl_new_std_menu_items(&mt9v032->ctrls,
782 &mt9v032_ctrl_ops, V4L2_CID_TEST_PATTERN, 918 &mt9v032_ctrl_ops, V4L2_CID_TEST_PATTERN,
@@ -819,12 +955,19 @@ static int mt9v032_probe(struct i2c_client *client,
819 mt9v032->crop.width = MT9V032_WINDOW_WIDTH_DEF; 955 mt9v032->crop.width = MT9V032_WINDOW_WIDTH_DEF;
820 mt9v032->crop.height = MT9V032_WINDOW_HEIGHT_DEF; 956 mt9v032->crop.height = MT9V032_WINDOW_HEIGHT_DEF;
821 957
822 mt9v032->format.code = V4L2_MBUS_FMT_SGRBG10_1X10; 958 if (mt9v032->model->color)
959 mt9v032->format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
960 else
961 mt9v032->format.code = V4L2_MBUS_FMT_Y10_1X10;
962
823 mt9v032->format.width = MT9V032_WINDOW_WIDTH_DEF; 963 mt9v032->format.width = MT9V032_WINDOW_WIDTH_DEF;
824 mt9v032->format.height = MT9V032_WINDOW_HEIGHT_DEF; 964 mt9v032->format.height = MT9V032_WINDOW_HEIGHT_DEF;
825 mt9v032->format.field = V4L2_FIELD_NONE; 965 mt9v032->format.field = V4L2_FIELD_NONE;
826 mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB; 966 mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB;
827 967
968 mt9v032->hratio = 1;
969 mt9v032->vratio = 1;
970
828 mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE; 971 mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE;
829 mt9v032->hblank = MT9V032_HORIZONTAL_BLANKING_DEF; 972 mt9v032->hblank = MT9V032_HORIZONTAL_BLANKING_DEF;
830 mt9v032->sysclk = MT9V032_SYSCLK_FREQ_DEF; 973 mt9v032->sysclk = MT9V032_SYSCLK_FREQ_DEF;
@@ -855,7 +998,10 @@ static int mt9v032_remove(struct i2c_client *client)
855} 998}
856 999
857static const struct i2c_device_id mt9v032_id[] = { 1000static const struct i2c_device_id mt9v032_id[] = {
858 { "mt9v032", 0 }, 1001 { "mt9v032", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_COLOR] },
1002 { "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_MONO] },
1003 { "mt9v034", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_COLOR] },
1004 { "mt9v034m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_MONO] },
859 { } 1005 { }
860}; 1006};
861MODULE_DEVICE_TABLE(i2c, mt9v032_id); 1007MODULE_DEVICE_TABLE(i2c, mt9v032_id);