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

V4L/DVB (4909): Add s/g_parm to cafe_ccic

Add s/g_parm support allowing applications to tweak the frame rate.
Signed-off-by: default avatarJonathan Corbet <corbet@lwn.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent a66d2336
...@@ -1671,6 +1671,37 @@ static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a) ...@@ -1671,6 +1671,37 @@ static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
return 0; return 0;
} }
/*
* G/S_PARM. Most of this is done by the sensor, but we are
* the level which controls the number of read buffers.
*/
static int cafe_vidioc_g_parm(struct file *filp, void *priv,
struct v4l2_streamparm *parms)
{
struct cafe_camera *cam = priv;
int ret;
mutex_lock(&cam->s_mutex);
ret = __cafe_cam_cmd(cam, VIDIOC_G_PARM, parms);
mutex_unlock(&cam->s_mutex);
parms->parm.capture.readbuffers = n_dma_bufs;
return ret;
}
static int cafe_vidioc_s_parm(struct file *filp, void *priv,
struct v4l2_streamparm *parms)
{
struct cafe_camera *cam = priv;
int ret;
mutex_lock(&cam->s_mutex);
ret = __cafe_cam_cmd(cam, VIDIOC_S_PARM, parms);
mutex_unlock(&cam->s_mutex);
parms->parm.capture.readbuffers = n_dma_bufs;
return ret;
}
static void cafe_v4l_dev_release(struct video_device *vd) static void cafe_v4l_dev_release(struct video_device *vd)
{ {
struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev); struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev);
...@@ -1724,7 +1755,8 @@ static struct video_device cafe_v4l_template = { ...@@ -1724,7 +1755,8 @@ static struct video_device cafe_v4l_template = {
.vidioc_queryctrl = cafe_vidioc_queryctrl, .vidioc_queryctrl = cafe_vidioc_queryctrl,
.vidioc_g_ctrl = cafe_vidioc_g_ctrl, .vidioc_g_ctrl = cafe_vidioc_g_ctrl,
.vidioc_s_ctrl = cafe_vidioc_s_ctrl, .vidioc_s_ctrl = cafe_vidioc_s_ctrl,
/* Do cropping someday */ .vidioc_g_parm = cafe_vidioc_g_parm,
.vidioc_s_parm = cafe_vidioc_s_parm,
}; };
......
...@@ -35,6 +35,11 @@ MODULE_LICENSE("GPL"); ...@@ -35,6 +35,11 @@ MODULE_LICENSE("GPL");
#define QCIF_WIDTH 176 #define QCIF_WIDTH 176
#define QCIF_HEIGHT 144 #define QCIF_HEIGHT 144
/*
* Our nominal (default) frame rate.
*/
#define OV7670_FRAME_RATE 30
/* /*
* The 7670 sits on i2c with ID 0x42 * The 7670 sits on i2c with ID 0x42
*/ */
...@@ -291,7 +296,7 @@ static struct regval_list ov7670_default_regs[] = { ...@@ -291,7 +296,7 @@ static struct regval_list ov7670_default_regs[] = {
{ 0xc9, 0x60 }, { REG_COM16, 0x38 }, { 0xc9, 0x60 }, { REG_COM16, 0x38 },
{ 0x56, 0x40 }, { 0x56, 0x40 },
{ 0x34, 0x11 }, { REG_COM11, COM11_EXP }, { 0x34, 0x11 }, { REG_COM11, COM11_EXP|COM11_HZAUTO },
{ 0xa4, 0x88 }, { 0x96, 0 }, { 0xa4, 0x88 }, { 0x96, 0 },
{ 0x97, 0x30 }, { 0x98, 0x20 }, { 0x97, 0x30 }, { 0x98, 0x20 },
{ 0x99, 0x30 }, { 0x9a, 0x84 }, { 0x99, 0x30 }, { 0x9a, 0x84 },
...@@ -721,6 +726,63 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) ...@@ -721,6 +726,63 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt)
return 0; return 0;
} }
/*
* Implement G/S_PARM. There is a "high quality" mode we could try
* to do someday; for now, we just do the frame rate tweak.
*/
static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
{
struct v4l2_captureparm *cp = &parms->parm.capture;
unsigned char clkrc;
int ret;
if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
ret = ov7670_read(c, REG_CLKRC, &clkrc);
if (ret < 0)
return ret;
memset(cp, 0, sizeof(struct v4l2_captureparm));
cp->capability = V4L2_CAP_TIMEPERFRAME;
cp->timeperframe.numerator = 1;
cp->timeperframe.denominator = OV7670_FRAME_RATE;
if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1)
cp->timeperframe.denominator /= (clkrc & CLK_SCALE);
return 0;
}
static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
{
struct v4l2_captureparm *cp = &parms->parm.capture;
struct v4l2_fract *tpf = &cp->timeperframe;
unsigned char clkrc;
int ret, div;
if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
if (cp->extendedmode != 0)
return -EINVAL;
/*
* CLKRC has a reserved bit, so let's preserve it.
*/
ret = ov7670_read(c, REG_CLKRC, &clkrc);
if (ret < 0)
return ret;
if (tpf->numerator == 0 || tpf->denominator == 0)
div = 1; /* Reset to full rate */
else
div = (tpf->numerator*OV7670_FRAME_RATE)/tpf->denominator;
if (div == 0)
div = 1;
else if (div > CLK_SCALE)
div = CLK_SCALE;
clkrc = (clkrc & 0x80) | div;
tpf->numerator = 1;
tpf->denominator = OV7670_FRAME_RATE/div;
return ov7670_write(c, REG_CLKRC, clkrc);
}
/* /*
* Code for dealing with controls. * Code for dealing with controls.
*/ */
...@@ -1231,10 +1293,10 @@ static int ov7670_command(struct i2c_client *client, unsigned int cmd, ...@@ -1231,10 +1293,10 @@ static int ov7670_command(struct i2c_client *client, unsigned int cmd,
return ov7670_s_ctrl(client, (struct v4l2_control *) arg); return ov7670_s_ctrl(client, (struct v4l2_control *) arg);
case VIDIOC_G_CTRL: case VIDIOC_G_CTRL:
return ov7670_g_ctrl(client, (struct v4l2_control *) arg); return ov7670_g_ctrl(client, (struct v4l2_control *) arg);
/* Todo: case VIDIOC_S_PARM:
g/s_parm return ov7670_s_parm(client, (struct v4l2_streamparm *) arg);
initialization case VIDIOC_G_PARM:
*/ return ov7670_g_parm(client, (struct v4l2_streamparm *) arg);
} }
return -EINVAL; return -EINVAL;
} }
......
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