aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorMichael Grzeschik <m.grzeschik@pengutronix.de>2011-07-12 11:39:05 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-07-27 16:56:10 -0400
commit7c58e7d06cf2566537714257094b852de6c294c3 (patch)
tree15b3eb8d97465cb729a916c68c4bdb63c726695f /drivers/media/video
parent9c56cbf9aadff79c25ccd424ae422971efd5c1a4 (diff)
[media] V4L: mt9m111: rewrite set_pixfmt
added new bit offset defines, more supported BE colour formats and also support BGR565 swapped pixel formats removed pixfmt helper functions and option flags setting the configuration register directly in set_pixfmt added reg_mask function reg_mask is basically the same as clearing & setting registers, but it is more convenient and faster (saves one rw cycle). Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> Signed-off-by: Philipp Wiesner <p.wiesner@phytec.de> Acked-by: Robert Jarzmik <robert.jarzmik@free.fr> [g.liakhovetski@gmx.de: remove Bayer swap, forward-port, rename macros] Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/mt9m111.c175
1 files changed, 69 insertions, 106 deletions
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index 8d8420acc9cf..a357aa889fc6 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -63,6 +63,12 @@
63#define MT9M111_RESET_RESTART_FRAME (1 << 1) 63#define MT9M111_RESET_RESTART_FRAME (1 << 1)
64#define MT9M111_RESET_RESET_MODE (1 << 0) 64#define MT9M111_RESET_RESET_MODE (1 << 0)
65 65
66#define MT9M111_RM_FULL_POWER_RD (0 << 10)
67#define MT9M111_RM_LOW_POWER_RD (1 << 10)
68#define MT9M111_RM_COL_SKIP_4X (1 << 5)
69#define MT9M111_RM_ROW_SKIP_4X (1 << 4)
70#define MT9M111_RM_COL_SKIP_2X (1 << 3)
71#define MT9M111_RM_ROW_SKIP_2X (1 << 2)
66#define MT9M111_RMB_MIRROR_COLS (1 << 1) 72#define MT9M111_RMB_MIRROR_COLS (1 << 1)
67#define MT9M111_RMB_MIRROR_ROWS (1 << 0) 73#define MT9M111_RMB_MIRROR_ROWS (1 << 0)
68#define MT9M111_CTXT_CTRL_RESTART (1 << 15) 74#define MT9M111_CTXT_CTRL_RESTART (1 << 15)
@@ -95,7 +101,8 @@
95 101
96#define MT9M111_OPMODE_AUTOEXPO_EN (1 << 14) 102#define MT9M111_OPMODE_AUTOEXPO_EN (1 << 14)
97#define MT9M111_OPMODE_AUTOWHITEBAL_EN (1 << 1) 103#define MT9M111_OPMODE_AUTOWHITEBAL_EN (1 << 1)
98 104#define MT9M111_OUTFMT_FLIP_BAYER_COL (1 << 9)
105#define MT9M111_OUTFMT_FLIP_BAYER_ROW (1 << 8)
99#define MT9M111_OUTFMT_PROCESSED_BAYER (1 << 14) 106#define MT9M111_OUTFMT_PROCESSED_BAYER (1 << 14)
100#define MT9M111_OUTFMT_BYPASS_IFP (1 << 10) 107#define MT9M111_OUTFMT_BYPASS_IFP (1 << 10)
101#define MT9M111_OUTFMT_INV_PIX_CLOCK (1 << 9) 108#define MT9M111_OUTFMT_INV_PIX_CLOCK (1 << 9)
@@ -110,9 +117,8 @@
110#define MT9M111_OUTFMT_TST_RAMP_FRAME (3 << 4) 117#define MT9M111_OUTFMT_TST_RAMP_FRAME (3 << 4)
111#define MT9M111_OUTFMT_SHIFT_3_UP (1 << 3) 118#define MT9M111_OUTFMT_SHIFT_3_UP (1 << 3)
112#define MT9M111_OUTFMT_AVG_CHROMA (1 << 2) 119#define MT9M111_OUTFMT_AVG_CHROMA (1 << 2)
113#define MT9M111_OUTFMT_SWAP_YCbCr_C_Y (1 << 1) 120#define MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN (1 << 1)
114#define MT9M111_OUTFMT_SWAP_RGB_EVEN (1 << 1) 121#define MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B (1 << 0)
115#define MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr (1 << 0)
116 122
117/* 123/*
118 * Camera control register addresses (0x200..0x2ff not implemented) 124 * Camera control register addresses (0x200..0x2ff not implemented)
@@ -122,6 +128,8 @@
122#define reg_write(reg, val) mt9m111_reg_write(client, MT9M111_##reg, (val)) 128#define reg_write(reg, val) mt9m111_reg_write(client, MT9M111_##reg, (val))
123#define reg_set(reg, val) mt9m111_reg_set(client, MT9M111_##reg, (val)) 129#define reg_set(reg, val) mt9m111_reg_set(client, MT9M111_##reg, (val))
124#define reg_clear(reg, val) mt9m111_reg_clear(client, MT9M111_##reg, (val)) 130#define reg_clear(reg, val) mt9m111_reg_clear(client, MT9M111_##reg, (val))
131#define reg_mask(reg, val, mask) mt9m111_reg_mask(client, MT9M111_##reg, \
132 (val), (mask))
125 133
126#define MT9M111_MIN_DARK_ROWS 8 134#define MT9M111_MIN_DARK_ROWS 8
127#define MT9M111_MIN_DARK_COLS 26 135#define MT9M111_MIN_DARK_COLS 26
@@ -153,7 +161,11 @@ static const struct mt9m111_datafmt mt9m111_colour_fmts[] = {
153 {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG}, 161 {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
154 {V4L2_MBUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG}, 162 {V4L2_MBUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG},
155 {V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, 163 {V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
164 {V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
156 {V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB}, 165 {V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
166 {V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
167 {V4L2_MBUS_FMT_BGR565_2X8_LE, V4L2_COLORSPACE_SRGB},
168 {V4L2_MBUS_FMT_BGR565_2X8_BE, V4L2_COLORSPACE_SRGB},
157 {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB}, 169 {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
158 {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, 170 {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
159}; 171};
@@ -178,10 +190,6 @@ struct mt9m111 {
178 unsigned int powered:1; 190 unsigned int powered:1;
179 unsigned int hflip:1; 191 unsigned int hflip:1;
180 unsigned int vflip:1; 192 unsigned int vflip:1;
181 unsigned int swap_rgb_even_odd:1;
182 unsigned int swap_rgb_red_blue:1;
183 unsigned int swap_yuv_y_chromas:1;
184 unsigned int swap_yuv_cb_cr:1;
185 unsigned int autowhitebalance:1; 193 unsigned int autowhitebalance:1;
186}; 194};
187 195
@@ -255,6 +263,17 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg,
255 return ret; 263 return ret;
256} 264}
257 265
266static int mt9m111_reg_mask(struct i2c_client *client, const u16 reg,
267 const u16 data, const u16 mask)
268{
269 int ret;
270
271 ret = mt9m111_reg_read(client, reg);
272 if (ret >= 0)
273 ret = mt9m111_reg_write(client, reg, (ret & ~mask) | data);
274 return ret;
275}
276
258static int mt9m111_set_context(struct mt9m111 *mt9m111, 277static int mt9m111_set_context(struct mt9m111 *mt9m111,
259 enum mt9m111_context ctxt) 278 enum mt9m111_context ctxt)
260{ 279{
@@ -317,80 +336,6 @@ static int mt9m111_setup_rect(struct mt9m111 *mt9m111,
317 return ret; 336 return ret;
318} 337}
319 338
320static int mt9m111_setup_pixfmt(struct i2c_client *client, u16 outfmt)
321{
322 int ret;
323 u16 mask = MT9M111_OUTFMT_PROCESSED_BAYER | MT9M111_OUTFMT_RGB |
324 MT9M111_OUTFMT_BYPASS_IFP | MT9M111_OUTFMT_SWAP_RGB_EVEN |
325 MT9M111_OUTFMT_RGB565 | MT9M111_OUTFMT_RGB555 |
326 MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr |
327 MT9M111_OUTFMT_SWAP_YCbCr_C_Y;
328
329 ret = reg_read(OUTPUT_FORMAT_CTRL2_A);
330 if (ret >= 0)
331 ret = reg_write(OUTPUT_FORMAT_CTRL2_A, (ret & ~mask) | outfmt);
332 if (!ret)
333 ret = reg_read(OUTPUT_FORMAT_CTRL2_B);
334 if (ret >= 0)
335 ret = reg_write(OUTPUT_FORMAT_CTRL2_B, (ret & ~mask) | outfmt);
336
337 return ret;
338}
339
340static int mt9m111_setfmt_bayer8(struct mt9m111 *mt9m111)
341{
342 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
343
344 return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_PROCESSED_BAYER |
345 MT9M111_OUTFMT_RGB);
346}
347
348static int mt9m111_setfmt_bayer10(struct mt9m111 *mt9m111)
349{
350 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
351
352 return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_BYPASS_IFP);
353}
354
355static int mt9m111_setfmt_rgb565(struct mt9m111 *mt9m111)
356{
357 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
358 int val = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565;
359
360 if (mt9m111->swap_rgb_red_blue)
361 val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr;
362 if (mt9m111->swap_rgb_even_odd)
363 val |= MT9M111_OUTFMT_SWAP_RGB_EVEN;
364
365 return mt9m111_setup_pixfmt(client, val);
366}
367
368static int mt9m111_setfmt_rgb555(struct mt9m111 *mt9m111)
369{
370 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
371 int val = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555;
372
373 if (mt9m111->swap_rgb_red_blue)
374 val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr;
375 if (mt9m111->swap_rgb_even_odd)
376 val |= MT9M111_OUTFMT_SWAP_RGB_EVEN;
377
378 return mt9m111_setup_pixfmt(client, val);
379}
380
381static int mt9m111_setfmt_yuv(struct mt9m111 *mt9m111)
382{
383 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
384 int val = 0;
385
386 if (mt9m111->swap_yuv_cb_cr)
387 val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr;
388 if (mt9m111->swap_yuv_y_chromas)
389 val |= MT9M111_OUTFMT_SWAP_YCbCr_C_Y;
390
391 return mt9m111_setup_pixfmt(client, val);
392}
393
394static int mt9m111_enable(struct mt9m111 *mt9m111) 339static int mt9m111_enable(struct mt9m111 *mt9m111)
395{ 340{
396 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); 341 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
@@ -515,49 +460,70 @@ static int mt9m111_g_fmt(struct v4l2_subdev *sd,
515static int mt9m111_set_pixfmt(struct mt9m111 *mt9m111, 460static int mt9m111_set_pixfmt(struct mt9m111 *mt9m111,
516 enum v4l2_mbus_pixelcode code) 461 enum v4l2_mbus_pixelcode code)
517{ 462{
518 struct i2c_client *client; 463 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
464 u16 data_outfmt2, mask_outfmt2 = MT9M111_OUTFMT_PROCESSED_BAYER |
465 MT9M111_OUTFMT_BYPASS_IFP | MT9M111_OUTFMT_RGB |
466 MT9M111_OUTFMT_RGB565 | MT9M111_OUTFMT_RGB555 |
467 MT9M111_OUTFMT_RGB444x | MT9M111_OUTFMT_RGBx444 |
468 MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |
469 MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
519 int ret; 470 int ret;
520 471
521 switch (code) { 472 switch (code) {
522 case V4L2_MBUS_FMT_SBGGR8_1X8: 473 case V4L2_MBUS_FMT_SBGGR8_1X8:
523 ret = mt9m111_setfmt_bayer8(mt9m111); 474 data_outfmt2 = MT9M111_OUTFMT_PROCESSED_BAYER |
475 MT9M111_OUTFMT_RGB;
524 break; 476 break;
525 case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE: 477 case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE:
526 ret = mt9m111_setfmt_bayer10(mt9m111); 478 data_outfmt2 = MT9M111_OUTFMT_BYPASS_IFP | MT9M111_OUTFMT_RGB;
527 break; 479 break;
528 case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: 480 case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
529 ret = mt9m111_setfmt_rgb555(mt9m111); 481 data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555 |
482 MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
483 break;
484 case V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE:
485 data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555;
530 break; 486 break;
531 case V4L2_MBUS_FMT_RGB565_2X8_LE: 487 case V4L2_MBUS_FMT_RGB565_2X8_LE:
532 ret = mt9m111_setfmt_rgb565(mt9m111); 488 data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
489 MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
490 break;
491 case V4L2_MBUS_FMT_RGB565_2X8_BE:
492 data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565;
493 break;
494 case V4L2_MBUS_FMT_BGR565_2X8_BE:
495 data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
496 MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
497 break;
498 case V4L2_MBUS_FMT_BGR565_2X8_LE:
499 data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
500 MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |
501 MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
533 break; 502 break;
534 case V4L2_MBUS_FMT_UYVY8_2X8: 503 case V4L2_MBUS_FMT_UYVY8_2X8:
535 mt9m111->swap_yuv_y_chromas = 0; 504 data_outfmt2 = 0;
536 mt9m111->swap_yuv_cb_cr = 0;
537 ret = mt9m111_setfmt_yuv(mt9m111);
538 break; 505 break;
539 case V4L2_MBUS_FMT_VYUY8_2X8: 506 case V4L2_MBUS_FMT_VYUY8_2X8:
540 mt9m111->swap_yuv_y_chromas = 0; 507 data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
541 mt9m111->swap_yuv_cb_cr = 1;
542 ret = mt9m111_setfmt_yuv(mt9m111);
543 break; 508 break;
544 case V4L2_MBUS_FMT_YUYV8_2X8: 509 case V4L2_MBUS_FMT_YUYV8_2X8:
545 mt9m111->swap_yuv_y_chromas = 1; 510 data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
546 mt9m111->swap_yuv_cb_cr = 0;
547 ret = mt9m111_setfmt_yuv(mt9m111);
548 break; 511 break;
549 case V4L2_MBUS_FMT_YVYU8_2X8: 512 case V4L2_MBUS_FMT_YVYU8_2X8:
550 mt9m111->swap_yuv_y_chromas = 1; 513 data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |
551 mt9m111->swap_yuv_cb_cr = 1; 514 MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
552 ret = mt9m111_setfmt_yuv(mt9m111);
553 break; 515 break;
554 default: 516 default:
555 client = v4l2_get_subdevdata(&mt9m111->subdev); 517 dev_err(&client->dev, "Pixel format not handled: %x\n", code);
556 dev_err(&client->dev, "Pixel format not handled : %x\n", 518 return -EINVAL;
557 code);
558 ret = -EINVAL;
559 } 519 }
560 520
521 ret = reg_mask(OUTPUT_FORMAT_CTRL2_A, data_outfmt2,
522 mask_outfmt2);
523 if (!ret)
524 ret = reg_mask(OUTPUT_FORMAT_CTRL2_B, data_outfmt2,
525 mask_outfmt2);
526
561 return ret; 527 return ret;
562} 528}
563 529
@@ -969,9 +935,6 @@ static int mt9m111_video_probe(struct soc_camera_device *icd,
969 mt9m111->autoexposure = 1; 935 mt9m111->autoexposure = 1;
970 mt9m111->autowhitebalance = 1; 936 mt9m111->autowhitebalance = 1;
971 937
972 mt9m111->swap_rgb_even_odd = 1;
973 mt9m111->swap_rgb_red_blue = 1;
974
975 data = reg_read(CHIP_VERSION); 938 data = reg_read(CHIP_VERSION);
976 939
977 switch (data) { 940 switch (data) {