diff options
author | Jonathan Corbet <corbet@lwn.net> | 2009-12-20 09:39:47 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-17 23:51:20 -0400 |
commit | d8d201552f518370d0a64cb758684f667fdd2012 (patch) | |
tree | e7d0704f71df4fe55acef6aa201eda9536132305 /drivers/media/video/ov7670.c | |
parent | 97693f9178ba83068f6b4e419a47ffd3d1a20897 (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.c | 45 |
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 | ||
203 | static inline struct ov7670_info *to_state(struct v4l2_subdev *sd) | 204 | static 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) | |||
791 | static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) | 788 | static 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 | } |