Hi, Manu and I were just discussing this, and we think we have come up with an idea. See the attached patch. Note: this is just an idea - it needs completed. The patch is just illustrative - it won't tune or anything. Anyway: if you look at the frontend_init() code. Instead of calling the attach methods (eg. stv0299_attach()) directly, we instead define something like the macros I have added (e.g. STV0299_ATTACH). These use symbol_get() to dynamically get the address of the XXX_attach() method and, if found, call it. Otherwise they fake a NULL return, and the normal frontend failure code comes into effect. This method (suprisingly!) seems to work really well - dmesg for my test card in this machine when I modprobed the modified budget-ci module: saa7146: register extension 'budget_ci dvb'. ACPI: PCI Interrupt 0000:05:06.0[A] -> Link [APC1] -> GSI 16 (level, low) -> IRQ 66 saa7146: found saa7146 @ mem ffffc20010d04000 (revision 1, irq 66) (0x13c2,0x100f). saa7146 (0): dma buffer size 192512 DVB: registering new adapter (TT-Budget/WinTV-NOVA-CI PCI). adapter has MAC addr = 00:d0:5c:21:10:f5 input: Budget-CI dvb ir receiver saa7146 (0) as /class/input/input6 DVB: registering frontend 0 (ST STV0299 DVB-S)... The only DVB modules loaded are however: budget_ci budget_core saa7146 ttpci_eeprom stv0299 dvb_core Can anyone see anything fundamentally wrong with doing it this way? Due to the frontend refactoring a while back, we already have these nice tables of function pointers everywhere anyway. We do have a few static function calls to deal with - I just hacked 'em out in the patch. With the PLL refactoring (see my other post) more of these are going away anyway, so the few remaining ones can be dealt with in some neater manner.
diff -r 2b05b5271ae1 linux/drivers/media/dvb/ttpci/budget-ci.c --- a/linux/drivers/media/dvb/ttpci/budget-ci.c Thu Apr 13 12:29:04 2006 -0400 +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c Tue Apr 18 00:19:36 2006 +0100 @@ -590,6 +590,7 @@ static u8 philips_su1278_tt_inittab[] = static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) { +/* stv0299_writereg(fe, 0x0e, 0x44); if (srate >= 10000000) { stv0299_writereg(fe, 0x13, 0x97); @@ -616,6 +617,7 @@ static int philips_su1278_tt_set_symbol_ stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); stv0299_writereg(fe, 0x21, (ratio) & 0xf0); +*/ return 0; } @@ -742,17 +744,17 @@ static int philips_tdm1316l_pll_set(stru // setup PLL filter and TDA9889 switch (params->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: - tda1004x_write_byte(fe, 0x0C, 0x14); +// tda1004x_write_byte(fe, 0x0C, 0x14); filter = 0; break; case BANDWIDTH_7_MHZ: - tda1004x_write_byte(fe, 0x0C, 0x80); +// tda1004x_write_byte(fe, 0x0C, 0x80); filter = 0; break; case BANDWIDTH_8_MHZ: - tda1004x_write_byte(fe, 0x0C, 0x14); +// tda1004x_write_byte(fe, 0x0C, 0x14); filter = 1; break; @@ -857,13 +859,13 @@ static int dvbc_philips_tdm1316l_pll_set tuner_buf[3] = (cp << 5) | (filter << 3) | band; tuner_buf[4] = 0x80; - stv0297_enable_plli2c(fe); +// stv0297_enable_plli2c(fe); if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) return -EIO; msleep(50); - stv0297_enable_plli2c(fe); +// stv0297_enable_plli2c(fe); if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) return -EIO; @@ -972,23 +974,52 @@ static struct stv0297_config dvbc_philip .pll_set = dvbc_philips_tdm1316l_pll_set, }; - - +#define STV0299_ATTACH(RESULT, CONFIG, I2C_ADAP) \ +{ \ + struct dvb_frontend* (*a)(const struct stv0299_config* config, struct i2c_adapter* i2c); \ + request_module("stv0299"); \ + a = symbol_get(stv0299_attach); \ + if (a) RESULT = a(CONFIG, I2C_ADAP); \ + else RESULT = NULL; \ +} + +#define STV0297_ATTACH(RESULT, CONFIG, I2C_ADAP) \ +{ \ + struct dvb_frontend* (*a)(const struct stv0297_config* config, struct i2c_adapter* i2c); \ + request_module("stv0297"); \ + a = symbol_get(stv0297_attach); \ + if (a) RESULT = a(CONFIG, I2C_ADAP); \ + else RESULT = NULL; \ +} + +#define TDA10045_ATTACH(RESULT, CONFIG, I2C_ADAP) {\ + struct dvb_frontend* (*a)(const struct tda1004x_config* config, struct i2c_adapter* i2c); \ + request_module("tda1004x"); \ + a = symbol_get(tda10045_attach); \ + if (a) RESULT = a(CONFIG, I2C_ADAP); \ + else RESULT = NULL; \ +} + +#define TDA10046_ATTACH(RESULT, CONFIG, I2C_ADAP) {\ + struct dvb_frontend* (*a)(const struct tda1004x_config* config, struct i2c_adapter* i2c); \ + request_module("tda1004x"); \ + a = symbol_get(tda10046_attach); \ + if (a) RESULT = a(CONFIG, I2C_ADAP); \ + else RESULT = NULL; \ +} static void frontend_init(struct budget_ci *budget_ci) { switch (budget_ci->budget.dev->pci->subsystem_device) { case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059)) - budget_ci->budget.dvb_frontend = - stv0299_attach(&alps_bsru6_config, &budget_ci->budget.i2c_adap); + STV0299_ATTACH(budget_ci->budget.dvb_frontend, &alps_bsru6_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { break; } break; case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059)) - budget_ci->budget.dvb_frontend = - stv0299_attach(&philips_su1278_tt_config, &budget_ci->budget.i2c_adap); + STV0299_ATTACH(budget_ci->budget.dvb_frontend, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { break; } @@ -996,8 +1027,7 @@ static void frontend_init(struct budget_ case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt)) budget_ci->tuner_pll_address = 0x61; - budget_ci->budget.dvb_frontend = - stv0297_attach(&dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap); + STV0297_ATTACH(budget_ci->budget.dvb_frontend, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { break; } @@ -1005,8 +1035,7 @@ static void frontend_init(struct budget_ case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889) budget_ci->tuner_pll_address = 0x63; - budget_ci->budget.dvb_frontend = - tda10045_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap); + TDA10045_ATTACH(budget_ci->budget.dvb_frontend, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { break; } @@ -1014,15 +1043,14 @@ static void frontend_init(struct budget_ case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt)) budget_ci->tuner_pll_address = 0x60; - budget_ci->budget.dvb_frontend = - tda10046_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap); + TDA10046_ATTACH(budget_ci->budget.dvb_frontend, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { break; } break; case 0x1017: // TT S-1500 PCI - budget_ci->budget.dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget_ci->budget.i2c_adap); + STV0299_ATTACH(budget_ci->budget.dvb_frontend, &alps_bsbe1_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { budget_ci->budget.dvb_frontend->ops->dishnetwork_send_legacy_command = NULL; if (lnbp21_init(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) {
_______________________________________________ linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb