Re: SAA7146 glitch on cold boot

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



And the inevitable version two of the patch fixing the thing I forgot. The 
previous one would only work if there was only one user of the demux.

Also, I've noticed that the only card I can reliably reproduce this on is an 
old l64781 based budget card. 

It does happen occasionally on my new tda10046 based budget-ci card, but only 
very infrequently.
diff -r 0bcf77433dc0 linux/drivers/media/dvb/ttpci/budget-av.c
--- a/linux/drivers/media/dvb/ttpci/budget-av.c	Thu Jun 29 21:30:51 2006 +0200
+++ b/linux/drivers/media/dvb/ttpci/budget-av.c	Fri Jun 30 11:58:45 2006 +0100
@@ -1196,6 +1196,9 @@ static void frontend_init(struct budget_
 			budget_av->budget.dvb_frontend->ops.release(budget_av->budget.dvb_frontend);
 		budget_av->budget.dvb_frontend = NULL;
 	}
+
+	if (budget_av->budget.dvb_frontend)
+		ttpci_install_ts_streaming_workaround(&budget_av->budget);
 }
 
 
diff -r 0bcf77433dc0 linux/drivers/media/dvb/ttpci/budget-ci.c
--- a/linux/drivers/media/dvb/ttpci/budget-ci.c	Thu Jun 29 21:30:51 2006 +0200
+++ b/linux/drivers/media/dvb/ttpci/budget-ci.c	Fri Jun 30 11:58:45 2006 +0100
@@ -1070,6 +1070,9 @@ static void frontend_init(struct budget_
 			budget_ci->budget.dvb_frontend = NULL;
 		}
 	}
+
+	if (budget_ci->budget.dvb_frontend)
+		ttpci_install_ts_streaming_workaround(&budget_ci->budget);
 }
 
 static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
