[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