diff options
author | Jonathan Corbet <corbet@lwn.net> | 2006-12-01 13:50:59 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-12-10 06:05:31 -0500 |
commit | c8f5b2f5607e78c61df229259c539a5d9488a013 (patch) | |
tree | 918f87bf2f2a85e020bac3f45297a1f4c05a6208 /drivers/media/video/ov7670.c | |
parent | a66d23368068d6027feedc010304d510e6d1fe56 (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>
Diffstat (limited to 'drivers/media/video/ov7670.c')
-rw-r--r-- | drivers/media/video/ov7670.c | 72 |
1 files changed, 67 insertions, 5 deletions
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 | */ | ||
733 | static 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 | |||
753 | static 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 | } |