All of lore.kernel.org
 help / color / mirror / Atom feed
From: Devin Heitmueller <dheitmueller@kernellabs.com>
To: linux-media@vger.kernel.org
Cc: Devin Heitmueller <dheitmueller@kernellabs.com>
Subject: [PATCH 03/24] au8522: properly recover from the au8522 delivering misaligned TS streams
Date: Mon,  6 Aug 2012 22:46:53 -0400	[thread overview]
Message-ID: <1344307634-11673-4-git-send-email-dheitmueller@kernellabs.com> (raw)
In-Reply-To: <1344307634-11673-1-git-send-email-dheitmueller@kernellabs.com>

There is an apparent bug in the au8522 TS clocking which can result in it
delivering a TS payload to the au0828 that is shifted by some number of bits.
For example, the device will announce a packet containing "FA 38 FF F8" which
if you shift left one bit is "1F 47 1F FF F0..."

This presents itself as no TS stream being delivered from the kernel to
userland, since the kernel demux will drop every packet.

In the event that this condition occurs, restart the DVB stream.

Also, this patch includes a couple of lines of cleanup to not change the
FIFO configuration while the FIFO is running (which can screw up the state
machine), and dequeue the buffers before turning off the FIFO.  This puts the
logic in sync with the Windows driver.

Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com>
---
 drivers/media/video/au0828/au0828-dvb.c |   54 +++++++++++++++++++++++++++---
 drivers/media/video/au0828/au0828.h     |    1 +
 2 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c
index 39ece8e..b328f65 100644
--- a/drivers/media/video/au0828/au0828-dvb.c
+++ b/drivers/media/video/au0828/au0828-dvb.c
@@ -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);
diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h
index 9cde353..61cd63e 100644
--- a/drivers/media/video/au0828/au0828.h
+++ b/drivers/media/video/au0828/au0828.h
@@ -197,6 +197,7 @@ struct au0828_dev {
 
 	/* Digital */
 	struct au0828_dvb		dvb;
+	struct work_struct              restart_streaming;
 
 	/* Analog */
 	struct v4l2_device v4l2_dev;
-- 
1.7.1


  parent reply	other threads:[~2012-08-07  2:47 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-07  2:46 [PATCH 00/24] Various HVR-950q and xc5000 fixes Devin Heitmueller
2012-08-07  2:46 ` [PATCH 01/24] au8522: fix intermittent lockup of analog video decoder Devin Heitmueller
2012-08-07  2:46 ` [PATCH 02/24] au8522: Fix off-by-one in SNR table for QAM256 Devin Heitmueller
2012-08-07  2:46 ` Devin Heitmueller [this message]
2012-08-07  2:46 ` [PATCH 04/24] au0828: Make the s_reg and g_reg advanced debug calls work against the bridge Devin Heitmueller
2012-08-07  2:46 ` [PATCH 05/24] xc5000: properly show quality register values Devin Heitmueller
2012-08-07  2:46 ` [PATCH 06/24] xc5000: add support for showing the SNR and gain in the debug output Devin Heitmueller
2012-08-07  2:46 ` [PATCH 07/24] xc5000: properly report i2c write failures Devin Heitmueller
     [not found]   ` <CAPLVkLv6JNvSdSFCY7YNRkmfzHv5+JD7Y5hxvjxdFtRT2JgE2A@mail.gmail.com>
2014-02-07 13:46     ` Devin Heitmueller
2014-02-10  8:25       ` Joonyoung Shim
2014-02-10 13:29         ` Devin Heitmueller
2012-08-07  2:46 ` [PATCH 08/24] au0828: fix race condition that causes xc5000 to not bind for digital Devin Heitmueller
2012-08-07  2:46 ` [PATCH 09/24] au0828: make sure video standard is setup in tuner-core Devin Heitmueller
2012-08-07  2:47 ` [PATCH 10/24] au8522: fix regression in logging introduced by separation of modules Devin Heitmueller
2012-08-07  2:47 ` [PATCH 11/24] xc5000: don't invoke auto calibration unless we really did reset tuner Devin Heitmueller
2012-08-07  2:47 ` [PATCH 12/24] au0828: prevent i2c gate from being kept open while in analog mode Devin Heitmueller
2012-08-07  2:47 ` [PATCH 13/24] au0828: fix case where STREAMOFF being called on stopped stream causes BUG() Devin Heitmueller
2012-08-07  2:47 ` [PATCH 14/24] au0828: speed up i2c clock when doing xc5000 firmware load Devin Heitmueller
2012-08-07  2:47 ` [PATCH 15/24] au0828: remove control buffer from send_control_msg Devin Heitmueller
2012-08-07  2:47 ` [PATCH 16/24] au0828: tune retry interval for i2c interaction Devin Heitmueller
2012-08-07  2:47 ` [PATCH 17/24] au0828: fix possible race condition in usage of dev->ctrlmsg Devin Heitmueller
2012-08-09 23:48   ` Mauro Carvalho Chehab
2012-08-10  0:57     ` Devin Heitmueller
2012-08-07  2:47 ` [PATCH 18/24] xc5000: reset device if encountering PLL lock failure Devin Heitmueller
2012-08-07  2:47 ` [PATCH 19/24] xc5000: add support for firmware load check and init status Devin Heitmueller
2012-08-07  2:47 ` [PATCH 20/24] au0828: tweak workaround for i2c clock stretching bug Devin Heitmueller
2012-08-07  2:47 ` [PATCH 21/24] xc5000: show debug version fields in decimal instead of hex Devin Heitmueller
2012-08-07  2:47 ` [PATCH 22/24] au0828: fix a couple of missed edge cases for i2c gate with analog Devin Heitmueller
2012-08-07  2:47 ` [PATCH 23/24] au0828: make xc5000 firmware speedup apply to the xc5000c as well Devin Heitmueller
2012-08-07  2:47 ` [PATCH 24/24] xc5000: change filename to production/redistributable xc5000c firmware Devin Heitmueller
2012-08-07  6:26 ` [PATCH 00/24] Various HVR-950q and xc5000 fixes Hans Verkuil
2012-08-07 12:48   ` Devin Heitmueller
2012-08-07 12:59     ` Hans Verkuil

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1344307634-11673-4-git-send-email-dheitmueller@kernellabs.com \
    --to=dheitmueller@kernellabs.com \
    --cc=linux-media@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.