aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/tv8532.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/tv8532.c')
-rw-r--r--drivers/media/video/gspca/tv8532.c142
1 files changed, 34 insertions, 108 deletions
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c
index 968a5911704f..94163cceb28a 100644
--- a/drivers/media/video/gspca/tv8532.c
+++ b/drivers/media/video/gspca/tv8532.c
@@ -30,15 +30,10 @@ MODULE_LICENSE("GPL");
30struct sd { 30struct sd {
31 struct gspca_dev gspca_dev; /* !! must be the first item */ 31 struct gspca_dev gspca_dev; /* !! must be the first item */
32 32
33 int buflen; /* current length of tmpbuf */ 33 __u16 brightness;
34 __u8 tmpbuf[352 * 288 + 10 * 288]; /* no protection... */ 34 __u16 contrast;
35 __u8 tmpbuf2[352 * 288]; /* no protection... */
36 35
37 unsigned short brightness; 36 __u8 packet;
38 unsigned short contrast;
39
40 char packet;
41 char synchro;
42}; 37};
43 38
44/* V4L2 controls supported by the driver */ 39/* V4L2 controls supported by the driver */
@@ -78,7 +73,7 @@ static struct ctrl sd_ctrls[] = {
78 }, 73 },
79}; 74};
80 75
81static struct v4l2_pix_format sif_mode[] = { 76static const struct v4l2_pix_format sif_mode[] = {
82 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 77 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
83 .bytesperline = 176, 78 .bytesperline = 176,
84 .sizeimage = 176 * 144, 79 .sizeimage = 176 * 144,
@@ -392,6 +387,8 @@ static void setbrightness(struct gspca_dev *gspca_dev)
392/* -- start the camera -- */ 387/* -- start the camera -- */
393static int sd_start(struct gspca_dev *gspca_dev) 388static int sd_start(struct gspca_dev *gspca_dev)
394{ 389{
390 struct sd *sd = (struct sd *) gspca_dev;
391
395 reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32); 392 reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32);
396 reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00); 393 reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00);
397 tv_8532ReadRegisters(gspca_dev); 394 tv_8532ReadRegisters(gspca_dev);
@@ -443,6 +440,10 @@ static int sd_start(struct gspca_dev *gspca_dev)
443 /************************************************/ 440 /************************************************/
444 tv_8532_PollReg(gspca_dev); 441 tv_8532_PollReg(gspca_dev);
445 reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */ 442 reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */
443
444 gspca_dev->empty_packet = 0; /* check the empty packets */
445 sd->packet = 0; /* ignore the first packets */
446
446 return 0; 447 return 0;
447} 448}
448 449
@@ -451,111 +452,36 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
451 reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b); 452 reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
452} 453}
453 454
454static void tv8532_preprocess(struct gspca_dev *gspca_dev)
455{
456 struct sd *sd = (struct sd *) gspca_dev;
457/* we should received a whole frame with header and EOL marker
458 * in gspca_dev->tmpbuf and return a GBRG pattern in gspca_dev->tmpbuf2
459 * sequence 2bytes header the Alternate pixels bayer GB 4 bytes
460 * Alternate pixels bayer RG 4 bytes EOL */
461 int width = gspca_dev->width;
462 int height = gspca_dev->height;
463 unsigned char *dst = sd->tmpbuf2;
464 unsigned char *data = sd->tmpbuf;
465 int i;
466
467 /* precompute where is the good bayer line */
468 if (((data[3] + data[width + 7]) >> 1)
469 + (data[4] >> 2)
470 + (data[width + 6] >> 1) >= ((data[2] + data[width + 6]) >> 1)
471 + (data[3] >> 2)
472 + (data[width + 5] >> 1))
473 data += 3;
474 else
475 data += 2;
476 for (i = 0; i < height / 2; i++) {
477 memcpy(dst, data, width);
478 data += width + 3;
479 dst += width;
480 memcpy(dst, data, width);
481 data += width + 7;
482 dst += width;
483 }
484}
485
486static void sd_pkt_scan(struct gspca_dev *gspca_dev, 455static void sd_pkt_scan(struct gspca_dev *gspca_dev,
487 struct gspca_frame *frame, /* target */ 456 struct gspca_frame *frame, /* target */
488 __u8 *data, /* isoc packet */ 457 __u8 *data, /* isoc packet */
489 int len) /* iso packet length */ 458 int len) /* iso packet length */
490{ 459{
491 struct sd *sd = (struct sd *) gspca_dev; 460 struct sd *sd = (struct sd *) gspca_dev;
492 461 int packet_type0, packet_type1;
493 if (data[0] != 0x80) { 462
494 sd->packet++; 463 packet_type0 = packet_type1 = INTER_PACKET;
495 if (sd->buflen + len > sizeof sd->tmpbuf) { 464 if (gspca_dev->empty_packet) {
496 if (gspca_dev->last_packet_type != DISCARD_PACKET) { 465 gspca_dev->empty_packet = 0;
497 PDEBUG(D_PACK, "buffer overflow"); 466 sd->packet = gspca_dev->height / 2;
498 gspca_dev->last_packet_type = DISCARD_PACKET; 467 packet_type0 = FIRST_PACKET;
499 } 468 } else if (sd->packet == 0)
500 return; 469 return; /* 2 more lines in 352x288 ! */
501 } 470 sd->packet--;
502 memcpy(&sd->tmpbuf[sd->buflen], data, len); 471 if (sd->packet == 0)
503 sd->buflen += len; 472 packet_type1 = LAST_PACKET;
504 return; 473
505 } 474 /* each packet contains:
506 475 * - header 2 bytes
507 /* here we detect 0x80 */ 476 * - RG line
508 /* counter is limited so we need few header for a frame :) */ 477 * - 4 bytes
509 478 * - GB line
510 /* header 0x80 0x80 0x80 0x80 0x80 */ 479 * - 4 bytes
511 /* packet 00 63 127 145 00 */ 480 */
512 /* sof 0 1 1 0 0 */ 481 gspca_frame_add(gspca_dev, packet_type0,
513 482 frame, data + 2, gspca_dev->width);
514 /* update sequence */ 483 gspca_frame_add(gspca_dev, packet_type1,
515 if (sd->packet == 63 || sd->packet == 127) 484 frame, data + gspca_dev->width + 6, gspca_dev->width);
516 sd->synchro = 1;
517
518 /* is there a frame start ? */
519 if (sd->packet >= (gspca_dev->height >> 1) - 1) {
520 PDEBUG(D_PACK, "SOF > %d packet %d", sd->synchro,
521 sd->packet);
522 if (!sd->synchro) { /* start of frame */
523 if (gspca_dev->last_packet_type == FIRST_PACKET) {
524 tv8532_preprocess(gspca_dev);
525 frame = gspca_frame_add(gspca_dev,
526 LAST_PACKET,
527 frame, sd->tmpbuf2,
528 gspca_dev->width *
529 gspca_dev->width);
530 }
531 gspca_frame_add(gspca_dev, FIRST_PACKET,
532 frame, data, 0);
533 memcpy(sd->tmpbuf, data, len);
534 sd->buflen = len;
535 sd->packet = 0;
536 return;
537 }
538 if (gspca_dev->last_packet_type != DISCARD_PACKET) {
539 PDEBUG(D_PACK,
540 "Warning wrong TV8532 frame detection %d",
541 sd->packet);
542 gspca_dev->last_packet_type = DISCARD_PACKET;
543 }
544 return;
545 }
546
547 if (!sd->synchro) {
548 /* Drop packet frame corrupt */
549 PDEBUG(D_PACK, "DROP SOF %d packet %d",
550 sd->synchro, sd->packet);
551 sd->packet = 0;
552 gspca_dev->last_packet_type = DISCARD_PACKET;
553 return;
554 }
555 sd->synchro = 1;
556 sd->packet++;
557 memcpy(&sd->tmpbuf[sd->buflen], data, len);
558 sd->buflen += len;
559} 485}
560 486
561static void setcontrast(struct gspca_dev *gspca_dev) 487static void setcontrast(struct gspca_dev *gspca_dev)