V4L/DVB (12827): tm6000: fix image hangs
A previous committed patch hanged image output. This patch corrects this issue. It also warrants that buffer is updated for each frame0+frame1 frame set. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Родитель
e381a81010
Коммит
204193d959
|
@ -410,15 +410,6 @@ static int tm6000_usb_probe(struct usb_interface *interface,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (interface->altsetting->desc.bAlternateSetting) {
|
|
||||||
printk("selecting alt setting %d\n",
|
|
||||||
interface->altsetting->desc.bAlternateSetting);
|
|
||||||
rc = usb_set_interface (usbdev,
|
|
||||||
interface->altsetting->desc.bInterfaceNumber,
|
|
||||||
interface->altsetting->desc.bAlternateSetting);
|
|
||||||
if (rc<0)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
printk("tm6000: New video device @ %s Mbps (%04x:%04x, ifnum %d)\n",
|
printk("tm6000: New video device @ %s Mbps (%04x:%04x, ifnum %d)\n",
|
||||||
speed,
|
speed,
|
||||||
|
|
|
@ -50,4 +50,8 @@ struct usb_isoc_ctl {
|
||||||
|
|
||||||
/* Stores the number of received fields */
|
/* Stores the number of received fields */
|
||||||
int nfields;
|
int nfields;
|
||||||
|
|
||||||
|
/* Checks if a complete field were received */
|
||||||
|
int last_line;
|
||||||
|
unsigned int fields:2;
|
||||||
};
|
};
|
||||||
|
|
|
@ -257,6 +257,22 @@ static int copy_packet (struct urb *urb, u32 header, u8 **ptr, u8 *endp,
|
||||||
" line=%d, field=%d\n",
|
" line=%d, field=%d\n",
|
||||||
size, block, line, field);
|
size, block, line, field);
|
||||||
|
|
||||||
|
/* Checks if a complete set of frame0 + frame 1 were received */
|
||||||
|
if (dev->isoc_ctl.last_line > line) {
|
||||||
|
if (dev->isoc_ctl.fields == 3) {
|
||||||
|
/* Announces that a new buffer were filled */
|
||||||
|
buffer_filled(dev, dma_q, *buf);
|
||||||
|
dprintk(dev, V4L2_DEBUG_ISOC,
|
||||||
|
"new buffer filled\n");
|
||||||
|
rc = get_next_buf(dma_q, buf);
|
||||||
|
|
||||||
|
dev->isoc_ctl.fields = 0;
|
||||||
|
} else {
|
||||||
|
dev->isoc_ctl.fields |= 1 << field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dev->isoc_ctl.last_line = line;
|
||||||
|
|
||||||
if ((last_line!=line)&&(last_line+1!=line) &&
|
if ((last_line!=line)&&(last_line+1!=line) &&
|
||||||
(cmd != TM6000_URB_MSG_ERR) ) {
|
(cmd != TM6000_URB_MSG_ERR) ) {
|
||||||
if (cmd != TM6000_URB_MSG_VIDEO) {
|
if (cmd != TM6000_URB_MSG_VIDEO) {
|
||||||
|
@ -277,12 +293,6 @@ static int copy_packet (struct urb *urb, u32 header, u8 **ptr, u8 *endp,
|
||||||
dev->isoc_ctl.nfields++;
|
dev->isoc_ctl.nfields++;
|
||||||
if (dev->isoc_ctl.nfields>=2) {
|
if (dev->isoc_ctl.nfields>=2) {
|
||||||
dev->isoc_ctl.nfields=0;
|
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");
|
|
||||||
rc=get_next_buf (dma_q, buf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -631,11 +641,17 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev,
|
||||||
int max_packets, int num_bufs)
|
int max_packets, int num_bufs)
|
||||||
{
|
{
|
||||||
struct tm6000_dmaqueue *dma_q = &dev->vidq;
|
struct tm6000_dmaqueue *dma_q = &dev->vidq;
|
||||||
int i;
|
int i, rc;
|
||||||
int sb_size, pipe;
|
int sb_size, pipe;
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
int j, k;
|
int j, k;
|
||||||
|
|
||||||
|
dprintk(dev, V4L2_DEBUG_QUEUE, "Allocating %dx%d packets"
|
||||||
|
" of %d bytes each to handle %u size\n",
|
||||||
|
max_packets, num_bufs,
|
||||||
|
dev->max_isoc_in, dev->isoc_ctl.max_pkt_size);
|
||||||
|
|
||||||
|
|
||||||
/* De-allocates all pending stuff */
|
/* De-allocates all pending stuff */
|
||||||
tm6000_uninit_isoc(dev);
|
tm6000_uninit_isoc(dev);
|
||||||
|
|
||||||
|
@ -684,6 +700,7 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev,
|
||||||
}
|
}
|
||||||
memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
|
memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
|
||||||
|
|
||||||
|
|
||||||
pipe=usb_rcvisocpipe(dev->udev,
|
pipe=usb_rcvisocpipe(dev->udev,
|
||||||
dev->isoc_in->desc.bEndpointAddress &
|
dev->isoc_in->desc.bEndpointAddress &
|
||||||
USB_ENDPOINT_NUMBER_MASK);
|
USB_ENDPOINT_NUMBER_MASK);
|
||||||
|
@ -862,7 +879,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
|
||||||
struct tm6000_fh *fh = vq->priv_data;
|
struct tm6000_fh *fh = vq->priv_data;
|
||||||
struct tm6000_buffer *buf = container_of(vb,struct tm6000_buffer,vb);
|
struct tm6000_buffer *buf = container_of(vb,struct tm6000_buffer,vb);
|
||||||
struct tm6000_core *dev = fh->dev;
|
struct tm6000_core *dev = fh->dev;
|
||||||
int rc=0, urbsize, urb_init=0, npackets=1;
|
int rc = 0, urb_init = 0;
|
||||||
|
|
||||||
BUG_ON(NULL == fh->fmt);
|
BUG_ON(NULL == fh->fmt);
|
||||||
|
|
||||||
|
@ -890,50 +907,11 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
|
||||||
urb_init=1;
|
urb_init=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!dev->isoc_ctl.num_bufs)
|
if (!dev->isoc_ctl.num_bufs)
|
||||||
urb_init=1;
|
urb_init=1;
|
||||||
|
|
||||||
if (urb_init) {
|
if (urb_init) {
|
||||||
/* memory for video
|
rc = tm6000_prepare_isoc(dev, 128, 1);
|
||||||
Should be at least
|
|
||||||
Vres x Vres x 2 bytes/pixel by frame */
|
|
||||||
urbsize=buf->vb.size;
|
|
||||||
|
|
||||||
/* Need also one PTS */
|
|
||||||
urbsize+=180;
|
|
||||||
|
|
||||||
/* memory for audio
|
|
||||||
Should be at least
|
|
||||||
bitrate * 2 channels * 2 bytes / frame rate */
|
|
||||||
if (dev->norm & V4L2_STD_525_60) {
|
|
||||||
urbsize+=(dev->audio_bitrate*4+29)/30;
|
|
||||||
} else {
|
|
||||||
urbsize+=(dev->audio_bitrate*4+24)/25;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* each audio frame seeems to have a frame number
|
|
||||||
with 2 bytes */
|
|
||||||
urbsize+=2;
|
|
||||||
|
|
||||||
/* Add 4 bytes by each 180 bytes frame */
|
|
||||||
urbsize+=((urbsize+179)/180)*4;
|
|
||||||
|
|
||||||
/* Round to an enough number of URBs */
|
|
||||||
urbsize=(urbsize+dev->max_isoc_in-1)/dev->max_isoc_in;
|
|
||||||
|
|
||||||
/* Avoids allocating big memory areas for URB */
|
|
||||||
while ((urbsize*dev->max_isoc_in)/npackets>65535) {
|
|
||||||
npackets++;
|
|
||||||
}
|
|
||||||
urbsize/=(urbsize+npackets-1)/npackets;
|
|
||||||
|
|
||||||
dprintk(dev, V4L2_DEBUG_QUEUE, "Allocating %dx%d packets"
|
|
||||||
" of %d bytes each to handle %lu size\n",
|
|
||||||
npackets,urbsize,dev->max_isoc_in,buf->vb.size);
|
|
||||||
|
|
||||||
rc = tm6000_prepare_isoc(dev, urbsize, npackets);
|
|
||||||
|
|
||||||
if (rc<0)
|
if (rc<0)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче