diff options
Diffstat (limited to 'drivers/media/video/cx88')
-rw-r--r-- | drivers/media/video/cx88/Kconfig | 2 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-alsa.c | 7 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-blackbird.c | 8 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-cards.c | 99 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-core.c | 11 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-dvb.c | 18 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-i2c.c | 41 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-input.c | 29 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-video.c | 52 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88.h | 24 |
10 files changed, 185 insertions, 106 deletions
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 2d250a2a7bc3..49952980dab3 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -61,7 +61,7 @@ config VIDEO_CX88_DVB select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_STV0288 if !DVB_FE_CUSTOMISE select DVB_STB6000 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE ---help--- This adds support for DVB/ATSC cards based on the Conexant 2388x chip. diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 66c755c116dc..ce98d955231a 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -803,9 +803,10 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, return (-ENOENT); } - card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx88_card_t)); - if (!card) - return (-ENOMEM); + err = snd_card_create(index[devno], id[devno], THIS_MODULE, + sizeof(snd_cx88_card_t), &card); + if (err < 0) + return err; card->private_free = snd_cx88_dev_free; diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 7f5b8bfd08ac..44eacfb0d0d6 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -746,7 +746,6 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, return -EINVAL; strlcpy(f->description, "MPEG", sizeof(f->description)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->pixelformat = V4L2_PIX_FMT_MPEG; return 0; } @@ -757,7 +756,6 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, struct cx8802_fh *fh = priv; struct cx8802_dev *dev = fh->dev; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */ @@ -776,7 +774,6 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, struct cx8802_fh *fh = priv; struct cx8802_dev *dev = fh->dev; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; @@ -793,7 +790,6 @@ static int vidioc_s_fmt_vid_cap (struct file *file, void *priv, struct cx8802_dev *dev = fh->dev; struct cx88_core *core = dev->core; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; @@ -919,7 +915,7 @@ static int vidioc_log_status (struct file *file, void *priv) snprintf(name, sizeof(name), "%s/2", core->name); printk("%s/2: ============ START LOG STATUS ============\n", core->name); - cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL); + call_all(core, core, log_status); cx2341x_log_status(&dev->params, name); printk("%s/2: ============= END LOG STATUS =============\n", core->name); @@ -974,7 +970,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, f->type = V4L2_TUNER_ANALOG_TV; f->frequency = core->freq; - cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f); + call_all(core, tuner, g_frequency, f); return 0; } diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 733ede34f93a..0363971a23a8 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -732,6 +732,8 @@ static const struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + /* Some variants use a tda9874 and so need the tvaudio module. */ + .audio_chip = V4L2_IDENT_TVAUDIO, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, @@ -1934,6 +1936,39 @@ static const struct cx88_board cx88_boards[] = { } }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII] = { + .name = "Terratec Cinergy HT PCI MKII", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .radio_type = TUNER_XC2028, + .radio_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x00001, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x004fb, + .gpio1 = 0x010ef, + .audioroute = 1, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x004fb, + .gpio1 = 0x010ef, + .audioroute = 1, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x0ff, + }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -2343,6 +2378,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0xb200, .subdevice = 0x4200, .card = CX88_BOARD_SATTRADE_ST4200, + }, { + .subvendor = 0x153b, + .subdevice = 0x1177, + .card = CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII, }, }; @@ -2819,6 +2858,7 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) */ break; case CX88_BOARD_PINNACLE_HYBRID_PCTV: + case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII: ctl->demod = XC3028_FE_ZARLINK456; ctl->mts = 1; break; @@ -2947,7 +2987,7 @@ static void cx88_card_setup(struct cx88_core *core) tea5767_cfg.tuner = TUNER_TEA5767; tea5767_cfg.priv = &ctl; - cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg); + call_all(core, tuner, s_config, &tea5767_cfg); break; } case CX88_BOARD_TEVII_S420: @@ -2972,7 +3012,7 @@ static void cx88_card_setup(struct cx88_core *core) tun_setup.type = core->board.radio_type; tun_setup.addr = core->board.radio_addr; tun_setup.tuner_callback = cx88_tuner_callback; - cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup); + call_all(core, tuner, s_type_addr, &tun_setup); mode_mask &= ~T_RADIO; } @@ -2982,7 +3022,7 @@ static void cx88_card_setup(struct cx88_core *core) tun_setup.addr = core->board.tuner_addr; tun_setup.tuner_callback = cx88_tuner_callback; - cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup); + call_all(core, tuner, s_type_addr, &tun_setup); } if (core->board.tda9887_conf) { @@ -2991,7 +3031,7 @@ static void cx88_card_setup(struct cx88_core *core) tda9887_cfg.tuner = TUNER_TDA9887; tda9887_cfg.priv = &core->board.tda9887_conf; - cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tda9887_cfg); + call_all(core, tuner, s_config, &tda9887_cfg); } if (core->board.tuner_type == TUNER_XC2028) { @@ -3007,9 +3047,9 @@ static void cx88_card_setup(struct cx88_core *core) xc2028_cfg.priv = &ctl; info_printk(core, "Asking xc2028/3028 to load firmware %s\n", ctl.fname); - cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg); + call_all(core, tuner, s_config, &xc2028_cfg); } - cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL); + call_all(core, core, s_standby, 0); } /* ------------------------------------------------------------------ */ @@ -3089,6 +3129,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) int i; core = kzalloc(sizeof(*core), GFP_KERNEL); + if (core == NULL) + return NULL; atomic_inc(&core->refcount); core->pci_bus = pci->bus->number; @@ -3100,7 +3142,15 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) core->nr = nr; sprintf(core->name, "cx88[%d]", core->nr); + + strcpy(core->v4l2_dev.name, core->name); + if (v4l2_device_register(NULL, &core->v4l2_dev)) { + kfree(core); + return NULL; + } + if (0 != cx88_get_resources(core, pci)) { + v4l2_device_unregister(&core->v4l2_dev); kfree(core); return NULL; } @@ -3111,6 +3161,11 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) pci_resource_len(pci, 0)); core->bmmio = (u8 __iomem *)core->lmmio; + if (core->lmmio == NULL) { + kfree(core); + return NULL; + } + /* board config */ core->boardnr = UNSET; if (card[core->nr] < ARRAY_SIZE(cx88_boards)) @@ -3149,8 +3204,36 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) cx88_i2c_init(core, pci); /* load tuner module, if needed */ - if (TUNER_ABSENT != core->board.tuner_type) - request_module("tuner"); + if (TUNER_ABSENT != core->board.tuner_type) { + /* Ignore 0x6b and 0x6f on cx88 boards. + * FusionHDTV5 RT Gold has an ir receiver at 0x6b + * and an RTC at 0x6f which can get corrupted if probed. */ + static const unsigned short tv_addrs[] = { + 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6c, 0x6d, 0x6e, + I2C_CLIENT_END + }; + int has_demod = (core->board.tda9887_conf & TDA9887_PRESENT); + + /* I don't trust the radio_type as is stored in the card + definitions, so we just probe for it. + The radio_type is sometimes missing, or set to UNSET but + later code configures a tea5767. + */ + v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_RADIO)); + if (has_demod) + v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + if (core->board.tuner_addr == ADDR_UNSET) { + v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", + "tuner", has_demod ? tv_addrs + 4 : tv_addrs); + } else { + v4l2_i2c_new_subdev(&core->i2c_adap, + "tuner", "tuner", core->board.tuner_addr); + } + } cx88_card_setup(core); cx88_ir_init(core, pci); diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index b045874ad04f..f2fb9f30bfc1 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -991,7 +991,7 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) set_tvaudio(core); // tell i2c chips - cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm); + call_all(core, tuner, s_std, norm); // done return 0; @@ -1011,7 +1011,8 @@ struct video_device *cx88_vdev_init(struct cx88_core *core, return NULL; *vfd = *template; vfd->minor = -1; - vfd->parent = &pci->dev; + vfd->v4l2_dev = &core->v4l2_dev; + vfd->parent = &pci->dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", core->name, type, core->board.name); @@ -1058,12 +1059,16 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) mutex_lock(&devlist); cx88_ir_fini(core); - if (0 == core->i2c_rc) + if (0 == core->i2c_rc) { + if (core->i2c_rtc) + i2c_unregister_device(core->i2c_rtc); i2c_del_adapter(&core->i2c_adap); + } list_del(&core->devlist); iounmap(core->lmmio); cx88_devcount--; mutex_unlock(&devlist); + v4l2_device_unregister(&core->v4l2_dev); kfree(core); } diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index aef5297534af..4ff4d9fe0355 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -241,6 +241,12 @@ static struct mt352_config dvico_fusionhdtv_dual = { .demod_init = dvico_dual_demod_init, }; +static struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, + .if2 = 45600, +}; + #if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) { @@ -1131,6 +1137,16 @@ static int dvb_register(struct cx8802_dev *dev) if (fe0->dvb.frontend != NULL) fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; break; + case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII: + fe0->dvb.frontend = dvb_attach(zl10353_attach, + &cx88_terratec_cinergy_ht_pci_mkii_config, + &core->i2c_adap); + if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; + if (attach_xc3028(0x61, dev) < 0) + goto frontend_detach; + } + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", core->name); @@ -1152,7 +1168,7 @@ static int dvb_register(struct cx8802_dev *dev) fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; /* Put the analog decoder in standby to keep it quiet */ - cx88_call_i2c_clients(core, TUNER_SET_STANDBY, NULL); + call_all(core, core, s_standby, 0); /* register everything */ return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index c0ff2305d804..996b4ed5a4fc 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -97,37 +97,6 @@ static int cx8800_bit_getsda(void *data) /* ----------------------------------------------------------------------- */ -static int attach_inform(struct i2c_client *client) -{ - struct cx88_core *core = i2c_get_adapdata(client->adapter); - - dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, client->addr, client->name); - return 0; -} - -static int detach_inform(struct i2c_client *client) -{ - struct cx88_core *core = i2c_get_adapdata(client->adapter); - - dprintk(1, "i2c detach [client=%s]\n", client->name); - return 0; -} - -void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) -{ - if (0 != core->i2c_rc) - return; - - if (core->gate_ctrl) - core->gate_ctrl(core, 1); - - i2c_clients_command(&core->i2c_adap, cmd, arg); - - if (core->gate_ctrl) - core->gate_ctrl(core, 0); -} - static const struct i2c_algo_bit_data cx8800_i2c_algo_template = { .setsda = cx8800_bit_setsda, .setscl = cx8800_bit_setscl, @@ -173,20 +142,14 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) memcpy(&core->i2c_algo, &cx8800_i2c_algo_template, sizeof(core->i2c_algo)); - if (core->board.tuner_type != TUNER_ABSENT) - core->i2c_adap.class |= I2C_CLASS_TV_ANALOG; - if (core->board.mpeg & CX88_MPEG_DVB) - core->i2c_adap.class |= I2C_CLASS_TV_DIGITAL; core->i2c_adap.dev.parent = &pci->dev; strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name)); core->i2c_adap.owner = THIS_MODULE; core->i2c_adap.id = I2C_HW_B_CX2388x; - core->i2c_adap.client_register = attach_inform; - core->i2c_adap.client_unregister = detach_inform; core->i2c_algo.udelay = i2c_udelay; core->i2c_algo.data = core; - i2c_set_adapdata(&core->i2c_adap,core); + i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev); core->i2c_adap.algo_data = &core->i2c_algo; core->i2c_client.adapter = &core->i2c_adap; strlcpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE); @@ -222,8 +185,6 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) /* ----------------------------------------------------------------------- */ -EXPORT_SYMBOL(cx88_call_i2c_clients); - /* * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 8683d104de72..ec05312a9b62 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -48,8 +48,7 @@ struct cx88_IR { /* poll external decoder */ int polling; - struct work_struct work; - struct timer_list timer; + struct delayed_work work; u32 gpio_addr; u32 last_gpio; u32 mask_keycode; @@ -143,27 +142,19 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) } } -static void ir_timer(unsigned long data) -{ - struct cx88_IR *ir = (struct cx88_IR *)data; - - schedule_work(&ir->work); -} - static void cx88_ir_work(struct work_struct *work) { - struct cx88_IR *ir = container_of(work, struct cx88_IR, work); + struct cx88_IR *ir = container_of(work, struct cx88_IR, work.work); cx88_ir_handle_key(ir); - mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); + schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); } void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) { if (ir->polling) { - setup_timer(&ir->timer, ir_timer, (unsigned long)ir); - INIT_WORK(&ir->work, cx88_ir_work); - schedule_work(&ir->work); + INIT_DELAYED_WORK(&ir->work, cx88_ir_work); + schedule_delayed_work(&ir->work, 0); } if (ir->sampling) { core->pci_irqmask |= PCI_INT_IR_SMPINT; @@ -179,10 +170,8 @@ void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) core->pci_irqmask &= ~PCI_INT_IR_SMPINT; } - if (ir->polling) { - del_timer_sync(&ir->timer); - flush_scheduled_work(); - } + if (ir->polling) + cancel_delayed_work_sync(&ir->work); } /* ---------------------------------------------------------------------- */ @@ -226,6 +215,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_HAUPPAUGE_HVR4000: case CX88_BOARD_HAUPPAUGE_HVR4000LITE: + case CX88_BOARD_PCHDTV_HD3000: + case CX88_BOARD_PCHDTV_HD5500: ir_codes = ir_codes_hauppauge_new; ir_type = IR_TYPE_RC5; ir->sampling = 1; @@ -466,6 +457,8 @@ void cx88_ir_irq(struct cx88_core *core) case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_HAUPPAUGE_HVR4000: case CX88_BOARD_HAUPPAUGE_HVR4000LITE: + case CX88_BOARD_PCHDTV_HD3000: + case CX88_BOARD_PCHDTV_HD5500: ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); ir_dprintk("biphase decoded: %x\n", ircode); /* diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 791e69d804f9..434237af5184 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -41,11 +41,6 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> -#ifdef CONFIG_VIDEO_V4L1_COMPAT -/* Include V4L1 specific functions. Should be removed soon */ -#include <linux/videodev.h> -#endif - MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -298,6 +293,7 @@ static struct cx88_ctrl cx8800_ctls[] = { }; static const int CX8800_CTLS = ARRAY_SIZE(cx8800_ctls); +/* Must be sorted from low to high control ID! */ const u32 cx88_user_ctrls[] = { V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, @@ -435,8 +431,7 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) struct v4l2_routing route; route.input = INPUT(input).audioroute; - cx88_call_i2c_clients(core, - VIDIOC_INT_S_AUDIO_ROUTING, &route); + call_all(core, audio, s_routing, &route); } /* cx2388's C-ADC is connected to the tuner only. When used with S-Video, that ADC is busy dealing with @@ -831,8 +826,7 @@ static int video_open(struct file *file) struct v4l2_routing route; route.input = core->board.radio.audioroute; - cx88_call_i2c_clients(core, - VIDIOC_INT_S_AUDIO_ROUTING, &route); + call_all(core, audio, s_routing, &route); } /* "I2S ADC mode" */ core->tvaudio = WW_I2SADC; @@ -843,7 +837,7 @@ static int video_open(struct file *file) cx88_set_tvaudio(core); cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); } - cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL); + call_all(core, tuner, s_radio); } unlock_kernel(); @@ -937,7 +931,7 @@ static int video_release(struct file *file) kfree(fh); if(atomic_dec_and_test(&dev->core->users)) - cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); + call_all(dev->core, core, s_standby, 0); return 0; } @@ -1276,15 +1270,12 @@ int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i) [ CX88_VMUX_DVB ] = "DVB", [ CX88_VMUX_DEBUG ] = "for debug only", }; - unsigned int n; + unsigned int n = i->index; - n = i->index; if (n >= 4) return -EINVAL; if (0 == INPUT(n).type) return -EINVAL; - memset(i,0,sizeof(*i)); - i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name,iname[INPUT(n).type]); if ((CX88_VMUX_TELEVISION == INPUT(n).type) || @@ -1402,7 +1393,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = core->freq; - cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f); + call_all(core, tuner, g_frequency, f); return 0; } @@ -1418,7 +1409,7 @@ int cx88_set_freq (struct cx88_core *core, mutex_lock(&core->lock); core->freq = f->frequency; cx88_newstation(core); - cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f); + call_all(core, tuner, s_frequency, f); /* When changing channels it is required to reset TVAUDIO */ msleep (10); @@ -1500,7 +1491,7 @@ static int radio_g_tuner (struct file *file, void *priv, strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; - cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t); + call_all(core, tuner, g_tuner, t); return 0; } @@ -1520,7 +1511,6 @@ static int radio_g_audio (struct file *file, void *priv, struct v4l2_audio *a) if (unlikely(a->index)) return -EINVAL; - memset(a,0,sizeof(*a)); strcpy(a->name,"Radio"); return 0; } @@ -1535,7 +1525,7 @@ static int radio_s_tuner (struct file *file, void *priv, if (0 != t->index) return -EINVAL; - cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t); + call_all(core, tuner, s_tuner, t); return 0; } @@ -1892,12 +1882,30 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, /* load and configure helper modules */ if (core->board.audio_chip == V4L2_IDENT_WM8775) - request_module("wm8775"); + v4l2_i2c_new_subdev(&core->i2c_adap, + "wm8775", "wm8775", 0x36 >> 1); + + if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { + /* This probes for a tda9874 as is used on some + Pixelview Ultra boards. */ + static const unsigned short i2c_addr[] = { + 0xb0 >> 1, I2C_CLIENT_END + }; + + v4l2_i2c_new_probed_subdev(&core->i2c_adap, + "tvaudio", "tvaudio", i2c_addr); + } switch (core->boardnr) { case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: - case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: + case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: { + static struct i2c_board_info rtc_info = { + I2C_BOARD_INFO("isl1208", 0x6f) + }; + request_module("rtc-isl1208"); + core->i2c_rtc = i2c_new_device(&core->i2c_adap, &rtc_info); + } /* break intentionally omitted */ case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: request_module("ir-kbd-i2c"); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 6025fdd23344..9a43fdf20fae 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -25,7 +25,7 @@ #include <linux/videodev2.h> #include <linux/kdev_t.h> -#include <media/v4l2-common.h> +#include <media/v4l2-device.h> #include <media/tuner.h> #include <media/tveeprom.h> #include <media/videobuf-dma-sg.h> @@ -231,6 +231,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_SATTRADE_ST4200 76 #define CX88_BOARD_TBS_8910 77 #define CX88_BOARD_PROF_6200 78 +#define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, @@ -302,7 +303,6 @@ struct cx88_dmaqueue { struct btcx_riscmem stopper; u32 count; }; -struct cx88_core; struct cx88_core { struct list_head devlist; @@ -327,6 +327,8 @@ struct cx88_core { u32 i2c_state, i2c_rc; /* config info -- analog */ + struct v4l2_device v4l2_dev; + struct i2c_client *i2c_rtc; unsigned int boardnr; struct cx88_board board; @@ -365,6 +367,22 @@ struct cx88_core { int active_fe_id; }; +static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct cx88_core, v4l2_dev); +} + +#define call_all(core, o, f, args...) \ + do { \ + if (!core->i2c_rc) { \ + if (core->gate_ctrl) \ + core->gate_ctrl(core, 1); \ + v4l2_device_call_all(&core->v4l2_dev, 0, o, f, ##args); \ + if (core->gate_ctrl) \ + core->gate_ctrl(core, 0); \ + } \ + } while (0) + struct cx8800_dev; struct cx8802_dev; @@ -610,8 +628,6 @@ extern struct videobuf_queue_ops cx8800_vbi_qops; /* cx88-i2c.c */ extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci); -extern void cx88_call_i2c_clients(struct cx88_core *core, - unsigned int cmd, void *arg); /* ----------------------------------------------------------- */ |