diff -r 0bcf77433dc0 linux/drivers/media/dvb/ttpci/budget-core.c
--- a/linux/drivers/media/dvb/ttpci/budget-core.c	Thu Jun 29 21:30:51 2006 +0200
+++ b/linux/drivers/media/dvb/ttpci/budget-core.c	Fri Jun 30 11:58:45 2006 +0100
@@ -59,26 +59,28 @@ MODULE_PARM_DESC(bufsize, "DMA buffer si
  * TT budget / WinTV Nova
  ****************************************************************************/
 
-static int stop_ts_capture(struct budget *budget)
-{
-	dprintk(2, "budget: %p\n", budget);
-
-	if (--budget->feeding)
-		return budget->feeding;
+static int stop_ts_capture(struct budget *budget, int force)
+{
+	dprintk(2, "budget: %p\n", budget);
+
+	if (!force)
+		if (--budget->feeding)
+			return budget->feeding;
 
 	saa7146_write(budget->dev, MC1, MASK_20);	// DMA3 off
 	SAA7146_IER_DISABLE(budget->dev, MASK_10);
 	return 0;
 }
 
-static int start_ts_capture(struct budget *budget)
+static int start_ts_capture(struct budget *budget, int force)
 {
 	struct saa7146_dev *dev = budget->dev;
 
 	dprintk(2, "budget: %p\n", budget);
 
-	if (budget->feeding)
-		return ++budget->feeding;
+	if (!force)
+		if (budget->feeding)
+			return ++budget->feeding;
 
 	saa7146_write(dev, MC1, MASK_20);	// DMA3 off
 
@@ -139,6 +141,9 @@ static int start_ts_capture(struct budge
 	SAA7146_IER_ENABLE(budget->dev, MASK_10);	/* VPE */
 	saa7146_write(dev, MC1, (MASK_04 | MASK_20));	/* DMA3 on */
 
+	if (force)
+		return 0;
+
 	return ++budget->feeding;
 }
 
@@ -276,7 +281,7 @@ static int budget_start_feed(struct dvb_
 
 	spin_lock(&budget->feedlock);
 	feed->pusi_seen = 0; /* have a clean section start */
-	status = start_ts_capture(budget);
+	status = start_ts_capture(budget, 0);
 	spin_unlock(&budget->feedlock);
 	return status;
 }
@@ -290,9 +295,29 @@ static int budget_stop_feed(struct dvb_d
 	dprintk(2, "budget: %p\n", budget);
 
 	spin_lock(&budget->feedlock);
-	status = stop_ts_capture(budget);
+	status = stop_ts_capture(budget, 0);
 	spin_unlock(&budget->feedlock);
 	return status;
+}
+
+static int budget_fix_feed(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct budget* budget = (struct budget*) fe->dvb->priv;
+	int ret = -EINVAL;
+
+	if (budget->read_status_fix)
+		ret = budget->read_status_fix(fe, status);
+
+	if ((ret == 0) && ((*status) & FE_HAS_LOCK)) {
+		spin_lock(&budget->feedlock);
+		stop_ts_capture(budget, 1);
+		start_ts_capture(budget, 1);
+		spin_unlock(&budget->feedlock);
+		dprintk(2, "budget: Performed SAA7146 ts streaming workaround %p\n", budget);
+		budget->dvb_frontend->ops.read_status = budget->read_status_fix;
+	}
+
+	return ret;
 }
 
 static int budget_register(struct budget *budget)
@@ -491,6 +516,14 @@ int ttpci_budget_deinit(struct budget *b
 	return 0;
 }
 
+void ttpci_install_ts_streaming_workaround(struct budget *budget)
+{
+	if (budget->dvb_frontend) {
+		budget->read_status_fix = budget->dvb_frontend->ops.read_status;
+		budget->dvb_frontend->ops.read_status = budget_fix_feed;
+	}
+}
+
 void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr)
 {
 	struct budget *budget = (struct budget *) dev->ext_priv;
@@ -510,8 +543,8 @@ void ttpci_budget_set_video_port(struct 
 	if (budget->feeding) {
 		int oldfeeding = budget->feeding;
 		budget->feeding = 1;
-		stop_ts_capture(budget);
-		start_ts_capture(budget);
+		stop_ts_capture(budget, 1);
+		start_ts_capture(budget, 1);
 		budget->feeding = oldfeeding;
 	}
 	spin_unlock(&budget->feedlock);
@@ -523,6 +556,7 @@ EXPORT_SYMBOL_GPL(ttpci_budget_deinit);
 EXPORT_SYMBOL_GPL(ttpci_budget_deinit);
 EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
 EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port);
+EXPORT_SYMBOL_GPL(ttpci_install_ts_streaming_workaround);
 EXPORT_SYMBOL_GPL(budget_debug);
 
 MODULE_LICENSE("GPL");
diff -r 0bcf77433dc0 linux/drivers/media/dvb/ttpci/budget-patch.c
--- a/linux/drivers/media/dvb/ttpci/budget-patch.c	Thu Jun 29 21:30:51 2006 +0200
+++ b/linux/drivers/media/dvb/ttpci/budget-patch.c	Fri Jun 30 11:58:45 2006 +0100
@@ -372,6 +372,9 @@ static void frontend_init(struct budget_
 			budget->dvb_frontend = NULL;
 		}
 	}
+
+	if (budget->dvb_frontend)
+		ttpci_install_ts_streaming_workaround(budget);
 }
 
 /* written by Emard */
diff -r 0bcf77433dc0 linux/drivers/media/dvb/ttpci/budget.c
--- a/linux/drivers/media/dvb/ttpci/budget.c	Thu Jun 29 21:30:51 2006 +0200
+++ b/linux/drivers/media/dvb/ttpci/budget.c	Fri Jun 30 11:58:45 2006 +0100
@@ -441,6 +441,7 @@ static void frontend_init(struct budget 
 		if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend))
 			goto error_out;
 	}
+	ttpci_install_ts_streaming_workaround(budget);
 	return;
 
 error_out:
diff -r 0bcf77433dc0 linux/drivers/media/dvb/ttpci/budget.h
--- a/linux/drivers/media/dvb/ttpci/budget.h	Thu Jun 29 21:30:51 2006 +0200
+++ b/linux/drivers/media/dvb/ttpci/budget.h	Fri Jun 30 11:58:45 2006 +0100
@@ -86,6 +86,7 @@ struct budget {
 
 	struct dvb_adapter dvb_adapter;
 	struct dvb_frontend *dvb_frontend;
+	int (*read_status_fix)(struct dvb_frontend* fe, fe_status_t* status);
 	void *priv;
 };
 
@@ -126,4 +127,8 @@ extern int ttpci_budget_debiwrite(struct
 extern int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, int count, u32 value,
 				  int uselocks, int nobusyloop);
 
+// should be called after the frontend is registered to install the fix
+// for cold-booted-no-TS-data saa7146 workaround.
+extern void ttpci_install_ts_streaming_workaround(struct budget *budget);
+
 #endif
_______________________________________________

linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux