diff options
author | Stefan Ringel <stefan.ringel@arcor.de> | 2010-05-19 12:58:26 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-06-01 00:22:01 -0400 |
commit | 4b6ed9fd0baf34da6912bebee46c36eda0411984 (patch) | |
tree | bf0a2f1d225e5766efd3c01bdac4fd424efe9431 | |
parent | 3569417e5a2c20764158961a2f6c514d26136e5f (diff) |
V4L/DVB: tm6000: bugfix video image
bugfix: Avoid loosing frames, causing image delays on some of the image lines.
[mchehab@redhat.com: Fix compilation breakage by merging with the patch fix]
Signed-off-by: Stefan Ringel <stefan.ringel@arcor.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/staging/tm6000/tm6000-video.c | 88 |
1 files changed, 45 insertions, 43 deletions
diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c index 02b88b550a47..8acfebdb5cda 100644 --- a/drivers/staging/tm6000/tm6000-video.c +++ b/drivers/staging/tm6000/tm6000-video.c | |||
@@ -339,14 +339,23 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, | |||
339 | return rc; | 339 | return rc; |
340 | } | 340 | } |
341 | 341 | ||
342 | static int copy_streams(u8 *data, u8 *out_p, unsigned long len, | 342 | static int copy_streams(u8 *data, unsigned long len, |
343 | struct urb *urb, struct tm6000_buffer **buf) | 343 | struct urb *urb) |
344 | { | 344 | { |
345 | struct tm6000_dmaqueue *dma_q = urb->context; | 345 | struct tm6000_dmaqueue *dma_q = urb->context; |
346 | struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); | 346 | struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); |
347 | u8 *ptr=data, *endp=data+len; | 347 | u8 *ptr=data, *endp=data+len; |
348 | unsigned long header=0; | 348 | unsigned long header=0; |
349 | int rc=0; | 349 | int rc=0; |
350 | struct tm6000_buffer *buf; | ||
351 | char *outp = NULL; | ||
352 | |||
353 | get_next_buf(dma_q, &buf); | ||
354 | if (buf) | ||
355 | outp = videobuf_to_vmalloc(&buf->vb); | ||
356 | |||
357 | if (!outp) | ||
358 | return 0; | ||
350 | 359 | ||
351 | for (ptr=data; ptr<endp;) { | 360 | for (ptr=data; ptr<endp;) { |
352 | if (!dev->isoc_ctl.cmd) { | 361 | if (!dev->isoc_ctl.cmd) { |
@@ -394,14 +403,14 @@ static int copy_streams(u8 *data, u8 *out_p, unsigned long len, | |||
394 | } | 403 | } |
395 | HEADER: | 404 | HEADER: |
396 | /* Copy or continue last copy */ | 405 | /* Copy or continue last copy */ |
397 | rc=copy_packet(urb,header,&ptr,endp,out_p,buf); | 406 | rc=copy_packet(urb,header,&ptr,endp,outp,&buf); |
398 | if (rc<0) { | 407 | if (rc<0) { |
399 | buf=NULL; | 408 | buf=NULL; |
400 | printk(KERN_ERR "tm6000: buffer underrun at %ld\n", | 409 | printk(KERN_ERR "tm6000: buffer underrun at %ld\n", |
401 | jiffies); | 410 | jiffies); |
402 | return rc; | 411 | return rc; |
403 | } | 412 | } |
404 | if (!*buf) | 413 | if (!buf) |
405 | return 0; | 414 | return 0; |
406 | } | 415 | } |
407 | 416 | ||
@@ -410,31 +419,40 @@ HEADER: | |||
410 | /* | 419 | /* |
411 | * Identify the tm5600/6000 buffer header type and properly handles | 420 | * Identify the tm5600/6000 buffer header type and properly handles |
412 | */ | 421 | */ |
413 | static int copy_multiplexed(u8 *ptr, u8 *out_p, unsigned long len, | 422 | static int copy_multiplexed(u8 *ptr, unsigned long len, |
414 | struct urb *urb, struct tm6000_buffer **buf) | 423 | struct urb *urb) |
415 | { | 424 | { |
416 | struct tm6000_dmaqueue *dma_q = urb->context; | 425 | struct tm6000_dmaqueue *dma_q = urb->context; |
417 | struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); | 426 | struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); |
418 | unsigned int pos=dev->isoc_ctl.pos,cpysize; | 427 | unsigned int pos=dev->isoc_ctl.pos,cpysize; |
419 | int rc=1; | 428 | int rc=1; |
429 | struct tm6000_buffer *buf; | ||
430 | char *outp = NULL; | ||
431 | |||
432 | get_next_buf(dma_q, &buf); | ||
433 | if (buf) | ||
434 | outp = videobuf_to_vmalloc(&buf->vb); | ||
435 | |||
436 | if (!outp) | ||
437 | return 0; | ||
420 | 438 | ||
421 | while (len>0) { | 439 | while (len>0) { |
422 | cpysize=min(len,(*buf)->vb.size-pos); | 440 | cpysize=min(len,buf->vb.size-pos); |
423 | //printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos); | 441 | //printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos); |
424 | memcpy(&out_p[pos], ptr, cpysize); | 442 | memcpy(&outp[pos], ptr, cpysize); |
425 | pos+=cpysize; | 443 | pos+=cpysize; |
426 | ptr+=cpysize; | 444 | ptr+=cpysize; |
427 | len-=cpysize; | 445 | len-=cpysize; |
428 | if (pos >= (*buf)->vb.size) { | 446 | if (pos >= buf->vb.size) { |
429 | pos=0; | 447 | pos=0; |
430 | /* Announces that a new buffer were filled */ | 448 | /* Announces that a new buffer were filled */ |
431 | buffer_filled (dev, dma_q, *buf); | 449 | buffer_filled (dev, dma_q, buf); |
432 | dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n"); | 450 | dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n"); |
433 | get_next_buf (dma_q, buf); | 451 | get_next_buf (dma_q, &buf); |
434 | if (!*buf) | 452 | if (!buf) |
435 | break; | 453 | break; |
436 | out_p = videobuf_to_vmalloc(&((*buf)->vb)); | 454 | outp = videobuf_to_vmalloc(&(buf->vb)); |
437 | if (!out_p) | 455 | if (!outp) |
438 | return rc; | 456 | return rc; |
439 | pos = 0; | 457 | pos = 0; |
440 | } | 458 | } |
@@ -493,52 +511,36 @@ static inline int tm6000_isoc_copy(struct urb *urb) | |||
493 | struct tm6000_dmaqueue *dma_q = urb->context; | 511 | struct tm6000_dmaqueue *dma_q = urb->context; |
494 | struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); | 512 | struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); |
495 | struct tm6000_buffer *buf; | 513 | struct tm6000_buffer *buf; |
496 | int i, len=0, rc=1; | 514 | int i, len=0, rc=1, status; |
497 | int size; | 515 | char *p; |
498 | char *outp = NULL, *p; | ||
499 | unsigned long copied; | ||
500 | 516 | ||
501 | get_next_buf(dma_q, &buf); | 517 | if (urb->status < 0) { |
502 | if (buf) | 518 | print_err_status (dev, -1, urb->status); |
503 | outp = videobuf_to_vmalloc(&buf->vb); | ||
504 | |||
505 | if (!outp) | ||
506 | return 0; | ||
507 | |||
508 | size = buf->vb.size; | ||
509 | |||
510 | copied=0; | ||
511 | |||
512 | if (urb->status<0) { | ||
513 | print_err_status (dev,-1,urb->status); | ||
514 | return 0; | 519 | return 0; |
515 | } | 520 | } |
516 | 521 | ||
517 | for (i = 0; i < urb->number_of_packets; i++) { | 522 | for (i = 0; i < urb->number_of_packets; i++) { |
518 | int status = urb->iso_frame_desc[i].status; | 523 | status = urb->iso_frame_desc[i].status; |
519 | 524 | ||
520 | if (status<0) { | 525 | if (status<0) { |
521 | print_err_status (dev,i,status); | 526 | print_err_status (dev,i,status); |
522 | continue; | 527 | continue; |
523 | } | 528 | } |
524 | 529 | ||
525 | len=urb->iso_frame_desc[i].actual_length; | 530 | len = urb->iso_frame_desc[i].actual_length; |
526 | 531 | ||
527 | // if (len>=TM6000_URB_MSG_LEN) { | 532 | if (len > 0) { |
528 | p=urb->transfer_buffer + urb->iso_frame_desc[i].offset; | 533 | p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; |
529 | if (!urb->iso_frame_desc[i].status) { | 534 | if (!urb->iso_frame_desc[i].status) { |
530 | if ((buf->fmt->fourcc)==V4L2_PIX_FMT_TM6000) { | 535 | if ((dev->fourcc)==V4L2_PIX_FMT_TM6000) { |
531 | rc=copy_multiplexed(p, outp, len, urb, &buf); | 536 | rc=copy_multiplexed(p, len, urb); |
532 | if (rc<=0) | 537 | if (rc<=0) |
533 | return rc; | 538 | return rc; |
534 | } else { | 539 | } else { |
535 | copy_streams(p, outp, len, urb, &buf); | 540 | copy_streams(p, len, urb); |
536 | } | 541 | } |
537 | } | 542 | } |
538 | copied += len; | 543 | } |
539 | if (copied >= size || !buf) | ||
540 | break; | ||
541 | // } | ||
542 | } | 544 | } |
543 | return rc; | 545 | return rc; |
544 | } | 546 | } |