>>> >>> >> Yes. More difficult. I can pollute tuner.ko with cx88 stuff, and have >> the specific 'gate' flag passed in tuner_setup, or added to cx88_core, >> but it didn't seem to make any sense when tuner.ko only knows about I2C >> clients and tuner types (not demods and specific demod behavior, or even >> DVB related things for that matter). >> > > No, we shouldn't add cx88 specific stuff to tuner.ko, but in > cx88 where the VIDIOC_S_FREQUENCY ioctl is processed you should be able > to open the i2c gate before cx88_call_i2c_clients(), no? > > I was trying to avoid any changes outside of cx88_dvb.ko -- It was probably unavoidable. A patch is attached for review. Here's a summary: 1. The cx22702 driver has two exported functions to open/close the plli2c on demand. 2. cx88_dvb.ko has two new functions which call the demod plli2c open/close exports driven by board type. 3. cx8800.ko (via the V4L ioctls) calls cx88_dvb-enable/disable when using cx88_call_i2c_clients, you will see this repeated everywhere throughout the module. (I tried moving the enable/disable into the actual cx88_call_i2c_clients function but ended up with circular depmod references in most of the cx88 modules. I can look into this tomorrow). Apart from that, we hold a reference to the cx8802_dev struct in cx88_core else cx88-video has no way to find the original dvb_frontend structure. cx88_dvb will also become a module dependency of cx8800. The patch is working here but looks (temporarily) ugly inside cx8800.ko. More cleanup is required. Comments/feedback welcome. Steve -------------- next part -------------- Index: linux/Documentation/video4linux/CARDLIST.cx88 =================================================================== RCS file: /cvs/video4linux/v4l-dvb/linux/Documentation/video4linux/CARDLIST.cx88,v retrieving revision 1.16 diff -u -p -r1.16 CARDLIST.cx88 --- linux/Documentation/video4linux/CARDLIST.cx88 22 Nov 2005 19:32:26 -0000 1.16 +++ linux/Documentation/video4linux/CARDLIST.cx88 30 Nov 2005 04:28:29 -0000 @@ -38,3 +38,4 @@ 37 -> Hauppauge Nova-S-Plus DVB-S [0070:9201,0070:9202] 38 -> Hauppauge Nova-SE2 DVB-S [0070:9200] 39 -> KWorld DVB-S 100 [17de:08b2] + 40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid [0070:9400,0070:9402] Index: linux/drivers/media/dvb/frontends/cx22702.c =================================================================== RCS file: /cvs/video4linux/v4l-dvb/linux/drivers/media/dvb/frontends/cx22702.c,v retrieving revision 1.14 diff -u -p -r1.14 cx22702.c --- linux/drivers/media/dvb/frontends/cx22702.c 26 Nov 2005 23:46:56 -0000 1.14 +++ linux/drivers/media/dvb/frontends/cx22702.c 30 Nov 2005 04:28:29 -0000 @@ -195,6 +195,20 @@ static int cx22702_get_tps (struct cx227 return 0; } +int cx22702_enable_plli2c(struct dvb_frontend* fe) +{ + struct cx22702_state* state = fe->demodulator_priv; + dprintk ("%s\n",__FUNCTION__); + return cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe); +} + +int cx22702_disable_plli2c(struct dvb_frontend* fe) +{ + struct cx22702_state* state = fe->demodulator_priv; + dprintk ("%s\n",__FUNCTION__); + return cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1); +} + /* Talk to the demod, set the FEC, GUARD, QAM settings etc */ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { @@ -202,7 +216,7 @@ static int cx22702_set_tps (struct dvb_f struct cx22702_state* state = fe->demodulator_priv; /* set PLL */ - cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe); + cx22702_enable_plli2c(fe); if (state->config->pll_set) { state->config->pll_set(fe, p); } else if (state->config->pll_desc) { @@ -216,7 +230,7 @@ static int cx22702_set_tps (struct dvb_f } else { BUG(); } - cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1); + cx22702_disable_plli2c(fe); /* set inversion */ cx22702_set_inversion (state, p->inversion); @@ -349,11 +363,10 @@ static int cx22702_init (struct dvb_fron cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02); /* init PLL */ - if (state->config->pll_init) { - cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) & 0xfe); + if (state->config->pll_init) state->config->pll_init(fe); - cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1); - } + + cx22702_disable_plli2c(fe); return 0; } @@ -541,3 +554,5 @@ MODULE_AUTHOR("Steven Toth"); MODULE_LICENSE("GPL"); EXPORT_SYMBOL(cx22702_attach); +EXPORT_SYMBOL(cx22702_enable_plli2c); +EXPORT_SYMBOL(cx22702_disable_plli2c); Index: linux/drivers/media/dvb/frontends/cx22702.h =================================================================== RCS file: /cvs/video4linux/v4l-dvb/linux/drivers/media/dvb/frontends/cx22702.h,v retrieving revision 1.6 diff -u -p -r1.6 cx22702.h --- linux/drivers/media/dvb/frontends/cx22702.h 26 Nov 2005 23:46:56 -0000 1.6 +++ linux/drivers/media/dvb/frontends/cx22702.h 30 Nov 2005 04:28:29 -0000 @@ -51,4 +51,7 @@ struct cx22702_config extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config, struct i2c_adapter* i2c); +extern int cx22702_enable_plli2c(struct dvb_frontend* fe); +extern int cx22702_disable_plli2c(struct dvb_frontend* fe); + #endif // CX22702_H Index: linux/drivers/media/video/cx88/cx88-cards.c =================================================================== RCS file: /cvs/video4linux/v4l-dvb/linux/drivers/media/video/cx88/cx88-cards.c,v retrieving revision 1.108 diff -u -p -r1.108 cx88-cards.c --- linux/drivers/media/video/cx88/cx88-cards.c 25 Nov 2005 10:24:13 -0000 1.108 +++ linux/drivers/media/video/cx88/cx88-cards.c 30 Nov 2005 04:28:29 -0000 @@ -903,7 +903,6 @@ struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - /* fixme: add the analog gpio stuff here */ .input = {{ .type = CX88_VMUX_DVB, .vmux = 0, @@ -946,6 +945,26 @@ struct cx88_board cx88_boards[] = { }}, .dvb = 1, }, + [CX88_BOARD_HAUPPAUGE_HVR1100] = { + .name = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid", + .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + }}, + /* fixme: Add radio support */ + .dvb = 1, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -1109,6 +1128,14 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x17de, .subdevice = 0x08b2, .card = CX88_BOARD_KWORLD_DVBS_100, + },{ + .subvendor = 0x0070, + .subdevice = 0x9400, + .card = CX88_BOARD_HAUPPAUGE_HVR1100, + },{ + .subvendor = 0x0070, + .subdevice = 0x9402, + .card = CX88_BOARD_HAUPPAUGE_HVR1100, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); @@ -1140,9 +1167,6 @@ static void __devinit leadtek_eeprom(str core->name, core->tuner_type, eeprom_data[0]); } - -/* ----------------------------------------------------------------------- */ - static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) { struct tveeprom tv; @@ -1161,7 +1185,8 @@ static void hauppauge_eeprom(struct cx88 case 90500: /* Nova-T-PCI (oem) */ case 90501: /* Nova-T-PCI (oem/IR) */ case 92000: /* Nova-SE2 (OEM, No Video or IR) */ - + case 94009: /* WinTV-HVR1100 (Video and IR Retail) */ + case 94501: /* WinTV-HVR1100 (Video and IR OEM) */ /* known */ break; default: @@ -1279,6 +1304,7 @@ void cx88_card_setup(struct cx88_core *c case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: case CX88_BOARD_HAUPPAUGE_DVB_T1: + case CX88_BOARD_HAUPPAUGE_HVR1100: if (0 == core->i2c_rc) hauppauge_eeprom(core,eeprom); break; Index: linux/drivers/media/video/cx88/cx88-dvb.c =================================================================== RCS file: /cvs/video4linux/v4l-dvb/linux/drivers/media/video/cx88/cx88-dvb.c,v retrieving revision 1.74 diff -u -p -r1.74 cx88-dvb.c --- linux/drivers/media/video/cx88/cx88-dvb.c 22 Nov 2005 19:32:26 -0000 1.74 +++ linux/drivers/media/video/cx88/cx88-dvb.c 30 Nov 2005 04:28:30 -0000 @@ -197,6 +197,14 @@ static struct cx22702_config hauppauge_n .pll_address = 0x61, .pll_desc = &dvb_pll_thomson_dtt759x, }; +static struct cx22702_config hauppauge_hvr1100_config = { + .demod_address = 0x63, +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12) + .output_mode = CX22702_SERIAL_OUTPUT, +#endif + .pll_address = 0x61, + .pll_desc = &dvb_pll_fmd1216me, +}; #endif #ifdef HAVE_OR51132 @@ -357,6 +365,32 @@ static struct cx24123_config kworld_dvbs }; #endif +/* Called from cx88-video if the I2C gate potentially needs to be opened */ +int cx8802_enable_plli2c(struct cx8802_dev *dev) +{ + dprintk(1, "%s\n", __FUNCTION__); +#ifdef HAVE_CX22702 + if (dev->core->board == CX88_BOARD_HAUPPAUGE_HVR1100) { + if (dev->dvb.frontend) + return cx22702_enable_plli2c(dev->dvb.frontend); + } +#endif + return 0; +} + +/* Called from cx88-video if the I2C gate potentially needs to be closed */ +int cx8802_disable_plli2c(struct cx8802_dev *dev) +{ + dprintk(1, "%s\n", __FUNCTION__); +#ifdef HAVE_CX22702 + if (dev->core->board == CX88_BOARD_HAUPPAUGE_HVR1100) { + if (dev->dvb.frontend) + return cx22702_disable_plli2c(dev->dvb.frontend); + } +#endif + return 0; +} + static int dvb_register(struct cx8802_dev *dev) { /* init struct videobuf_dvb */ @@ -376,6 +410,10 @@ static int dvb_register(struct cx8802_de dev->dvb.frontend = cx22702_attach(&connexant_refboard_config, &dev->core->i2c_adap); break; + case CX88_BOARD_HAUPPAUGE_HVR1100: + dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config, + &dev->core->i2c_adap); + break; #endif #ifdef HAVE_MT352 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: @@ -538,6 +576,9 @@ static int __devinit dvb_probe(struct pc err = dvb_register(dev); if (0 != err) goto fail_fini; + + /* Maintain a reference to cx88-video can query the 8802 device. */ + core->dvbdev = dev; return 0; fail_fini: @@ -553,6 +594,9 @@ static void __devexit dvb_remove(struct { struct cx8802_dev *dev = pci_get_drvdata(pci_dev); + /* Destroy any 8802 reference. */ + dev->core->dvbdev = NULL; + /* dvb */ videobuf_dvb_unregister(&dev->dvb); @@ -604,6 +648,9 @@ static void dvb_fini(void) module_init(dvb_init); module_exit(dvb_fini); +EXPORT_SYMBOL(cx8802_enable_plli2c); +EXPORT_SYMBOL(cx8802_disable_plli2c); + /* * Local variables: * c-basic-offset: 8 Index: linux/drivers/media/video/cx88/cx88-input.c =================================================================== RCS file: /cvs/video4linux/v4l-dvb/linux/drivers/media/video/cx88/cx88-input.c,v retrieving revision 1.23 diff -u -p -r1.23 cx88-input.c --- linux/drivers/media/video/cx88/cx88-input.c 18 Nov 2005 01:02:18 -0000 1.23 +++ linux/drivers/media/video/cx88/cx88-input.c 30 Nov 2005 04:28:30 -0000 @@ -385,6 +385,7 @@ int cx88_ir_init(struct cx88_core *core, case CX88_BOARD_HAUPPAUGE_DVB_T1: case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: + case CX88_BOARD_HAUPPAUGE_HVR1100: ir_codes = ir_codes_hauppauge_new; ir_type = IR_TYPE_RC5; ir->sampling = 1; Index: linux/drivers/media/video/cx88/cx88-video.c =================================================================== RCS file: /cvs/video4linux/v4l-dvb/linux/drivers/media/video/cx88/cx88-video.c,v retrieving revision 1.102 diff -u -p -r1.102 cx88-video.c --- linux/drivers/media/video/cx88/cx88-video.c 10 Nov 2005 12:40:42 -0000 1.102 +++ linux/drivers/media/video/cx88/cx88-video.c 30 Nov 2005 04:28:30 -0000 @@ -1127,7 +1127,11 @@ static int video_release(struct inode *i file->private_data = NULL; kfree(fh); + if (dev->core->dvbdev) + cx8802_enable_plli2c(dev->core->dvbdev); cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); + if (dev->core->dvbdev) + cx8802_disable_plli2c(dev->core->dvbdev); return 0; } @@ -1559,9 +1563,13 @@ int cx88_do_ioctl(struct inode *inode, s if (i == ARRAY_SIZE(tvnorms)) return -EINVAL; + if (core->dvbdev) + cx8802_enable_plli2c(core->dvbdev); down(&core->lock); cx88_set_tvnorm(core,&tvnorms[i]); up(&core->lock); + if (core->dvbdev) + cx8802_disable_plli2c(core->dvbdev); return 0; } @@ -1739,7 +1747,11 @@ int cx88_do_ioctl(struct inode *inode, s down(&core->lock); core->freq = f->frequency; cx88_newstation(core); + if (core->dvbdev) + cx8802_enable_plli2c(core->dvbdev); cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f); + if (core->dvbdev) + cx8802_disable_plli2c(core->dvbdev); /* When changing channels it is required to reset TVAUDIO */ msleep (10); @@ -2230,7 +2242,11 @@ static int __devinit cx8800_initdev(stru /* initial device configuration */ down(&core->lock); init_controls(core); + if (core->dvbdev) + cx8802_enable_plli2c(core->dvbdev); cx88_set_tvnorm(core,tvnorms); + if (core->dvbdev) + cx8802_disable_plli2c(core->dvbdev); video_mux(core,0); up(&core->lock); Index: linux/drivers/media/video/cx88/cx88.h =================================================================== RCS file: /cvs/video4linux/v4l-dvb/linux/drivers/media/video/cx88/cx88.h,v retrieving revision 1.91 diff -u -p -r1.91 cx88.h --- linux/drivers/media/video/cx88/cx88.h 22 Nov 2005 19:32:26 -0000 1.91 +++ linux/drivers/media/video/cx88/cx88.h 30 Nov 2005 04:28:30 -0000 @@ -189,6 +189,7 @@ extern struct sram_channel cx88_sram_cha #define CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1 37 #define CX88_BOARD_HAUPPAUGE_NOVASE2_S1 38 #define CX88_BOARD_KWORLD_DVBS_100 39 +#define CX88_BOARD_HAUPPAUGE_HVR1100 40 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, @@ -314,6 +315,9 @@ struct cx88_core { /* various v4l controls */ u32 freq; + + /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ + struct cx8802_dev *dvbdev; }; struct cx8800_dev; @@ -609,6 +613,9 @@ void cx8802_fini_common(struct cx8802_de int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state); int cx8802_resume_common(struct pci_dev *pci_dev); +int cx8802_enable_plli2c(struct cx8802_dev *dev); +int cx8802_disable_plli2c(struct cx8802_dev *dev); + /* ----------------------------------------------------------- */ /* cx88-video.c */ extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,