Commit bd99ffbd authored by Erik Andr?n's avatar Erik Andr?n Committed by Mauro Carvalho Chehab

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: default avatarErik Andr?n <erik.andren@gmail.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 6b055500
...@@ -51,7 +51,7 @@ int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data) ...@@ -51,7 +51,7 @@ int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data)
address, *i2c_data); address, *i2c_data);
/* usb_control_msg(...) returns the number of bytes sent upon success, /* usb_control_msg(...) returns the number of bytes sent upon success,
mask that and return zero upon success instead*/ mask that and return zero instead*/
return (err < 0) ? err : 0; return (err < 0) ? err : 0;
} }
...@@ -76,7 +76,7 @@ int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data) ...@@ -76,7 +76,7 @@ int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data)
4, M5602_URB_MSG_TIMEOUT); 4, M5602_URB_MSG_TIMEOUT);
/* usb_control_msg(...) returns the number of bytes sent upon success, /* usb_control_msg(...) returns the number of bytes sent upon success,
mask that and return zero upon success instead */ mask that and return zero instead */
return (err < 0) ? err : 0; return (err < 0) ? err : 0;
} }
......
...@@ -180,7 +180,7 @@ static struct v4l2_pix_format ov9650_modes[] = { ...@@ -180,7 +180,7 @@ static struct v4l2_pix_format ov9650_modes[] = {
176 * 144, 176 * 144,
.bytesperline = 176, .bytesperline = 176,
.colorspace = V4L2_COLORSPACE_SRGB, .colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0 .priv = 9
}, { }, {
320, 320,
240, 240,
...@@ -190,7 +190,7 @@ static struct v4l2_pix_format ov9650_modes[] = { ...@@ -190,7 +190,7 @@ static struct v4l2_pix_format ov9650_modes[] = {
320 * 240, 320 * 240,
.bytesperline = 320, .bytesperline = 320,
.colorspace = V4L2_COLORSPACE_SRGB, .colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0 .priv = 8
}, { }, {
352, 352,
288, 288,
...@@ -200,7 +200,7 @@ static struct v4l2_pix_format ov9650_modes[] = { ...@@ -200,7 +200,7 @@ static struct v4l2_pix_format ov9650_modes[] = {
352 * 288, 352 * 288,
.bytesperline = 352, .bytesperline = 352,
.colorspace = V4L2_COLORSPACE_SRGB, .colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0 .priv = 9
}, { }, {
640, 640,
480, 480,
...@@ -210,7 +210,7 @@ static struct v4l2_pix_format ov9650_modes[] = { ...@@ -210,7 +210,7 @@ static struct v4l2_pix_format ov9650_modes[] = {
640 * 480, 640 * 480,
.bytesperline = 640, .bytesperline = 640,
.colorspace = V4L2_COLORSPACE_SRGB, .colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0 .priv = 9
} }
}; };
...@@ -295,13 +295,22 @@ int ov9650_init(struct sd *sd) ...@@ -295,13 +295,22 @@ int ov9650_init(struct sd *sd)
int ov9650_start(struct sd *sd) int ov9650_start(struct sd *sd)
{ {
u8 data;
int i, err = 0; int i, err = 0;
struct cam *cam = &sd->gspca_dev.cam; 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); err = ov9650_init(sd);
if (err < 0) if (err < 0)
return err; return err;
/* Synthesize the vsync/hsync setup */
for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) { for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
if (res_init_ov9650[i][0] == BRIDGE) if (res_init_ov9650[i][0] == BRIDGE)
err = m5602_write_bridge(sd, res_init_ov9650[i][1], err = m5602_write_bridge(sd, res_init_ov9650[i][1],
...@@ -315,70 +324,87 @@ int ov9650_start(struct sd *sd) ...@@ -315,70 +324,87 @@ int ov9650_start(struct sd *sd)
if (err < 0) if (err < 0)
return err; 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: case 640:
PDEBUG(D_V4L2, "Configuring camera for VGA mode"); PDEBUG(D_V4L2, "Configuring camera for VGA mode");
for (i = 0; i < ARRAY_SIZE(VGA_ov9650) && !err; i++) { data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
if (VGA_ov9650[i][0] == SENSOR) { OV9650_RAW_RGB_SELECT;
u8 data = VGA_ov9650[i][2];
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; break;
case 352: case 352:
PDEBUG(D_V4L2, "Configuring camera for CIF mode"); PDEBUG(D_V4L2, "Configuring camera for CIF mode");
for (i = 0; i < ARRAY_SIZE(CIF_ov9650) && !err; i++) { data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
if (CIF_ov9650[i][0] == SENSOR) { OV9650_RAW_RGB_SELECT;
u8 data = CIF_ov9650[i][2];
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; break;
case 320: case 320:
PDEBUG(D_V4L2, "Configuring camera for QVGA mode"); PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
for (i = 0; i < ARRAY_SIZE(QVGA_ov9650) && !err; i++) { data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
if (QVGA_ov9650[i][0] == SENSOR) { OV9650_RAW_RGB_SELECT;
u8 data = QVGA_ov9650[i][2];
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; break;
case 176: case 176:
PDEBUG(D_V4L2, "Configuring camera for QCIF mode"); PDEBUG(D_V4L2, "Configuring camera for QCIF mode");
for (i = 0; i < ARRAY_SIZE(QCIF_ov9650) && !err; i++) { data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
if (QCIF_ov9650[i][0] == SENSOR) { OV9650_RAW_RGB_SELECT;
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;
err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
break;
} }
return err; return err;
} }
......
...@@ -120,6 +120,8 @@ ...@@ -120,6 +120,8 @@
#define OV9650_SOFT_SLEEP (1 << 4) #define OV9650_SOFT_SLEEP (1 << 4)
#define OV9650_OUTPUT_DRIVE_2X (1 << 0) #define OV9650_OUTPUT_DRIVE_2X (1 << 0)
#define OV9650_LEFT_OFFSET 0x62
#define GAIN_DEFAULT 0x14 #define GAIN_DEFAULT 0x14
#define RED_GAIN_DEFAULT 0x70 #define RED_GAIN_DEFAULT 0x70
#define BLUE_GAIN_DEFAULT 0x20 #define BLUE_GAIN_DEFAULT 0x20
...@@ -335,84 +337,4 @@ static const unsigned char res_init_ov9650[][3] = ...@@ -335,84 +337,4 @@ static const unsigned char res_init_ov9650[][3] =
{BRIDGE, M5602_XB_SIG_INI, 0x01} {BRIDGE, M5602_XB_SIG_INI, 0x01}
}; };
static const unsigned char VGA_ov9650[][3] =
{
/* Moves the view window in a vertical orientation */
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x09},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
{BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, /* 480 */
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_HSYNC_PARA, 0x62}, /* 98 */
{BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, /* 640 + 98 */
{BRIDGE, M5602_XB_HSYNC_PARA, 0xe2},
{SENSOR, OV9650_COM7, OV9650_VGA_SELECT |
OV9650_RGB_SELECT |
OV9650_RAW_RGB_SELECT},
};
static const unsigned char CIF_ov9650[][3] =
{
/* Moves the view window in a vertical orientation */
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x09},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x20}, /* 288 */
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_HSYNC_PARA, 0x62}, /* 98 */
{BRIDGE, M5602_XB_HSYNC_PARA, 0x01}, /* 352 + 98 */
{BRIDGE, M5602_XB_HSYNC_PARA, 0xc2},
{SENSOR, OV9650_COM7, OV9650_CIF_SELECT |
OV9650_RGB_SELECT |
OV9650_RAW_RGB_SELECT},
};
static const unsigned char QVGA_ov9650[][3] =
{
/* Moves the view window in a vertical orientation */
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x08},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0xf0}, /* 240 */
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_HSYNC_PARA, 0x31}, /* 50 */
{BRIDGE, M5602_XB_HSYNC_PARA, 0x01}, /* 320 + 50 */
{BRIDGE, M5602_XB_HSYNC_PARA, 0x71},
{SENSOR, OV9650_COM7, OV9650_QVGA_SELECT |
OV9650_RGB_SELECT |
OV9650_RAW_RGB_SELECT},
};
static const unsigned char QCIF_ov9650[][3] =
{
/* Moves the view window in a vertical orientation */
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x09},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x90}, /* 144 */
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
{BRIDGE, M5602_XB_HSYNC_PARA, 0x31}, /* 48 */
{BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, /* 176 + 49 */
{BRIDGE, M5602_XB_HSYNC_PARA, 0xe1},
{SENSOR, OV9650_COM7, OV9650_QCIF_SELECT |
OV9650_RGB_SELECT |
OV9650_RAW_RGB_SELECT},
};
#endif #endif
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