aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9m111.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/mt9m111.c')
-rw-r--r--drivers/media/video/mt9m111.c137
1 files changed, 76 insertions, 61 deletions
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index 95ca6c74f5d..71d862bfd9f 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -139,6 +139,46 @@
139#define MT9M111_MAX_HEIGHT 1024 139#define MT9M111_MAX_HEIGHT 1024
140#define MT9M111_MAX_WIDTH 1280 140#define MT9M111_MAX_WIDTH 1280
141 141
142struct mt9m111_context {
143 u16 read_mode;
144 u16 blanking_h;
145 u16 blanking_v;
146 u16 reducer_xzoom;
147 u16 reducer_yzoom;
148 u16 reducer_xsize;
149 u16 reducer_ysize;
150 u16 output_fmt_ctrl2;
151 u16 control;
152};
153
154static struct mt9m111_context context_a = {
155 .read_mode = MT9M111_READ_MODE_A,
156 .blanking_h = MT9M111_HORIZONTAL_BLANKING_A,
157 .blanking_v = MT9M111_VERTICAL_BLANKING_A,
158 .reducer_xzoom = MT9M111_REDUCER_XZOOM_A,
159 .reducer_yzoom = MT9M111_REDUCER_YZOOM_A,
160 .reducer_xsize = MT9M111_REDUCER_XSIZE_A,
161 .reducer_ysize = MT9M111_REDUCER_YSIZE_A,
162 .output_fmt_ctrl2 = MT9M111_OUTPUT_FORMAT_CTRL2_A,
163 .control = MT9M111_CTXT_CTRL_RESTART,
164};
165
166static struct mt9m111_context context_b = {
167 .read_mode = MT9M111_READ_MODE_B,
168 .blanking_h = MT9M111_HORIZONTAL_BLANKING_B,
169 .blanking_v = MT9M111_VERTICAL_BLANKING_B,
170 .reducer_xzoom = MT9M111_REDUCER_XZOOM_B,
171 .reducer_yzoom = MT9M111_REDUCER_YZOOM_B,
172 .reducer_xsize = MT9M111_REDUCER_XSIZE_B,
173 .reducer_ysize = MT9M111_REDUCER_YSIZE_B,
174 .output_fmt_ctrl2 = MT9M111_OUTPUT_FORMAT_CTRL2_B,
175 .control = MT9M111_CTXT_CTRL_RESTART |
176 MT9M111_CTXT_CTRL_DEFECTCOR_B | MT9M111_CTXT_CTRL_RESIZE_B |
177 MT9M111_CTXT_CTRL_CTRL2_B | MT9M111_CTXT_CTRL_GAMMA_B |
178 MT9M111_CTXT_CTRL_READ_MODE_B | MT9M111_CTXT_CTRL_VBLANK_SEL_B |
179 MT9M111_CTXT_CTRL_HBLANK_SEL_B,
180};
181
142/* MT9M111 has only one fixed colorspace per pixelcode */ 182/* MT9M111 has only one fixed colorspace per pixelcode */
143struct mt9m111_datafmt { 183struct mt9m111_datafmt {
144 enum v4l2_mbus_pixelcode code; 184 enum v4l2_mbus_pixelcode code;
@@ -173,18 +213,13 @@ static const struct mt9m111_datafmt mt9m111_colour_fmts[] = {
173 {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, 213 {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
174}; 214};
175 215
176enum mt9m111_context {
177 HIGHPOWER = 0,
178 LOWPOWER,
179};
180
181struct mt9m111 { 216struct mt9m111 {
182 struct v4l2_subdev subdev; 217 struct v4l2_subdev subdev;
183 struct v4l2_ctrl_handler hdl; 218 struct v4l2_ctrl_handler hdl;
184 struct v4l2_ctrl *gain; 219 struct v4l2_ctrl *gain;
185 int model; /* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code 220 int model; /* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code
186 * from v4l2-chip-ident.h */ 221 * from v4l2-chip-ident.h */
187 enum mt9m111_context context; 222 struct mt9m111_context *ctx;
188 struct v4l2_rect rect; 223 struct v4l2_rect rect;
189 struct mutex power_lock; /* lock to protect power_count */ 224 struct mutex power_lock; /* lock to protect power_count */
190 int power_count; 225 int power_count;
@@ -275,35 +310,33 @@ static int mt9m111_reg_mask(struct i2c_client *client, const u16 reg,
275} 310}
276 311
277static int mt9m111_set_context(struct mt9m111 *mt9m111, 312static int mt9m111_set_context(struct mt9m111 *mt9m111,
278 enum mt9m111_context ctxt) 313 struct mt9m111_context *ctx)
279{ 314{
280 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); 315 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
281 int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B 316 return reg_write(CONTEXT_CONTROL, ctx->control);
282 | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B 317}
283 | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B 318
284 | MT9M111_CTXT_CTRL_VBLANK_SEL_B 319static int mt9m111_setup_rect_ctx(struct mt9m111 *mt9m111,
285 | MT9M111_CTXT_CTRL_HBLANK_SEL_B; 320 struct v4l2_rect *rect, struct mt9m111_context *ctx)
286 int valA = MT9M111_CTXT_CTRL_RESTART; 321{
287 322 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
288 if (ctxt == HIGHPOWER) 323 int ret = mt9m111_reg_write(client, ctx->reducer_xzoom, MT9M111_MAX_WIDTH);
289 return reg_write(CONTEXT_CONTROL, valB); 324 if (!ret)
290 else 325 ret = mt9m111_reg_write(client, ctx->reducer_yzoom, MT9M111_MAX_HEIGHT);
291 return reg_write(CONTEXT_CONTROL, valA); 326 if (!ret)
327 ret = mt9m111_reg_write(client, ctx->reducer_xsize, rect->width);
328 if (!ret)
329 ret = mt9m111_reg_write(client, ctx->reducer_ysize, rect->height);
330 return ret;
292} 331}
293 332
294static int mt9m111_setup_rect(struct mt9m111 *mt9m111, 333static int mt9m111_setup_rect(struct mt9m111 *mt9m111,
295 struct v4l2_rect *rect) 334 struct v4l2_rect *rect)
296{ 335{
297 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); 336 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
298 int ret, is_raw_format; 337 int ret;
299 int width = rect->width; 338 bool is_raw_format = mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
300 int height = rect->height; 339 mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE;
301
302 if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
303 mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE)
304 is_raw_format = 1;
305 else
306 is_raw_format = 0;
307 340
308 ret = reg_write(COLUMN_START, rect->left); 341 ret = reg_write(COLUMN_START, rect->left);
309 if (!ret) 342 if (!ret)
@@ -311,26 +344,14 @@ static int mt9m111_setup_rect(struct mt9m111 *mt9m111,
311 344
312 if (is_raw_format) { 345 if (is_raw_format) {
313 if (!ret) 346 if (!ret)
314 ret = reg_write(WINDOW_WIDTH, width); 347 ret = reg_write(WINDOW_WIDTH, rect->width);
315 if (!ret) 348 if (!ret)
316 ret = reg_write(WINDOW_HEIGHT, height); 349 ret = reg_write(WINDOW_HEIGHT, rect->height);
317 } else { 350 } else {
318 if (!ret) 351 if (!ret)
319 ret = reg_write(REDUCER_XZOOM_B, MT9M111_MAX_WIDTH); 352 ret = mt9m111_setup_rect_ctx(mt9m111, rect, &context_b);
320 if (!ret)
321 ret = reg_write(REDUCER_YZOOM_B, MT9M111_MAX_HEIGHT);
322 if (!ret)
323 ret = reg_write(REDUCER_XSIZE_B, width);
324 if (!ret) 353 if (!ret)
325 ret = reg_write(REDUCER_YSIZE_B, height); 354 ret = mt9m111_setup_rect_ctx(mt9m111, rect, &context_a);
326 if (!ret)
327 ret = reg_write(REDUCER_XZOOM_A, MT9M111_MAX_WIDTH);
328 if (!ret)
329 ret = reg_write(REDUCER_YZOOM_A, MT9M111_MAX_HEIGHT);
330 if (!ret)
331 ret = reg_write(REDUCER_XSIZE_A, width);
332 if (!ret)
333 ret = reg_write(REDUCER_YSIZE_A, height);
334 } 355 }
335 356
336 return ret; 357 return ret;
@@ -503,11 +524,11 @@ static int mt9m111_set_pixfmt(struct mt9m111 *mt9m111,
503 return -EINVAL; 524 return -EINVAL;
504 } 525 }
505 526
506 ret = reg_mask(OUTPUT_FORMAT_CTRL2_A, data_outfmt2, 527 ret = mt9m111_reg_mask(client, context_a.output_fmt_ctrl2,
507 mask_outfmt2); 528 data_outfmt2, mask_outfmt2);
508 if (!ret) 529 if (!ret)
509 ret = reg_mask(OUTPUT_FORMAT_CTRL2_B, data_outfmt2, 530 ret = mt9m111_reg_mask(client, context_b.output_fmt_ctrl2,
510 mask_outfmt2); 531 data_outfmt2, mask_outfmt2);
511 532
512 return ret; 533 return ret;
513} 534}
@@ -649,17 +670,10 @@ static int mt9m111_set_flip(struct mt9m111 *mt9m111, int flip, int mask)
649 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); 670 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
650 int ret; 671 int ret;
651 672
652 if (mt9m111->context == HIGHPOWER) { 673 if (flip)
653 if (flip) 674 ret = mt9m111_reg_set(client, mt9m111->ctx->read_mode, mask);
654 ret = reg_set(READ_MODE_B, mask); 675 else
655 else 676 ret = mt9m111_reg_clear(client, mt9m111->ctx->read_mode, mask);
656 ret = reg_clear(READ_MODE_B, mask);
657 } else {
658 if (flip)
659 ret = reg_set(READ_MODE_A, mask);
660 else
661 ret = reg_clear(READ_MODE_A, mask);
662 }
663 677
664 return ret; 678 return ret;
665} 679}
@@ -744,7 +758,7 @@ static int mt9m111_suspend(struct mt9m111 *mt9m111)
744 758
745static void mt9m111_restore_state(struct mt9m111 *mt9m111) 759static void mt9m111_restore_state(struct mt9m111 *mt9m111)
746{ 760{
747 mt9m111_set_context(mt9m111, mt9m111->context); 761 mt9m111_set_context(mt9m111, mt9m111->ctx);
748 mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code); 762 mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code);
749 mt9m111_setup_rect(mt9m111, &mt9m111->rect); 763 mt9m111_setup_rect(mt9m111, &mt9m111->rect);
750 v4l2_ctrl_handler_setup(&mt9m111->hdl); 764 v4l2_ctrl_handler_setup(&mt9m111->hdl);
@@ -769,12 +783,13 @@ static int mt9m111_init(struct mt9m111 *mt9m111)
769 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); 783 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
770 int ret; 784 int ret;
771 785
772 mt9m111->context = HIGHPOWER; 786 /* Default HIGHPOWER context */
787 mt9m111->ctx = &context_b;
773 ret = mt9m111_enable(mt9m111); 788 ret = mt9m111_enable(mt9m111);
774 if (!ret) 789 if (!ret)
775 ret = mt9m111_reset(mt9m111); 790 ret = mt9m111_reset(mt9m111);
776 if (!ret) 791 if (!ret)
777 ret = mt9m111_set_context(mt9m111, mt9m111->context); 792 ret = mt9m111_set_context(mt9m111, mt9m111->ctx);
778 if (ret) 793 if (ret)
779 dev_err(&client->dev, "mt9m111 init failed: %d\n", ret); 794 dev_err(&client->dev, "mt9m111 init failed: %d\n", ret);
780 return ret; 795 return ret;