summaryrefslogtreecommitdiff
path: root/linux/drivers/media
diff options
context:
space:
mode:
authorHolger Waechtler <devnull@localhost>2003-02-03 08:23:35 +0000
committerHolger Waechtler <devnull@localhost>2003-02-03 08:23:35 +0000
commita862459628a05dd5a3a454c0e7fa2e6dd5384035 (patch)
treec670fb852bef6460d84c546e83eda71baac978ca /linux/drivers/media
parentb512dccd9c99886629b04291b4b391c5c6639a45 (diff)
downloadmediapointer-dvb-s2-a862459628a05dd5a3a454c0e7fa2e6dd5384035.tar.gz
mediapointer-dvb-s2-a862459628a05dd5a3a454c0e7fa2e6dd5384035.tar.bz2
new fidbirq() by <emard@softhome.net> w/ heuristic recovery code for
lost interrupts. Let's see how it works... CPU and PCI can be heavy loaded and not properly configured, VSYNC trigger timing can be inaccurate. Two DVB cards can share the same interrupt, sometimes even whole interrupt can be lost.
Diffstat (limited to 'linux/drivers/media')
-rw-r--r--linux/drivers/media/dvb/ttpci-budget/budget-core.c78
-rw-r--r--linux/drivers/media/dvb/ttpci-budget/budget.h8
2 files changed, 69 insertions, 17 deletions
diff --git a/linux/drivers/media/dvb/ttpci-budget/budget-core.c b/linux/drivers/media/dvb/ttpci-budget/budget-core.c
index 90b4d4227..d7ce45356 100644
--- a/linux/drivers/media/dvb/ttpci-budget/budget-core.c
+++ b/linux/drivers/media/dvb/ttpci-budget/budget-core.c
@@ -105,32 +105,80 @@ TTBStart(struct budget_s *budget)
return ++budget->feeding;
}
+/* TS_PACKETS is minumum number of accumulated 188-byte packets
+** (TS_SIZE=188) that is considered 'complete' and can
+** be delivered to the sw_demux in one 'quantum'.
+** TS_QUANTUM is size in bytes of TS_PACKETS
+** TS_MAX_PACKETS is number of TS_PACKETS in one DMA window
+** TS_BUFLEN is 1024*188
+*/
static
void fidbirq (unsigned long data)
{
struct budget_s *budget = (struct budget_s*) data;
u8 *mem=(u8 *)(budget->grabbing);
- int num=512;
- int field=0x80 & saa7146_read(budget->dev, PSR);
+ u8 oldtsf = budget->tsf;
+ u8 newtsf = 0x80 & saa7146_read(budget->dev, PSR);
+ u16 oldpkt = budget->ttbp;
+ u16 newpkt = saa7146_read(budget->dev, PCI_VDP3)/TS_QUANTUM; /* PCI_VDP3 = 0..TS_BUFLEN-1 */
+ u8 *olddma = mem + oldpkt*TS_QUANTUM; /* rounded to first complete packet */
DEB_EE(("budget: %p\n",budget));
+
+ /* Zero-Packet-Loss fidbirq by EMARD */
- if (field) {
- if (field==budget->tsf)
- num=1024;
- else
- mem+=TS_BUFLEN/2;
- } else {
- if (field==budget->tsf) {
- if (budget->feeding && mem[TS_BUFLEN/2]==0x47)
- dvb_dmx_swfilter_packets(&budget->demux,
- mem+TS_BUFLEN/2, 512 );
+ budget->ttbp = newpkt;
+ budget->tsf = newtsf;
+
+ /* exit immediately when the card is not set for feeding
+ ** or when values are out of expected boundaries
+ */
+ if(budget->feeding == 0 ||
+ oldpkt >= TS_MAX_PACKETS || newpkt >= TS_MAX_PACKETS)
+ return;
+
+ /* use heuristic methods for recovering from lost interrupt
+ */
+ if(oldtsf == newtsf)
+ {
+ /* interrupt is probably lost, some data can't be
+ ** retrieved because of DMA overwriting, but let's
+ ** try to save what is left of good data in the DMA
+ ** window.
+ */
+ if(newpkt != oldpkt)
+ { /* DMA is probably in progress right now,
+ ** overwriting data. Shift oldpkt 1 packets
+ ** forward from newpkt as a gap for racing with
+ ** ongoing DMA transfer. Consider TS_MAX_PACKETS-1 packets
+ ** are still valid in DMA window.
+ */
+ oldpkt = (newpkt + 1) % TS_MAX_PACKETS;
+ olddma = mem + oldpkt*TS_QUANTUM;
+ /* from now on, proceed as usual */
}
}
- budget->tsf=field;
- if (budget->feeding && mem[0]==0x47)
- dvb_dmx_swfilter_packets(&budget->demux, mem, num);
+ if(oldpkt < newpkt)
+ { /* no wraparound - dump linear data
+ ** from olddma to newdma
+ */
+ if(*olddma == 0x47)
+ dvb_dmx_swfilter_packets(&budget->demux, olddma,
+ TS_PACKETS*(newpkt-oldpkt));
+ }
+ else
+ { /* wraparound - dump in two chunks,
+ ** from olddma to end of DMA window
+ ** and from begin of DMA window to newdma
+ */
+ if(*olddma == 0x47)
+ dvb_dmx_swfilter_packets(&budget->demux, olddma,
+ TS_PACKETS*(TS_MAX_PACKETS - oldpkt));
+ if(*mem == 0x47 && newpkt > 0)
+ dvb_dmx_swfilter_packets(&budget->demux, mem,
+ TS_PACKETS*newpkt);
+ }
}
inline static void
diff --git a/linux/drivers/media/dvb/ttpci-budget/budget.h b/linux/drivers/media/dvb/ttpci-budget/budget.h
index 7df52e804..0a0a5b16b 100644
--- a/linux/drivers/media/dvb/ttpci-budget/budget.h
+++ b/linux/drivers/media/dvb/ttpci-budget/budget.h
@@ -46,8 +46,8 @@ struct budget_s {
int fe_synced;
struct semaphore pid_mutex;
- int tsf;
- u32 ttbp;
+ u8 tsf;
+ u16 ttbp;
int feeding;
int registered;
@@ -68,6 +68,10 @@ static struct saa7146_pci_extension_data x_var = { \
#define TS_HEIGHT (1024/4)
#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
+#define TS_PACKETS 1
+#define TS_QUANTUM (TS_PACKETS*TS_SIZE)
+#define TS_MAX_PACKETS (TS_BUFLEN/TS_QUANTUM)
+
#define BUDGET_TT 0
#define BUDGET_TT_HW_DISEQC 1
#define BUDGET_KNC1 2