Commit c4ee3fd4 authored by Johannes Stezenbach's avatar Johannes Stezenbach Committed by Linus Torvalds

[PATCH] dvb: flexcop: use hw pid filter

- 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: default avatarPatrick Boettcher <pb@linuxtv.org>
Signed-off-by: default avatarJohannes Stezenbach <js@linuxtv.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 4853f16a
...@@ -76,8 +76,10 @@ struct flexcop_device { ...@@ -76,8 +76,10 @@ struct flexcop_device {
struct semaphore i2c_sem; struct semaphore i2c_sem;
/* options and status */ /* options and status */
int extra_feedcount;
int feedcount; int feedcount;
int pid_filtering; int pid_filtering;
int fullts_streaming_state;
/* bus specific callbacks */ /* bus specific callbacks */
flexcop_ibi_value (*read_ibi_reg) (struct flexcop_device *, flexcop_ibi_register); flexcop_ibi_value (*read_ibi_reg) (struct flexcop_device *, flexcop_ibi_register);
......
...@@ -104,6 +104,9 @@ static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc, u16 pid, int ono ...@@ -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) 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"); 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. /* 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 ...@@ -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 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; 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 */ /* toggle complete-TS-streaming when:
if (fc->pid_filtering) * - pid_filtering is not enabled and it is the first or last feed requested
flexcop_pid_control(fc,dvbdmxfeed->index,dvbdmxfeed->pid,onoff); * - 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->pid_filtering && fc->feedcount == onoff)
if (fc->feedcount == onoff && onoff) { flexcop_toggle_fullts_streaming(fc,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->stream_control) if (fc->pid_filtering) {
fc->stream_control(fc,1); flexcop_pid_control(fc,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
flexcop_rcv_data_ctrl(fc,1);
if (fc->extra_feedcount > 0)
/* if there is no more feed left to feed */ flexcop_toggle_fullts_streaming(fc,1);
} else if (fc->feedcount == onoff && !onoff) { else if (dvbdmxfeed->pid == 0x2000)
if (!fc->pid_filtering) { flexcop_toggle_fullts_streaming(fc,onoff);
deb_ts("disabling full TS transfer\n"); else
flexcop_pid_group_filter(fc, 0, 0x1fe0); flexcop_toggle_fullts_streaming(fc,0);
flexcop_pid_group_filter_ctrl(fc,0);
}
flexcop_rcv_data_ctrl(fc,0);
if (fc->stream_control)
fc->stream_control(fc,0);
} }
/* if pid_filtering is on and more pids than the hw-filter can provide are /* if it was the first or last feed request change the stream-status */
* requested enable the whole bandwidth. if (fc->feedcount == onoff) {
*/ flexcop_rcv_data_ctrl(fc,onoff);
if (fc->pid_filtering && fc->feedcount > max_pid_filter) { if (fc->stream_control)
flexcop_pid_group_filter(fc, 0,0); fc->stream_control(fc,onoff);
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);
} }
return 0; return 0;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#define FC_LOG_PREFIX "flexcop-pci" #define FC_LOG_PREFIX "flexcop-pci"
#include "flexcop-common.h" #include "flexcop-common.h"
static int enable_pid_filtering = 0; static int enable_pid_filtering = 1;
module_param(enable_pid_filtering, int, 0444); module_param(enable_pid_filtering, int, 0444);
MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1"); MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1");
...@@ -45,13 +45,14 @@ struct flexcop_pci { ...@@ -45,13 +45,14 @@ struct flexcop_pci {
void __iomem *io_mem; void __iomem *io_mem;
u32 irq; u32 irq;
/* buffersize (at least for DMA1, need to be % 188 == 0, /* 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_DMA1_BUFSIZE (1280 * 188)
#define FC_DEFAULT_DMA2_BUFSIZE (10 * 188) #define FC_DEFAULT_DMA2_BUFSIZE (10 * 188)
struct flexcop_dma dma[2]; struct flexcop_dma dma[2];
int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */ 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 */ u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */
int count;
spinlock_t irq_lock; spinlock_t irq_lock;
...@@ -99,15 +100,6 @@ static irqreturn_t flexcop_pci_irq(int irq, void *dev_id, struct pt_regs *regs) ...@@ -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); 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 (v.irq_20c.DMA1_IRQ_Status == 1) {
if (fc_pci->active_dma1_addr == 0) 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); 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) ...@@ -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; fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2;
u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0; 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 /* buffer end was reached, restarted from the beginning
* pass the data from last_cur_pos to the buffer end to the demux * pass the data from last_cur_pos to the buffer end to the demux
*/ */
if (cur_pos < fc_pci->last_dma1_cur_pos) { 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, flexcop_pass_dmx_data(fc_pci->fc_dev,
fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos, 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->last_dma1_cur_pos = 0;
fc_pci->count = 0;
} }
if (cur_pos > fc_pci->last_dma1_cur_pos) { 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, flexcop_pass_dmx_data(fc_pci->fc_dev,
fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos, fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos,
cur_pos - 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; fc_pci->last_dma1_cur_pos = cur_pos;
} else } else
...@@ -301,6 +300,11 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e ...@@ -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; 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->pid_filtering = enable_pid_filtering;
fc->bus_type = FC_PCI; fc->bus_type = FC_PCI;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment