summaryrefslogtreecommitdiff
path: root/drivers/media/video/gspca/m5602/m5602_ov9650.c
diff options
context:
space:
mode:
authorErik Andr?n <erik.andren@gmail.com>2009-01-03 16:55:52 +0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-04-07 04:44:44 +0400
commitbd99ffbd2aa51bca79a34aed0bc5b54ecd2b6751 (patch)
tree339cef2b69831ea4499402b0f383b784b4792b9b /drivers/media/video/gspca/m5602/m5602_ov9650.c
parent6b0555008e03209b1590054960b4a3506301071c (diff)
downloadlinux-bd99ffbd2aa51bca79a34aed0bc5b54ecd2b6751.tar.xz
V4L/DVB (11421): gspca - m5602-ov9650: Synthesize modesetting.
Previously all resolution setting was done with precalculated tables. When the image is vflipped we need to adjust the alignment which would require another table. Now we can adjust the parameters on the fly instead. Signed-off-by: Erik Andr?n <erik.andren@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/m5602/m5602_ov9650.c')
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.c118
1 files changed, 72 insertions, 46 deletions
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c
index 292f2d41fba5..15288a114fe2 100644
--- a/drivers/media/video/gspca/m5602/m5602_ov9650.c
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c
@@ -180,7 +180,7 @@ static struct v4l2_pix_format ov9650_modes[] = {
176 * 144,
.bytesperline = 176,
.colorspace = V4L2_COLORSPACE_SRGB,
- .priv = 0
+ .priv = 9
}, {
320,
240,
@@ -190,7 +190,7 @@ static struct v4l2_pix_format ov9650_modes[] = {
320 * 240,
.bytesperline = 320,
.colorspace = V4L2_COLORSPACE_SRGB,
- .priv = 0
+ .priv = 8
}, {
352,
288,
@@ -200,7 +200,7 @@ static struct v4l2_pix_format ov9650_modes[] = {
352 * 288,
.bytesperline = 352,
.colorspace = V4L2_COLORSPACE_SRGB,
- .priv = 0
+ .priv = 9
}, {
640,
480,
@@ -210,7 +210,7 @@ static struct v4l2_pix_format ov9650_modes[] = {
640 * 480,
.bytesperline = 640,
.colorspace = V4L2_COLORSPACE_SRGB,
- .priv = 0
+ .priv = 9
}
};
@@ -295,13 +295,22 @@ int ov9650_init(struct sd *sd)
int ov9650_start(struct sd *sd)
{
+ u8 data;
int i, err = 0;
struct cam *cam = &sd->gspca_dev.cam;
+ int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
+ int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
+ int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
+ int hor_offs = OV9650_LEFT_OFFSET;
+
+ if (width <= 320)
+ hor_offs /= 2;
err = ov9650_init(sd);
if (err < 0)
return err;
+ /* Synthesize the vsync/hsync setup */
for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
if (res_init_ov9650[i][0] == BRIDGE)
err = m5602_write_bridge(sd, res_init_ov9650[i][1],
@@ -315,70 +324,87 @@ int ov9650_start(struct sd *sd)
if (err < 0)
return err;
- switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, ((ver_offs >> 8) & 0xff));
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < 2 && !err; i++) {
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
+ }
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (hor_offs >> 8) & 0xff);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, ((width + hor_offs) >> 8) & 0xff);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, ((width + hor_offs) & 0xff));
+ if (err < 0)
+ return err;
+
+ switch (width) {
case 640:
PDEBUG(D_V4L2, "Configuring camera for VGA mode");
- for (i = 0; i < ARRAY_SIZE(VGA_ov9650) && !err; i++) {
- if (VGA_ov9650[i][0] == SENSOR) {
- u8 data = VGA_ov9650[i][2];
+ data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
+ OV9650_RAW_RGB_SELECT;
+
+ err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
- err = m5602_write_sensor(sd,
- VGA_ov9650[i][1], &data, 1);
- } else {
- err = m5602_write_bridge(sd, VGA_ov9650[i][1],
- VGA_ov9650[i][2]);
- }
- }
break;
case 352:
PDEBUG(D_V4L2, "Configuring camera for CIF mode");
- for (i = 0; i < ARRAY_SIZE(CIF_ov9650) && !err; i++) {
- if (CIF_ov9650[i][0] == SENSOR) {
- u8 data = CIF_ov9650[i][2];
+ data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
+ OV9650_RAW_RGB_SELECT;
+
+ err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
- err = m5602_write_sensor(sd,
- CIF_ov9650[i][1], &data, 1);
- } else {
- err = m5602_write_bridge(sd, CIF_ov9650[i][1],
- CIF_ov9650[i][2]);
- }
- }
break;
case 320:
PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
- for (i = 0; i < ARRAY_SIZE(QVGA_ov9650) && !err; i++) {
- if (QVGA_ov9650[i][0] == SENSOR) {
- u8 data = QVGA_ov9650[i][2];
+ data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
+ OV9650_RAW_RGB_SELECT;
+
+ err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
- err = m5602_write_sensor(sd,
- QVGA_ov9650[i][1], &data, 1);
- } else {
- err = m5602_write_bridge(sd, QVGA_ov9650[i][1],
- QVGA_ov9650[i][2]);
- }
- }
break;
case 176:
PDEBUG(D_V4L2, "Configuring camera for QCIF mode");
- for (i = 0; i < ARRAY_SIZE(QCIF_ov9650) && !err; i++) {
- if (QCIF_ov9650[i][0] == SENSOR) {
- u8 data = QCIF_ov9650[i][2];
- err = m5602_write_sensor(sd,
- QCIF_ov9650[i][1], &data, 1);
- } else {
- err = m5602_write_bridge(sd, QCIF_ov9650[i][1],
- QCIF_ov9650[i][2]);
- }
- }
- break;
+ data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
+ OV9650_RAW_RGB_SELECT;
+ err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
+ break;
}
return err;
}