diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2010-05-08 17:28:41 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-20 23:04:41 -0400 |
commit | 959f3bdadfefb59e27c53c2e9ab13192119b0e3c (patch) | |
tree | 576e7dfcfc0af4808a6ca55f30b1a4a632c5e3d0 /drivers/media/video/ov7670.c | |
parent | d7709ffff4117f7c7700755accfe9d5e429efc53 (diff) |
V4L/DVB: ov7670: add enum/try/s_mbus_fmt support
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/ov7670.c')
-rw-r--r-- | drivers/media/video/ov7670.c | 94 |
1 files changed, 80 insertions, 14 deletions
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index 91c886ab15c6..715feb12f47c 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/videodev2.h> | 18 | #include <linux/videodev2.h> |
19 | #include <media/v4l2-device.h> | 19 | #include <media/v4l2-device.h> |
20 | #include <media/v4l2-chip-ident.h> | 20 | #include <media/v4l2-chip-ident.h> |
21 | #include <media/v4l2-mediabus.h> | ||
21 | #include <media/v4l2-i2c-drv.h> | 22 | #include <media/v4l2-i2c-drv.h> |
22 | 23 | ||
23 | 24 | ||
@@ -572,11 +573,13 @@ static int ov7670_detect(struct v4l2_subdev *sd) | |||
572 | /* | 573 | /* |
573 | * Store information about the video data format. The color matrix | 574 | * Store information about the video data format. The color matrix |
574 | * is deeply tied into the format, so keep the relevant values here. | 575 | * is deeply tied into the format, so keep the relevant values here. |
575 | * The magic matrix nubmers come from OmniVision. | 576 | * The magic matrix numbers come from OmniVision. |
576 | */ | 577 | */ |
577 | static struct ov7670_format_struct { | 578 | static struct ov7670_format_struct { |
578 | __u8 *desc; | 579 | __u8 *desc; |
579 | __u32 pixelformat; | 580 | __u32 pixelformat; |
581 | enum v4l2_mbus_pixelcode mbus_code; | ||
582 | enum v4l2_colorspace colorspace; | ||
580 | struct regval_list *regs; | 583 | struct regval_list *regs; |
581 | int cmatrix[CMATRIX_LEN]; | 584 | int cmatrix[CMATRIX_LEN]; |
582 | int bpp; /* Bytes per pixel */ | 585 | int bpp; /* Bytes per pixel */ |
@@ -584,6 +587,8 @@ static struct ov7670_format_struct { | |||
584 | { | 587 | { |
585 | .desc = "YUYV 4:2:2", | 588 | .desc = "YUYV 4:2:2", |
586 | .pixelformat = V4L2_PIX_FMT_YUYV, | 589 | .pixelformat = V4L2_PIX_FMT_YUYV, |
590 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
591 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
587 | .regs = ov7670_fmt_yuv422, | 592 | .regs = ov7670_fmt_yuv422, |
588 | .cmatrix = { 128, -128, 0, -34, -94, 128 }, | 593 | .cmatrix = { 128, -128, 0, -34, -94, 128 }, |
589 | .bpp = 2, | 594 | .bpp = 2, |
@@ -591,6 +596,8 @@ static struct ov7670_format_struct { | |||
591 | { | 596 | { |
592 | .desc = "RGB 444", | 597 | .desc = "RGB 444", |
593 | .pixelformat = V4L2_PIX_FMT_RGB444, | 598 | .pixelformat = V4L2_PIX_FMT_RGB444, |
599 | .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, | ||
600 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
594 | .regs = ov7670_fmt_rgb444, | 601 | .regs = ov7670_fmt_rgb444, |
595 | .cmatrix = { 179, -179, 0, -61, -176, 228 }, | 602 | .cmatrix = { 179, -179, 0, -61, -176, 228 }, |
596 | .bpp = 2, | 603 | .bpp = 2, |
@@ -598,6 +605,8 @@ static struct ov7670_format_struct { | |||
598 | { | 605 | { |
599 | .desc = "RGB 565", | 606 | .desc = "RGB 565", |
600 | .pixelformat = V4L2_PIX_FMT_RGB565, | 607 | .pixelformat = V4L2_PIX_FMT_RGB565, |
608 | .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, | ||
609 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
601 | .regs = ov7670_fmt_rgb565, | 610 | .regs = ov7670_fmt_rgb565, |
602 | .cmatrix = { 179, -179, 0, -61, -176, 228 }, | 611 | .cmatrix = { 179, -179, 0, -61, -176, 228 }, |
603 | .bpp = 2, | 612 | .bpp = 2, |
@@ -605,6 +614,8 @@ static struct ov7670_format_struct { | |||
605 | { | 614 | { |
606 | .desc = "Raw RGB Bayer", | 615 | .desc = "Raw RGB Bayer", |
607 | .pixelformat = V4L2_PIX_FMT_SBGGR8, | 616 | .pixelformat = V4L2_PIX_FMT_SBGGR8, |
617 | .mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8, | ||
618 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
608 | .regs = ov7670_fmt_raw, | 619 | .regs = ov7670_fmt_raw, |
609 | .cmatrix = { 0, 0, 0, 0, 0, 0 }, | 620 | .cmatrix = { 0, 0, 0, 0, 0, 0 }, |
610 | .bpp = 1 | 621 | .bpp = 1 |
@@ -748,37 +759,45 @@ static int ov7670_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) | |||
748 | return 0; | 759 | return 0; |
749 | } | 760 | } |
750 | 761 | ||
762 | static int ov7670_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, | ||
763 | enum v4l2_mbus_pixelcode *code) | ||
764 | { | ||
765 | if (index >= N_OV7670_FMTS) | ||
766 | return -EINVAL; | ||
767 | |||
768 | *code = ov7670_formats[index].mbus_code; | ||
769 | return 0; | ||
770 | } | ||
751 | 771 | ||
752 | static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, | 772 | static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, |
753 | struct v4l2_format *fmt, | 773 | struct v4l2_mbus_framefmt *fmt, |
754 | struct ov7670_format_struct **ret_fmt, | 774 | struct ov7670_format_struct **ret_fmt, |
755 | struct ov7670_win_size **ret_wsize) | 775 | struct ov7670_win_size **ret_wsize) |
756 | { | 776 | { |
757 | int index; | 777 | int index; |
758 | struct ov7670_win_size *wsize; | 778 | struct ov7670_win_size *wsize; |
759 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
760 | 779 | ||
761 | for (index = 0; index < N_OV7670_FMTS; index++) | 780 | for (index = 0; index < N_OV7670_FMTS; index++) |
762 | if (ov7670_formats[index].pixelformat == pix->pixelformat) | 781 | if (ov7670_formats[index].mbus_code == fmt->code) |
763 | break; | 782 | break; |
764 | if (index >= N_OV7670_FMTS) { | 783 | if (index >= N_OV7670_FMTS) { |
765 | /* default to first format */ | 784 | /* default to first format */ |
766 | index = 0; | 785 | index = 0; |
767 | pix->pixelformat = ov7670_formats[0].pixelformat; | 786 | fmt->code = ov7670_formats[0].mbus_code; |
768 | } | 787 | } |
769 | if (ret_fmt != NULL) | 788 | if (ret_fmt != NULL) |
770 | *ret_fmt = ov7670_formats + index; | 789 | *ret_fmt = ov7670_formats + index; |
771 | /* | 790 | /* |
772 | * Fields: the OV devices claim to be progressive. | 791 | * Fields: the OV devices claim to be progressive. |
773 | */ | 792 | */ |
774 | pix->field = V4L2_FIELD_NONE; | 793 | fmt->field = V4L2_FIELD_NONE; |
775 | /* | 794 | /* |
776 | * Round requested image size down to the nearest | 795 | * Round requested image size down to the nearest |
777 | * we support, but not below the smallest. | 796 | * we support, but not below the smallest. |
778 | */ | 797 | */ |
779 | for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES; | 798 | for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES; |
780 | wsize++) | 799 | wsize++) |
781 | if (pix->width >= wsize->width && pix->height >= wsize->height) | 800 | if (fmt->width >= wsize->width && fmt->height >= wsize->height) |
782 | break; | 801 | break; |
783 | if (wsize >= ov7670_win_sizes + N_WIN_SIZES) | 802 | if (wsize >= ov7670_win_sizes + N_WIN_SIZES) |
784 | wsize--; /* Take the smallest one */ | 803 | wsize--; /* Take the smallest one */ |
@@ -787,30 +806,54 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, | |||
787 | /* | 806 | /* |
788 | * Note the size we'll actually handle. | 807 | * Note the size we'll actually handle. |
789 | */ | 808 | */ |
790 | pix->width = wsize->width; | 809 | fmt->width = wsize->width; |
791 | pix->height = wsize->height; | 810 | fmt->height = wsize->height; |
792 | pix->bytesperline = pix->width*ov7670_formats[index].bpp; | 811 | fmt->colorspace = ov7670_formats[index].colorspace; |
793 | pix->sizeimage = pix->height*pix->bytesperline; | ||
794 | return 0; | 812 | return 0; |
795 | } | 813 | } |
796 | 814 | ||
797 | static int ov7670_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | 815 | static int ov7670_try_mbus_fmt(struct v4l2_subdev *sd, |
816 | struct v4l2_mbus_framefmt *fmt) | ||
798 | { | 817 | { |
799 | return ov7670_try_fmt_internal(sd, fmt, NULL, NULL); | 818 | return ov7670_try_fmt_internal(sd, fmt, NULL, NULL); |
800 | } | 819 | } |
801 | 820 | ||
821 | static int ov7670_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | ||
822 | { | ||
823 | struct v4l2_mbus_framefmt mbus_fmt; | ||
824 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
825 | unsigned index; | ||
826 | int ret; | ||
827 | |||
828 | for (index = 0; index < N_OV7670_FMTS; index++) | ||
829 | if (ov7670_formats[index].pixelformat == pix->pixelformat) | ||
830 | break; | ||
831 | if (index >= N_OV7670_FMTS) { | ||
832 | index = 0; | ||
833 | pix->pixelformat = ov7670_formats[index].pixelformat; | ||
834 | } | ||
835 | v4l2_fill_mbus_format(&mbus_fmt, pix, ov7670_formats[index].mbus_code); | ||
836 | ret = ov7670_try_fmt_internal(sd, &mbus_fmt, NULL, NULL); | ||
837 | v4l2_fill_pix_format(pix, &mbus_fmt); | ||
838 | pix->bytesperline = pix->width * ov7670_formats[index].bpp; | ||
839 | pix->sizeimage = pix->height * pix->bytesperline; | ||
840 | return ret; | ||
841 | } | ||
842 | |||
802 | /* | 843 | /* |
803 | * Set a format. | 844 | * Set a format. |
804 | */ | 845 | */ |
805 | static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | 846 | static int ov7670_s_mbus_fmt(struct v4l2_subdev *sd, |
847 | struct v4l2_mbus_framefmt *fmt) | ||
806 | { | 848 | { |
807 | int ret; | ||
808 | struct ov7670_format_struct *ovfmt; | 849 | struct ov7670_format_struct *ovfmt; |
809 | struct ov7670_win_size *wsize; | 850 | struct ov7670_win_size *wsize; |
810 | struct ov7670_info *info = to_state(sd); | 851 | struct ov7670_info *info = to_state(sd); |
811 | unsigned char com7; | 852 | unsigned char com7; |
853 | int ret; | ||
812 | 854 | ||
813 | ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize); | 855 | ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize); |
856 | |||
814 | if (ret) | 857 | if (ret) |
815 | return ret; | 858 | return ret; |
816 | /* | 859 | /* |
@@ -845,6 +888,26 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | |||
845 | */ | 888 | */ |
846 | if (ret == 0) | 889 | if (ret == 0) |
847 | ret = ov7670_write(sd, REG_CLKRC, info->clkrc); | 890 | ret = ov7670_write(sd, REG_CLKRC, info->clkrc); |
891 | return 0; | ||
892 | } | ||
893 | |||
894 | static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | ||
895 | { | ||
896 | struct v4l2_mbus_framefmt mbus_fmt; | ||
897 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
898 | unsigned index; | ||
899 | int ret; | ||
900 | |||
901 | for (index = 0; index < N_OV7670_FMTS; index++) | ||
902 | if (ov7670_formats[index].pixelformat == pix->pixelformat) | ||
903 | break; | ||
904 | if (index >= N_OV7670_FMTS) { | ||
905 | index = 0; | ||
906 | pix->pixelformat = ov7670_formats[index].pixelformat; | ||
907 | } | ||
908 | v4l2_fill_mbus_format(&mbus_fmt, pix, ov7670_formats[index].mbus_code); | ||
909 | ret = ov7670_s_mbus_fmt(sd, &mbus_fmt); | ||
910 | v4l2_fill_pix_format(pix, &mbus_fmt); | ||
848 | return ret; | 911 | return ret; |
849 | } | 912 | } |
850 | 913 | ||
@@ -1445,6 +1508,9 @@ static const struct v4l2_subdev_video_ops ov7670_video_ops = { | |||
1445 | .enum_fmt = ov7670_enum_fmt, | 1508 | .enum_fmt = ov7670_enum_fmt, |
1446 | .try_fmt = ov7670_try_fmt, | 1509 | .try_fmt = ov7670_try_fmt, |
1447 | .s_fmt = ov7670_s_fmt, | 1510 | .s_fmt = ov7670_s_fmt, |
1511 | .enum_mbus_fmt = ov7670_enum_mbus_fmt, | ||
1512 | .try_mbus_fmt = ov7670_try_mbus_fmt, | ||
1513 | .s_mbus_fmt = ov7670_s_mbus_fmt, | ||
1448 | .s_parm = ov7670_s_parm, | 1514 | .s_parm = ov7670_s_parm, |
1449 | .g_parm = ov7670_g_parm, | 1515 | .g_parm = ov7670_g_parm, |
1450 | }; | 1516 | }; |