Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b6ed9fd authored by Stefan Ringel's avatar Stefan Ringel Committed by Mauro Carvalho Chehab
Browse files

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: default avatarStefan Ringel <stefan.ringel@arcor.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 3569417e
Loading
Loading
Loading
Loading
+45 −43
Original line number Diff line number Diff line
@@ -339,14 +339,23 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp,
	return rc;
}

static int copy_streams(u8 *data, u8 *out_p, unsigned long len,
			struct urb *urb, struct tm6000_buffer **buf)
static int copy_streams(u8 *data, unsigned long len,
			struct urb *urb)
{
	struct tm6000_dmaqueue  *dma_q = urb->context;
	struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
	u8 *ptr=data, *endp=data+len;
	unsigned long header=0;
	int rc=0;
	struct tm6000_buffer *buf;
	char *outp = NULL;

	get_next_buf(dma_q, &buf);
	if (buf)
		outp = videobuf_to_vmalloc(&buf->vb);

	if (!outp)
		return 0;

	for (ptr=data; ptr<endp;) {
		if (!dev->isoc_ctl.cmd) {
@@ -394,14 +403,14 @@ static int copy_streams(u8 *data, u8 *out_p, unsigned long len,
		}
HEADER:
		/* Copy or continue last copy */
		rc=copy_packet(urb,header,&ptr,endp,out_p,buf);
		rc=copy_packet(urb,header,&ptr,endp,outp,&buf);
		if (rc<0) {
			buf=NULL;
			printk(KERN_ERR "tm6000: buffer underrun at %ld\n",
					jiffies);
			return rc;
		}
		if (!*buf)
		if (!buf)
			return 0;
	}

@@ -410,31 +419,40 @@ HEADER:
/*
 * Identify the tm5600/6000 buffer header type and properly handles
 */
static int copy_multiplexed(u8 *ptr, u8 *out_p, unsigned long len,
			struct urb *urb, struct tm6000_buffer **buf)
static int copy_multiplexed(u8 *ptr, unsigned long len,
			struct urb *urb)
{
	struct tm6000_dmaqueue  *dma_q = urb->context;
	struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
	unsigned int pos=dev->isoc_ctl.pos,cpysize;
	int rc=1;
	struct tm6000_buffer *buf;
	char *outp = NULL;

	get_next_buf(dma_q, &buf);
	if (buf)
		outp = videobuf_to_vmalloc(&buf->vb);

	if (!outp)
		return 0;

	while (len>0) {
		cpysize=min(len,(*buf)->vb.size-pos);
		cpysize=min(len,buf->vb.size-pos);
		//printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos);
		memcpy(&out_p[pos], ptr, cpysize);
		memcpy(&outp[pos], ptr, cpysize);
		pos+=cpysize;
		ptr+=cpysize;
		len-=cpysize;
		if (pos >= (*buf)->vb.size) {
		if (pos >= buf->vb.size) {
			pos=0;
			/* Announces that a new buffer were filled */
			buffer_filled (dev, dma_q, *buf);
			buffer_filled (dev, dma_q, buf);
			dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n");
			get_next_buf (dma_q, buf);
			if (!*buf)
			get_next_buf (dma_q, &buf);
			if (!buf)
				break;
			out_p = videobuf_to_vmalloc(&((*buf)->vb));
			if (!out_p)
			outp = videobuf_to_vmalloc(&(buf->vb));
			if (!outp)
				return rc;
			pos = 0;
		}
@@ -493,21 +511,8 @@ static inline int tm6000_isoc_copy(struct urb *urb)
	struct tm6000_dmaqueue  *dma_q = urb->context;
	struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
	struct tm6000_buffer *buf;
	int i, len=0, rc=1;
	int size;
	char *outp = NULL, *p;
	unsigned long copied;

	get_next_buf(dma_q, &buf);
	if (buf)
		outp = videobuf_to_vmalloc(&buf->vb);

	if (!outp)
		return 0;

	size = buf->vb.size;

	copied=0;
	int i, len=0, rc=1, status;
	char *p;

	if (urb->status < 0) {
		print_err_status (dev, -1, urb->status);
@@ -515,7 +520,7 @@ static inline int tm6000_isoc_copy(struct urb *urb)
	}

	for (i = 0; i < urb->number_of_packets; i++) {
		int status = urb->iso_frame_desc[i].status;
		status = urb->iso_frame_desc[i].status;

		if (status<0) {
			print_err_status (dev,i,status);
@@ -524,21 +529,18 @@ static inline int tm6000_isoc_copy(struct urb *urb)

		len = urb->iso_frame_desc[i].actual_length;

//		if (len>=TM6000_URB_MSG_LEN) {
		if (len > 0) {
			p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
			if (!urb->iso_frame_desc[i].status) {
				if ((buf->fmt->fourcc)==V4L2_PIX_FMT_TM6000) {
					rc=copy_multiplexed(p, outp, len, urb, &buf);
				if ((dev->fourcc)==V4L2_PIX_FMT_TM6000) {
					rc=copy_multiplexed(p, len, urb);
					if (rc<=0)
						return rc;
				} else {
					copy_streams(p, outp, len, urb, &buf);
					copy_streams(p, len, urb);
				}
			}
		}
			copied += len;
			if (copied >= size || !buf)
				break;
//		}
	}
	return rc;
}