[linux-dvb] [RFC] multi std silicon tuners and analog tuners

Manu Abraham abraham.manu at gmail.com
Wed Apr 4 22:16:27 CEST 2007


Hi All,

Currently, we have silicon tuners loading FIR filter specific DSP boot
codes for tuners as well, of course Silicon tuners. While working with
the STB6100 silicon tuner which had been a rogue for that matter, found
that the same could be extended for tuners as well.

Some tuners as what i see, loads delivery system specific firmware to
optimize the FIR filter characteristics on the teeny DSP of the silicon
tuner. In some cases the DSP boot code is as well included in the
firmware which needs a reset of the DSP, but in many cases doesn't need so

The approach can be used for *all* hybrid tuners how complex it might be
since it leaves room for future expansion as well.

My thoughts go like this.

currently the existing infrastructure is assumed to be thus ...

DVB API is modified with the multiproto API update which thus has the
enhanced Silicon tuner changes already for the STB6100.

with regards to the DVB API , the userspace sets a delivery system for
the demodulator, which can be a cached parameter at the bridge(ie, the
card config to be precise, which is also known as the glue logic)

so when subsystem A acquires control, a lock is acquired by the bridge
(the bridge can be imagined as a fulcrum for switching between systems)
This locking would be a FSM for handling different switches.

now the bridge can acquire/release locks, needs some code additions to
the bridge to have this, for old devices it doesn't matter at all.

now when subsystem B request control, it makes a request to the control
manager on the bridge, the control is passed all the way down from the
frontend(DVB)/ tuner(V4L) so it still remains quite independent the
tuner/frontend part from the bridge

the silicon tuners, since it is a FIR filter, it will need parameter
specific firmware loads since the FIR characteristics needs to be
modified. In such a case the current delivery system switch that we use
for multiproto can be used

