aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Andr?n <erik.andren@gmail.com>2009-01-03 08:55:52 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-04-06 20:44:44 -0400
commitbd99ffbd2aa51bca79a34aed0bc5b54ecd2b6751 (patch)
tree339cef2b69831ea4499402b0f383b784b4792b9b
parent6b0555008e03209b1590054960b4a3506301071c (diff)
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>
-rw-r--r--drivers/media/video/gspca/m5602/m5602_core.c4
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.c118
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.h82
3 files changed, 76 insertions, 128 deletions
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c
index bae7aa6f0f80..0d84a12d59f0 100644
--- a/drivers/media/video/gspca/m5602/m5602_core.c
+++ b/drivers/media/video/gspca/m5602/m5602_core.c
@@ -51,7 +51,7 @@ int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data)
51 address, *i2c_data); 51 address, *i2c_data);
52 52
53 /* usb_control_msg(...) returns the number of bytes sent upon success, 53 /* usb_control_msg(...) returns the number of bytes sent upon success,
54 mask that and return zero upon success instead*/ 54 mask that and return zero instead*/
55 return (err < 0) ? err : 0; 55 return (err < 0) ? err : 0;
56} 56}
57 57
@@ -76,7 +76,7 @@ int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data)
76 4, M5602_URB_MSG_TIMEOUT); 76 4, M5602_URB_MSG_TIMEOUT);
77 77
78 /* usb_control_msg(...) returns the number of bytes sent upon success, 78 /* usb_control_msg(...) returns the number of bytes sent upon success,
79 mask that and return zero upon success instead */ 79 mask that and return zero instead */
80 return (err < 0) ? err : 0; 80 return (err < 0) ? err : 0;
81} 81}
82 82
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[] = {
180 176 * 144, 180 176 * 144,
181 .bytesperline = 176, 181 .bytesperline = 176,
182 .colorspace = V4L2_COLORSPACE_SRGB, 182 .colorspace = V4L2_COLORSPACE_SRGB,
183 .priv = 0 183 .priv = 9
184 }, { 184 }, {
185 320, 185 320,
186 240, 186 240,
@@ -190,7 +190,7 @@ static struct v4l2_pix_format ov9650_modes[] = {
190 320 * 240, 190 320 * 240,
191 .bytesperline = 320, 191 .bytesperline = 320,
192 .colorspace = V4L2_COLORSPACE_SRGB, 192 .colorspace = V4L2_COLORSPACE_SRGB,
193 .priv = 0 193 .priv = 8
194 }, { 194 }, {
195 352, 195 352,
196 288, 196 288,
@@ -200,7 +200,7 @@ static struct v4l2_pix_format ov9650_modes[] = {
200 352 * 288, 200 352 * 288,
201 .bytesperline = 352, 201 .bytesperline = 352,
202 .colorspace = V4L2_COLORSPACE_SRGB, 202 .colorspace = V4L2_COLORSPACE_SRGB,
203 .priv = 0 203 .priv = 9
204 }, { 204 }, {
205 640, 205 640,
206 480, 206 480,
@@ -210,7 +210,7 @@ static struct v4l2_pix_format ov9650_modes[] = {
210 640 * 480, 210 640 * 480,
211 .bytesperline = 640, 211 .bytesperline = 640,
212 .colorspace = V4L2_COLORSPACE_SRGB, 212 .colorspace = V4L2_COLORSPACE_SRGB,
213 .priv = 0 213 .priv = 9
214 } 214 }
215}; 215};
216 216
@@ -295,13 +295,22 @@ int ov9650_init(struct sd *sd)
295 295
296int ov9650_start(struct sd *sd) 296int ov9650_start(struct sd *sd)
297{ 297{
298 u8 data;
298 int i, err = 0; 299 int i, err = 0;
299 struct cam *cam = &sd->gspca_dev.cam; 300 struct cam *cam = &sd->gspca_dev.cam;
301 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
302 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
303 int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
304 int hor_offs = OV9650_LEFT_OFFSET;
305
306 if (width <= 320)
307 hor_offs /= 2;
300 308
301 err = ov9650_init(sd); 309 err = ov9650_init(sd);
302 if (err < 0) 310 if (err < 0)
303 return err; 311 return err;
304 312
313 /* Synthesize the vsync/hsync setup */
305 for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) { 314 for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
306 if (res_init_ov9650[i][0] == BRIDGE) 315 if (res_init_ov9650[i][0] == BRIDGE)
307 err = m5602_write_bridge(sd, res_init_ov9650[i][1], 316 err = m5602_write_bridge(sd, res_init_ov9650[i][1],
@@ -315,70 +324,87 @@ int ov9650_start(struct sd *sd)
315 if (err < 0) 324 if (err < 0)
316 return err; 325 return err;
317 326
318 switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) { 327 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, ((ver_offs >> 8) & 0xff));
328 if (err < 0)
329 return err;
330
331 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
332 if (err < 0)
333 return err;
334
335 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
336 if (err < 0)
337 return err;
338
339 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
340 if (err < 0)
341 return err;
342
343 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
344 if (err < 0)
345 return err;
346
347 for (i = 0; i < 2 && !err; i++) {
348 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
349 }
350 if (err < 0)
351 return err;
352
353 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (hor_offs >> 8) & 0xff);
354 if (err < 0)
355 return err;
356
357 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff);
358 if (err < 0)
359 return err;
360
361 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, ((width + hor_offs) >> 8) & 0xff);
362 if (err < 0)
363 return err;
364
365 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, ((width + hor_offs) & 0xff));
366 if (err < 0)
367 return err;
368
369 switch (width) {
319 case 640: 370 case 640:
320 PDEBUG(D_V4L2, "Configuring camera for VGA mode"); 371 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
321 372
322 for (i = 0; i < ARRAY_SIZE(VGA_ov9650) && !err; i++) { 373 data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
323 if (VGA_ov9650[i][0] == SENSOR) { 374 OV9650_RAW_RGB_SELECT;
324 u8 data = VGA_ov9650[i][2]; 375
376 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
325 377
326 err = m5602_write_sensor(sd,
327 VGA_ov9650[i][1], &data, 1);
328 } else {
329 err = m5602_write_bridge(sd, VGA_ov9650[i][1],
330 VGA_ov9650[i][2]);
331 }
332 }
333 break; 378 break;
334 379
335 case 352: 380 case 352:
336 PDEBUG(D_V4L2, "Configuring camera for CIF mode"); 381 PDEBUG(D_V4L2, "Configuring camera for CIF mode");
337 382
338 for (i = 0; i < ARRAY_SIZE(CIF_ov9650) && !err; i++) { 383 data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
339 if (CIF_ov9650[i][0] == SENSOR) { 384 OV9650_RAW_RGB_SELECT;
340 u8 data = CIF_ov9650[i][2]; 385
386 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
341 387
342 err = m5602_write_sensor(sd,
343 CIF_ov9650[i][1], &data, 1);
344 } else {
345 err = m5602_write_bridge(sd, CIF_ov9650[i][1],
346 CIF_ov9650[i][2]);
347 }
348 }
349 break; 388 break;
350 389
351 case 320: 390 case 320:
352 PDEBUG(D_V4L2, "Configuring camera for QVGA mode"); 391 PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
353 392
354 for (i = 0; i < ARRAY_SIZE(QVGA_ov9650) && !err; i++) { 393 data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
355 if (QVGA_ov9650[i][0] == SENSOR) { 394 OV9650_RAW_RGB_SELECT;
356 u8 data = QVGA_ov9650[i][2]; 395
396 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
357 397
358 err = m5602_write_sensor(sd,
359 QVGA_ov9650[i][1], &data, 1);
360 } else {
361 err = m5602_write_bridge(sd, QVGA_ov9650[i][1],
362 QVGA_ov9650[i][2]);
363 }
364 }
365 break; 398 break;
366 399
367 case 176: 400 case 176:
368 PDEBUG(D_V4L2, "Configuring camera for QCIF mode"); 401 PDEBUG(D_V4L2, "Configuring camera for QCIF mode");
369 402
370 for (i = 0; i < ARRAY_SIZE(QCIF_ov9650) && !err; i++) { 403 data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
371 if (QCIF_ov9650[i][0] == SENSOR) { 404 OV9650_RAW_RGB_SELECT;
372 u8 data = QCIF_ov9650[i][2];
373 err = m5602_write_sensor(sd,
374 QCIF_ov9650[i][1], &data, 1);
375 } else {
376 err = m5602_write_bridge(sd, QCIF_ov9650[i][1],
377 QCIF_ov9650[i][2]);
378 }
379 }
380 break;
381 405
406 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
407 break;
382 } 408 }
383 return err; 409 return err;
384} 410}
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h
index ca0e42ee05ce..cc39d76e5221 100644
--- a/drivers/media/video/gspca/m5602/m5602_ov9650.h
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.h
@@ -120,6 +120,8 @@
120#define OV9650_SOFT_SLEEP (1 << 4) 120#define OV9650_SOFT_SLEEP (1 << 4)
121#define OV9650_OUTPUT_DRIVE_2X (1 << 0) 121#define OV9650_OUTPUT_DRIVE_2X (1 << 0)
122 122
123#define OV9650_LEFT_OFFSET 0x62
124
123#define GAIN_DEFAULT 0x14 125#define GAIN_DEFAULT 0x14
124#define RED_GAIN_DEFAULT 0x70 126#define RED_GAIN_DEFAULT 0x70
125#define BLUE_GAIN_DEFAULT 0x20 127#define BLUE_GAIN_DEFAULT 0x20
@@ -335,84 +337,4 @@ static const unsigned char res_init_ov9650[][3] =
335 {BRIDGE, M5602_XB_SIG_INI, 0x01} 337 {BRIDGE, M5602_XB_SIG_INI, 0x01}
336}; 338};
337 339
338static const unsigned char VGA_ov9650[][3] =
339{
340 /* Moves the view window in a vertical orientation */
341 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
342 {BRIDGE, M5602_XB_VSYNC_PARA, 0x09},
343 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
344 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
345 {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, /* 480 */
346 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
347 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
348 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
349 {BRIDGE, M5602_XB_HSYNC_PARA, 0x62}, /* 98 */
350 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, /* 640 + 98 */
351 {BRIDGE, M5602_XB_HSYNC_PARA, 0xe2},
352
353 {SENSOR, OV9650_COM7, OV9650_VGA_SELECT |
354 OV9650_RGB_SELECT |
355 OV9650_RAW_RGB_SELECT},
356};
357
358static const unsigned char CIF_ov9650[][3] =
359{
360 /* Moves the view window in a vertical orientation */
361 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
362 {BRIDGE, M5602_XB_VSYNC_PARA, 0x09},
363 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
364 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
365 {BRIDGE, M5602_XB_VSYNC_PARA, 0x20}, /* 288 */
366 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
367 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
368 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
369 {BRIDGE, M5602_XB_HSYNC_PARA, 0x62}, /* 98 */
370 {BRIDGE, M5602_XB_HSYNC_PARA, 0x01}, /* 352 + 98 */
371 {BRIDGE, M5602_XB_HSYNC_PARA, 0xc2},
372
373 {SENSOR, OV9650_COM7, OV9650_CIF_SELECT |
374 OV9650_RGB_SELECT |
375 OV9650_RAW_RGB_SELECT},
376};
377
378static const unsigned char QVGA_ov9650[][3] =
379{
380 /* Moves the view window in a vertical orientation */
381 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
382 {BRIDGE, M5602_XB_VSYNC_PARA, 0x08},
383 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
384 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
385 {BRIDGE, M5602_XB_VSYNC_PARA, 0xf0}, /* 240 */
386 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
387 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
388 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
389 {BRIDGE, M5602_XB_HSYNC_PARA, 0x31}, /* 50 */
390 {BRIDGE, M5602_XB_HSYNC_PARA, 0x01}, /* 320 + 50 */
391 {BRIDGE, M5602_XB_HSYNC_PARA, 0x71},
392
393 {SENSOR, OV9650_COM7, OV9650_QVGA_SELECT |
394 OV9650_RGB_SELECT |
395 OV9650_RAW_RGB_SELECT},
396};
397
398static const unsigned char QCIF_ov9650[][3] =
399{
400 /* Moves the view window in a vertical orientation */
401 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
402 {BRIDGE, M5602_XB_VSYNC_PARA, 0x09},
403 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
404 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
405 {BRIDGE, M5602_XB_VSYNC_PARA, 0x90}, /* 144 */
406 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
407 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
408 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
409 {BRIDGE, M5602_XB_HSYNC_PARA, 0x31}, /* 48 */
410 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, /* 176 + 49 */
411 {BRIDGE, M5602_XB_HSYNC_PARA, 0xe1},
412
413 {SENSOR, OV9650_COM7, OV9650_QCIF_SELECT |
414 OV9650_RGB_SELECT |
415 OV9650_RAW_RGB_SELECT},
416};
417
418#endif 340#endif