Commit d8d20155 authored by Jonathan Corbet's avatar Jonathan Corbet Committed by Mauro Carvalho Chehab

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: default avatarJonathan Corbet <corbet@lwn.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 97693f91
...@@ -198,6 +198,7 @@ struct ov7670_info { ...@@ -198,6 +198,7 @@ struct ov7670_info {
struct ov7670_format_struct *fmt; /* Current format */ struct ov7670_format_struct *fmt; /* Current format */
unsigned char sat; /* Saturation value */ unsigned char sat; /* Saturation value */
int hue; /* Hue value */ int hue; /* Hue value */
u8 clkrc; /* Clock divider value */
}; };
static inline struct ov7670_info *to_state(struct v4l2_subdev *sd) static inline struct ov7670_info *to_state(struct v4l2_subdev *sd)
...@@ -744,21 +745,11 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) ...@@ -744,21 +745,11 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
struct ov7670_format_struct *ovfmt; struct ov7670_format_struct *ovfmt;
struct ov7670_win_size *wsize; struct ov7670_win_size *wsize;
struct ov7670_info *info = to_state(sd); struct ov7670_info *info = to_state(sd);
unsigned char com7, clkrc = 0; unsigned char com7;
ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize); ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize);
if (ret) if (ret)
return ret; return ret;
/*
* HACK: if we're running rgb565 we need to grab then rewrite
* CLKRC. If we're *not*, however, then rewriting clkrc hoses
* the colors.
*/
if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
ret = ov7670_read(sd, REG_CLKRC, &clkrc);
if (ret)
return ret;
}
/* /*
* COM7 is a pain in the ass, it doesn't like to be read then * COM7 is a pain in the ass, it doesn't like to be read then
* quickly written afterward. But we have everything we need * quickly written afterward. But we have everything we need
...@@ -779,8 +770,14 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) ...@@ -779,8 +770,14 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
ret = ov7670_write_array(sd, wsize->regs); ret = ov7670_write_array(sd, wsize->regs);
info->fmt = ovfmt; info->fmt = ovfmt;
/*
* If we're running RGB565, we must rewrite clkrc after setting
* the other parameters or the image looks poor. If we're *not*
* doing RGB565, we must not rewrite clkrc or the image looks
* *really* poor.
*/
if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0) if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0)
ret = ov7670_write(sd, REG_CLKRC, clkrc); ret = ov7670_write(sd, REG_CLKRC, info->clkrc);
return ret; return ret;
} }
...@@ -791,20 +788,17 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) ...@@ -791,20 +788,17 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
{ {
struct v4l2_captureparm *cp = &parms->parm.capture; struct v4l2_captureparm *cp = &parms->parm.capture;
unsigned char clkrc; struct ov7670_info *info = to_state(sd);
int ret;
if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
ret = ov7670_read(sd, REG_CLKRC, &clkrc);
if (ret < 0)
return ret;
memset(cp, 0, sizeof(struct v4l2_captureparm)); memset(cp, 0, sizeof(struct v4l2_captureparm));
cp->capability = V4L2_CAP_TIMEPERFRAME; cp->capability = V4L2_CAP_TIMEPERFRAME;
cp->timeperframe.numerator = 1; cp->timeperframe.numerator = 1;
cp->timeperframe.denominator = OV7670_FRAME_RATE; cp->timeperframe.denominator = OV7670_FRAME_RATE;
if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1) if ((info->clkrc & CLK_EXT) == 0 && (info->clkrc & CLK_SCALE) > 1)
cp->timeperframe.denominator /= (clkrc & CLK_SCALE); cp->timeperframe.denominator /= (info->clkrc & CLK_SCALE);
return 0; return 0;
} }
...@@ -812,6 +806,7 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ...@@ -812,6 +806,7 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
{ {
struct v4l2_captureparm *cp = &parms->parm.capture; struct v4l2_captureparm *cp = &parms->parm.capture;
struct v4l2_fract *tpf = &cp->timeperframe; struct v4l2_fract *tpf = &cp->timeperframe;
struct ov7670_info *info = to_state(sd);
unsigned char clkrc; unsigned char clkrc;
int ret, div; int ret, div;
...@@ -819,12 +814,7 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ...@@ -819,12 +814,7 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
return -EINVAL; return -EINVAL;
if (cp->extendedmode != 0) if (cp->extendedmode != 0)
return -EINVAL; return -EINVAL;
/*
* CLKRC has a reserved bit, so let's preserve it.
*/
ret = ov7670_read(sd, REG_CLKRC, &clkrc);
if (ret < 0)
return ret;
if (tpf->numerator == 0 || tpf->denominator == 0) if (tpf->numerator == 0 || tpf->denominator == 0)
div = 1; /* Reset to full rate */ div = 1; /* Reset to full rate */
else else
...@@ -833,10 +823,10 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ...@@ -833,10 +823,10 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
div = 1; div = 1;
else if (div > CLK_SCALE) else if (div > CLK_SCALE)
div = CLK_SCALE; div = CLK_SCALE;
clkrc = (clkrc & 0x80) | div; info->clkrc = (info->clkrc & 0x80) | div;
tpf->numerator = 1; tpf->numerator = 1;
tpf->denominator = OV7670_FRAME_RATE/div; tpf->denominator = OV7670_FRAME_RATE/div;
return ov7670_write(sd, REG_CLKRC, clkrc); return ov7670_write(sd, REG_CLKRC, info->clkrc);
} }
...@@ -1268,6 +1258,7 @@ static int ov7670_probe(struct i2c_client *client, ...@@ -1268,6 +1258,7 @@ static int ov7670_probe(struct i2c_client *client,
info->fmt = &ov7670_formats[0]; info->fmt = &ov7670_formats[0];
info->sat = 128; /* Review this */ info->sat = 128; /* Review this */
info->clkrc = 1; /* 30fps */
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment