diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2012-07-18 09:58:25 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-15 16:12:23 -0400 |
commit | 4ead963009f295dc8589720d22fa4fb288be9edb (patch) | |
tree | be89c14f39f93827a002a79a40e62fcdab9b39d3 | |
parent | f223d5b7184a743bf2b724698f7a84a963638bb6 (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.c | 162 |
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 | */ |
390 | struct regval_list { | ||
391 | unsigned char reg_num; | ||
392 | unsigned char value; | ||
393 | }; | ||
394 | 380 | ||
395 | struct ov772x_color_format { | 381 | struct 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 | ||
404 | struct ov772x_win_size { | 390 | struct 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 | ||
412 | struct ov772x_priv { | 396 | struct 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 | */ | ||
430 | static 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 | |||
440 | static 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 | ||
535 | static const struct ov772x_win_size ov772x_win_sizes[] = { | 488 | static 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 | ||
570 | static 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 | |||
582 | static int ov772x_mask_set(struct i2c_client *client, u8 command, u8 mask, | 529 | static 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 | ||