On Fri, May 28, 2010 at 08:03:40PM +0200, stefan.ringel@xxxxxxxx wrote: > From: Stefan Ringel <stefan.ringel@xxxxxxxx> > > fusion function copy streams and copy_packets to new function copy_streams. > > Signed-off-by: Stefan Ringel <stefan.ringel@xxxxxxxx> > --- > drivers/staging/tm6000/tm6000-usb-isoc.h | 5 +- > drivers/staging/tm6000/tm6000-video.c | 329 +++++++++++------------------- > 2 files changed, 119 insertions(+), 215 deletions(-) > > diff --git a/drivers/staging/tm6000/tm6000-usb-isoc.h b/drivers/staging/tm6000/tm6000-usb-isoc.h > index 5a5049a..138716a 100644 > --- a/drivers/staging/tm6000/tm6000-usb-isoc.h > +++ b/drivers/staging/tm6000/tm6000-usb-isoc.h > @@ -39,7 +39,7 @@ struct usb_isoc_ctl { > int pos, size, pktsize; > > /* Last field: ODD or EVEN? */ > - int field; > + int vfield; > > /* Stores incomplete commands */ > u32 tmp_buf; > @@ -47,7 +47,4 @@ struct usb_isoc_ctl { > > /* Stores already requested buffers */ > struct tm6000_buffer *buf; > - > - /* Stores the number of received fields */ > - int nfields; > }; > diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c > index 2a61cc3..058c6e9 100644 > --- a/drivers/staging/tm6000/tm6000-video.c > +++ b/drivers/staging/tm6000/tm6000-video.c > @@ -186,234 +186,145 @@ const char *tm6000_msg_type[] = { > /* > * Identify the tm5600/6000 buffer header type and properly handles > */ > -static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, > - u8 *out_p, struct tm6000_buffer **buf) > -{ > - struct tm6000_dmaqueue *dma_q = urb->context; > - struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); > - u8 c; > - unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0; > - int rc = 0; > - /* FIXME: move to tm6000-isoc */ > - static int last_line = -2, start_line = -2, last_field = -2; > - > - /* FIXME: this is the hardcoded window size > - */ > - unsigned int linewidth = (*buf)->vb.width << 1; > - > - if (!dev->isoc_ctl.cmd) { > - c = (header >> 24) & 0xff; > - > - /* split the header fields */ > - size = ((header & 0x7e) << 1); > - > - if (size > 0) > - size -= 4; > - > - block = (header >> 7) & 0xf; > - field = (header >> 11) & 0x1; > - line = (header >> 12) & 0x1ff; > - cmd = (header >> 21) & 0x7; > - > - /* Validates header fields */ > - if(size > TM6000_URB_MSG_LEN) > - size = TM6000_URB_MSG_LEN; > - > - if (cmd == TM6000_URB_MSG_VIDEO) { > - if ((block+1)*TM6000_URB_MSG_LEN>linewidth) > - cmd = TM6000_URB_MSG_ERR; > - > - /* FIXME: Mounts the image as field0+field1 > - * It should, instead, check if the user selected > - * entrelaced or non-entrelaced mode > - */ > - pos= ((line<<1)+field)*linewidth + > - block*TM6000_URB_MSG_LEN; > - > - /* Don't allow to write out of the buffer */ > - if (pos+TM6000_URB_MSG_LEN > (*buf)->vb.size) { > - dprintk(dev, V4L2_DEBUG_ISOC, > - "ERR: size=%d, num=%d, line=%d, " > - "field=%d\n", > - size, block, line, field); > - > - cmd = TM6000_URB_MSG_ERR; > - } > - } else { > - pos=0; > - } > - > - /* Prints debug info */ > - dprintk(dev, V4L2_DEBUG_ISOC, "size=%d, num=%d, " > - " line=%d, field=%d\n", > - size, block, line, field); > - > - if ((last_line!=line)&&(last_line+1!=line) && > - (cmd != TM6000_URB_MSG_ERR) ) { > - if (cmd != TM6000_URB_MSG_VIDEO) { > - dprintk(dev, V4L2_DEBUG_ISOC, "cmd=%d, " > - "size=%d, num=%d, line=%d, field=%d\n", > - cmd, size, block, line, field); > - } > - if (start_line<0) > - start_line=last_line; > - /* Prints debug info */ > - dprintk(dev, V4L2_DEBUG_ISOC, "lines= %d-%d, " > - "field=%d\n", > - start_line, last_line, field); > - > - if ((start_line<6 && last_line>200) && > - (last_field != field) ) { > - > - dev->isoc_ctl.nfields++; > - if (dev->isoc_ctl.nfields>=2) { > - dev->isoc_ctl.nfields=0; > - > - /* Announces that a new buffer were filled */ > - buffer_filled (dev, dma_q, *buf); > - dprintk(dev, V4L2_DEBUG_ISOC, > - "new buffer filled\n"); > - get_next_buf (dma_q, buf); > - if (!*buf) > - return rc; > - out_p = videobuf_to_vmalloc(&((*buf)->vb)); > - if (!out_p) > - return rc; > - > - pos = dev->isoc_ctl.pos = 0; > - } > - } > - > - start_line=line; > - last_field=field; > - } > - if (cmd == TM6000_URB_MSG_VIDEO) > - last_line = line; > - > - pktsize = TM6000_URB_MSG_LEN; > - } else { > - /* Continue the last copy */ > - cmd = dev->isoc_ctl.cmd; > - size= dev->isoc_ctl.size; > - pos = dev->isoc_ctl.pos; > - pktsize = dev->isoc_ctl.pktsize; > - } > - > - cpysize = (endp-(*ptr) > size) ? size : endp - *ptr; > - > - if (cpysize) { > - /* handles each different URB message */ > - switch(cmd) { > - case TM6000_URB_MSG_VIDEO: > - /* Fills video buffer */ > - memcpy(&out_p[pos], *ptr, cpysize); > - break; > - case TM6000_URB_MSG_PTS: > - break; > - case TM6000_URB_MSG_AUDIO: > - /* Need some code to process audio */ > - printk ("%ld: cmd=%s, size=%d\n", jiffies, > - tm6000_msg_type[cmd],size); > - break; > - case TM6000_URB_MSG_VBI: > - break; > - default: > - dprintk (dev, V4L2_DEBUG_ISOC, "cmd=%s, size=%d\n", > - tm6000_msg_type[cmd],size); > - } > - } > - if (cpysize<size) { > - /* End of URB packet, but cmd processing is not > - * complete. Preserve the state for a next packet > - */ > - dev->isoc_ctl.pos = pos+cpysize; > - dev->isoc_ctl.size= size-cpysize; > - dev->isoc_ctl.cmd = cmd; > - dev->isoc_ctl.pktsize = pktsize-cpysize; > - (*ptr)+=cpysize; > - } else { > - dev->isoc_ctl.cmd = 0; > - (*ptr)+=pktsize; > - } > - > - return rc; > -} > - > 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; > + u8 *ptr=data, *endp=data+len, c; > 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); > + unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0; > + struct tm6000_buffer *vbuf; > + char *voutp = NULL; > + unsigned int linewidth; > > - if (!outp) > + /* get video buffer */ > + get_next_buf (dma_q, &vbuf); > + if (!vbuf) > + return rc; > + voutp = videobuf_to_vmalloc(&vbuf->vb); > + if (!voutp) > return 0; > > - for (ptr=data; ptr<endp;) { > + for (ptr = data; ptr < endp;) { > if (!dev->isoc_ctl.cmd) { > - u8 *p=(u8 *)&dev->isoc_ctl.tmp_buf; > - /* FIXME: This seems very complex > - * It just recovers up to 3 bytes of the header that > - * might be at the previous packet > - */ > - if (dev->isoc_ctl.tmp_buf_len) { > - while (dev->isoc_ctl.tmp_buf_len) { > - if ( *(ptr+3-dev->isoc_ctl.tmp_buf_len) == 0x47) { > - break; > - } > - p++; > - dev->isoc_ctl.tmp_buf_len--; > - } > - if (dev->isoc_ctl.tmp_buf_len) { > - memcpy(&header, p, > - dev->isoc_ctl.tmp_buf_len); > - memcpy((u8 *)&header + > + /* Header */ > + if (dev->isoc_ctl.tmp_buf_len > 0) { > + /* from last urb or packet */ > + header = dev->isoc_ctl.tmp_buf; > + if (4 - dev->isoc_ctl.tmp_buf_len > 0) > + memcpy ((u8 *)&header + > dev->isoc_ctl.tmp_buf_len, > ptr, > 4 - dev->isoc_ctl.tmp_buf_len); > ptr += 4 - dev->isoc_ctl.tmp_buf_len; > - goto HEADER; > } This brace has to be removed. - } > + dev->isoc_ctl.tmp_buf_len = 0; > + } else { > + if (ptr + 3 >= endp) { > + /* have incomplete header */ > + dev->isoc_ctl.tmp_buf_len = endp - ptr; > + memcpy (&dev->isoc_ctl.tmp_buf, ptr, > + dev->isoc_ctl.tmp_buf_len); > + return rc; > + } > + /* Seek for sync */ > + for (; ptr < endp - 3; ptr++) { > + if (*(ptr + 3) == 0x47) > + break; > + } > + /* Get message header */ > + header = *(unsigned long *)ptr; > + ptr += 4; > } > - /* Seek for sync */ > - for (;ptr<endp-3;ptr++) { > - if (*(ptr+3)==0x47) > - break; > + /* split the header fields */ > + c = (header >> 24) & 0xff; > + size = ((header & 0x7e) << 1); > + if (size > 0) > + size -= 4; > + block = (header >> 7) & 0xf; > + field = (header >> 11) & 0x1; > + line = (header >> 12) & 0x1ff; > + cmd = (header >> 21) & 0x7; > + /* Validates haeder fields */ > + if (size > TM6000_URB_MSG_LEN) > + size = TM6000_URB_MSG_LEN; > + pktsize = TM6000_URB_MSG_LEN; > + /* calculate position in buffer > + * and change the buffer > + */ > + switch (cmd) { > + case TM6000_URB_MSG_VIDEO: > + if ((dev->isoc_ctl.vfield != field) && > + (field == 1) { Missing closing parenthesis. + (field == 1)) { > + /* Announces that a new buffer > + * were filled > + */ > + buffer_filled (dev, dma_q, vbuf); > + dprintk (dev, V4L2_DEBUG_ISOC, > + "new buffer filled\n"); > + get_next_buf (dma_q, &vbuf); > + if (!vbuf) > + return rc; > + voutp = videobuf_to_vmalloc (&vbuf->vb); > + if (!voutp) > + return rc; > + } > + linewidth = vbuf->vb.width << 1; > + pos = ((line << 1) - field - 1) * linewidth + > + block * TM6000_URB_MSG_LEN; > + /* Don't allow to write out of the buffer */ > + if (pos + size > vbuf->vb.size) > + cmd = TM6000_URB_MSG_ERR; > + dev->isoc_ctl.vfield = field; > + break; > + case TM6000_URB_MSG_AUDIO: > + case TM6000_URB_MSG_VBI: > + case TM6000_URB_MSG_PTS: > + break; > } > - > - if (ptr+3>=endp) { > - dev->isoc_ctl.tmp_buf_len=endp-ptr; > - memcpy (&dev->isoc_ctl.tmp_buf,ptr, > - dev->isoc_ctl.tmp_buf_len); > - dev->isoc_ctl.cmd=0; > - return rc; > + } else { > + /* Continue the last copy */ > + cmd = dev->isoc_ctl.cmd; > + size = dev->isoc_ctl.size; > + pos = dev->isoc_ctl.pos; > + pktsize = dev->isoc_ctl-pktsize; A typo: the dash has to be a dot. + pktsize = dev->isoc_ctl.pktsize; > + } > + cpysize = (endp - ptr > size) ? size : endp - ptr; > + if (cpysize) { > + /* copy data in different buffers */ > + switch (cmd) { > + case TM6000_URB_MSG_VIDEO: > + /* Fills video buffer */ > + if (vbuf) > + memcpy (&voutp[pos], ptr, cpysize); > + break; > + case TM6000_URB_MSG_AUDIO: > + /* Need some code to copy audio buffer */ > + break; > + case TM6000_URB_MSG_VBI: > + /* Need some code to copy vbi buffer */ > + break; > + case TM6000_URB_MSG_PTS: > + /* Need some code to copy pts */ > + break; > } > - > - /* Get message header */ > - header=*(unsigned long *)ptr; > - ptr+=4; > } > -HEADER: > - /* Copy or continue last copy */ > - 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 (ptr + pktsize > endp) { > + /* End of URB packet, but cmd processing is not > + * complete. Preserve the state for a next packet > + */ > + dev->isoc_ctl.pos = pos + cpysize; > + dev->isoc_ctl.size = size - cpysize; > + dev->isoc_ctl.cmd = cmd; > + dev->isoc_ctl.pktsize = pktsize - (endp - ptr); > + ptr += end - ptr; A typo: missing p + ptr += endp - ptr; I've compiled and tested the patches from May 10th with the above fixes and analog video working great on HVR-900H. Regards George -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html