diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2011-11-03 07:14:56 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-01-06 08:00:29 -0500 |
commit | 47921932f36c79e51f3bf40ab9632fa50309079a (patch) | |
tree | a0b4051a6b5c9a6fc17e5288243acd60c6a2c308 /drivers/media/video/mt9m111.c | |
parent | 8843d119eaf1a7a87a2cf8c3eadbd1937b16bc27 (diff) |
[media] mt9m111: cleanly separate register contexts
Cleanly separating register contexts A and B will allow us to configure
the contexts independently.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/mt9m111.c')
-rw-r--r-- | drivers/media/video/mt9m111.c | 137 |
1 files changed, 76 insertions, 61 deletions
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 95ca6c74f5df..71d862bfd9fd 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 | ||
142 | struct 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 | |||
154 | static 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 | |||
166 | static 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 */ |
143 | struct mt9m111_datafmt { | 183 | struct 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 | ||
176 | enum mt9m111_context { | ||
177 | HIGHPOWER = 0, | ||
178 | LOWPOWER, | ||
179 | }; | ||
180 | |||
181 | struct mt9m111 { | 216 | struct 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 | ||
277 | static int mt9m111_set_context(struct mt9m111 *mt9m111, | 312 | static 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 | 319 | static 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 | ||
294 | static int mt9m111_setup_rect(struct mt9m111 *mt9m111, | 333 | static 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 | ||
745 | static void mt9m111_restore_state(struct mt9m111 *mt9m111) | 759 | static 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; |