The stb0899 uses a set_delsys callback to handle different delivery systems

     1324 void stb0899_set_delsys(struct stb0899_state *state)
     1325 {
     1326   u8 reg;
     1327   u8 stop_clk[2];
     1328
     1329   stop_clk[0] = stb0899_read_reg(state, STB0899_STOPCLK1);
     1330   stop_clk[1] = stb0899_read_reg(state, STB0899_STOPCLK2);
     1331
     1332   switch (state->delsys) {
     1333   case DVBFE_DELSYS_DVBS:
    1334           dprintk(verbose, FE_DEBUG, 1, "Delivery System --
DVB-S");
     1335           /* FECM/Viterbi ON      */
     1336           reg = stb0899_read_reg(state, STB0899_FECM);
     1337           STB0899_SETFIELD_VAL(reg, 0,
STB0899_WIDTH_FECM_RSVD0, STB0899_OFFST_FECM_RSVD0);
     1338           STB0899_SETFIELD_VAL(reg, 1,
STB0899_WIDTH_FECM_VITERBI_ON, STB0899_OFFST_FECM_VITERBI_ON);
     1339           stb0899_write_reg(state, STB0899_FECM, reg);
     1340
     1341           stb0899_write_reg(state, STB0899_RSULC, 0xb1);
     1342           stb0899_write_reg(state, STB0899_TSULC, 0x40);
     1343           stb0899_write_reg(state, STB0899_RSLLC, 0x42);
     1344           stb0899_write_reg(state, STB0899_TSLPL, 0x12);
     1345
     1346           reg = stb0899_read_reg(state, STB0899_TSTRES);
     1347           STB0899_SETFIELD_VAL(reg, 1, STB0899_WIDTH_FRESLDPC,
STB0899_OFFST_FRESLDPC);
     1348           stb0899_write_reg(state, STB0899_TSTRES, reg);
     1349
     1350           STB0899_SETFIELD_VAL(stop_clk[0], 1,
STB0899_WIDTH_STOP_CHK8PSK, STB0899_OFFST_STOP_CHK8PSK);
     1351           STB0899_SETFIELD_VAL(stop_clk[0], 1,
STB0899_WIDTH_STOP_CKFEC108, STB0899_OFFST_STOP_CKFEC108);
     1352           STB0899_SETFIELD_VAL(stop_clk[0], 1,
STB0899_WIDTH_STOP_CKFEC216, STB0899_OFFST_STOP_CKFEC216);
     1353
     1354           STB0899_SETFIELD_VAL(stop_clk[1], 1,
STB0899_WIDTH_STOP_CKPKDLIN108, STB0899_OFFST_STOP_CKPKDLIN108);
     1355           STB0899_SETFIELD_VAL(stop_clk[1], 1,
STB0899_WIDTH_STOP_CKPKDLIN216, STB0899_OFFST_STOP_CKPKDLIN216);
     1356
     1357           STB0899_SETFIELD_VAL(stop_clk[0], 1,
STB0899_WIDTH_STOP_CKINTBUF216, STB0899_OFFST_STOP_CKINTBUF216);
     1358           STB0899_SETFIELD_VAL(stop_clk[0], 1,
STB0899_WIDTH_STOP_CKCORE216, STB0899_OFFST_STOP_CKCORE216);
     1359
     1360           STB0899_SETFIELD_VAL(stop_clk[1], 1,
STB0899_WIDTH_STOP_CKS2DMD108, STB0899_OFFST_STOP_CKS2DMD108);
     1361           break;
     1362   case DVBFE_DELSYS_DVBS2:
     1363           /* FECM/Viterbi OFF      */
     1364           reg = stb0899_read_reg(state, STB0899_FECM);
     1365           STB0899_SETFIELD_VAL(reg, 0,
STB0899_WIDTH_FECM_RSVD0, STB0899_OFFST_FECM_RSVD0);
     1366           STB0899_SETFIELD_VAL(reg, 0,
STB0899_WIDTH_FECM_VITERBI_ON, STB0899_OFFST_FECM_VITERBI_ON);
     1367           stb0899_write_reg(state, STB0899_FECM, reg);
     1368
     1369           stb0899_write_reg(state, STB0899_RSULC, 0xb1);
     1370           stb0899_write_reg(state, STB0899_TSULC, 0x42);
     1371           stb0899_write_reg(state, STB0899_RSLLC, 0x40);
     1372           stb0899_write_reg(state, STB0899_TSLPL, 0x02);
     1373
     1374           reg = stb0899_read_reg(state, STB0899_TSTRES);
     1375           STB0899_SETFIELD_VAL(reg, 0, STB0899_WIDTH_FRESLDPC,
STB0899_OFFST_FRESLDPC);
     1376           stb0899_write_reg(state, STB0899_TSTRES, reg);
     1377
     1378           STB0899_SETFIELD_VAL(stop_clk[0], 1,
STB0899_WIDTH_STOP_CHK8PSK, STB0899_OFFST_STOP_CHK8PSK);
     1379           STB0899_SETFIELD_VAL(stop_clk[0], 0,
STB0899_WIDTH_STOP_CKFEC108, STB0899_OFFST_STOP_CKFEC108);
     1380           STB0899_SETFIELD_VAL(stop_clk[0], 0,
STB0899_WIDTH_STOP_CKFEC216, STB0899_OFFST_STOP_CKFEC216);
     1381
     1382           STB0899_SETFIELD_VAL(stop_clk[1], 0,
STB0899_WIDTH_STOP_CKPKDLIN108, STB0899_OFFST_STOP_CKPKDLIN108);
     1383           STB0899_SETFIELD_VAL(stop_clk[1], 0,
STB0899_WIDTH_STOP_CKPKDLIN216, STB0899_OFFST_STOP_CKPKDLIN216);
     1384
     1385           STB0899_SETFIELD_VAL(stop_clk[0], 0,
STB0899_WIDTH_STOP_CKINTBUF216, STB0899_OFFST_STOP_CKINTBUF216);
     1386           STB0899_SETFIELD_VAL(stop_clk[0], 0,
STB0899_WIDTH_STOP_CKCORE216, STB0899_OFFST_STOP_CKCORE216);
     1387
     1388           STB0899_SETFIELD_VAL(stop_clk[1], 0,
STB0899_WIDTH_STOP_CKS2DMD108, STB0899_OFFST_STOP_CKS2DMD108);
     1389           break;
     1390   case DVBFE_DELSYS_DSS:
     1391           /* FECM/Viterbi ON      */
     1392           reg = stb0899_read_reg(state, STB0899_FECM);
     1393           STB0899_SETFIELD_VAL(reg, 1,
STB0899_WIDTH_FECM_RSVD0, STB0899_OFFST_FECM_RSVD0);
     1394           STB0899_SETFIELD_VAL(reg, 1,
STB0899_WIDTH_FECM_VITERBI_ON, STB0899_OFFST_FECM_VITERBI_ON);
     1395           stb0899_write_reg(state, STB0899_FECM, reg);
     1396
     1397           stb0899_write_reg(state, STB0899_RSULC, 0xa1);
     1398           stb0899_write_reg(state, STB0899_TSULC, 0x61);
     1399           stb0899_write_reg(state, STB0899_RSLLC, 0x42);
     1400
     1401           reg = stb0899_read_reg(state, STB0899_TSTRES);
     1402           STB0899_SETFIELD_VAL(reg, 1, STB0899_WIDTH_FRESLDPC,
STB0899_OFFST_FRESLDPC);
     1403           stb0899_write_reg(state, STB0899_TSTRES, reg);
     1404
     1405           STB0899_SETFIELD_VAL(stop_clk[0], 1,
STB0899_WIDTH_STOP_CHK8PSK, STB0899_OFFST_STOP_CHK8PSK);
     1406           STB0899_SETFIELD_VAL(stop_clk[0], 1,
STB0899_WIDTH_STOP_CKFEC108, STB0899_OFFST_STOP_CKFEC108);
     1407           STB0899_SETFIELD_VAL(stop_clk[0], 1,
STB0899_WIDTH_STOP_CKFEC216, STB0899_OFFST_STOP_CKFEC216);
     1408
     1409           STB0899_SETFIELD_VAL(stop_clk[1], 1,
STB0899_WIDTH_STOP_CKPKDLIN108, STB0899_OFFST_STOP_CKPKDLIN108);
     1410           STB0899_SETFIELD_VAL(stop_clk[1], 1,
STB0899_WIDTH_STOP_CKPKDLIN216, STB0899_OFFST_STOP_CKPKDLIN216);
     1411
     1412           STB0899_SETFIELD_VAL(stop_clk[0], 0,
STB0899_WIDTH_STOP_CKCORE216, STB0899_OFFST_STOP_CKCORE216);
     1413
     1414           STB0899_SETFIELD_VAL(stop_clk[1], 1,
STB0899_WIDTH_STOP_CKS2DMD108, STB0899_OFFST_STOP_CKS2DMD108);
     1415           break;
     1416   default:
     1417           dprintk(verbose, FE_ERROR, 1, "Unsupported delivery
system");
     1418           break;
     1419   }
     1422 }

The same can be used to achieve delivery system dependent FIR filter
characteric boot codes for the tuner DSP just how it is used for the demod

The finer aspect is that, even that can be still made easier with the
updated
silicon tuner callbacks in dvb_frontend.h

With regards to the DVB_FRONTEND the changes do look like this ..

http://linuxtv.org/hg/~manu/stb0899-c5?f=5d0d69f5fabf;file=linux/drivers/media/dvb/dvb-core/dvb_frontend.h;style=gitweb

        struct dvb_tuner_info {
               char name[128];
               u32 frequency_min;
               u32 frequency_max;
               u32 frequency_step;
               u32 bandwidth_min;
               u32 bandwidth_max;
               u32 bandwidth_step;
       };


      enum tuner_param {
      	DVBFE_TUNER_FREQUENCY                = (1 <<  0),
        DVBFE_TUNER_TUNERSTEP                = (1 <<  1),
        DVBFE_TUNER_IFFREQ                = (1 <<  2),
        DVBFE_TUNER_BANDWIDTH                = (1 <<  3),
        DVBFE_TUNER_REFCLOCK                = (1 <<  4),
        DVBFE_TUNER_IQSENSE                = (1 <<  5),
        DVBFE_TUNER_DUMMY                = (1 << 31)

      };


    /**
       * These are provided seperately from set_params in order to
facilitate silicon
       * tuners which require sophisticated tuning loops,
controlling each parameter seperately.
       */

      int (*set_state)(struct dvb_frontend *fe, enum tuner_param
param, struct tuner_state *state);

      int (*get_state)(struct dvb_frontend *fe, enum tuner_param
param, struct tuner_state *state);



with regards to TUNER (V4L) the same can be achieved using set standard
or similar.
Will have additionally one more callback (a new one)


Manu




More information about the linux-dvb mailing list