diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2008-10-27 03:43:49 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-29 14:53:29 -0500 |
commit | 2e0903b00131e751ac91720162d62415613e9bc5 (patch) | |
tree | d80e5f3fbc55060dec793ee26b047ff342de6248 | |
parent | 42ec3135b1715f44ef3c2b10fb06d5a5d5c836d1 (diff) |
V4L/DVB (9552): gspca: Simplify the ISOC packet scanning in tv8532.
This patch
- makes unuseful the temporary buffers
- and also fixes the bad colors problem.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/gspca/tv8532.c | 122 |
1 files changed, 25 insertions, 97 deletions
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index f6a4733d0262..3eac1cb88520 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c | |||
@@ -30,10 +30,6 @@ MODULE_LICENSE("GPL"); | |||
30 | struct sd { | 30 | struct 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 | __u32 buflen; /* current length of tmpbuf */ | ||
34 | __u8 tmpbuf[352 * 288 + 10 * 288]; /* no protection... */ | ||
35 | __u8 tmpbuf2[352 * 288]; /* no protection... */ | ||
36 | |||
37 | __u16 brightness; | 33 | __u16 brightness; |
38 | __u16 contrast; | 34 | __u16 contrast; |
39 | 35 | ||
@@ -391,6 +387,8 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
391 | /* -- start the camera -- */ | 387 | /* -- start the camera -- */ |
392 | static int sd_start(struct gspca_dev *gspca_dev) | 388 | static int sd_start(struct gspca_dev *gspca_dev) |
393 | { | 389 | { |
390 | struct sd *sd = (struct sd *) gspca_dev; | ||
391 | |||
394 | reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32); | 392 | reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32); |
395 | reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00); | 393 | reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00); |
396 | tv_8532ReadRegisters(gspca_dev); | 394 | tv_8532ReadRegisters(gspca_dev); |
@@ -444,6 +442,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
444 | reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */ | 442 | reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */ |
445 | 443 | ||
446 | gspca_dev->empty_packet = 0; /* check the empty packets */ | 444 | gspca_dev->empty_packet = 0; /* check the empty packets */ |
445 | sd->packet = 0; /* ignore the first packets */ | ||
447 | 446 | ||
448 | return 0; | 447 | return 0; |
449 | } | 448 | } |
@@ -453,107 +452,36 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
453 | reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b); | 452 | reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b); |
454 | } | 453 | } |
455 | 454 | ||
456 | static void tv8532_preprocess(struct gspca_dev *gspca_dev) | ||
457 | { | ||
458 | struct sd *sd = (struct sd *) gspca_dev; | ||
459 | /* we should received a whole frame with header and EOL marker | ||
460 | * in sd->tmpbuf and return a GBRG pattern in sd->tmpbuf2 | ||
461 | * sequence 2bytes header the Alternate pixels bayer GB 4 bytes | ||
462 | * Alternate pixels bayer RG 4 bytes EOL */ | ||
463 | int width = gspca_dev->width; | ||
464 | int height = gspca_dev->height; | ||
465 | unsigned char *dst = sd->tmpbuf2; | ||
466 | unsigned char *data = sd->tmpbuf; | ||
467 | int i; | ||
468 | |||
469 | /* precompute where is the good bayer line */ | ||
470 | if (((data[3] + data[width + 7]) >> 1) | ||
471 | + (data[4] >> 2) | ||
472 | + (data[width + 6] >> 1) >= ((data[2] + data[width + 6]) >> 1) | ||
473 | + (data[3] >> 2) | ||
474 | + (data[width + 5] >> 1)) | ||
475 | data += 3; | ||
476 | else | ||
477 | data += 2; | ||
478 | for (i = 0; i < height / 2; i++) { | ||
479 | memcpy(dst, data, width); | ||
480 | data += width + 3; | ||
481 | dst += width; | ||
482 | memcpy(dst, data, width); | ||
483 | data += width + 7; | ||
484 | dst += width; | ||
485 | } | ||
486 | } | ||
487 | |||
488 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 455 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
489 | struct gspca_frame *frame, /* target */ | 456 | struct gspca_frame *frame, /* target */ |
490 | __u8 *data, /* isoc packet */ | 457 | __u8 *data, /* isoc packet */ |
491 | int len) /* iso packet length */ | 458 | int len) /* iso packet length */ |
492 | { | 459 | { |
493 | struct sd *sd = (struct sd *) gspca_dev; | 460 | struct sd *sd = (struct sd *) gspca_dev; |
461 | int packet_type0, packet_type1; | ||
494 | 462 | ||
495 | if (data[0] != 0x80) { | 463 | packet_type0 = packet_type1 = INTER_PACKET; |
496 | sd->packet++; | ||
497 | if (sd->buflen + len > sizeof sd->tmpbuf) { | ||
498 | if (gspca_dev->last_packet_type != DISCARD_PACKET) { | ||
499 | PDEBUG(D_PACK, "buffer overflow"); | ||
500 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
501 | } | ||
502 | return; | ||
503 | } | ||
504 | memcpy(&sd->tmpbuf[sd->buflen], data, len); | ||
505 | sd->buflen += len; | ||
506 | return; | ||
507 | } | ||
508 | |||
509 | /* here we detect 0x80 */ | ||
510 | /* counter is limited so we need few header for a frame :) */ | ||
511 | |||
512 | /* header 0x80 0x80 0x80 0x80 0x80 */ | ||
513 | /* packet 00 63 127 145 00 */ | ||
514 | /* empty 1 0 0 1 1 */ | ||
515 | |||
516 | /* update sequence */ | ||
517 | if (sd->packet == 63 || sd->packet == 127) | ||
518 | gspca_dev->empty_packet = 0; | ||
519 | |||
520 | /* is there a frame start ? */ | ||
521 | /* (each packet is 2 lines plus 10 bytes) */ | ||
522 | if (sd->packet >= (gspca_dev->height >> 1) - 1) { | ||
523 | PDEBUG(D_PACK, "empty %d packet %d", | ||
524 | gspca_dev->empty_packet, sd->packet); | ||
525 | if (gspca_dev->empty_packet) { /* start of frame */ | ||
526 | if (gspca_dev->last_packet_type == FIRST_PACKET) { | ||
527 | tv8532_preprocess(gspca_dev); | ||
528 | frame = gspca_frame_add(gspca_dev, | ||
529 | LAST_PACKET, | ||
530 | frame, sd->tmpbuf2, | ||
531 | gspca_dev->height * | ||
532 | gspca_dev->width); | ||
533 | } | ||
534 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
535 | frame, data, 0); | ||
536 | memcpy(sd->tmpbuf, data, len); | ||
537 | sd->buflen = len; | ||
538 | sd->packet = 0; | ||
539 | return; | ||
540 | } | ||
541 | if (gspca_dev->last_packet_type != DISCARD_PACKET) { | ||
542 | PDEBUG(D_PACK, | ||
543 | "Warning wrong TV8532 frame detection %d", | ||
544 | sd->packet); | ||
545 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
546 | } | ||
547 | return; | ||
548 | } | ||
549 | |||
550 | if (gspca_dev->empty_packet) { | 464 | if (gspca_dev->empty_packet) { |
551 | /* Drop packet frame corrupt */ | 465 | gspca_dev->empty_packet = 0; |
552 | PDEBUG(D_PACK, "DROP empty %d packet %d", | 466 | sd->packet = gspca_dev->height / 2; |
553 | gspca_dev->empty_packet, sd->packet); | 467 | packet_type0 = FIRST_PACKET; |
554 | sd->packet = 0; | 468 | } else if (sd->packet == 0) |
555 | gspca_dev->last_packet_type = DISCARD_PACKET; | 469 | return; /* 2 more lines in 352x288 ! */ |
556 | } | 470 | sd->packet--; |
471 | if (sd->packet == 0) | ||
472 | packet_type1 = LAST_PACKET; | ||
473 | |||
474 | /* each packet contains: | ||
475 | * - header 2 bytes | ||
476 | * - RG line | ||
477 | * - 4 bytes | ||
478 | * - GB line | ||
479 | * - 4 bytes | ||
480 | */ | ||
481 | gspca_frame_add(gspca_dev, packet_type0, | ||
482 | frame, data + 2, gspca_dev->width); | ||
483 | gspca_frame_add(gspca_dev, packet_type1, | ||
484 | frame, data + gspca_dev->width + 6, gspca_dev->width); | ||
557 | } | 485 | } |
558 | 486 | ||
559 | static void setcontrast(struct gspca_dev *gspca_dev) | 487 | static void setcontrast(struct gspca_dev *gspca_dev) |