aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ov7670.c
diff options
context:
space:
mode:
authorJonathan Corbet <corbet@lwn.net>2009-12-20 09:39:47 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-17 23:51:20 -0400
commitd8d201552f518370d0a64cb758684f667fdd2012 (patch)
treee7d0704f71df4fe55acef6aa201eda9536132305 /drivers/media/video/ov7670.c
parent97693f9178ba83068f6b4e419a47ffd3d1a20897 (diff)
V4L/DVB: ov7670: Avoid reading clkrc
Reading the clkrc register creates flaky behavior in some situations, and we can easily track its state separately. Signed-off-by: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/ov7670.c')
-rw-r--r--drivers/media/video/ov7670.c45
1 files changed, 18 insertions, 27 deletions
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index b44762adb1e9..b2e6f8e730a3 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -198,6 +198,7 @@ struct ov7670_info {
198 struct ov7670_format_struct *fmt; /* Current format */ 198 struct ov7670_format_struct *fmt; /* Current format */
199 unsigned char sat; /* Saturation value */ 199 unsigned char sat; /* Saturation value */
200 int hue; /* Hue value */ 200 int hue; /* Hue value */
201 u8 clkrc; /* Clock divider value */
201}; 202};
202 203
203static inline struct ov7670_info *to_state(struct v4l2_subdev *sd) 204static inline struct ov7670_info *to_state(struct v4l2_subdev *sd)
@@ -744,22 +745,12 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
744 struct ov7670_format_struct *ovfmt; 745 struct ov7670_format_struct *ovfmt;
745 struct ov7670_win_size *wsize; 746 struct ov7670_win_size *wsize;
746 struct ov7670_info *info = to_state(sd); 747 struct ov7670_info *info = to_state(sd);
747 unsigned char com7, clkrc = 0; 748 unsigned char com7;
748 749
749 ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize); 750 ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize);
750 if (ret) 751 if (ret)
751 return ret; 752 return ret;
752 /* 753 /*
753 * HACK: if we're running rgb565 we need to grab then rewrite
754 * CLKRC. If we're *not*, however, then rewriting clkrc hoses
755 * the colors.
756 */
757 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
758 ret = ov7670_read(sd, REG_CLKRC, &clkrc);
759 if (ret)
760 return ret;
761 }
762 /*
763 * COM7 is a pain in the ass, it doesn't like to be read then 754 * COM7 is a pain in the ass, it doesn't like to be read then
764 * quickly written afterward. But we have everything we need 755 * quickly written afterward. But we have everything we need
765 * to set it absolutely here, as long as the format-specific 756 * to set it absolutely here, as long as the format-specific
@@ -779,8 +770,14 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
779 ret = ov7670_write_array(sd, wsize->regs); 770 ret = ov7670_write_array(sd, wsize->regs);
780 info->fmt = ovfmt; 771 info->fmt = ovfmt;
781 772
773 /*
774 * If we're running RGB565, we must rewrite clkrc after setting
775 * the other parameters or the image looks poor. If we're *not*
776 * doing RGB565, we must not rewrite clkrc or the image looks
777 * *really* poor.
778 */
782 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0) 779 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0)
783 ret = ov7670_write(sd, REG_CLKRC, clkrc); 780 ret = ov7670_write(sd, REG_CLKRC, info->clkrc);
784 return ret; 781 return ret;
785} 782}
786 783
@@ -791,20 +788,17 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
791static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) 788static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
792{ 789{
793 struct v4l2_captureparm *cp = &parms->parm.capture; 790 struct v4l2_captureparm *cp = &parms->parm.capture;
794 unsigned char clkrc; 791 struct ov7670_info *info = to_state(sd);
795 int ret;
796 792
797 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 793 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
798 return -EINVAL; 794 return -EINVAL;
799 ret = ov7670_read(sd, REG_CLKRC, &clkrc); 795
800 if (ret < 0)
801 return ret;
802 memset(cp, 0, sizeof(struct v4l2_captureparm)); 796 memset(cp, 0, sizeof(struct v4l2_captureparm));
803 cp->capability = V4L2_CAP_TIMEPERFRAME; 797 cp->capability = V4L2_CAP_TIMEPERFRAME;
804 cp->timeperframe.numerator = 1; 798 cp->timeperframe.numerator = 1;
805 cp->timeperframe.denominator = OV7670_FRAME_RATE; 799 cp->timeperframe.denominator = OV7670_FRAME_RATE;
806 if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1) 800 if ((info->clkrc & CLK_EXT) == 0 && (info->clkrc & CLK_SCALE) > 1)
807 cp->timeperframe.denominator /= (clkrc & CLK_SCALE); 801 cp->timeperframe.denominator /= (info->clkrc & CLK_SCALE);
808 return 0; 802 return 0;
809} 803}
810 804
@@ -812,6 +806,7 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
812{ 806{
813 struct v4l2_captureparm *cp = &parms->parm.capture; 807 struct v4l2_captureparm *cp = &parms->parm.capture;
814 struct v4l2_fract *tpf = &cp->timeperframe; 808 struct v4l2_fract *tpf = &cp->timeperframe;
809 struct ov7670_info *info = to_state(sd);
815 unsigned char clkrc; 810 unsigned char clkrc;
816 int ret, div; 811 int ret, div;
817 812
@@ -819,12 +814,7 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
819 return -EINVAL; 814 return -EINVAL;
820 if (cp->extendedmode != 0) 815 if (cp->extendedmode != 0)
821 return -EINVAL; 816 return -EINVAL;
822 /* 817
823 * CLKRC has a reserved bit, so let's preserve it.
824 */
825 ret = ov7670_read(sd, REG_CLKRC, &clkrc);
826 if (ret < 0)
827 return ret;
828 if (tpf->numerator == 0 || tpf->denominator == 0) 818 if (tpf->numerator == 0 || tpf->denominator == 0)
829 div = 1; /* Reset to full rate */ 819 div = 1; /* Reset to full rate */
830 else 820 else
@@ -833,10 +823,10 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
833 div = 1; 823 div = 1;
834 else if (div > CLK_SCALE) 824 else if (div > CLK_SCALE)
835 div = CLK_SCALE; 825 div = CLK_SCALE;
836 clkrc = (clkrc & 0x80) | div; 826 info->clkrc = (info->clkrc & 0x80) | div;
837 tpf->numerator = 1; 827 tpf->numerator = 1;
838 tpf->denominator = OV7670_FRAME_RATE/div; 828 tpf->denominator = OV7670_FRAME_RATE/div;
839 return ov7670_write(sd, REG_CLKRC, clkrc); 829 return ov7670_write(sd, REG_CLKRC, info->clkrc);
840} 830}
841 831
842 832
@@ -1268,6 +1258,7 @@ static int ov7670_probe(struct i2c_client *client,
1268 1258
1269 info->fmt = &ov7670_formats[0]; 1259 info->fmt = &ov7670_formats[0];
1270 info->sat = 128; /* Review this */ 1260 info->sat = 128; /* Review this */
1261 info->clkrc = 1; /* 30fps */
1271 1262
1272 return 0; 1263 return 0;
1273} 1264}