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