[PATCH] dvb: flexcop: use hw pid filter
authorJohannes Stezenbach <js@linuxtv.org>
Tue, 17 May 2005 04:54:15 +0000 (21:54 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 17 May 2005 14:59:25 +0000 (07:59 -0700)
- enabled the HW PID by default for the PCI cards

- correct the TS demux parsing when PID filter is enabled (and thus the
  timer IRQ)

- rewrote the PID-filter and FULLTS control part in flexcop-hw-filter
  (thanks to Krzysztof Matula for pointing that out)

Signed-off-by: Patrick Boettcher <pb@linuxtv.org>
Signed-off-by: Johannes Stezenbach <js@linuxtv.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/media/dvb/b2c2/flexcop-common.h
drivers/media/dvb/b2c2/flexcop-hw-filter.c
drivers/media/dvb/b2c2/flexcop-pci.c

index 534876d616b86b47c15d7635ffd5bdb6f5e0225f..79e8581b4fb709e1c5f73271951b7907e048fcdc 100644 (file)
@@ -76,8 +76,10 @@ struct flexcop_device {
        struct semaphore i2c_sem;
 
        /* options and status */
+       int extra_feedcount;
        int feedcount;
        int pid_filtering;
+       int fullts_streaming_state;
 
        /* bus specific callbacks */
        flexcop_ibi_value (*read_ibi_reg)  (struct flexcop_device *, flexcop_ibi_register);
index 7a5399b569c7495664d7a9e9fd695c886565fcd5..2baf43d3ce8ffdcce73d556b107c12e36208f08d 100644 (file)
@@ -104,6 +104,9 @@ static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc, u16 pid, int ono
 
 static void flexcop_pid_control(struct flexcop_device *fc, int index, u16 pid,int onoff)
 {
+       if (pid == 0x2000)
+               return;
+
        deb_ts("setting pid: %5d %04x at index %d '%s'\n",pid,pid,index,onoff ? "on" : "off");
 
        /* We could use bit magic here to reduce source code size.
@@ -133,50 +136,50 @@ static void flexcop_pid_control(struct flexcop_device *fc, int index, u16 pid,in
        }
 }
 
+static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc,int onoff)
+{
+       if (fc->fullts_streaming_state != onoff) {
+               deb_ts("%s full TS transfer\n",onoff ? "enabling" : "disabling");
+               flexcop_pid_group_filter(fc, 0, 0x1fe0 * (!onoff));
+               flexcop_pid_group_filter_ctrl(fc,onoff);
+               fc->fullts_streaming_state = onoff;
+       }
+       return 0;
+}
+
 int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff)
 {
        int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32;
 
-       fc->feedcount += (onoff ? 1 : -1);
+       fc->feedcount += onoff ? 1 : -1;
+       if (dvbdmxfeed->index >= max_pid_filter)
+               fc->extra_feedcount += onoff ? 1 : -1;
 
-       /* when doing hw pid filtering, set the pid */
-       if (fc->pid_filtering)
-               flexcop_pid_control(fc,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
+       /* toggle complete-TS-streaming when:
+        * - pid_filtering is not enabled and it is the first or last feed requested
+        * - pid_filtering is enabled,
+        *   - but the number of requested feeds is exceeded
+        *   - or the requested pid is 0x2000 */
 
-       /* if it was the first feed request */
-       if (fc->feedcount == onoff && onoff) {
-               if (!fc->pid_filtering) {
-                       deb_ts("enabling full TS transfer\n");
-                       flexcop_pid_group_filter(fc, 0,0);
-                       flexcop_pid_group_filter_ctrl(fc,1);
-               }
+       if (!fc->pid_filtering && fc->feedcount == onoff)
+               flexcop_toggle_fullts_streaming(fc,onoff);
 
-               if (fc->stream_control)
-                       fc->stream_control(fc,1);
-               flexcop_rcv_data_ctrl(fc,1);
-
-       /* if there is no more feed left to feed */
-       } else if (fc->feedcount == onoff && !onoff) {
-               if (!fc->pid_filtering) {
-                       deb_ts("disabling full TS transfer\n");
-                       flexcop_pid_group_filter(fc, 0, 0x1fe0);
-                       flexcop_pid_group_filter_ctrl(fc,0);
-               }
-
-               flexcop_rcv_data_ctrl(fc,0);
-               if (fc->stream_control)
-                       fc->stream_control(fc,0);
+       if (fc->pid_filtering) {
+               flexcop_pid_control(fc,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
+
+               if (fc->extra_feedcount > 0)
+                       flexcop_toggle_fullts_streaming(fc,1);
+               else if (dvbdmxfeed->pid == 0x2000)
+                       flexcop_toggle_fullts_streaming(fc,onoff);
+               else
+                       flexcop_toggle_fullts_streaming(fc,0);
        }
 
-       /* if pid_filtering is on and more pids than the hw-filter can provide are
-        * requested enable the whole bandwidth.
-        */
-       if (fc->pid_filtering && fc->feedcount > max_pid_filter) {
-               flexcop_pid_group_filter(fc, 0,0);
-               flexcop_pid_group_filter_ctrl(fc,1);
-       } else if (fc->pid_filtering && fc->feedcount <= max_pid_filter) {
-               flexcop_pid_group_filter(fc, 0,0x1fe0);
-               flexcop_pid_group_filter_ctrl(fc,0);
+       /* if it was the first or last feed request change the stream-status */
+       if (fc->feedcount == onoff) {
+               flexcop_rcv_data_ctrl(fc,onoff);
+               if (fc->stream_control)
+                       fc->stream_control(fc,onoff);
        }
 
        return 0;
index c52286ea669f50c711ecc336105a51567fb88f41..78952096fb7478bc045b8c465d06ff744bc48eae 100644 (file)
@@ -9,7 +9,7 @@
 #define FC_LOG_PREFIX "flexcop-pci"
 #include "flexcop-common.h"
 
-static int enable_pid_filtering = 0;
+static int enable_pid_filtering = 1;
 module_param(enable_pid_filtering, int, 0444);
 MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1");
 
@@ -45,13 +45,14 @@ struct flexcop_pci {
        void __iomem *io_mem;
        u32 irq;
 /* buffersize (at least for DMA1, need to be % 188 == 0,
- * this is logic is required */
+ * this logic is required */
 #define FC_DEFAULT_DMA1_BUFSIZE (1280 * 188)
 #define FC_DEFAULT_DMA2_BUFSIZE (10 * 188)
        struct flexcop_dma dma[2];
 
        int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */
        u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */
+       int count;
 
        spinlock_t irq_lock;
 
@@ -99,15 +100,6 @@ static irqreturn_t flexcop_pci_irq(int irq, void *dev_id, struct pt_regs *regs)
 
        spin_lock_irq(&fc_pci->irq_lock);
 
-       deb_irq("irq: %08x cur_addr: %08x (%d), our addrs. 1: %08x 2: %08x; 0x000: "
-                       "%08x, 0x00c: %08x\n",v.raw,
-                       fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2,
-                       fc_pci->active_dma1_addr,
-                       fc_pci->dma[0].dma_addr0,fc_pci->dma[0].dma_addr1,
-                       fc->read_ibi_reg(fc,dma1_000).raw,
-                       fc->read_ibi_reg(fc,dma1_00c).raw);
-
-
        if (v.irq_20c.DMA1_IRQ_Status == 1) {
                if (fc_pci->active_dma1_addr == 0)
                        flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr0,fc_pci->dma[0].size / 188);
@@ -123,21 +115,28 @@ static irqreturn_t flexcop_pci_irq(int irq, void *dev_id, struct pt_regs *regs)
                        fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2;
                u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0;
 
+               deb_irq("irq: %08x cur_addr: %08x: cur_pos: %08x, last_cur_pos: %08x ",
+                               v.raw,cur_addr,cur_pos,fc_pci->last_dma1_cur_pos);
+
                /* buffer end was reached, restarted from the beginning
                 * pass the data from last_cur_pos to the buffer end to the demux
                 */
                if (cur_pos < fc_pci->last_dma1_cur_pos) {
+                       deb_irq(" end was reached: passing %d bytes ",(fc_pci->dma[0].size*2 - 1) - fc_pci->last_dma1_cur_pos);
                        flexcop_pass_dmx_data(fc_pci->fc_dev,
                                        fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos,
-                                       (fc_pci->dma[0].size*2 - 1) - fc_pci->last_dma1_cur_pos);
+                                       (fc_pci->dma[0].size*2) - fc_pci->last_dma1_cur_pos);
                        fc_pci->last_dma1_cur_pos = 0;
+                       fc_pci->count = 0;
                }
 
                if (cur_pos > fc_pci->last_dma1_cur_pos) {
+                       deb_irq(" passing %d bytes ",cur_pos - fc_pci->last_dma1_cur_pos);
                        flexcop_pass_dmx_data(fc_pci->fc_dev,
                                        fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos,
                                        cur_pos - fc_pci->last_dma1_cur_pos);
                }
+               deb_irq("\n");
 
                fc_pci->last_dma1_cur_pos = cur_pos;
        } else
@@ -301,6 +300,11 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
        fc->stream_control = flexcop_pci_stream_control;
 
+       if (enable_pid_filtering)
+               info("will use the HW PID filter.");
+       else
+               info("will pass the complete TS to the demuxer.");
+
        fc->pid_filtering = enable_pid_filtering;
        fc->bus_type = FC_PCI;