diff options
| author | rmcc@localhost.localdomain <rmcc@localhost.localdomain> | 2006-05-18 16:06:06 +0100 |
|---|---|---|
| committer | rmcc@localhost.localdomain <rmcc@localhost.localdomain> | 2006-05-18 16:06:06 +0100 |
| commit | aad2e973e44590acd4c1b55dd32eadad842e7fdb (patch) | |
| tree | de152190bd763eb849cf2952cfb468169f3881ba /linux/drivers/media/dvb/ttpci | |
| parent | f637ab4e875bd28b68bbd4d776c2071683050b5c (diff) | |
| parent | 122bd90fa6f72e1366146662e7fb9a6581aab68e (diff) | |
| download | mediapointer-dvb-s2-aad2e973e44590acd4c1b55dd32eadad842e7fdb.tar.gz mediapointer-dvb-s2-aad2e973e44590acd4c1b55dd32eadad842e7fdb.tar.bz2 | |
merge: from master
From: Ricardo Cerqueira <v4l@cerqueira.org>
merging master changes
Signed-off-by: Ricardo Cerqueira <v4l@cerqueira.org>
Diffstat (limited to 'linux/drivers/media/dvb/ttpci')
| -rw-r--r-- | linux/drivers/media/dvb/ttpci/Kconfig | 15 | ||||
| -rw-r--r-- | linux/drivers/media/dvb/ttpci/Makefile | 2 | ||||
| -rw-r--r-- | linux/drivers/media/dvb/ttpci/av7110.c | 85 | ||||
| -rw-r--r-- | linux/drivers/media/dvb/ttpci/av7110_av.c | 2 | ||||
| -rw-r--r-- | linux/drivers/media/dvb/ttpci/budget-av.c | 288 | ||||
| -rw-r--r-- | linux/drivers/media/dvb/ttpci/budget-ci.c | 154 | ||||
| -rw-r--r-- | linux/drivers/media/dvb/ttpci/budget-core.c | 82 | ||||
| -rw-r--r-- | linux/drivers/media/dvb/ttpci/budget-patch.c | 45 | ||||
| -rw-r--r-- | linux/drivers/media/dvb/ttpci/budget.c | 45 | ||||
| -rw-r--r-- | linux/drivers/media/dvb/ttpci/budget.h | 13 |
10 files changed, 510 insertions, 221 deletions
diff --git a/linux/drivers/media/dvb/ttpci/Kconfig b/linux/drivers/media/dvb/ttpci/Kconfig index 5b2aadb83..8ffaac634 100644 --- a/linux/drivers/media/dvb/ttpci/Kconfig +++ b/linux/drivers/media/dvb/ttpci/Kconfig @@ -1,8 +1,7 @@ config DVB_AV7110 tristate "AV7110 cards" - depends on DVB_CORE && PCI + depends on DVB_CORE && PCI && VIDEO_V4L1 select FW_LOADER - select VIDEO_DEV select VIDEO_SAA7146_VV select DVB_VES1820 select DVB_VES1X93 @@ -11,6 +10,7 @@ config DVB_AV7110 select DVB_SP8870 select DVB_STV0297 select DVB_L64781 + select DVB_LNBP21 help Support for SAA7146 and AV7110 based DVB cards as produced by Fujitsu-Siemens, Technotrend, Hauppauge and others. @@ -59,7 +59,7 @@ config DVB_AV7110_OSD config DVB_BUDGET tristate "Budget cards" - depends on DVB_CORE && PCI + depends on DVB_CORE && PCI && VIDEO_V4L1 select VIDEO_SAA7146 select DVB_STV0299 select DVB_VES1X93 @@ -68,6 +68,7 @@ config DVB_BUDGET select DVB_TDA8083 select DVB_TDA10021 select DVB_S5H1420 + select DVB_LNBP21 help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard @@ -80,11 +81,12 @@ config DVB_BUDGET config DVB_BUDGET_CI tristate "Budget cards with onboard CI connector" - depends on DVB_CORE && PCI + depends on DVB_CORE && PCI && VIDEO_V4L1 select VIDEO_SAA7146 select DVB_STV0297 select DVB_STV0299 select DVB_TDA1004X + select DVB_LNBP21 help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard @@ -100,8 +102,7 @@ config DVB_BUDGET_CI config DVB_BUDGET_AV tristate "Budget cards with analog video inputs" - depends on DVB_CORE && PCI - select VIDEO_DEV + depends on DVB_CORE && PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV select DVB_STV0299 select DVB_TDA1004X @@ -119,7 +120,7 @@ config DVB_BUDGET_AV config DVB_BUDGET_PATCH tristate "AV7110 cards with Budget Patch" - depends on DVB_CORE && DVB_BUDGET + depends on DVB_CORE && DVB_BUDGET && VIDEO_V4L1 select DVB_AV7110 select DVB_STV0299 select DVB_VES1X93 diff --git a/linux/drivers/media/dvb/ttpci/Makefile b/linux/drivers/media/dvb/ttpci/Makefile index a690730ac..c98c8e013 100644 --- a/linux/drivers/media/dvb/ttpci/Makefile +++ b/linux/drivers/media/dvb/ttpci/Makefile @@ -15,7 +15,7 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ hostprogs-y := fdump -ifdef CONFIG_DVB_AV7110_FIRMWARE +ifeq (CONFIG_DVB_AV7110_FIRMWARE,y) $(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h $(obj)/av7110_firm.h: diff --git a/linux/drivers/media/dvb/ttpci/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c index 87741cf17..dbb332304 100644 --- a/linux/drivers/media/dvb/ttpci/av7110.c +++ b/linux/drivers/media/dvb/ttpci/av7110.c @@ -87,6 +87,7 @@ static int volume = 255; static int budgetpatch; static int wss_cfg_4_3 = 0x4008; static int wss_cfg_16_9 = 0x0007; +static int tv_standard; module_param_named(debug, av7110_debug, int, 0644); MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)"); @@ -109,6 +110,8 @@ module_param(wss_cfg_4_3, int, 0444); MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data"); module_param(wss_cfg_16_9, int, 0444); MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14: burst mode, 13..0: wss data"); +module_param(tv_standard, int, 0444); +MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC"); static void restart_feeds(struct av7110 *av7110); @@ -1549,7 +1552,7 @@ static int get_firmware(struct av7110* av7110) #endif -static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct av7110* av7110 = (struct av7110*) fe->dvb->priv; u8 pwr = 0; @@ -1572,6 +1575,8 @@ static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param // NOTE: since we're using a prescaler of 2, we set the // divisor frequency to 62.5kHz and divide by 125 above + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -1581,10 +1586,9 @@ static struct ves1x93_config alps_bsrv2_config = { .demod_address = 0x08, .xin = 90100000UL, .invert_pwm = 0, - .pll_set = alps_bsrv2_pll_set, }; -static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct av7110* av7110 = fe->dvb->priv; u32 div; @@ -1598,6 +1602,8 @@ static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param data[2] = 0x85 | ((div >> 10) & 0x60); data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81); + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -1608,14 +1614,12 @@ static struct ves1820_config alps_tdbe2_config = { .xin = 57840000UL, .invert = 1, .selagc = VES1820_SELAGC_SIGNAMPERR, - .pll_set = alps_tdbe2_pll_set, }; -static int grundig_29504_451_pll_set(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params) +static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct av7110* av7110 = fe->dvb->priv; u32 div; @@ -1628,6 +1632,8 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe, data[2] = 0x8e; data[3] = 0x00; + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -1635,13 +1641,11 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe, static struct tda8083_config grundig_29504_451_config = { .demod_address = 0x68, - .pll_set = grundig_29504_451_pll_set, }; -static int philips_cd1516_pll_set(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params) +static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct av7110* av7110 = fe->dvb->priv; u32 div; @@ -1656,6 +1660,8 @@ static int philips_cd1516_pll_set(struct dvb_frontend* fe, data[2] = 0x8e; data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34); + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -1666,12 +1672,11 @@ static struct ves1820_config philips_cd1516_config = { .xin = 57840000UL, .invert = 1, .selagc = VES1820_SELAGC_SIGNAMPERR, - .pll_set = philips_cd1516_pll_set, }; -static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct av7110* av7110 = fe->dvb->priv; u32 div, pwr; @@ -1690,6 +1695,8 @@ static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param data[2] = 0x85; data[3] = pwr << 6; + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -1705,7 +1712,6 @@ static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct fir static struct sp8870_config alps_tdlb7_config = { .demod_address = 0x71, - .pll_set = alps_tdlb7_pll_set, .request_firmware = alps_tdlb7_request_firmware, }; @@ -1803,7 +1809,7 @@ static u8 nexusca_stv0297_inittab[] = { 0xff, 0xff, }; -static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct av7110* av7110 = fe->dvb->priv; u32 div; @@ -1829,7 +1835,8 @@ static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_ else return -EINVAL; - stv0297_enable_plli2c(fe); + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) { printk("nexusca: pll transfer failed!\n"); return -EIO; @@ -1837,8 +1844,8 @@ static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_ // wait for PLL lock for(i = 0; i < 20; i++) { - - stv0297_enable_plli2c(fe); + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1) if (data[0] & 0x40) break; msleep(10); @@ -1852,12 +1859,12 @@ static struct stv0297_config nexusca_stv0297_config = { .demod_address = 0x1C, .inittab = nexusca_stv0297_inittab, .invert = 1, - .pll_set = nexusca_stv0297_pll_set, + .stop_during_read = 1, }; -static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct av7110* av7110 = (struct av7110*) fe->dvb->priv; u32 div; @@ -1884,13 +1891,14 @@ static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_fronten data[2] = ((div >> 10) & 0x60) | cfg; data[3] = (cpump << 6) | band_select; + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } static struct l64781_config grundig_29504_401_config = { .demod_address = 0x55, - .pll_set = grundig_29504_401_pll_set, }; @@ -2076,6 +2084,9 @@ static int frontend_init(struct av7110 *av7110) case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??)) av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap, read_pwm(av7110)); + if (av7110->fe) { + av7110->fe->ops->tuner_ops.set_params = philips_cd1516_tuner_set_params; + } break; } @@ -2088,6 +2099,7 @@ static int frontend_init(struct av7110 *av7110) // try the ALPS BSRV2 first of all av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap); if (av7110->fe) { + av7110->fe->ops->tuner_ops.set_params = alps_bsrv2_tuner_set_params; av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; av7110->fe->ops->set_tone = av7110_set_tone; @@ -2098,6 +2110,9 @@ static int frontend_init(struct av7110 *av7110) // try the ALPS BSRU6 now av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap); if (av7110->fe) { + av7110->fe->ops->tuner_ops.set_params = alps_bsru6_tuner_set_params; + av7110->fe->tuner_priv = &av7110->i2c_adap; + av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; av7110->fe->ops->set_tone = av7110_set_tone; @@ -2108,6 +2123,7 @@ static int frontend_init(struct av7110 *av7110) // Try the grundig 29504-451 av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); if (av7110->fe) { + av7110->fe->ops->tuner_ops.set_params = grundig_29504_451_tuner_set_params; av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; av7110->fe->ops->set_tone = av7110_set_tone; @@ -2121,11 +2137,17 @@ static int frontend_init(struct av7110 *av7110) /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */ av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap, read_pwm(av7110)); + if (av7110->fe) { + av7110->fe->ops->tuner_ops.set_params = philips_cd1516_tuner_set_params; + } break; case 0x0003: - /* Haupauge DVB-C 2.1 VES1820/ALPS TDBE2 */ + /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */ av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); + if (av7110->fe) { + av7110->fe->ops->tuner_ops.set_params = alps_tdbe2_tuner_set_params; + } break; } break; @@ -2134,17 +2156,24 @@ static int frontend_init(struct av7110 *av7110) // ALPS TDLB7 av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap); + if (av7110->fe) { + av7110->fe->ops->tuner_ops.set_params = alps_tdlb7_tuner_set_params; + } break; case 0x0002: // Hauppauge/TT DVB-C premium rev2.X av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); + if (av7110->fe) { + av7110->fe->ops->tuner_ops.set_params = alps_tdbe2_tuner_set_params; + } break; case 0x0004: // Galaxis DVB-S rev1.3 /* ALPS BSRV2 */ av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap); if (av7110->fe) { + av7110->fe->ops->tuner_ops.set_params = alps_bsrv2_tuner_set_params; av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; av7110->fe->ops->set_tone = av7110_set_tone; @@ -2156,6 +2185,7 @@ static int frontend_init(struct av7110 *av7110) /* Grundig 29504-451 */ av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); if (av7110->fe) { + av7110->fe->ops->tuner_ops.set_params = grundig_29504_451_tuner_set_params; av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; av7110->fe->ops->set_tone = av7110_set_tone; @@ -2166,12 +2196,17 @@ static int frontend_init(struct av7110 *av7110) case 0x0008: // Hauppauge/TT DVB-T av7110->fe = l64781_attach(&grundig_29504_401_config, &av7110->i2c_adap); + if (av7110->fe) { + av7110->fe->ops->tuner_ops.set_params = grundig_29504_401_tuner_set_params; + } break; case 0x000A: // Hauppauge/TT Nexus-CA rev1.X av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap); if (av7110->fe) { + av7110->fe->ops->tuner_ops.set_params = nexusca_stv0297_tuner_set_params; + /* set TDA9819 into DVB mode */ saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD) saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) @@ -2186,7 +2221,10 @@ static int frontend_init(struct av7110 *av7110) /* ALPS BSBE1 */ av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap); if (av7110->fe) { - if (lnbp21_init(av7110->fe, &av7110->i2c_adap, 0, 0)) { + av7110->fe->ops->tuner_ops.set_params = alps_bsbe1_tuner_set_params; + av7110->fe->tuner_priv = &av7110->i2c_adap; + + if (lnbp21_attach(av7110->fe, &av7110->i2c_adap, 0, 0)) { printk("dvb-ttpci: LNBP21 not found!\n"); if (av7110->fe->ops->release) av7110->fe->ops->release(av7110->fe); @@ -2410,7 +2448,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev, goto err_kfree_0; ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name, - THIS_MODULE); + THIS_MODULE, &dev->pci->dev); if (ret < 0) goto err_put_firmware_1; @@ -2543,6 +2581,9 @@ static int __devinit av7110_attach(struct saa7146_dev* dev, av7110->osdwin = 1; mutex_init(&av7110->osd_mutex); + /* TV standard */ + av7110->vidmode = tv_standard == 1 ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL; + /* ARM "watchdog" */ init_waitqueue_head(&av7110->arm_wait); av7110->arm_thread = NULL; diff --git a/linux/drivers/media/dvb/ttpci/av7110_av.c b/linux/drivers/media/dvb/ttpci/av7110_av.c index 400facec7..2eff09f63 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_av.c +++ b/linux/drivers/media/dvb/ttpci/av7110_av.c @@ -1479,8 +1479,6 @@ int av7110_av_init(struct av7110 *av7110) void (*play[])(u8 *, int, void *) = { play_audio_cb, play_video_cb }; int i, ret; - av7110->vidmode = VIDEO_MODE_PAL; - for (i = 0; i < 2; i++) { struct ipack *ipack = av7110->ipack + i; diff --git a/linux/drivers/media/dvb/ttpci/budget-av.c b/linux/drivers/media/dvb/ttpci/budget-av.c index 9dd4745f5..3ff67523c 100644 --- a/linux/drivers/media/dvb/ttpci/budget-av.c +++ b/linux/drivers/media/dvb/ttpci/budget-av.c @@ -50,6 +50,12 @@ #define DEBICICAM 0x02420000 +#define SLOTSTATUS_NONE 1 +#define SLOTSTATUS_PRESENT 2 +#define SLOTSTATUS_RESET 4 +#define SLOTSTATUS_READY 8 +#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) + struct budget_av { struct budget budget; struct video_device *vd; @@ -58,13 +64,20 @@ struct budget_av { struct tasklet_struct ciintf_irq_tasklet; int slot_status; struct dvb_ca_en50221 ca; + u8 reinitialise_demod:1; + u8 tda10021_poclkp:1; + u8 tda10021_ts_enabled; + int (*tda10021_set_frontend)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p); }; -/* GPIO CI Connections: - * 0 - Vcc/Reset (Reset is controlled by capacitor) - * 1 - Attribute Memory - * 2 - Card Enable (Active Low) - * 3 - Card Detect +static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot); + + +/* GPIO Connections: + * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*! + * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory + * 2 - CI Card Enable (Active Low) + * 3 - CI Card Detect */ /**************************************************************************** @@ -129,9 +142,10 @@ static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int ad udelay(1); result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1); - - if (result == -ETIMEDOUT) - budget_av->slot_status = 0; + if (result == -ETIMEDOUT) { + ciintf_slot_shutdown(ca, slot); + printk(KERN_INFO "budget-av: cam ejected 1\n"); + } return result; } @@ -147,9 +161,10 @@ static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int a udelay(1); result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1); - - if (result == -ETIMEDOUT) - budget_av->slot_status = 0; + if (result == -ETIMEDOUT) { + ciintf_slot_shutdown(ca, slot); + printk(KERN_INFO "budget-av: cam ejected 2\n"); + } return result; } @@ -165,9 +180,11 @@ static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addre udelay(1); result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0); - - if (result == -ETIMEDOUT) - budget_av->slot_status = 0; + if ((result == -ETIMEDOUT) || ((result == 0xff) && ((address & 3) < 2))) { + ciintf_slot_shutdown(ca, slot); + printk(KERN_INFO "budget-av: cam ejected 3\n"); + return -ETIMEDOUT; + } return result; } @@ -183,9 +200,10 @@ static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addr udelay(1); result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0); - - if (result == -ETIMEDOUT) - budget_av->slot_status = 0; + if (result == -ETIMEDOUT) { + ciintf_slot_shutdown(ca, slot); + printk(KERN_INFO "budget-av: cam ejected 5\n"); + } return result; } @@ -193,12 +211,12 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) { struct budget_av *budget_av = (struct budget_av *) ca->data; struct saa7146_dev *saa = budget_av->budget.dev; - int timeout = 50; // 5 seconds (4.4.6 Ready) if (slot != 0) return -EINVAL; dprintk(1, "ciintf_slot_reset\n"); + budget_av->slot_status = SLOTSTATUS_RESET; saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */ @@ -208,17 +226,17 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) msleep(20); /* 20 ms Vcc settling time */ saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */ + ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); + msleep(20); - /* This should have been based on pin 16 READY of the pcmcia port, - * but AFAICS it is not routed to the saa7146 */ - while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d) - msleep(100); + /* reinitialise the frontend if necessary */ + if (budget_av->reinitialise_demod) + dvb_frontend_reinitialise(budget_av->budget.dvb_frontend); - if (timeout <= 0) - { - printk(KERN_ERR "budget-av: cam reset failed (timeout).\n"); - saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */ - return -ETIMEDOUT; + /* set tda10021 back to original clock configuration on reset */ + if (budget_av->tda10021_poclkp) { + tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0); + budget_av->tda10021_ts_enabled = 0; } return 0; @@ -235,7 +253,13 @@ static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) dprintk(1, "ciintf_slot_shutdown\n"); ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); - budget_av->slot_status = 0; + budget_av->slot_status = SLOTSTATUS_NONE; + + /* set tda10021 back to original clock configuration when cam removed */ + if (budget_av->tda10021_poclkp) { + tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0); + budget_av->tda10021_ts_enabled = 0; + } return 0; } @@ -250,6 +274,13 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status); ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA); + + /* tda10021 seems to need a different TS clock config when data is routed to the CAM */ + if (budget_av->tda10021_poclkp) { + tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1); + budget_av->tda10021_ts_enabled = 1; + } + return 0; } @@ -257,50 +288,61 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open { struct budget_av *budget_av = (struct budget_av *) ca->data; struct saa7146_dev *saa = budget_av->budget.dev; - int cam_present = 0; + int result; if (slot != 0) return -EINVAL; - if (!budget_av->slot_status) - { - // first of all test the card detect line + /* test the card detect line - needs to be done carefully + * since it never goes high for some CAMs on this interface (e.g. topuptv) */ + if (budget_av->slot_status == SLOTSTATUS_NONE) { saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); udelay(1); - if (saa7146_read(saa, PSR) & MASK_06) - { - cam_present = 1; + if (saa7146_read(saa, PSR) & MASK_06) { + if (budget_av->slot_status == SLOTSTATUS_NONE) { + budget_av->slot_status = SLOTSTATUS_PRESENT; + printk(KERN_INFO "budget-av: cam inserted A\n"); + } } saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); + } - // that is unreliable however, so try and read from IO memory - if (!cam_present) - { - saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); - if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) != -ETIMEDOUT) - { - cam_present = 1; + /* We also try and read from IO memory to work round the above detection bug. If + * there is no CAM, we will get a timeout. Only done if there is no cam + * present, since this test actually breaks some cams :( + * + * if the CI interface is not open, we also do the above test since we + * don't care if the cam has problems - we'll be resetting it on open() anyway */ + if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) { + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); + result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1); + if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) { + budget_av->slot_status = SLOTSTATUS_PRESENT; + printk(KERN_INFO "budget-av: cam inserted B\n"); + } else if (result < 0) { + if (budget_av->slot_status != SLOTSTATUS_NONE) { + ciintf_slot_shutdown(ca, slot); + printk(KERN_INFO "budget-av: cam ejected 5\n"); + return 0; } } + } - // did we find something? - if (cam_present) { - printk(KERN_INFO "budget-av: cam inserted\n"); - budget_av->slot_status = 1; - } - } else if (!open) { - saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); - if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT) - { - printk(KERN_INFO "budget-av: cam ejected\n"); - saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */ - budget_av->slot_status = 0; + /* read from attribute memory in reset/ready state to know when the CAM is ready */ + if (budget_av->slot_status == SLOTSTATUS_RESET) { + result = ciintf_read_attribute_mem(ca, slot, 0); + if (result == 0x1d) { + budget_av->slot_status = SLOTSTATUS_READY; } } - if (budget_av->slot_status == 1) - return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; - + /* work out correct return code */ + if (budget_av->slot_status != SLOTSTATUS_NONE) { + if (budget_av->slot_status & SLOTSTATUS_READY) { + return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; + } + return DVB_CA_EN50221_POLL_CAM_PRESENT; + } return 0; } @@ -330,6 +372,8 @@ static int ciintf_init(struct budget_av *budget_av) budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable; budget_av->ca.poll_slot_status = ciintf_poll_slot_status; budget_av->ca.data = budget_av; + budget_av->budget.ci_present = 1; + budget_av->slot_status = SLOTSTATUS_NONE; if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter, &budget_av->ca, 0, 1)) != 0) { @@ -338,7 +382,6 @@ static int ciintf_init(struct budget_av *budget_av) } printk(KERN_INFO "budget-av: ci interface initialised.\n"); - budget_av->budget.ci_present = 1; return 0; error: @@ -469,12 +512,12 @@ static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 sra return 0; } -static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe, - struct i2c_adapter *i2c, - struct dvb_frontend_parameters *params) +static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) { u32 div; u8 buf[4]; + struct budget *budget = (struct budget *) fe->dvb->priv; struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; if ((params->frequency < 950000) || (params->frequency > 2150000)) @@ -498,7 +541,9 @@ static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe, else if (params->frequency < 2150000) buf[3] |= 0xC0; - if (i2c_transfer(i2c, &msg, 1) != 1) + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); + if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } @@ -506,9 +551,8 @@ static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe, #define MIN2(a,b) ((a) < (b) ? (a) : (b)) #define MIN3(a,b,c) MIN2(MIN2(a,b),c) -static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe, - struct i2c_adapter *i2c, - struct dvb_frontend_parameters *params) +static int philips_su1278sh2_tua6100_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) { u8 reg0 [2] = { 0x00, 0x00 }; u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 }; @@ -518,6 +562,7 @@ static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe, int R, A, N, P, M; struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = NULL,.len = 0 }; int freq = params->frequency; + struct budget *budget = (struct budget *) fe->dvb->priv; first_ZF = (freq) / 1000; @@ -617,21 +662,25 @@ static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe, reg0[1] |= 0x03; /* already enabled - do not reenable i2c repeater or TX fails */ + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); msg.buf = reg0; msg.len = sizeof(reg0); - if (i2c_transfer(i2c, &msg, 1) != 1) + if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1) return -EIO; - stv0299_enable_plli2c(fe); + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); msg.buf = reg1; msg.len = sizeof(reg1); - if (i2c_transfer(i2c, &msg, 1) != 1) + if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1) return -EIO; - stv0299_enable_plli2c(fe); + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); msg.buf = reg2; msg.len = sizeof(reg2); - if (i2c_transfer(i2c, &msg, 1) != 1) + if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -689,7 +738,6 @@ static struct stv0299_config typhoon_config = { .volt13_op0_op1 = STV0299_VOLT13_OP0, .min_delay_ms = 100, .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, - .pll_set = philips_su1278_ty_ci_pll_set, }; @@ -703,7 +751,6 @@ static struct stv0299_config cinergy_1200s_config = { .volt13_op0_op1 = STV0299_VOLT13_OP0, .min_delay_ms = 100, .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, - .pll_set = philips_su1278_ty_ci_pll_set, }; static struct stv0299_config cinergy_1200s_1894_0010_config = { @@ -716,10 +763,9 @@ static struct stv0299_config cinergy_1200s_1894_0010_config = { .volt13_op0_op1 = STV0299_VOLT13_OP0, .min_delay_ms = 100, .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, - .pll_set = philips_su1278sh2_tua6100_pll_set, }; -static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct budget *budget = (struct budget *) fe->dvb->priv; u8 buf[4]; @@ -735,6 +781,8 @@ static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p buf[3] = (params->frequency < 150000000 ? 0x01 : params->frequency < 445000000 ? 0x02 : 0x04); + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -742,19 +790,20 @@ static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p static struct tda10021_config philips_cu1216_config = { .demod_address = 0x0c, - .pll_set = philips_cu1216_pll_set, }; -static int philips_tu1216_pll_init(struct dvb_frontend *fe) +static int philips_tu1216_tuner_init(struct dvb_frontend *fe) { struct budget *budget = (struct budget *) fe->dvb->priv; static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab }; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) }; // setup PLL configuration + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1) return -EIO; msleep(1); @@ -762,7 +811,7 @@ static int philips_tu1216_pll_init(struct dvb_frontend *fe) return 0; } -static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct budget *budget = (struct budget *) fe->dvb->priv; u8 tuner_buf[4]; @@ -836,6 +885,8 @@ static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p tuner_buf[2] = 0xca; tuner_buf[3] = (cp << 5) | (filter << 3) | band; + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1) return -EIO; @@ -859,9 +910,6 @@ static struct tda1004x_config philips_tu1216_config = { .xtal_freq = TDA10046_XTAL_4M, .agc_config = TDA10046_AGC_DEFAULT, .if_freq = TDA10046_FREQ_3617, - .pll_init = philips_tu1216_pll_init, - .pll_set = philips_tu1216_pll_set, - .pll_sleep = NULL, .request_firmware = philips_tu1216_request_firmware, }; @@ -908,13 +956,13 @@ static u8 philips_sd1878_inittab[] = { 0xff, 0xff }; -static int philips_sd1878_tda8261_pll_set(struct dvb_frontend *fe, - struct i2c_adapter *i2c, - struct dvb_frontend_parameters *params) +static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) { u8 buf[4]; int rc; struct i2c_msg tuner_msg = {.addr=0x60,.flags=0,.buf=buf,.len=sizeof(buf)}; + struct budget *budget = (struct budget *) fe->dvb->priv; if((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL; @@ -923,7 +971,9 @@ static int philips_sd1878_tda8261_pll_set(struct dvb_frontend *fe, params->frequency, 0); if(rc < 0) return rc; - if(i2c_transfer(i2c, &tuner_msg, 1) != 1) + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); + if(i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1) return -EIO; return 0; @@ -966,7 +1016,7 @@ static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe, static struct stv0299_config philips_sd1878_config = { .demod_address = 0x68, - .inittab = philips_sd1878_inittab, + .inittab = philips_sd1878_inittab, .mclk = 88000000UL, .invert = 0, .skip_reinit = 0, @@ -974,7 +1024,6 @@ static struct stv0299_config philips_sd1878_config = { .volt13_op0_op1 = STV0299_VOLT13_OP0, .min_delay_ms = 100, .set_symbol_rate = philips_sd1878_ci_set_symbol_rate, - .pll_set = philips_sd1878_tda8261_pll_set, }; static u8 read_pwm(struct budget_av *budget_av) @@ -1009,17 +1058,36 @@ static u8 read_pwm(struct budget_av *budget_av) #define SUBID_DVBT_KNC1 0x0030 #define SUBID_DVBT_CINERGY1200 0x1157 + +static int tda10021_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct budget_av* budget_av = fe->dvb->priv; + int result; + + result = budget_av->tda10021_set_frontend(fe, p); + if (budget_av->tda10021_ts_enabled) { + tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1); + } else { + tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0); + } + + return result; +} + static void frontend_init(struct budget_av *budget_av) { struct saa7146_dev * saa = budget_av->budget.dev; struct dvb_frontend * fe = NULL; + /* Enable / PowerON Frontend */ + saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); + + /* additional setup necessary for the PLUS cards */ switch (saa->pci->subsystem_device) { case SUBID_DVBS_KNC1_PLUS: case SUBID_DVBC_KNC1_PLUS: case SUBID_DVBT_KNC1_PLUS: - // Enable / PowerON Frontend - saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI); break; } @@ -1030,9 +1098,15 @@ static void frontend_init(struct budget_av *budget_av) if (saa->pci->subsystem_vendor == 0x1894) { fe = stv0299_attach(&cinergy_1200s_1894_0010_config, &budget_av->budget.i2c_adap); + if (fe) { + fe->ops->tuner_ops.set_params = philips_su1278sh2_tua6100_tuner_set_params; + } } else { fe = stv0299_attach(&typhoon_config, &budget_av->budget.i2c_adap); + if (fe) { + fe->ops->tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params; + } } break; @@ -1042,41 +1116,53 @@ static void frontend_init(struct budget_av *budget_av) case SUBID_DVBS_EASYWATCH: fe = stv0299_attach(&philips_sd1878_config, &budget_av->budget.i2c_adap); + if (fe) { + fe->ops->tuner_ops.set_params = philips_sd1878_tda8261_tuner_set_params; + } break; case SUBID_DVBS_KNC1_PLUS: case SUBID_DVBS_TYPHOON: fe = stv0299_attach(&typhoon_config, &budget_av->budget.i2c_adap); + if (fe) { + fe->ops->tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params; + } break; case SUBID_DVBS_CINERGY1200: fe = stv0299_attach(&cinergy_1200s_config, &budget_av->budget.i2c_adap); + if (fe) { + fe->ops->tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params; + } break; case SUBID_DVBC_KNC1: case SUBID_DVBC_KNC1_PLUS: + case SUBID_DVBC_CINERGY1200: + budget_av->reinitialise_demod = 1; fe = tda10021_attach(&philips_cu1216_config, &budget_av->budget.i2c_adap, read_pwm(budget_av)); + if (fe) { + budget_av->tda10021_poclkp = 1; + budget_av->tda10021_set_frontend = fe->ops->set_frontend; + fe->ops->set_frontend = tda10021_set_frontend; + fe->ops->tuner_ops.set_params = philips_cu1216_tuner_set_params; + } break; case SUBID_DVBT_KNC1: case SUBID_DVBT_KNC1_PLUS: - fe = tda10046_attach(&philips_tu1216_config, - &budget_av->budget.i2c_adap); - break; - - case SUBID_DVBC_CINERGY1200: - fe = tda10021_attach(&philips_cu1216_config, - &budget_av->budget.i2c_adap, - read_pwm(budget_av)); - break; - case SUBID_DVBT_CINERGY1200: + budget_av->reinitialise_demod = 1; fe = tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap); + if (fe) { + fe->ops->tuner_ops.init = philips_tu1216_tuner_init; + fe->ops->tuner_ops.set_params = philips_tu1216_tuner_set_params; + } break; } @@ -1187,8 +1273,6 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio SAA7146_HPS_SYNC_PORT_A); saa7113_setinput(budget_av, 0); - } else { - ciintf_init(budget_av); } /* fixme: find some sane values here... */ @@ -1208,6 +1292,10 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio budget_av->budget.dvb_adapter.priv = budget_av; frontend_init(budget_av); + if (!budget_av->has_saa7113) { + ciintf_init(budget_av); + } + return 0; } diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c index 5f91036f5..eb03b140b 100644 --- a/linux/drivers/media/dvb/ttpci/budget-ci.c +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c @@ -71,6 +71,7 @@ struct budget_ci { struct tasklet_struct msp430_irq_tasklet; struct tasklet_struct ciintf_irq_tasklet; int slot_status; + int ci_irq; struct dvb_ca_en50221 ca; char ir_dev_name[50]; u8 tuner_pll_address; /* used for philips_tdm1316l configs */ @@ -276,8 +277,10 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) if (slot != 0) return -EINVAL; - // trigger on RISING edge during reset so we know when READY is re-asserted - saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + if (budget_ci->ci_irq) { + // trigger on RISING edge during reset so we know when READY is re-asserted + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + } budget_ci->slot_status = SLOTSTATUS_RESET; ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0); msleep(1); @@ -370,11 +373,50 @@ static void ciintf_interrupt(unsigned long data) } } +static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) +{ + struct budget_ci *budget_ci = (struct budget_ci *) ca->data; + unsigned int flags; + + // ensure we don't get spurious IRQs during initialisation + if (!budget_ci->budget.ci_present) + return -EINVAL; + + // read the CAM status + flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0); + if (flags & CICONTROL_CAMDETECT) { + // mark it as present if it wasn't before + if (budget_ci->slot_status & SLOTSTATUS_NONE) { + budget_ci->slot_status = SLOTSTATUS_PRESENT; + } + + // during a RESET, we check if we can read from IO memory to see when CAM is ready + if (budget_ci->slot_status & SLOTSTATUS_RESET) { + if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) { + budget_ci->slot_status = SLOTSTATUS_READY; + } + } + } else { + budget_ci->slot_status = SLOTSTATUS_NONE; + } + + if (budget_ci->slot_status != SLOTSTATUS_NONE) { + if (budget_ci->slot_status & SLOTSTATUS_READY) { + return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; + } + return DVB_CA_EN50221_POLL_CAM_PRESENT; + } + + return 0; +} + static int ciintf_init(struct budget_ci *budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; int flags; int result; + int ci_version; + int ca_flags; memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221)); @@ -382,16 +424,29 @@ static int ciintf_init(struct budget_ci *budget_ci) saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); // test if it is there - if ((ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0) & 0xa0) != 0xa0) { + ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0); + if ((ci_version & 0xa0) != 0xa0) { result = -ENODEV; goto error; } + // determine whether a CAM is present or not flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0); budget_ci->slot_status = SLOTSTATUS_NONE; if (flags & CICONTROL_CAMDETECT) budget_ci->slot_status = SLOTSTATUS_PRESENT; + // version 0xa2 of the CI firmware doesn't generate interrupts + if (ci_version == 0xa2) { + ca_flags = 0; + budget_ci->ci_irq = 0; + } else { + ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | + DVB_CA_EN50221_FLAG_IRQ_FR | + DVB_CA_EN50221_FLAG_IRQ_DA; + budget_ci->ci_irq = 1; + } + // register CI interface budget_ci->ca.owner = THIS_MODULE; budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem; @@ -401,23 +456,27 @@ static int ciintf_init(struct budget_ci *budget_ci) budget_ci->ca.slot_reset = ciintf_slot_reset; budget_ci->ca.slot_shutdown = ciintf_slot_shutdown; budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable; + budget_ci->ca.poll_slot_status = ciintf_poll_slot_status; budget_ci->ca.data = budget_ci; if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter, &budget_ci->ca, - DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | - DVB_CA_EN50221_FLAG_IRQ_FR | - DVB_CA_EN50221_FLAG_IRQ_DA, 1)) != 0) { + ca_flags, 1)) != 0) { printk("budget_ci: CI interface detected, but initialisation failed.\n"); goto error; } + // Setup CI slot IRQ - tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci); - if (budget_ci->slot_status != SLOTSTATUS_NONE) { - saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); - } else { - saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + if (budget_ci->ci_irq) { + tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci); + if (budget_ci->slot_status != SLOTSTATUS_NONE) { + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); + } else { + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + } + saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); } - saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); + + // enable interface ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET, 1, 0); @@ -426,10 +485,12 @@ static int ciintf_init(struct budget_ci *budget_ci) budget_ci->budget.ci_present = 1; // forge a fake CI IRQ so the CAM state is setup correctly - flags = DVB_CA_EN50221_CAMCHANGE_REMOVED; - if (budget_ci->slot_status != SLOTSTATUS_NONE) - flags = DVB_CA_EN50221_CAMCHANGE_INSERTED; - dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags); + if (budget_ci->ci_irq) { + flags = DVB_CA_EN50221_CAMCHANGE_REMOVED; + if (budget_ci->slot_status != SLOTSTATUS_NONE) + flags = DVB_CA_EN50221_CAMCHANGE_INSERTED; + dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags); + } return 0; @@ -443,9 +504,13 @@ static void ciintf_deinit(struct budget_ci *budget_ci) struct saa7146_dev *saa = budget_ci->budget.dev; // disable CI interrupts - saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); - saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); - tasklet_kill(&budget_ci->ciintf_irq_tasklet); + if (budget_ci->ci_irq) { + saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); + saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); + tasklet_kill(&budget_ci->ciintf_irq_tasklet); + } + + // reset interface ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0); msleep(1); ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, @@ -473,7 +538,7 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) if (*isr & MASK_10) ttpci_budget_irq10_handler(dev, isr); - if ((*isr & MASK_03) && (budget_ci->budget.ci_present)) + if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq)) tasklet_schedule(&budget_ci->ciintf_irq_tasklet); } @@ -555,10 +620,10 @@ static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, return 0; } -static int philips_su1278_tt_pll_set(struct dvb_frontend *fe, - struct i2c_adapter *i2c, - struct dvb_frontend_parameters *params) +static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) { + struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; u32 div; u8 buf[4]; struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) }; @@ -584,7 +649,9 @@ static int philips_su1278_tt_pll_set(struct dvb_frontend *fe, else if (params->frequency < 2150000) buf[3] |= 0xC0; - if (i2c_transfer(i2c, &msg, 1) != 1) + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); + if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1) return -EIO; return 0; } @@ -600,12 +667,11 @@ static struct stv0299_config philips_su1278_tt_config = { .volt13_op0_op1 = STV0299_VOLT13_OP1, .min_delay_ms = 50, .set_symbol_rate = philips_su1278_tt_set_symbol_rate, - .pll_set = philips_su1278_tt_pll_set, }; -static int philips_tdm1316l_pll_init(struct dvb_frontend *fe) +static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe) { struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab }; @@ -614,6 +680,8 @@ static int philips_tdm1316l_pll_init(struct dvb_frontend *fe) sizeof(td1316_init) }; // setup PLL configuration + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) return -EIO; msleep(1); @@ -622,14 +690,18 @@ static int philips_tdm1316l_pll_init(struct dvb_frontend *fe) tuner_msg.addr = 0x65; tuner_msg.buf = disable_mc44BC374c; tuner_msg.len = sizeof(disable_mc44BC374c); + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) { + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1); } return 0; } -static int philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; u8 tuner_buf[4]; @@ -705,6 +777,8 @@ static int philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend tuner_buf[2] = 0xca; tuner_buf[3] = (cp << 5) | (filter << 3) | band; + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) return -EIO; @@ -728,13 +802,10 @@ static struct tda1004x_config philips_tdm1316l_config = { .xtal_freq = TDA10046_XTAL_4M, .agc_config = TDA10046_AGC_DEFAULT, .if_freq = TDA10046_FREQ_3617, - .pll_init = philips_tdm1316l_pll_init, - .pll_set = philips_tdm1316l_pll_set, - .pll_sleep = NULL, .request_firmware = philips_tdm1316l_request_firmware, }; -static int dvbc_philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; u8 tuner_buf[5]; @@ -792,13 +863,15 @@ static int dvbc_philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_fro tuner_buf[3] = (cp << 5) | (filter << 3) | band; tuner_buf[4] = 0x80; - stv0297_enable_plli2c(fe); + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) return -EIO; msleep(50); - stv0297_enable_plli2c(fe); + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) return -EIO; @@ -904,7 +977,7 @@ static struct stv0297_config dvbc_philips_tdm1316l_config = { .demod_address = 0x1c, .inittab = dvbc_philips_tdm1316l_inittab, .invert = 0, - .pll_set = dvbc_philips_tdm1316l_pll_set, + .stop_during_read = 1, }; @@ -917,6 +990,8 @@ static void frontend_init(struct budget_ci *budget_ci) budget_ci->budget.dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { + budget_ci->budget.dvb_frontend->ops->tuner_ops.set_params = alps_bsru6_tuner_set_params; + budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap; break; } break; @@ -925,6 +1000,7 @@ static void frontend_init(struct budget_ci *budget_ci) budget_ci->budget.dvb_frontend = stv0299_attach(&philips_su1278_tt_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { + budget_ci->budget.dvb_frontend->ops->tuner_ops.set_params = philips_su1278_tt_tuner_set_params; break; } break; @@ -934,6 +1010,7 @@ static void frontend_init(struct budget_ci *budget_ci) budget_ci->budget.dvb_frontend = stv0297_attach(&dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { + budget_ci->budget.dvb_frontend->ops->tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params; break; } break; @@ -943,6 +1020,8 @@ static void frontend_init(struct budget_ci *budget_ci) budget_ci->budget.dvb_frontend = tda10045_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { + budget_ci->budget.dvb_frontend->ops->tuner_ops.init = philips_tdm1316l_tuner_init; + budget_ci->budget.dvb_frontend->ops->tuner_ops.set_params = philips_tdm1316l_tuner_set_params; break; } break; @@ -952,6 +1031,8 @@ static void frontend_init(struct budget_ci *budget_ci) budget_ci->budget.dvb_frontend = tda10046_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { + budget_ci->budget.dvb_frontend->ops->tuner_ops.init = philips_tdm1316l_tuner_init; + budget_ci->budget.dvb_frontend->ops->tuner_ops.set_params = philips_tdm1316l_tuner_set_params; break; } break; @@ -959,8 +1040,11 @@ static void frontend_init(struct budget_ci *budget_ci) case 0x1017: // TT S-1500 PCI budget_ci->budget.dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { + budget_ci->budget.dvb_frontend->ops->tuner_ops.set_params = alps_bsbe1_tuner_set_params; + budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap; + 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)) { + if (lnbp21_attach(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) { printk("%s: No LNBP21 found!\n", __FUNCTION__); if (budget_ci->budget.dvb_frontend->ops->release) budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend); diff --git a/linux/drivers/media/dvb/ttpci/budget-core.c b/linux/drivers/media/dvb/ttpci/budget-core.c index 633e68c34..e4cf7775e 100644 --- a/linux/drivers/media/dvb/ttpci/budget-core.c +++ b/linux/drivers/media/dvb/ttpci/budget-core.c @@ -39,9 +39,21 @@ #include "budget.h" #include "ttpci-eeprom.h" +#define TS_WIDTH (2 * TS_SIZE) +#define TS_WIDTH_ACTIVY TS_SIZE +#define TS_HEIGHT_MASK 0xf00 +#define TS_HEIGHT_MASK_ACTIVY 0xc00 +#define TS_MIN_BUFSIZE_K 188 +#define TS_MAX_BUFSIZE_K 1410 +#define TS_MAX_BUFSIZE_K_ACTIVY 564 +#define BUFFER_WARNING_WAIT (30*HZ) + int budget_debug; +static int dma_buffer_size = TS_MIN_BUFSIZE_K; module_param_named(debug, budget_debug, int, 0644); +module_param_named(bufsize, dma_buffer_size, int, 0444); MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off)."); +MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)"); /**************************************************************************** * TT budget / WinTV Nova @@ -70,11 +82,10 @@ static int start_ts_capture(struct budget *budget) saa7146_write(dev, MC1, MASK_20); // DMA3 off - memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH); + memset(budget->grabbing, 0x00, budget->buffer_size); saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000)); - budget->tsf = 0xff; budget->ttbp = 0; /* @@ -115,16 +126,12 @@ static int start_ts_capture(struct budget *budget) saa7146_write(dev, BASE_ODD3, 0); saa7146_write(dev, BASE_EVEN3, 0); - saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT); + saa7146_write(dev, PROT_ADDR3, budget->buffer_size); saa7146_write(dev, BASE_PAGE3, budget->pt.dma | ME1 | 0x90); - if (budget->card->type == BUDGET_FS_ACTIVY) { - saa7146_write(dev, PITCH3, TS_WIDTH / 2); - saa7146_write(dev, NUM_LINE_BYTE3, ((TS_HEIGHT * 2) << 16) | (TS_WIDTH / 2)); - } else { - saa7146_write(dev, PITCH3, TS_WIDTH); - saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH); - } + saa7146_write(dev, PITCH3, budget->buffer_width); + saa7146_write(dev, NUM_LINE_BYTE3, + (budget->buffer_height << 16) | budget->buffer_width); saa7146_write(dev, MC2, (MASK_04 | MASK_20)); @@ -141,11 +148,12 @@ static void vpeirq(unsigned long data) u8 *mem = (u8 *) (budget->grabbing); u32 olddma = budget->ttbp; u32 newdma = saa7146_read(budget->dev, PCI_VDP3); + u32 count; /* nearest lower position divisible by 188 */ newdma -= newdma % 188; - if (newdma >= TS_BUFLEN) + if (newdma >= budget->buffer_size) return; budget->ttbp = newdma; @@ -154,11 +162,24 @@ static void vpeirq(unsigned long data) return; if (newdma > olddma) { /* no wraparound, dump olddma..newdma */ - dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (newdma - olddma) / 188); + count = newdma - olddma; + dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188); } else { /* wraparound, dump olddma..buflen and 0..newdma */ - dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (TS_BUFLEN - olddma) / 188); + count = budget->buffer_size - olddma; + dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188); + count += newdma; dvb_dmx_swfilter_packets(&budget->demux, mem, newdma / 188); } + + if (count > budget->buffer_warning_threshold) + budget->buffer_warnings++; + + if (budget->buffer_warnings && time_after(jiffies, budget->buffer_warning_time)) { + printk("%s %s: used %d times >80%% of buffer (%u bytes now)\n", + budget->dev->name, __FUNCTION__, budget->buffer_warnings, count); + budget->buffer_warning_time = jiffies + BUFFER_WARNING_WAIT; + budget->buffer_warnings = 0; + } } @@ -341,9 +362,10 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, struct saa7146_pci_extension_data *info, struct module *owner) { - int length = TS_WIDTH * TS_HEIGHT; int ret = 0; struct budget_info *bi = info->ext_priv; + int max_bufsize; + int height_mask; memset(budget, 0, sizeof(struct budget)); @@ -352,7 +374,35 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, budget->card = bi; budget->dev = (struct saa7146_dev *) dev; - dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner); + if (budget->card->type == BUDGET_FS_ACTIVY) { + budget->buffer_width = TS_WIDTH_ACTIVY; + max_bufsize = TS_MAX_BUFSIZE_K_ACTIVY; + height_mask = TS_HEIGHT_MASK_ACTIVY; + } else { + budget->buffer_width = TS_WIDTH; + max_bufsize = TS_MAX_BUFSIZE_K; + height_mask = TS_HEIGHT_MASK; + } + + if (dma_buffer_size < TS_MIN_BUFSIZE_K) + dma_buffer_size = TS_MIN_BUFSIZE_K; + else if (dma_buffer_size > max_bufsize) + dma_buffer_size = max_bufsize; + + budget->buffer_height = dma_buffer_size * 1024 / budget->buffer_width; + budget->buffer_height &= height_mask; + budget->buffer_size = budget->buffer_height * budget->buffer_width; + budget->buffer_warning_threshold = budget->buffer_size * 80/100; + budget->buffer_warnings = 0; + budget->buffer_warning_time = jiffies; + + dprintk(2, "%s: width = %d, height = %d\n", + budget->dev->name, budget->buffer_width, budget->buffer_height); + printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size); + + if ((ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner, &budget->dev->pci->dev)) < 0) { + return ret; + } /* set dd1 stream a & b */ saa7146_write(dev, DD1_STREAM_B, 0x00000000); @@ -392,7 +442,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac); if (NULL == - (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, length, &budget->pt))) { + (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt))) { ret = -ENOMEM; goto err; } diff --git a/linux/drivers/media/dvb/ttpci/budget-patch.c b/linux/drivers/media/dvb/ttpci/budget-patch.c index 5ea95da4f..843d6245a 100644 --- a/linux/drivers/media/dvb/ttpci/budget-patch.c +++ b/linux/drivers/media/dvb/ttpci/budget-patch.c @@ -258,7 +258,7 @@ static int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_c return 0; } -static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; u8 pwr = 0; @@ -281,7 +281,10 @@ static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param // NOTE: since we're using a prescaler of 2, we set the // divisor frequency to 62.5kHz and divide by 125 above - if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) + return -EIO; return 0; } @@ -289,10 +292,9 @@ static struct ves1x93_config alps_bsrv2_config = { .demod_address = 0x08, .xin = 90100000UL, .invert_pwm = 0, - .pll_set = alps_bsrv2_pll_set, }; -static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; u32 div; @@ -305,13 +307,15 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_fronten data[2] = 0x8e; data[3] = 0x00; - if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) + return -EIO; return 0; } static struct tda8083_config grundig_29504_451_config = { .demod_address = 0x68, - .pll_set = grundig_29504_451_pll_set, }; static void frontend_init(struct budget_patch* budget) @@ -323,6 +327,7 @@ static void frontend_init(struct budget_patch* budget) // try the ALPS BSRV2 first of all budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap); if (budget->dvb_frontend) { + budget->dvb_frontend->ops->tuner_ops.set_params = alps_bsrv2_tuner_set_params; budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd; budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst; budget->dvb_frontend->ops->set_tone = budget_patch_set_tone; @@ -332,6 +337,9 @@ static void frontend_init(struct budget_patch* budget) // try the ALPS BSRU6 now budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); if (budget->dvb_frontend) { + budget->dvb_frontend->ops->tuner_ops.set_params = alps_bsru6_tuner_set_params; + budget->dvb_frontend->tuner_priv = &budget->i2c_adap; + budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; budget->dvb_frontend->ops->set_tone = budget_set_tone; @@ -341,6 +349,7 @@ static void frontend_init(struct budget_patch* budget) // Try the grundig 29504-451 budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap); if (budget->dvb_frontend) { + budget->dvb_frontend->ops->tuner_ops.set_params = grundig_29504_451_tuner_set_params; budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; budget->dvb_frontend->ops->set_tone = budget_set_tone; @@ -577,6 +586,17 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // Set RPS1 Address register to point to RPS code (r108 p42) saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle); + + if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL))) + return -ENOMEM; + + dprintk(2, "budget: %p\n", budget); + + if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) { + kfree (budget); + return err; + } + // Set Source Line Counter Threshold, using BRS (rCC p43) // It generates HS event every TS_HEIGHT lines // this is related to TS_WIDTH set in register @@ -585,24 +605,13 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte //,then RPS_THRESH1 // should be set to trigger every TS_HEIGHT (512) lines. // - saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 ); + saa7146_write(dev, RPS_THRESH1, budget->buffer_height | MASK_12 ); // saa7146_write(dev, RPS_THRESH0, ((TS_HEIGHT/2)<<16) |MASK_28| (TS_HEIGHT/2) |MASK_12 ); // Enable RPS1 (rFC p33) saa7146_write(dev, MC1, (MASK_13 | MASK_29)); - if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL))) - return -ENOMEM; - - dprintk(2, "budget: %p\n", budget); - - if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) { - kfree (budget); - return err; - } - - dev->ext_priv = budget; budget->dvb_adapter.priv = budget; diff --git a/linux/drivers/media/dvb/ttpci/budget.c b/linux/drivers/media/dvb/ttpci/budget.c index c23c02d95..d98395fef 100644 --- a/linux/drivers/media/dvb/ttpci/budget.c +++ b/linux/drivers/media/dvb/ttpci/budget.c @@ -186,7 +186,7 @@ static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t m return 0; } -static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; u8 pwr = 0; @@ -209,6 +209,8 @@ static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param // NOTE: since we're using a prescaler of 2, we set the // divisor frequency to 62.5kHz and divide by 125 above + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } @@ -218,10 +220,9 @@ static struct ves1x93_config alps_bsrv2_config = .demod_address = 0x08, .xin = 90100000UL, .invert_pwm = 0, - .pll_set = alps_bsrv2_pll_set, }; -static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; u32 div; @@ -235,6 +236,8 @@ static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param data[2] = 0x85 | ((div >> 10) & 0x60); data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81); + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } @@ -244,10 +247,9 @@ static struct ves1820_config alps_tdbe2_config = { .xin = 57840000UL, .invert = 1, .selagc = VES1820_SELAGC_SIGNAMPERR, - .pll_set = alps_tdbe2_pll_set, }; -static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; u32 div; @@ -274,16 +276,17 @@ static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_fronten data[2] = ((div >> 10) & 0x60) | cfg; data[3] = (cpump << 6) | band_select; + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } static struct l64781_config grundig_29504_401_config = { .demod_address = 0x55, - .pll_set = grundig_29504_401_pll_set, }; -static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; u32 div; @@ -296,16 +299,17 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_fronten data[2] = 0x8e; data[3] = 0x00; + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } static struct tda8083_config grundig_29504_451_config = { .demod_address = 0x68, - .pll_set = grundig_29504_451_pll_set, }; -static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout) +static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; u32 div; @@ -326,16 +330,16 @@ static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete else data[3] = 0xc0; + if (fe->ops->i2c_gate_ctrl) + fe->ops->i2c_gate_ctrl(fe, 1); if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; - *freqout = div * 1000; return 0; } static struct s5h1420_config s5h1420_config = { .demod_address = 0x53, .invert = 1, - .pll_set = s5h1420_pll_set, }; static u8 read_pwm(struct budget* budget) @@ -359,6 +363,7 @@ static void frontend_init(struct budget *budget) // try the ALPS BSRV2 first of all budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap); if (budget->dvb_frontend) { + budget->dvb_frontend->ops->tuner_ops.set_params = alps_bsrv2_tuner_set_params; budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; budget->dvb_frontend->ops->set_tone = budget_set_tone; @@ -368,6 +373,8 @@ static void frontend_init(struct budget *budget) // try the ALPS BSRU6 now budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); if (budget->dvb_frontend) { + budget->dvb_frontend->ops->tuner_ops.set_params = alps_bsru6_tuner_set_params; + budget->dvb_frontend->tuner_priv = &budget->i2c_adap; budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; budget->dvb_frontend->ops->set_tone = budget_set_tone; @@ -378,18 +385,26 @@ static void frontend_init(struct budget *budget) case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659)) budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget)); - if (budget->dvb_frontend) break; + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->tuner_ops.set_params = alps_tdbe2_tuner_set_params; + break; + } break; case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060)) budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap); - if (budget->dvb_frontend) break; + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->tuner_ops.set_params = grundig_29504_401_tuner_set_params; + break; + } break; case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059)) budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); if (budget->dvb_frontend) { + budget->dvb_frontend->ops->tuner_ops.set_params = alps_bsru6_tuner_set_params; + budget->dvb_frontend->tuner_priv = &budget->i2c_adap; budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage; budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL; } @@ -398,6 +413,7 @@ static void frontend_init(struct budget *budget) case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522)) budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap); if (budget->dvb_frontend) { + budget->dvb_frontend->ops->tuner_ops.set_params = grundig_29504_451_tuner_set_params; budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage; budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL; } @@ -406,7 +422,8 @@ static void frontend_init(struct budget *budget) case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260)) budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap); if (budget->dvb_frontend) { - if (lnbp21_init(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) { + budget->dvb_frontend->ops->tuner_ops.set_params = s5h1420_tuner_set_params; + if (lnbp21_attach(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) { printk("%s: No LNBP21 found!\n", __FUNCTION__); goto error_out; } diff --git a/linux/drivers/media/dvb/ttpci/budget.h b/linux/drivers/media/dvb/ttpci/budget.h index 30f74b416..c5c226d4f 100644 --- a/linux/drivers/media/dvb/ttpci/budget.h +++ b/linux/drivers/media/dvb/ttpci/budget.h @@ -70,7 +70,13 @@ struct budget { int ci_present; int video_port; - u8 tsf; + u32 buffer_width; + u32 buffer_height; + u32 buffer_size; + u32 buffer_warning_threshold; + u32 buffer_warnings; + unsigned long buffer_warning_time; + u32 ttbp; int feeding; @@ -91,11 +97,6 @@ static struct saa7146_pci_extension_data x_var = { \ .ext_priv = &x_var ## _info, \ .ext = &budget_extension }; -#define TS_WIDTH (376) -#define TS_HEIGHT (512) -#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT) -#define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE) - #define BUDGET_TT 0 #define BUDGET_TT_HW_DISEQC 1 #define BUDGET_PATCH 3 |
