aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-07-18 09:58:25 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-08-15 16:12:23 -0400
commit4ead963009f295dc8589720d22fa4fb288be9edb (patch)
treebe89c14f39f93827a002a79a40e62fcdab9b39d3
parentf223d5b7184a743bf2b724698f7a84a963638bb6 (diff)
[media] ov772x: Compute window size registers at runtime
Instead of hardcoding register arrays, compute the values at runtime. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> [g.liakhovetski@gmx.de: keep (Q)VGA_* macros for now] Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/i2c/soc_camera/ov772x.c162
1 files changed, 67 insertions, 95 deletions
diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c
index a19769a8142b..76a80b652407 100644
--- a/drivers/media/i2c/soc_camera/ov772x.c
+++ b/drivers/media/i2c/soc_camera/ov772x.c
@@ -318,8 +318,15 @@
318#define SGLF_ON_OFF 0x02 /* Single frame ON/OFF selection */ 318#define SGLF_ON_OFF 0x02 /* Single frame ON/OFF selection */
319#define SGLF_TRIG 0x01 /* Single frame transfer trigger */ 319#define SGLF_TRIG 0x01 /* Single frame transfer trigger */
320 320
321/* HREF */
322#define HREF_VSTART_SHIFT 6 /* VSTART LSB */
323#define HREF_HSTART_SHIFT 4 /* HSTART 2 LSBs */
324#define HREF_VSIZE_SHIFT 2 /* VSIZE LSB */
325#define HREF_HSIZE_SHIFT 0 /* HSIZE 2 LSBs */
326
321/* EXHCH */ 327/* EXHCH */
322#define VSIZE_LSB 0x04 /* Vertical data output size LSB */ 328#define EXHCH_VSIZE_SHIFT 2 /* VOUTSIZE LSB */
329#define EXHCH_HSIZE_SHIFT 0 /* HOUTSIZE 2 LSBs */
323 330
324/* DSP_CTRL1 */ 331/* DSP_CTRL1 */
325#define FIFO_ON 0x80 /* FIFO enable/disable selection */ 332#define FIFO_ON 0x80 /* FIFO enable/disable selection */
@@ -345,30 +352,6 @@
345#define DSP_OFMT_RAW8 0x02 352#define DSP_OFMT_RAW8 0x02
346#define DSP_OFMT_RAW10 0x03 353#define DSP_OFMT_RAW10 0x03
347 354
348/* HSTART */
349#define HST_VGA 0x23
350#define HST_QVGA 0x3F
351
352/* HSIZE */
353#define HSZ_VGA 0xA0
354#define HSZ_QVGA 0x50
355
356/* VSTART */
357#define VST_VGA 0x07
358#define VST_QVGA 0x03
359
360/* VSIZE */
361#define VSZ_VGA 0xF0
362#define VSZ_QVGA 0x78
363
364/* HOUTSIZE */
365#define HOSZ_VGA 0xA0
366#define HOSZ_QVGA 0x50
367
368/* VOUTSIZE */
369#define VOSZ_VGA 0xF0
370#define VOSZ_QVGA 0x78
371
372/* DSPAUTO (DSP Auto Function ON/OFF Control) */ 355/* DSPAUTO (DSP Auto Function ON/OFF Control) */
373#define AWB_ACTRL 0x80 /* AWB auto threshold control */ 356#define AWB_ACTRL 0x80 /* AWB auto threshold control */
374#define DENOISE_ACTRL 0x40 /* De-noise auto threshold control */ 357#define DENOISE_ACTRL 0x40 /* De-noise auto threshold control */
@@ -377,6 +360,13 @@
377#define SCAL0_ACTRL 0x08 /* Auto scaling factor control */ 360#define SCAL0_ACTRL 0x08 /* Auto scaling factor control */
378#define SCAL1_2_ACTRL 0x04 /* Auto scaling factor control */ 361#define SCAL1_2_ACTRL 0x04 /* Auto scaling factor control */
379 362
363#define VGA_WIDTH 640
364#define VGA_HEIGHT 480
365#define QVGA_WIDTH 320
366#define QVGA_HEIGHT 240
367#define OV772X_MAX_WIDTH VGA_WIDTH
368#define OV772X_MAX_HEIGHT VGA_HEIGHT
369
380/* 370/*
381 * ID 371 * ID
382 */ 372 */
@@ -387,10 +377,6 @@
387/* 377/*
388 * struct 378 * struct
389 */ 379 */
390struct regval_list {
391 unsigned char reg_num;
392 unsigned char value;
393};
394 380
395struct ov772x_color_format { 381struct ov772x_color_format {
396 enum v4l2_mbus_pixelcode code; 382 enum v4l2_mbus_pixelcode code;
@@ -403,10 +389,8 @@ struct ov772x_color_format {
403 389
404struct ov772x_win_size { 390struct ov772x_win_size {
405 char *name; 391 char *name;
406 __u32 width;
407 __u32 height;
408 unsigned char com7_bit; 392 unsigned char com7_bit;
409 const struct regval_list *regs; 393 struct v4l2_rect rect;
410}; 394};
411 395
412struct ov772x_priv { 396struct ov772x_priv {
@@ -422,31 +406,6 @@ struct ov772x_priv {
422 unsigned short band_filter; 406 unsigned short band_filter;
423}; 407};
424 408
425#define ENDMARKER { 0xff, 0xff }
426
427/*
428 * register setting for window size
429 */
430static const struct regval_list ov772x_qvga_regs[] = {
431 { HSTART, HST_QVGA },
432 { HSIZE, HSZ_QVGA },
433 { VSTART, VST_QVGA },
434 { VSIZE, VSZ_QVGA },
435 { HOUTSIZE, HOSZ_QVGA },
436 { VOUTSIZE, VOSZ_QVGA },
437 ENDMARKER,
438};
439
440static const struct regval_list ov772x_vga_regs[] = {
441 { HSTART, HST_VGA },
442 { HSIZE, HSZ_VGA },
443 { VSTART, VST_VGA },
444 { VSIZE, VSZ_VGA },
445 { HOUTSIZE, HOSZ_VGA },
446 { VOUTSIZE, VOSZ_VGA },
447 ENDMARKER,
448};
449
450/* 409/*
451 * supported color format list 410 * supported color format list
452 */ 411 */
@@ -525,26 +484,26 @@ static const struct ov772x_color_format ov772x_cfmts[] = {
525/* 484/*
526 * window size list 485 * window size list
527 */ 486 */
528#define VGA_WIDTH 640
529#define VGA_HEIGHT 480
530#define QVGA_WIDTH 320
531#define QVGA_HEIGHT 240
532#define MAX_WIDTH VGA_WIDTH
533#define MAX_HEIGHT VGA_HEIGHT
534 487
535static const struct ov772x_win_size ov772x_win_sizes[] = { 488static const struct ov772x_win_size ov772x_win_sizes[] = {
536 { 489 {
537 .name = "VGA", 490 .name = "VGA",
538 .width = VGA_WIDTH,
539 .height = VGA_HEIGHT,
540 .com7_bit = SLCT_VGA, 491 .com7_bit = SLCT_VGA,
541 .regs = ov772x_vga_regs, 492 .rect = {
493 .left = 140,
494 .top = 14,
495 .width = VGA_WIDTH,
496 .height = VGA_HEIGHT,
497 },
542 }, { 498 }, {
543 .name = "QVGA", 499 .name = "QVGA",
544 .width = QVGA_WIDTH,
545 .height = QVGA_HEIGHT,
546 .com7_bit = SLCT_QVGA, 500 .com7_bit = SLCT_QVGA,
547 .regs = ov772x_qvga_regs, 501 .rect = {
502 .left = 252,
503 .top = 6,
504 .width = QVGA_WIDTH,
505 .height = QVGA_HEIGHT,
506 },
548 }, 507 },
549}; 508};
550 509
@@ -567,18 +526,6 @@ static inline int ov772x_write(struct i2c_client *client, u8 addr, u8 value)
567 return i2c_smbus_write_byte_data(client, addr, value); 526 return i2c_smbus_write_byte_data(client, addr, value);
568} 527}
569 528
570static int ov772x_write_array(struct i2c_client *client,
571 const struct regval_list *vals)
572{
573 while (vals->reg_num != 0xff) {
574 int ret = ov772x_write(client, vals->reg_num, vals->value);
575 if (ret < 0)
576 return ret;
577 vals++;
578 }
579 return 0;
580}
581
582static int ov772x_mask_set(struct i2c_client *client, u8 command, u8 mask, 529static int ov772x_mask_set(struct i2c_client *client, u8 command, u8 mask,
583 u8 set) 530 u8 set)
584{ 531{
@@ -726,8 +673,8 @@ static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height)
726 unsigned int i; 673 unsigned int i;
727 674
728 for (i = 0; i < ARRAY_SIZE(ov772x_win_sizes); ++i) { 675 for (i = 0; i < ARRAY_SIZE(ov772x_win_sizes); ++i) {
729 u32 diff = abs(width - ov772x_win_sizes[i].width) 676 u32 diff = abs(width - ov772x_win_sizes[i].rect.width)
730 + abs(height - ov772x_win_sizes[i].height); 677 + abs(height - ov772x_win_sizes[i].rect.height);
731 if (diff < best_diff) { 678 if (diff < best_diff) {
732 best_diff = diff; 679 best_diff = diff;
733 win = &ov772x_win_sizes[i]; 680 win = &ov772x_win_sizes[i];
@@ -817,10 +764,35 @@ static int ov772x_set_params(struct ov772x_priv *priv,
817 goto ov772x_set_fmt_error; 764 goto ov772x_set_fmt_error;
818 } 765 }
819 766
820 /* 767 /* Format and window size */
821 * set size format 768 ret = ov772x_write(client, HSTART, win->rect.left >> 2);
822 */ 769 if (ret < 0)
823 ret = ov772x_write_array(client, win->regs); 770 goto ov772x_set_fmt_error;
771 ret = ov772x_write(client, HSIZE, win->rect.width >> 2);
772 if (ret < 0)
773 goto ov772x_set_fmt_error;
774 ret = ov772x_write(client, VSTART, win->rect.top >> 1);
775 if (ret < 0)
776 goto ov772x_set_fmt_error;
777 ret = ov772x_write(client, VSIZE, win->rect.height >> 1);
778 if (ret < 0)
779 goto ov772x_set_fmt_error;
780 ret = ov772x_write(client, HOUTSIZE, win->rect.width >> 2);
781 if (ret < 0)
782 goto ov772x_set_fmt_error;
783 ret = ov772x_write(client, VOUTSIZE, win->rect.height >> 1);
784 if (ret < 0)
785 goto ov772x_set_fmt_error;
786 ret = ov772x_write(client, HREF,
787 ((win->rect.top & 1) << HREF_VSTART_SHIFT) |
788 ((win->rect.left & 3) << HREF_HSTART_SHIFT) |
789 ((win->rect.height & 1) << HREF_VSIZE_SHIFT) |
790 ((win->rect.width & 3) << HREF_HSIZE_SHIFT));
791 if (ret < 0)
792 goto ov772x_set_fmt_error;
793 ret = ov772x_write(client, EXHCH,
794 ((win->rect.height & 1) << EXHCH_VSIZE_SHIFT) |
795 ((win->rect.width & 3) << EXHCH_HSIZE_SHIFT));
824 if (ret < 0) 796 if (ret < 0)
825 goto ov772x_set_fmt_error; 797 goto ov772x_set_fmt_error;
826 798
@@ -901,8 +873,8 @@ static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
901{ 873{
902 a->bounds.left = 0; 874 a->bounds.left = 0;
903 a->bounds.top = 0; 875 a->bounds.top = 0;
904 a->bounds.width = VGA_WIDTH; 876 a->bounds.width = OV772X_MAX_WIDTH;
905 a->bounds.height = VGA_HEIGHT; 877 a->bounds.height = OV772X_MAX_HEIGHT;
906 a->defrect = a->bounds; 878 a->defrect = a->bounds;
907 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 879 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
908 a->pixelaspect.numerator = 1; 880 a->pixelaspect.numerator = 1;
@@ -916,8 +888,8 @@ static int ov772x_g_fmt(struct v4l2_subdev *sd,
916{ 888{
917 struct ov772x_priv *priv = to_ov772x(sd); 889 struct ov772x_priv *priv = to_ov772x(sd);
918 890
919 mf->width = priv->win->width; 891 mf->width = priv->win->rect.width;
920 mf->height = priv->win->height; 892 mf->height = priv->win->rect.height;
921 mf->code = priv->cfmt->code; 893 mf->code = priv->cfmt->code;
922 mf->colorspace = priv->cfmt->colorspace; 894 mf->colorspace = priv->cfmt->colorspace;
923 mf->field = V4L2_FIELD_NONE; 895 mf->field = V4L2_FIELD_NONE;
@@ -942,8 +914,8 @@ static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
942 priv->cfmt = cfmt; 914 priv->cfmt = cfmt;
943 915
944 mf->code = cfmt->code; 916 mf->code = cfmt->code;
945 mf->width = win->width; 917 mf->width = win->rect.width;
946 mf->height = win->height; 918 mf->height = win->rect.height;
947 mf->field = V4L2_FIELD_NONE; 919 mf->field = V4L2_FIELD_NONE;
948 mf->colorspace = cfmt->colorspace; 920 mf->colorspace = cfmt->colorspace;
949 921
@@ -959,8 +931,8 @@ static int ov772x_try_fmt(struct v4l2_subdev *sd,
959 ov772x_select_params(mf, &cfmt, &win); 931 ov772x_select_params(mf, &cfmt, &win);
960 932
961 mf->code = cfmt->code; 933 mf->code = cfmt->code;
962 mf->width = win->width; 934 mf->width = win->rect.width;
963 mf->height = win->height; 935 mf->height = win->rect.height;
964 mf->field = V4L2_FIELD_NONE; 936 mf->field = V4L2_FIELD_NONE;
965 mf->colorspace = cfmt->colorspace; 937 mf->colorspace = cfmt->colorspace;
966 938