aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ov7670.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2010-05-08 17:28:41 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-10-20 23:04:41 -0400
commit959f3bdadfefb59e27c53c2e9ab13192119b0e3c (patch)
tree576e7dfcfc0af4808a6ca55f30b1a4a632c5e3d0 /drivers/media/video/ov7670.c
parentd7709ffff4117f7c7700755accfe9d5e429efc53 (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.c94
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 */
577static struct ov7670_format_struct { 578static 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
762static 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
752static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, 772static 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
797static int ov7670_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) 815static 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
821static 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 */
805static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) 846static 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
894static 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};