|
@@ -101,11 +101,14 @@ static struct tda18271_config hauppauge_woodbury_tunerconfig = {
|
|
|
.gate = TDA18271_GATE_DIGITAL,
|
|
|
};
|
|
|
|
|
|
+static void au0828_restart_dvb_streaming(struct work_struct *work);
|
|
|
+
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
static void urb_completion(struct urb *purb)
|
|
|
{
|
|
|
struct au0828_dev *dev = purb->context;
|
|
|
int ptype = usb_pipetype(purb->pipe);
|
|
|
+ unsigned char *ptr;
|
|
|
|
|
|
dprintk(2, "%s()\n", __func__);
|
|
|
|
|
@@ -121,6 +124,16 @@ static void urb_completion(struct urb *purb)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ /* See if the stream is corrupted (to work around a hardware
|
|
|
+ bug where the stream gets misaligned */
|
|
|
+ ptr = purb->transfer_buffer;
|
|
|
+ if (purb->actual_length > 0 && ptr[0] != 0x47) {
|
|
|
+ dprintk(1, "Need to restart streaming %02x len=%d!\n",
|
|
|
+ ptr[0], purb->actual_length);
|
|
|
+ schedule_work(&dev->restart_streaming);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
/* Feed the transport payload into the kernel demux */
|
|
|
dvb_dmx_swfilter_packets(&dev->dvb.demux,
|
|
|
purb->transfer_buffer, purb->actual_length / 188);
|
|
@@ -138,14 +151,13 @@ static int stop_urb_transfer(struct au0828_dev *dev)
|
|
|
|
|
|
dprintk(2, "%s()\n", __func__);
|
|
|
|
|
|
+ dev->urb_streaming = 0;
|
|
|
for (i = 0; i < URB_COUNT; i++) {
|
|
|
usb_kill_urb(dev->urbs[i]);
|
|
|
kfree(dev->urbs[i]->transfer_buffer);
|
|
|
usb_free_urb(dev->urbs[i]);
|
|
|
}
|
|
|
|
|
|
- dev->urb_streaming = 0;
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -246,11 +258,8 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
|
|
|
mutex_lock(&dvb->lock);
|
|
|
if (--dvb->feeding == 0) {
|
|
|
/* Stop transport */
|
|
|
- au0828_write(dev, 0x608, 0x00);
|
|
|
- au0828_write(dev, 0x609, 0x00);
|
|
|
- au0828_write(dev, 0x60a, 0x00);
|
|
|
- au0828_write(dev, 0x60b, 0x00);
|
|
|
ret = stop_urb_transfer(dev);
|
|
|
+ au0828_write(dev, 0x60b, 0x00);
|
|
|
}
|
|
|
mutex_unlock(&dvb->lock);
|
|
|
}
|
|
@@ -258,6 +267,37 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static void au0828_restart_dvb_streaming(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct au0828_dev *dev = container_of(work, struct au0828_dev,
|
|
|
+ restart_streaming);
|
|
|
+ struct au0828_dvb *dvb = &dev->dvb;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (dev->urb_streaming == 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ dprintk(1, "Restarting streaming...!\n");
|
|
|
+
|
|
|
+ mutex_lock(&dvb->lock);
|
|
|
+
|
|
|
+ /* Stop transport */
|
|
|
+ ret = stop_urb_transfer(dev);
|
|
|
+ au0828_write(dev, 0x608, 0x00);
|
|
|
+ au0828_write(dev, 0x609, 0x00);
|
|
|
+ au0828_write(dev, 0x60a, 0x00);
|
|
|
+ au0828_write(dev, 0x60b, 0x00);
|
|
|
+
|
|
|
+ /* Start transport */
|
|
|
+ au0828_write(dev, 0x608, 0x90);
|
|
|
+ au0828_write(dev, 0x609, 0x72);
|
|
|
+ au0828_write(dev, 0x60a, 0x71);
|
|
|
+ au0828_write(dev, 0x60b, 0x01);
|
|
|
+ ret = start_urb_transfer(dev);
|
|
|
+
|
|
|
+ mutex_unlock(&dvb->lock);
|
|
|
+}
|
|
|
+
|
|
|
static int dvb_register(struct au0828_dev *dev)
|
|
|
{
|
|
|
struct au0828_dvb *dvb = &dev->dvb;
|
|
@@ -265,6 +305,8 @@ static int dvb_register(struct au0828_dev *dev)
|
|
|
|
|
|
dprintk(1, "%s()\n", __func__);
|
|
|
|
|
|
+ INIT_WORK(&dev->restart_streaming, au0828_restart_dvb_streaming);
|
|
|
+
|
|
|
/* register adapter */
|
|
|
result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
|
|
|
&dev->usbdev->dev, adapter_nr);
|