linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c
<<
>>
Prefs
   1/*
   2 * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
   3 *
   4 * flexcop-hw-filter.c - pid and mac address filtering and corresponding control functions.
   5 *
   6 * see flexcop.c for copyright information.
   7 */
   8#include "flexcop.h"
   9
  10static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff)
  11{
  12        flexcop_set_ibi_value(ctrl_208,Rcv_Data_sig,onoff);
  13
  14        deb_ts("rcv_data is now: '%s'\n",onoff ? "on" : "off");
  15}
  16
  17void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff)
  18{
  19        flexcop_set_ibi_value(ctrl_208,SMC_Enable_sig,onoff);
  20}
  21
  22static void flexcop_null_filter_ctrl(struct flexcop_device *fc, int onoff)
  23{
  24        flexcop_set_ibi_value(ctrl_208,Null_filter_sig,onoff);
  25}
  26
  27void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6])
  28{
  29        flexcop_ibi_value v418,v41c;
  30        v41c = fc->read_ibi_reg(fc,mac_address_41c);
  31
  32        v418.mac_address_418.MAC1 = mac[0];
  33        v418.mac_address_418.MAC2 = mac[1];
  34        v418.mac_address_418.MAC3 = mac[2];
  35        v418.mac_address_418.MAC6 = mac[3];
  36        v41c.mac_address_41c.MAC7 = mac[4];
  37        v41c.mac_address_41c.MAC8 = mac[5];
  38
  39        fc->write_ibi_reg(fc,mac_address_418,v418);
  40        fc->write_ibi_reg(fc,mac_address_41c,v41c);
  41}
  42
  43void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff)
  44{
  45        flexcop_set_ibi_value(ctrl_208,MAC_filter_Mode_sig,onoff);
  46}
  47
  48static void flexcop_pid_group_filter(struct flexcop_device *fc, u16 pid, u16 mask)
  49{
  50        /* index_reg_310.extra_index_reg need to 0 or 7 to work */
  51        flexcop_ibi_value v30c;
  52        v30c.pid_filter_30c_ext_ind_0_7.Group_PID = pid;
  53        v30c.pid_filter_30c_ext_ind_0_7.Group_mask = mask;
  54        fc->write_ibi_reg(fc,pid_filter_30c,v30c);
  55}
  56
  57static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int onoff)
  58{
  59        flexcop_set_ibi_value(ctrl_208,Mask_filter_sig,onoff);
  60}
  61
  62/* this fancy define reduces the code size of the quite similar PID controlling of
  63 * the first 6 PIDs
  64 */
  65
  66#define pid_ctrl(vregname,field,enablefield,trans_field,transval) \
  67        flexcop_ibi_value vpid = fc->read_ibi_reg(fc, vregname), \
  68                                          v208 = fc->read_ibi_reg(fc, ctrl_208); \
  69\
  70        vpid.vregname.field = onoff ? pid : 0x1fff; \
  71        vpid.vregname.trans_field = transval; \
  72        v208.ctrl_208.enablefield = onoff; \
  73\
  74        fc->write_ibi_reg(fc,vregname,vpid); \
  75        fc->write_ibi_reg(fc,ctrl_208,v208);
  76
  77static void flexcop_pid_Stream1_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
  78{
  79        pid_ctrl(pid_filter_300,Stream1_PID,Stream1_filter_sig,Stream1_trans,0);
  80}
  81
  82static void flexcop_pid_Stream2_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
  83{
  84        pid_ctrl(pid_filter_300,Stream2_PID,Stream2_filter_sig,Stream2_trans,0);
  85}
  86
  87static void flexcop_pid_PCR_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
  88{
  89        pid_ctrl(pid_filter_304,PCR_PID,PCR_filter_sig,PCR_trans,0);
  90}
  91
  92static void flexcop_pid_PMT_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
  93{
  94        pid_ctrl(pid_filter_304,PMT_PID,PMT_filter_sig,PMT_trans,0);
  95}
  96
  97static void flexcop_pid_EMM_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
  98{
  99        pid_ctrl(pid_filter_308,EMM_PID,EMM_filter_sig,EMM_trans,0);
 100}
 101
 102static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
 103{
 104        pid_ctrl(pid_filter_308,ECM_PID,ECM_filter_sig,ECM_trans,0);
 105}
 106
 107static void flexcop_pid_control(struct flexcop_device *fc, int index, u16 pid,int onoff)
 108{
 109        if (pid == 0x2000)
 110                return;
 111
 112        deb_ts("setting pid: %5d %04x at index %d '%s'\n",pid,pid,index,onoff ? "on" : "off");
 113
 114        /* We could use bit magic here to reduce source code size.
 115         * I decided against it, but to use the real register names */
 116        switch (index) {
 117                case 0: flexcop_pid_Stream1_PID_ctrl(fc,pid,onoff); break;
 118                case 1: flexcop_pid_Stream2_PID_ctrl(fc,pid,onoff); break;
 119                case 2: flexcop_pid_PCR_PID_ctrl(fc,pid,onoff); break;
 120                case 3: flexcop_pid_PMT_PID_ctrl(fc,pid,onoff); break;
 121                case 4: flexcop_pid_EMM_PID_ctrl(fc,pid,onoff); break;
 122                case 5: flexcop_pid_ECM_PID_ctrl(fc,pid,onoff); break;
 123                default:
 124                        if (fc->has_32_hw_pid_filter && index < 38) {
 125                                flexcop_ibi_value vpid,vid;
 126
 127                                /* set the index */
 128                                vid = fc->read_ibi_reg(fc,index_reg_310);
 129                                vid.index_reg_310.index_reg = index - 6;
 130                                fc->write_ibi_reg(fc,index_reg_310, vid);
 131
 132                                vpid = fc->read_ibi_reg(fc,pid_n_reg_314);
 133                                vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff;
 134                                vpid.pid_n_reg_314.PID_enable_bit = onoff;
 135                                fc->write_ibi_reg(fc,pid_n_reg_314, vpid);
 136                        }
 137                        break;
 138        }
 139}
 140
 141static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc,int onoff)
 142{
 143        if (fc->fullts_streaming_state != onoff) {
 144                deb_ts("%s full TS transfer\n",onoff ? "enabling" : "disabling");
 145                flexcop_pid_group_filter(fc, 0, 0x1fe0 * (!onoff));
 146                flexcop_pid_group_filter_ctrl(fc,onoff);
 147                fc->fullts_streaming_state = onoff;
 148        }
 149        return 0;
 150}
 151
 152int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff)
 153{
 154        int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32;
 155
 156        fc->feedcount += onoff ? 1 : -1; /* the number of PIDs/Feed currently requested */
 157        if (dvbdmxfeed->index >= max_pid_filter)
 158                fc->extra_feedcount += onoff ? 1 : -1;
 159
 160        /* toggle complete-TS-streaming when:
 161         * - pid_filtering is not enabled and it is the first or last feed requested
 162         * - pid_filtering is enabled,
 163         *   - but the number of requested feeds is exceeded
 164         *   - or the requested pid is 0x2000 */
 165
 166        if (!fc->pid_filtering && fc->feedcount == onoff)
 167                flexcop_toggle_fullts_streaming(fc,onoff);
 168
 169        if (fc->pid_filtering) {
 170                flexcop_pid_control(fc,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
 171
 172                if (fc->extra_feedcount > 0)
 173                        flexcop_toggle_fullts_streaming(fc,1);
 174                else if (dvbdmxfeed->pid == 0x2000)
 175                        flexcop_toggle_fullts_streaming(fc,onoff);
 176                else
 177                        flexcop_toggle_fullts_streaming(fc,0);
 178        }
 179
 180        /* if it was the first or last feed request change the stream-status */
 181        if (fc->feedcount == onoff) {
 182                flexcop_rcv_data_ctrl(fc,onoff);
 183                if (fc->stream_control) /* device specific stream control */
 184                        fc->stream_control(fc,onoff);
 185
 186                /* feeding stopped -> reset the flexcop filter*/
 187                if (onoff == 0) {
 188                        flexcop_reset_block_300(fc);
 189                        flexcop_hw_filter_init(fc);
 190                }
 191        }
 192
 193        return 0;
 194}
 195
 196void flexcop_hw_filter_init(struct flexcop_device *fc)
 197{
 198        int i;
 199        flexcop_ibi_value v;
 200        for (i = 0; i < 6 + 32*fc->has_32_hw_pid_filter; i++)
 201                flexcop_pid_control(fc,i,0x1fff,0);
 202
 203        flexcop_pid_group_filter(fc, 0, 0x1fe0);
 204        flexcop_pid_group_filter_ctrl(fc,0);
 205
 206        v = fc->read_ibi_reg(fc,pid_filter_308);
 207        v.pid_filter_308.EMM_filter_4 = 1;
 208        v.pid_filter_308.EMM_filter_6 = 0;
 209        fc->write_ibi_reg(fc,pid_filter_308,v);
 210
 211        flexcop_null_filter_ctrl(fc, 1);
 212}
 213
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.