aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Corbet <corbet@lwn.net>2006-12-01 13:50:59 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-12-10 06:05:31 -0500
commitc8f5b2f5607e78c61df229259c539a5d9488a013 (patch)
tree918f87bf2f2a85e020bac3f45297a1f4c05a6208
parenta66d23368068d6027feedc010304d510e6d1fe56 (diff)
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: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/video/cafe_ccic.c34
-rw-r--r--drivers/media/video/ov7670.c72
2 files changed, 100 insertions, 6 deletions
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index 9d9844e22951..e347c7ebc984 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -1671,6 +1671,37 @@ static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
1671 return 0; 1671 return 0;
1672} 1672}
1673 1673
1674/*
1675 * G/S_PARM. Most of this is done by the sensor, but we are
1676 * the level which controls the number of read buffers.
1677 */
1678static int cafe_vidioc_g_parm(struct file *filp, void *priv,
1679 struct v4l2_streamparm *parms)
1680{
1681 struct cafe_camera *cam = priv;
1682 int ret;
1683
1684 mutex_lock(&cam->s_mutex);
1685 ret = __cafe_cam_cmd(cam, VIDIOC_G_PARM, parms);
1686 mutex_unlock(&cam->s_mutex);
1687 parms->parm.capture.readbuffers = n_dma_bufs;
1688 return ret;
1689}
1690
1691static int cafe_vidioc_s_parm(struct file *filp, void *priv,
1692 struct v4l2_streamparm *parms)
1693{
1694 struct cafe_camera *cam = priv;
1695 int ret;
1696
1697 mutex_lock(&cam->s_mutex);
1698 ret = __cafe_cam_cmd(cam, VIDIOC_S_PARM, parms);
1699 mutex_unlock(&cam->s_mutex);
1700 parms->parm.capture.readbuffers = n_dma_bufs;
1701 return ret;
1702}
1703
1704
1674static void cafe_v4l_dev_release(struct video_device *vd) 1705static void cafe_v4l_dev_release(struct video_device *vd)
1675{ 1706{
1676 struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev); 1707 struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev);
@@ -1724,7 +1755,8 @@ static struct video_device cafe_v4l_template = {
1724 .vidioc_queryctrl = cafe_vidioc_queryctrl, 1755 .vidioc_queryctrl = cafe_vidioc_queryctrl,
1725 .vidioc_g_ctrl = cafe_vidioc_g_ctrl, 1756 .vidioc_g_ctrl = cafe_vidioc_g_ctrl,
1726 .vidioc_s_ctrl = cafe_vidioc_s_ctrl, 1757 .vidioc_s_ctrl = cafe_vidioc_s_ctrl,
1727 /* Do cropping someday */ 1758 .vidioc_g_parm = cafe_vidioc_g_parm,
1759 .vidioc_s_parm = cafe_vidioc_s_parm,
1728}; 1760};
1729 1761
1730 1762
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index 7d380d76338a..89dd18c3c5cc 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -36,6 +36,11 @@ MODULE_LICENSE("GPL");
36#define QCIF_HEIGHT 144 36#define QCIF_HEIGHT 144
37 37
38/* 38/*
39 * Our nominal (default) frame rate.
40 */
41#define OV7670_FRAME_RATE 30
42
43/*
39 * The 7670 sits on i2c with ID 0x42 44 * The 7670 sits on i2c with ID 0x42
40 */ 45 */
41#define OV7670_I2C_ADDR 0x42 46#define OV7670_I2C_ADDR 0x42
@@ -291,7 +296,7 @@ static struct regval_list ov7670_default_regs[] = {
291 { 0xc9, 0x60 }, { REG_COM16, 0x38 }, 296 { 0xc9, 0x60 }, { REG_COM16, 0x38 },
292 { 0x56, 0x40 }, 297 { 0x56, 0x40 },
293 298
294 { 0x34, 0x11 }, { REG_COM11, COM11_EXP }, 299 { 0x34, 0x11 }, { REG_COM11, COM11_EXP|COM11_HZAUTO },
295 { 0xa4, 0x88 }, { 0x96, 0 }, 300 { 0xa4, 0x88 }, { 0x96, 0 },
296 { 0x97, 0x30 }, { 0x98, 0x20 }, 301 { 0x97, 0x30 }, { 0x98, 0x20 },
297 { 0x99, 0x30 }, { 0x9a, 0x84 }, 302 { 0x99, 0x30 }, { 0x9a, 0x84 },
@@ -722,6 +727,63 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt)
722} 727}
723 728
724/* 729/*
730 * Implement G/S_PARM. There is a "high quality" mode we could try
731 * to do someday; for now, we just do the frame rate tweak.
732 */
733static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
734{
735 struct v4l2_captureparm *cp = &parms->parm.capture;
736 unsigned char clkrc;
737 int ret;
738
739 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
740 return -EINVAL;
741 ret = ov7670_read(c, REG_CLKRC, &clkrc);
742 if (ret < 0)
743 return ret;
744 memset(cp, 0, sizeof(struct v4l2_captureparm));
745 cp->capability = V4L2_CAP_TIMEPERFRAME;
746 cp->timeperframe.numerator = 1;
747 cp->timeperframe.denominator = OV7670_FRAME_RATE;
748 if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1)
749 cp->timeperframe.denominator /= (clkrc & CLK_SCALE);
750 return 0;
751}
752
753static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
754{
755 struct v4l2_captureparm *cp = &parms->parm.capture;
756 struct v4l2_fract *tpf = &cp->timeperframe;
757 unsigned char clkrc;
758 int ret, div;
759
760 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
761 return -EINVAL;
762 if (cp->extendedmode != 0)
763 return -EINVAL;
764 /*
765 * CLKRC has a reserved bit, so let's preserve it.
766 */
767 ret = ov7670_read(c, REG_CLKRC, &clkrc);
768 if (ret < 0)
769 return ret;
770 if (tpf->numerator == 0 || tpf->denominator == 0)
771 div = 1; /* Reset to full rate */
772 else
773 div = (tpf->numerator*OV7670_FRAME_RATE)/tpf->denominator;
774 if (div == 0)
775 div = 1;
776 else if (div > CLK_SCALE)
777 div = CLK_SCALE;
778 clkrc = (clkrc & 0x80) | div;
779 tpf->numerator = 1;
780 tpf->denominator = OV7670_FRAME_RATE/div;
781 return ov7670_write(c, REG_CLKRC, clkrc);
782}
783
784
785
786/*
725 * Code for dealing with controls. 787 * Code for dealing with controls.
726 */ 788 */
727 789
@@ -1231,10 +1293,10 @@ static int ov7670_command(struct i2c_client *client, unsigned int cmd,
1231 return ov7670_s_ctrl(client, (struct v4l2_control *) arg); 1293 return ov7670_s_ctrl(client, (struct v4l2_control *) arg);
1232 case VIDIOC_G_CTRL: 1294 case VIDIOC_G_CTRL:
1233 return ov7670_g_ctrl(client, (struct v4l2_control *) arg); 1295 return ov7670_g_ctrl(client, (struct v4l2_control *) arg);
1234 /* Todo: 1296 case VIDIOC_S_PARM:
1235 g/s_parm 1297 return ov7670_s_parm(client, (struct v4l2_streamparm *) arg);
1236 initialization 1298 case VIDIOC_G_PARM:
1237 */ 1299 return ov7670_g_parm(client, (struct v4l2_streamparm *) arg);
1238 } 1300 }
1239 return -EINVAL; 1301 return -EINVAL;
1240} 1302}