From: Michael Hunold - av7110: fixed av7110_before_after_tune()/av7110_fe_lock_fix(): firmware >= 261d: wait for empty message queue, firmware <= 261c: wait 50ms - av7110: add __user and __iomem annotations, remove some unnecessary cast (patch by C.Y.M) - av7110: __av7110_send_fw_cmd(): added some sanity checks suggested by Werner Fin - av7110: added support for full-featured DVB-C cards: 13c2:0000 Siemens DVB-C (full-length card) VES1820/Philips CD1516 and 13c2:0003 Haupauge DVB-C 2.1 VES1820/ALPS TDBE2 - av7110: follow saa7146 changes, remove superflous casts, and other misc. minor cleanups - av7110: Fixed race condition between driver and av7110 while accessing the COMMAND register in DPRAM. See http://www.linuxtv.org/mailinglists/vdr/2004/01-2004/msg00331.html - budget: various cleanups by Adrian bunk Signed-off-by: Michael Hunold Signed-off-by: Andrew Morton --- 25-akpm/drivers/media/dvb/ttpci/av7110.c | 166 +++++++------ 25-akpm/drivers/media/dvb/ttpci/av7110.h | 12 25-akpm/drivers/media/dvb/ttpci/av7110_hw.c | 92 ++++++- 25-akpm/drivers/media/dvb/ttpci/av7110_hw.h | 4 25-akpm/drivers/media/dvb/ttpci/av7110_v4l.c | 124 +++++++-- 25-akpm/drivers/media/dvb/ttpci/budget-av.c | 26 -- 25-akpm/drivers/media/dvb/ttpci/budget-ci.c | 1 25-akpm/drivers/media/dvb/ttpci/budget-core.c | 4 25-akpm/drivers/media/dvb/ttusb-budget/Kconfig | 2 25-akpm/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 176 +++++++++++++- 25-akpm/include/linux/dvb/frontend.h | 2 11 files changed, 468 insertions(+), 141 deletions(-) diff -puN drivers/media/dvb/ttpci/av7110.c~dvb-av7110-driver-update drivers/media/dvb/ttpci/av7110.c --- 25/drivers/media/dvb/ttpci/av7110.c~dvb-av7110-driver-update Fri Dec 10 15:14:21 2004 +++ 25-akpm/drivers/media/dvb/ttpci/av7110.c Fri Dec 10 15:14:21 2004 @@ -77,7 +77,7 @@ static int rgb_on; static int volume = 255; module_param_named(debug, av7110_debug, int, 0644); -MODULE_PARM_DESC(av7110_debug, "Turn on/off debugging (default:off)."); +MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)"); module_param(vidmode, int, 0444); MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC"); module_param(pids_off, int, 0444); @@ -117,7 +117,7 @@ static void init_av7110_av(struct av7110 /* handle different card types */ /* remaining inits according to card and frontend type */ - av7110->has_analog_tuner = 0; + av7110->analog_tuner_flags = 0; av7110->current_input = 0; if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) { printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n", @@ -149,10 +149,12 @@ static void init_av7110_av(struct av7110 // switch DVB SCART on av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0); av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1); - if (rgb_on) + if (rgb_on && + (av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) { saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16 //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8 } + } av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right); av7110_setup_irc_config(av7110, 0); @@ -192,9 +194,10 @@ static int arm_thread(void *data) av7110->arm_thread = current; - while (1) { - timeout = wait_event_interruptible_timeout(av7110->arm_wait,0 != av7110->arm_rmmod, 5*HZ); - if (-ERESTARTSYS == timeout || 0 != av7110->arm_rmmod) { + for (;;) { + timeout = wait_event_interruptible_timeout(av7110->arm_wait, + av7110->arm_rmmod, 5 * HZ); + if (-ERESTARTSYS == timeout || av7110->arm_rmmod) { /* got signal or told to quit*/ break; } @@ -287,7 +290,7 @@ static void IR_handle(struct av7110 *av7 * IRQ handling ****************************************************************************/ -static inline int DvbDmxFilterCallback(u8 * buffer1, size_t buffer1_len, +static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len, u8 * buffer2, size_t buffer2_len, struct dvb_demux_filter *dvbdmxfilter, enum dmx_success success, @@ -355,9 +358,8 @@ static void debiirq (unsigned long data) // dprintk(4, "%p\n",av7110); print_time("debi"); - saa7146_write(av7110->dev, IER, - saa7146_read(av7110->dev, IER) & ~MASK_19 ); - saa7146_write(av7110->dev, ISR, MASK_19 ); + SAA7146_IER_DISABLE(av7110->dev, MASK_19); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19); if (type==-1) { printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n", @@ -493,9 +495,8 @@ static void gpioirq (unsigned long data) ARM_ClearIrq(av7110); - saa7146_write(av7110->dev, IER, - saa7146_read(av7110->dev, IER) & ~MASK_19 ); - saa7146_write(av7110->dev, ISR, MASK_19 ); + SAA7146_IER_DISABLE(av7110->dev, MASK_19); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19); av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2); av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2); @@ -822,9 +823,13 @@ static int StartHWFilter(struct dvb_demu buf[3] = mode; ret = av7110_fw_request(av7110, buf, 20, &handle, 1); - if (ret < 0) { - dprintk(1, "StartHWFilter error\n"); - return ret; + if (ret != 0 || handle >= 32) { + printk("dvb-ttpci: %s error buf %04x %04x %04x %04x " + "ret %x handle %04x\n", + __FUNCTION__, buf[0], buf[1], buf[2], buf[3], + ret, handle); + dvbdmxfilter->hw_handle = 0xffff; + return -1; } av7110->handle2filter[handle] = dvbdmxfilter; @@ -844,8 +849,9 @@ static int StopHWFilter(struct dvb_demux dprintk(4, "%p\n", av7110); handle = dvbdmxfilter->hw_handle; - if (handle > 32) { - dprintk(1, "StopHWFilter tried to stop invalid filter %d, filter type = %d\n", handle, dvbdmxfilter->type); + if (handle >= 32) { + printk("%s tried to stop invalid filter %04x, filter type = %x\n", + __FUNCTION__, handle, dvbdmxfilter->type); return 0; } @@ -855,11 +861,11 @@ static int StopHWFilter(struct dvb_demux buf[1] = 1; buf[2] = handle; ret = av7110_fw_request(av7110, buf, 3, answ, 2); - if (ret) - dprintk(1, "StopHWFilter error\n"); - - if (answ[1] != handle) { - dprintk(2, "filter %d shutdown error :%d\n", handle, answ[1]); + if (ret != 0 || answ[1] != handle) { + printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x " + "resp %04x %04x pid %d\n", + __FUNCTION__, buf[0], buf[1], buf[2], ret, + answ[0], answ[1], dvbdmxfilter->feed->pid); ret = -1; } return ret; @@ -937,7 +943,7 @@ static void dvb_feed_stop_pid(struct dvb static int av7110_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct av7110 *av7110 = (struct av7110 *) demux->priv; + struct av7110 *av7110 = demux->priv; dprintk(4, "%p\n", av7110); @@ -995,7 +1001,7 @@ static int av7110_start_feed(struct dvb_ static int av7110_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct av7110 *av7110 = (struct av7110 *) demux->priv; + struct av7110 *av7110 = demux->priv; dprintk(4, "%p\n", av7110); @@ -1119,18 +1125,20 @@ static int av7110_set_tone(struct dvb_fr return 0; } -static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) +static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe, + struct dvb_diseqc_master_cmd* cmd) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1); return 0; } -static int av7110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) +static int av7110_diseqc_send_burst(struct dvb_frontend* fe, + fe_sec_mini_cmd_t minicmd) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; av7110_diseqc_send(av7110, 0, NULL, minicmd); @@ -1223,7 +1231,8 @@ static void dvb_unregister(struct av7110 dvb_dmxdev_release(&av7110->dmxdev); dvb_dmx_release(&av7110->demux); - if (av7110->fe != NULL) dvb_unregister_frontend(av7110->fe); + if (av7110->fe != NULL) + dvb_unregister_frontend(av7110->fe); dvb_unregister_device(av7110->osd_dev); av7110_av_unregister(av7110); av7110_ca_unregister(av7110); @@ -1519,7 +1528,7 @@ static struct stv0299_config alps_bsru6_ static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; u32 div; u8 data[4]; struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) }; @@ -1547,9 +1556,10 @@ static struct ves1820_config alps_tdbe2_ -static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int grundig_29504_451_pll_set(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; u32 div; u8 data[4]; struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; @@ -1572,9 +1582,10 @@ static struct tda8083_config grundig_295 -static int philips_cd1516_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int philips_cd1516_pll_set(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; u32 div; u32 f = params->frequency; u8 data[4]; @@ -1604,7 +1615,7 @@ static struct ves1820_config philips_cd1 static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; u32 div, pwr; u8 data[4]; struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) }; @@ -1644,19 +1655,18 @@ static struct sp8870_config alps_tdlb7_c static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; u32 div; u8 data[4]; struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) }; struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 }; int i; - // this calculation does not match the TDA6405TS datasheet! div = (params->frequency + 36150000 + 31250) / 62500; data[0] = (div >> 8) & 0x7f; data[1] = div & 0xff; - data[2] = 0xce; // this value does not match the TDA6405TS datasheet! + data[2] = 0xce; if (params->frequency < 45000000) return -EINVAL; @@ -1696,9 +1706,14 @@ static struct stv0297_config nexusca_stv static void av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status) { - msleep (50); + int synced = (status & FE_HAS_LOCK) ? 1 : 0; - av7110->fe_synced = (status & FE_HAS_LOCK) ? 1 : 0; + av7110->fe_status = status; + + if (av7110->fe_synced == synced) + return; + + av7110->fe_synced = synced; if (av7110->playing) return; @@ -1714,16 +1729,23 @@ static void av7110_fe_lock_fix(struct av av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0); } else { SetPIDs(av7110, 0, 0, 0, 0, 0); - av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, FlushTSQueue, 0); + av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0); + av7110_wait_msgstate(av7110, GPMQBusy); } - av7110->fe_status = status; up(&av7110->pid_mutex); } +static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = fe->dvb->priv; + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_set_frontend(fe, params); +} + static int av7110_fe_init(struct dvb_frontend* fe) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; av7110_fe_lock_fix(av7110, 0); return av7110->fe_init(fe); @@ -1731,7 +1753,7 @@ static int av7110_fe_init(struct dvb_fro static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; int ret; /* call the real implementation */ @@ -1748,15 +1770,16 @@ static int av7110_fe_read_status(struct static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; av7110_fe_lock_fix(av7110, 0); return av7110->fe_diseqc_reset_overload(fe); } -static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) +static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe, + struct dvb_diseqc_master_cmd* cmd) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; av7110_fe_lock_fix(av7110, 0); return av7110->fe_diseqc_send_master_cmd(fe, cmd); @@ -1764,7 +1787,7 @@ static int av7110_fe_diseqc_send_master_ static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; av7110_fe_lock_fix(av7110, 0); return av7110->fe_diseqc_send_burst(fe, minicmd); @@ -1772,7 +1795,7 @@ static int av7110_fe_diseqc_send_burst(s static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; av7110_fe_lock_fix(av7110, 0); return av7110->fe_set_tone(fe, tone); @@ -1780,7 +1803,7 @@ static int av7110_fe_set_tone(struct dvb static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; av7110_fe_lock_fix(av7110, 0); return av7110->fe_set_voltage(fe, voltage); @@ -1788,7 +1811,7 @@ static int av7110_fe_set_voltage(struct static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned int cmd) { - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + struct av7110* av7110 = fe->dvb->priv; av7110_fe_lock_fix(av7110, 0); return av7110->fe_dishnetwork_send_legacy_command(fe, cmd); @@ -1812,9 +1835,8 @@ static void frontend_init(struct av7110 if (av7110->dev->pci->subsystem_vendor == 0x110a) { switch(av7110->dev->pci->subsystem_device) { 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) - break; + av7110->fe = ves1820_attach(&philips_cd1516_config, + &av7110->i2c_adap, read_pwm(av7110)); break; } @@ -1850,27 +1872,41 @@ static void frontend_init(struct av7110 av7110->fe->ops->set_tone = av7110_set_tone; break; } + + /* Try DVB-C cards */ + switch(av7110->dev->pci->subsystem_device) { + case 0x0000: + /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */ + av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap, + read_pwm(av7110)); + break; + case 0x0003: + /* Haupauge DVB-C 2.1 VES1820/ALPS TDBE2 */ + av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, + read_pwm(av7110)); + break; + } break; case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X // ALPS TDLB7 av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap); - if (av7110->fe) - break; 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) - break; break; case 0x000A: // Hauppauge/TT Nexus-CA rev1.X av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap, 0x7b); if (av7110->fe) { + /* set TDA9819 into DVB mode */ + saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD) + saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) + /* tuner on this needs a slower i2c bus speed */ av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240; break; @@ -1893,6 +1929,8 @@ static void frontend_init(struct av7110 FE_FUNC_OVERRIDE(av7110->fe->ops->set_tone, av7110->fe_set_tone, av7110_fe_set_tone); FE_FUNC_OVERRIDE(av7110->fe->ops->set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;) FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command); + FE_FUNC_OVERRIDE(av7110->fe->ops->set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend); + if (dvb_register_frontend(av7110->dvb_adapter, av7110->fe)) { printk("av7110: Frontend registration failed!\n"); if (av7110->fe->ops->release) @@ -1969,7 +2007,6 @@ static int av7110_attach(struct saa7146_ /* locks for data transfers from/to AV7110 */ spin_lock_init (&av7110->debilock); sema_init(&av7110->dcomlock, 1); - av7110->debilock=SPIN_LOCK_UNLOCKED; av7110->debitype=-1; /* default OSD window */ @@ -2086,11 +2123,8 @@ static int av7110_detach (struct saa7146 dvb_unregister(av7110); - IER_DISABLE(saa, (MASK_19 | MASK_03)); -// saa7146_write (av7110->dev, IER, -// saa7146_read(av7110->dev, IER) & ~(MASK_19 | MASK_03)); - - saa7146_write(av7110->dev, ISR,(MASK_19 | MASK_03)); + SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03); + SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03); av7110_ca_exit(av7110); av7110_av_exit(av7110); @@ -2117,7 +2151,7 @@ static int av7110_detach (struct saa7146 static void av7110_irq(struct saa7146_dev* dev, u32 *isr) { - struct av7110 *av7110 = (struct av7110*)dev->ext_priv; + struct av7110 *av7110 = dev->ext_priv; if (*isr & MASK_19) tasklet_schedule (&av7110->debi_tasklet); diff -puN drivers/media/dvb/ttpci/av7110.h~dvb-av7110-driver-update drivers/media/dvb/ttpci/av7110.h --- 25/drivers/media/dvb/ttpci/av7110.h~dvb-av7110-driver-update Fri Dec 10 15:14:21 2004 +++ 25-akpm/drivers/media/dvb/ttpci/av7110.h Fri Dec 10 15:14:21 2004 @@ -34,6 +34,11 @@ #include + +#define ANALOG_TUNER_VES1820 1 +#define ANALOG_TUNER_STV0297 2 +#define ANALOG_TUNER_VBI 0x100 + extern int av7110_debug; #define dprintk(level,args...) \ @@ -82,7 +87,7 @@ struct av7110 { char *card_name; /* support for analog module of dvb-c */ - int has_analog_tuner; + int analog_tuner_flags; int current_input; u32 current_freq; @@ -122,8 +127,8 @@ struct av7110 { spinlock_t debilock; struct semaphore dcomlock; - int debitype; - int debilen; + volatile int debitype; + volatile int debilen; /* Recording and playback flags */ @@ -235,6 +240,7 @@ struct av7110 { int (*fe_set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone); int (*fe_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd); + int (*fe_set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; diff -puN drivers/media/dvb/ttpci/av7110_hw.c~dvb-av7110-driver-update drivers/media/dvb/ttpci/av7110_hw.c --- 25/drivers/media/dvb/ttpci/av7110_hw.c~dvb-av7110-driver-update Fri Dec 10 15:14:21 2004 +++ 25-akpm/drivers/media/dvb/ttpci/av7110_hw.c Fri Dec 10 15:14:21 2004 @@ -110,16 +110,16 @@ void av7110_reset_arm(struct av7110 *av7 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO); /* Disable DEBI and GPIO irq */ - IER_DISABLE(av7110->dev, (MASK_19 | MASK_03)); - saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); + SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI); msleep(30); /* the firmware needs some time to initialize */ ARM_ResetMailBox(av7110); - saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); - IER_ENABLE(av7110->dev, MASK_03); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); + SAA7146_IER_ENABLE(av7110->dev, MASK_03); av7110->arm_ready = 1; dprintk(1, "reset ARM\n"); @@ -223,8 +223,8 @@ int av7110_bootarm(struct av7110 *av7110 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO); /* Disable DEBI and GPIO irq */ - IER_DISABLE(av7110->dev, MASK_03 | MASK_19); - saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); + SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); /* enable DEBI */ saa7146_write(av7110->dev, MC1, 0x08800880); @@ -280,8 +280,8 @@ int av7110_bootarm(struct av7110 *av7110 //ARM_ClearIrq(av7110); ARM_ResetMailBox(av7110); - saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); - IER_ENABLE(av7110->dev, MASK_03); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); + SAA7146_IER_ENABLE(av7110->dev, MASK_03); av7110->arm_errors = 0; av7110->arm_ready = 1; @@ -293,13 +293,44 @@ int av7110_bootarm(struct av7110 *av7110 * DEBI command polling ****************************************************************************/ +int av7110_wait_msgstate(struct av7110 *av7110, u16 flags) +{ + unsigned long start; + u32 stat; + + if (FW_VERSION(av7110->arm_app) <= 0x261c) { + /* not supported by old firmware */ + msleep(50); + return 0; + } + + /* new firmware */ + start = jiffies; + for (;;) { + if (down_interruptible(&av7110->dcomlock)) + return -ERESTARTSYS; + stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); + up(&av7110->dcomlock); + if ((stat & flags) == 0) { + break; + } + if (time_after(jiffies, start + ARM_WAIT_FREE)) { + printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n", + __FUNCTION__, stat & flags); + return -1; + } + msleep(1); + } + return 0; +} + int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) { int i; unsigned long start; -#ifdef COM_DEBUG + char *type = NULL; + u16 flags[2] = {0, 0}; u32 stat; -#endif // dprintk(4, "%p\n", av7110); @@ -330,14 +361,45 @@ int __av7110_send_fw_cmd(struct av7110 * } #endif + switch ((buf[0] >> 8) & 0xff) { + case COMTYPE_PIDFILTER: + case COMTYPE_ENCODER: + case COMTYPE_REC_PLAY: + case COMTYPE_MPEGDECODER: + type = "MSG"; + flags[0] = GPMQOver; + flags[1] = GPMQFull; + break; + case COMTYPE_OSD: + type = "OSD"; + flags[0] = OSDQOver; + flags[1] = OSDQFull; + break; + default: + break; + } + + if (type != NULL) { + /* non-immediate COMMAND type */ start = jiffies; - while (rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2) & OSDQFull) { - msleep(1); - if (time_after(jiffies, start + ARM_WAIT_OSD)) { - printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for !OSDQFull\n", __FUNCTION__); + for (;;) { + stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); + if (stat & flags[0]) { + printk(KERN_ERR "%s: %s QUEUE overflow\n", + __FUNCTION__, type); + return -1; + } + if ((stat & flags[1]) == 0) + break; + if (time_after(jiffies, start + ARM_WAIT_FREE)) { + printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n", + __FUNCTION__, type); return -1; } + msleep(1); + } } + for (i = 2; i < length; i++) wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2); @@ -972,7 +1034,7 @@ int av7110_osd_cmd(struct av7110 *av7110 goto out; } else { int i, len = dc->x0-dc->color+1; - u8 __user *colors = dc->data; + u8 __user *colors = (u8 *)dc->data; u8 r, g, b, blend; for (i = 0; i= 261d */ +#define HPQBusy 0x0080 +#define OSDQBusy 0x0100 /* hw section filter flags */ #define SECTION_EIT 0x01 @@ -368,6 +371,7 @@ extern int av7110_firmversion(struct av7 #define FW_4M_SDRAM(arm_app) ((arm_app) & 0x40000000) #define FW_VERSION(arm_app) ((arm_app) & 0x0000FFFF) +extern int av7110_wait_msgstate(struct av7110 *av7110, u16 flags); extern int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...); extern int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length); extern int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length); diff -puN drivers/media/dvb/ttpci/av7110_v4l.c~dvb-av7110-driver-update drivers/media/dvb/ttpci/av7110_v4l.c --- 25/drivers/media/dvb/ttpci/av7110_v4l.c~dvb-av7110-driver-update Fri Dec 10 15:14:21 2004 +++ 25-akpm/drivers/media/dvb/ttpci/av7110_v4l.c Fri Dec 10 15:14:21 2004 @@ -92,10 +92,8 @@ static struct v4l2_input inputs[2] = { } }; -/* for Siemens DVB-C analog module: (taken from ves1820.c) */ -static int ves1820_writereg(struct saa7146_dev *dev, u8 reg, u8 data) +static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data) { - u8 addr = 0x09; u8 buf[] = { 0x00, reg, data }; struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 }; @@ -106,6 +104,17 @@ static int ves1820_writereg(struct saa71 return 0; } +static int stv0297_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data) +{ + u8 buf [] = { reg, data }; + struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 2 }; + + if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1)) + return -1; + return 0; +} + + static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4]) { struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 }; @@ -117,12 +126,7 @@ static int tuner_write(struct saa7146_de return 0; } - -/** - * set up the downconverter frequency divisor for a - * reference clock comparision frequency of 62.5 kHz. - */ -static int tuner_set_tv_freq(struct saa7146_dev *dev, u32 freq) +static int ves1820_set_tv_freq(struct saa7146_dev *dev, u32 freq) { u32 div; u8 config; @@ -151,6 +155,34 @@ static int tuner_set_tv_freq(struct saa7 return tuner_write(dev, 0x61, buf); } +static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq) +{ + u32 div; + u8 data[4]; + + div = (freq + 38900000 + 31250) / 62500; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0xce; + + if (freq < 45000000) + return -EINVAL; + else if (freq < 137000000) + data[3] = 0x01; + else if (freq < 403000000) + data[3] = 0x02; + else if (freq < 860000000) + data[3] = 0x04; + else + return -EINVAL; + + stv0297_writereg(dev, 0x1C, 0x87, 0x78); + stv0297_writereg(dev, 0x1C, 0x86, 0xc8); + return tuner_write(dev, 0x63, data); +} + + static struct saa7146_standard analog_standard[]; static struct saa7146_standard dvb_standard[]; @@ -168,7 +200,6 @@ static int av7110_dvb_c_switch(struct sa struct saa7146_vv *vv = dev->vv_data; struct av7110 *av7110 = (struct av7110*)dev->ext_priv; u16 adswitch; - u8 band = 0; int source, sync, err; dprintk(4, "%p\n", av7110); @@ -184,7 +215,6 @@ static int av7110_dvb_c_switch(struct sa if (0 != av7110->current_input) { adswitch = 1; - band = 0x60; /* analog band */ source = SAA7146_HPS_SOURCE_PORT_B; sync = SAA7146_HPS_SYNC_PORT_B; memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2); @@ -195,9 +225,16 @@ static int av7110_dvb_c_switch(struct sa msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume + + if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) { + if (ves1820_writereg(dev, 0x09, 0x0f, 0x60)) + dprintk(1, "setting band in demodulator failed.\n"); + } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD) + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF) + } } else { adswitch = 0; - band = 0x20; /* digital band */ source = SAA7146_HPS_SOURCE_PORT_A; sync = SAA7146_HPS_SYNC_PORT_A; memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2); @@ -208,15 +245,20 @@ static int av7110_dvb_c_switch(struct sa msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume + + if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) { + if (ves1820_writereg(dev, 0x09, 0x0f, 0x20)) + dprintk(1, "setting band in demodulator failed.\n"); + } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD) + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) + } } /* hmm, this does not do anything!? */ if (av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, adswitch)) dprintk(1, "ADSwitch error\n"); - if (ves1820_writereg(dev, 0x0f, band)) - dprintk(1, "setting band in demodulator failed.\n"); - saa7146_set_hps_source_and_sync(dev, source, sync); if (vv->ov_suspend != NULL) { @@ -242,7 +284,7 @@ static int av7110_ioctl(struct saa7146_f dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index); - if (!av7110->has_analog_tuner || t->index != 0) + if (!av7110->analog_tuner_flags || t->index != 0) return -EINVAL; memset(t, 0, sizeof(*t)); @@ -285,7 +327,7 @@ static int av7110_ioctl(struct saa7146_f u16 fm_matrix, src; dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index); - if (!av7110->has_analog_tuner || av7110->current_input != 1) + if (!av7110->analog_tuner_flags || av7110->current_input != 1) return -EINVAL; switch (t->audmode) { @@ -322,7 +364,7 @@ static int av7110_ioctl(struct saa7146_f dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency); - if (!av7110->has_analog_tuner || av7110->current_input != 1) + if (!av7110->analog_tuner_flags || av7110->current_input != 1) return -EINVAL; memset(f, 0, sizeof(*f)); @@ -336,7 +378,7 @@ static int av7110_ioctl(struct saa7146_f dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency); - if (!av7110->has_analog_tuner || av7110->current_input != 1) + if (!av7110->analog_tuner_flags || av7110->current_input != 1) return -EINVAL; if (V4L2_TUNER_ANALOG_TV != f->type) @@ -346,7 +388,11 @@ static int av7110_ioctl(struct saa7146_f msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0); /* tune in desired frequency */ - tuner_set_tv_freq(dev, f->frequency); + if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) { + ves1820_set_tv_freq(dev, f->frequency); + } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { + stv0297_set_tv_freq(dev, f->frequency); + } av7110->current_freq = f->frequency; msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); // start stereo detection @@ -361,7 +407,7 @@ static int av7110_ioctl(struct saa7146_f dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index); - if (av7110->has_analog_tuner ) { + if (av7110->analog_tuner_flags) { if (i->index < 0 || i->index >= 2) return -EINVAL; } else { @@ -386,7 +432,7 @@ static int av7110_ioctl(struct saa7146_f dprintk(2, "VIDIOC_S_INPUT: %d\n", input); - if (!av7110->has_analog_tuner ) + if (!av7110->analog_tuner_flags) return 0; if (input < 0 || input >= 2) @@ -528,7 +574,27 @@ int av7110_init_analog_module(struct av7 INFO(("saa7113 not accessible.\n")); } else { u8 *i = saa7113_init_regs; - av7110->has_analog_tuner = 1; + + if ((av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) { + /* Fujitsu/Siemens DVB-Cable */ + av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820; + } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x0002)) { + /* Hauppauge/TT DVB-C premium */ + av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820; + } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x000A)) { + /* Hauppauge/TT DVB-C premium */ + av7110->analog_tuner_flags |= ANALOG_TUNER_STV0297; + } + + /* setup for DVB by default */ + if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) { + if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20)) + dprintk(1, "setting band in demodulator failed.\n"); + } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { + saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD) + saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) + } + /* init the saa7113 */ while (*i != 0xff) { if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) { @@ -579,7 +645,7 @@ int av7110_init_v4l(struct av7110 *av711 /* special case DVB-C: these cards have an analog tuner plus need some special handling, so we have separate saa7146_ext_vv data for these... */ - if (av7110->has_analog_tuner) + if (av7110->analog_tuner_flags) ret = saa7146_vv_init(dev, &av7110_vv_data_c); else ret = saa7146_vv_init(dev, &av7110_vv_data_st); @@ -594,12 +660,12 @@ int av7110_init_v4l(struct av7110 *av711 saa7146_vv_release(dev); return -ENODEV; } - if (av7110->has_analog_tuner) { + if (av7110->analog_tuner_flags) { if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) { ERR(("cannot register vbi v4l2 device. skipping.\n")); - } else - /* we use this to remember that this dvb-c card can do vbi */ - av7110->has_analog_tuner = 2; + } else { + av7110->analog_tuner_flags |= ANALOG_TUNER_VBI; + } } return 0; } @@ -607,7 +673,7 @@ int av7110_init_v4l(struct av7110 *av711 int av7110_exit_v4l(struct av7110 *av7110) { saa7146_unregister_device(&av7110->v4l_dev, av7110->dev); - if (2 == av7110->has_analog_tuner) + if (av7110->analog_tuner_flags & ANALOG_TUNER_VBI) saa7146_unregister_device(&av7110->vbi_dev, av7110->dev); return 0; } diff -puN drivers/media/dvb/ttpci/budget-av.c~dvb-av7110-driver-update drivers/media/dvb/ttpci/budget-av.c --- 25/drivers/media/dvb/ttpci/budget-av.c~dvb-av7110-driver-update Fri Dec 10 15:14:21 2004 +++ 25-akpm/drivers/media/dvb/ttpci/budget-av.c Fri Dec 10 15:14:21 2004 @@ -563,23 +563,13 @@ static int philips_tu1216_pll_init(struc { struct budget *budget = (struct budget *) fe->dvb->priv; static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab }; - static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; - struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = - sizeof(tu1216_init) }; + struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) }; // setup PLL configuration if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1) return -EIO; msleep(1); - // disable the mc44BC374c (do not check for errors) - tuner_msg.addr = 0x65; - tuner_msg.buf = disable_mc44BC374c; - tuner_msg.len = sizeof(disable_mc44BC374c); - if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1) { - i2c_transfer(&budget->i2c_adap, &tuner_msg, 1); - } - return 0; } @@ -593,7 +583,7 @@ static int philips_tu1216_pll_set(struct u8 band, cp, filter; // determine charge pump - tuner_frequency = params->frequency + 36130000; + tuner_frequency = params->frequency + 36166000; if (tuner_frequency < 87000000) return -EINVAL; else if (tuner_frequency < 130000000) @@ -620,7 +610,7 @@ static int philips_tu1216_pll_set(struct // determine band if (params->frequency < 49000000) return -EINVAL; - else if (params->frequency < 159000000) + else if (params->frequency < 161000000) band = 1; else if (params->frequency < 444000000) band = 2; @@ -632,17 +622,14 @@ static int philips_tu1216_pll_set(struct // setup PLL filter switch (params->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: - tda1004x_write_byte(fe, 0x0C, 0); filter = 0; break; case BANDWIDTH_7_MHZ: - tda1004x_write_byte(fe, 0x0C, 0); filter = 0; break; case BANDWIDTH_8_MHZ: - tda1004x_write_byte(fe, 0x0C, 0xFF); filter = 1; break; @@ -651,11 +638,11 @@ static int philips_tu1216_pll_set(struct } // calculate divisor - // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6) - tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000; + // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6) + tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000; // setup tuner buffer - tuner_buf[0] = tuner_frequency >> 8; + tuner_buf[0] = (tuner_frequency >> 8) & 0x7f; tuner_buf[1] = tuner_frequency & 0xff; tuner_buf[2] = 0xca; tuner_buf[3] = (cp << 5) | (filter << 3) | band; @@ -679,6 +666,7 @@ struct tda1004x_config philips_tu1216_co .demod_address = 0x8, .invert = 1, + .invert_oclk = 1, .pll_init = philips_tu1216_pll_init, .pll_set = philips_tu1216_pll_set, .request_firmware = philips_tu1216_request_firmware, diff -puN drivers/media/dvb/ttpci/budget-ci.c~dvb-av7110-driver-update drivers/media/dvb/ttpci/budget-ci.c --- 25/drivers/media/dvb/ttpci/budget-ci.c~dvb-av7110-driver-update Fri Dec 10 15:14:21 2004 +++ 25-akpm/drivers/media/dvb/ttpci/budget-ci.c Fri Dec 10 15:14:21 2004 @@ -844,6 +844,7 @@ static struct tda1004x_config philips_td .demod_address = 0x8, .invert = 0, + .invert_oclk = 0, .pll_init = philips_tdm1316l_pll_init, .pll_set = philips_tdm1316l_pll_set, .request_firmware = philips_tdm1316l_request_firmware, diff -puN drivers/media/dvb/ttpci/budget-core.c~dvb-av7110-driver-update drivers/media/dvb/ttpci/budget-core.c --- 25/drivers/media/dvb/ttpci/budget-core.c~dvb-av7110-driver-update Fri Dec 10 15:14:21 2004 +++ 25-akpm/drivers/media/dvb/ttpci/budget-core.c Fri Dec 10 15:14:21 2004 @@ -56,7 +56,7 @@ static int stop_ts_capture(struct budget return budget->feeding; saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off - IER_DISABLE(budget->dev, MASK_10); + SAA7146_IER_DISABLE(budget->dev, MASK_10); return 0; } @@ -124,7 +124,7 @@ static int start_ts_capture (struct budg saa7146_write(dev, MC2, (MASK_04 | MASK_20)); saa7146_write(dev, MC1, (MASK_04 | MASK_20)); // DMA3 on - IER_ENABLE(budget->dev, MASK_10); // VPE + SAA7146_IER_ENABLE(budget->dev, MASK_10); // VPE return ++budget->feeding; } diff -puN drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c~dvb-av7110-driver-update drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c --- 25/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c~dvb-av7110-driver-update Fri Dec 10 15:14:21 2004 +++ 25-akpm/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c Fri Dec 10 15:14:21 2004 @@ -26,6 +26,8 @@ #include "dvb_net.h" #include "cx22700.h" #include "tda1004x.h" +#include "stv0299.h" +#include "tda8083.h" #include #include @@ -489,7 +491,6 @@ static int ttusb_send_diseqc(struct dvb_ } #endif -#if 0 static int ttusb_update_lnb(struct ttusb *ttusb) { u8 b[] = { 0xaa, ++ttusb->c, 0x16, 5, /*power: */ 1, @@ -524,7 +525,6 @@ static int ttusb_set_tone(struct dvb_fro return ttusb_update_lnb(ttusb); } #endif -#endif #if 0 @@ -1177,7 +1177,8 @@ static int philips_tdm1316l_pll_set(stru tuner_buf[2] = 0xca; tuner_buf[3] = (cp << 5) | (filter << 3) | band; - if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO; + if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) + return -EIO; msleep(1); return 0; @@ -1194,24 +1195,187 @@ static struct tda1004x_config philips_td .demod_address = 0x8, .invert = 1, + .invert_oclk = 0, .pll_init = philips_tdm1316l_pll_init, .pll_set = philips_tdm1316l_pll_set, .request_firmware = philips_tdm1316l_request_firmware, }; +static u8 alps_bsru6_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x52, + 0xff, 0xff +}; + +static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { + aclk = 0xb7; + bclk = 0x47; + } else if (srate < 3000000) { + aclk = 0xb7; + bclk = 0x4b; + } else if (srate < 7000000) { + aclk = 0xb7; + bclk = 0x4f; + } else if (srate < 14000000) { + aclk = 0xb7; + bclk = 0x53; + } else if (srate < 30000000) { + aclk = 0xb6; + bclk = 0x53; + } else if (srate < 45000000) { + aclk = 0xb4; + bclk = 0x51; + } + + stv0299_writereg(fe, 0x13, aclk); + stv0299_writereg(fe, 0x14, bclk); + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, (ratio) & 0xf0); + + return 0; +} + +static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + u8 buf[4]; + u32 div; + struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + buf[3] = 0xC4; + + if (params->frequency > 1530000) + buf[3] = 0xc0; + + if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) + return -EIO; + + return 0; +} + +static struct stv0299_config alps_bsru6_config = { + + .demod_address = 0x68, + .inittab = alps_bsru6_inittab, + .mclk = 88000000UL, + .invert = 1, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, + .pll_set = alps_bsru6_pll_set, +}; + +static int ttusb_novas_grundig_29504_491_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + u8 buf[4]; + u32 div; + struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; + + div = params->frequency / 125; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x8e; + buf[3] = 0x00; + + if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) + return -EIO; + + return 0; +} + +static struct tda8083_config ttusb_novas_grundig_29504_491_config = { + + .demod_address = 0x68, + .pll_set = ttusb_novas_grundig_29504_491_pll_set, +}; + + static void frontend_init(struct ttusb* ttusb) { switch(ttusb->dev->descriptor.idProduct) { + case 0x1003: // Hauppauge/TT Nova-USB-S budget (stv0299/ALPS BSRU6(tsa5059) + // try the ALPS BSRU6 first + ttusb->fe = stv0299_attach(&alps_bsru6_config, &ttusb->i2c_adap); + if (ttusb->fe != NULL) { + ttusb->fe->ops->set_voltage = ttusb_set_voltage; + break; + } + + // Grundig 29504-491 + ttusb->fe = tda8083_attach(&ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap); + if (ttusb->fe != NULL) { + ttusb->fe->ops->set_voltage = ttusb_set_voltage; + break; + } + + break; + case 0x1005: // Hauppauge/TT Nova-USB-t budget (tda10046/Philips td1316(tda6651tt) OR cx22700/ALPS TDMB7(??)) // try the ALPS TDMB7 first ttusb->fe = cx22700_attach(&alps_tdmb7_config, &ttusb->i2c_adap); - if (ttusb->fe != NULL) break; + if (ttusb->fe != NULL) + break; // Philips td1316 ttusb->fe = tda10046_attach(&philips_tdm1316l_config, &ttusb->i2c_adap); - if (ttusb->fe != NULL) break; + if (ttusb->fe != NULL) + break; break; } @@ -1382,7 +1546,7 @@ static void ttusb_disconnect(struct usb_ } static struct usb_device_id ttusb_table[] = { -/* {USB_DEVICE(0xb48, 0x1003)},UNDEFINED HARDWARE - mail linuxtv.org list */ + {USB_DEVICE(0xb48, 0x1003)}, /* {USB_DEVICE(0xb48, 0x1004)},UNDEFINED HARDWARE - mail linuxtv.org list*/ /* to be confirmed ???? */ {USB_DEVICE(0xb48, 0x1005)}, {} diff -puN drivers/media/dvb/ttusb-budget/Kconfig~dvb-av7110-driver-update drivers/media/dvb/ttusb-budget/Kconfig --- 25/drivers/media/dvb/ttusb-budget/Kconfig~dvb-av7110-driver-update Fri Dec 10 15:14:21 2004 +++ 25-akpm/drivers/media/dvb/ttusb-budget/Kconfig Fri Dec 10 15:14:21 2004 @@ -3,6 +3,8 @@ config DVB_TTUSB_BUDGET depends on DVB_CORE && USB select DVB_CX22700 select DVB_TDA1004X + select DVB_TDA8083 + select DVB_STV0299 help Support for external USB adapters designed by Technotrend and produced by Hauppauge, shipped under the brand name 'Nova-USB'. diff -puN include/linux/dvb/frontend.h~dvb-av7110-driver-update include/linux/dvb/frontend.h --- 25/include/linux/dvb/frontend.h~dvb-av7110-driver-update Fri Dec 10 15:14:21 2004 +++ 25-akpm/include/linux/dvb/frontend.h Fri Dec 10 15:14:21 2004 @@ -62,7 +62,7 @@ typedef enum fe_caps { FE_CAN_HIERARCHY_AUTO = 0x100000, FE_CAN_8VSB = 0x200000, FE_CAN_16VSB = 0x400000, - FE_NEEDS_BENDING = 0x20000000, // frontend requires frequency bending + FE_NEEDS_BENDING = 0x20000000, // not supported anymore, don't use (frontend requires frequency bending) FE_CAN_RECOVER = 0x40000000, // frontend can recover from a cable unplug automatically FE_CAN_MUTE_TS = 0x80000000 // frontend can stop spurious TS data output } fe_caps_t; _