diff options
Diffstat (limited to 'linux/drivers/media/video/cx88')
-rw-r--r-- | linux/drivers/media/video/cx88/cx88-blackbird.c | 8 | ||||
-rw-r--r-- | linux/drivers/media/video/cx88/cx88-cards.c | 49 | ||||
-rw-r--r-- | linux/drivers/media/video/cx88/cx88-core.c | 9 | ||||
-rw-r--r-- | linux/drivers/media/video/cx88/cx88-dvb.c | 2 | ||||
-rw-r--r-- | linux/drivers/media/video/cx88/cx88-i2c.c | 39 | ||||
-rw-r--r-- | linux/drivers/media/video/cx88/cx88-video.c | 49 | ||||
-rw-r--r-- | linux/drivers/media/video/cx88/cx88.h | 16 |
7 files changed, 97 insertions, 75 deletions
diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index 46e009403..b62eadc71 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -761,7 +761,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; } @@ -772,7 +771,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; */ @@ -791,7 +789,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; */; @@ -808,7 +805,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; */; @@ -938,7 +934,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); @@ -993,7 +989,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/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index 2f30d34be..a4d49fbf7 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -733,6 +733,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, @@ -3018,7 +3020,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: @@ -3043,7 +3045,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; } @@ -3053,7 +3055,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) { @@ -3062,7 +3064,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) { @@ -3078,9 +3080,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, tuner, s_standby); } /* ------------------------------------------------------------------ */ @@ -3235,8 +3237,39 @@ 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->v4l2_dev, &core->i2c_adap, + "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_RADIO)); + if (has_demod) + v4l2_i2c_new_probed_subdev(&core->v4l2_dev, + &core->i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + if (core->board.tuner_addr == ADDR_UNSET) { + v4l2_i2c_new_probed_subdev(&core->v4l2_dev, + &core->i2c_adap, "tuner", "tuner", + has_demod ? tv_addrs + 4 : tv_addrs); + } else { + v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, + "tuner", "tuner", core->board.tuner_addr); + } + } cx88_card_setup(core); cx88_ir_init(core, pci); diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c index ca36a48fa..71dccf6af 100644 --- a/linux/drivers/media/video/cx88/cx88-core.c +++ b/linux/drivers/media/video/cx88/cx88-core.c @@ -1020,7 +1020,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, core, s_std, norm); // done return 0; @@ -1088,8 +1088,13 @@ 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 LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + if (0 == core->i2c_rc) { + if (core->i2c_rtc) + i2c_unregister_device(core->i2c_rtc); i2c_del_adapter(&core->i2c_adap); + } +#endif list_del(&core->devlist); iounmap(core->lmmio); cx88_devcount--; diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 10cf470ce..f32cece95 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -1175,7 +1175,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, tuner, s_standby); /* register everything */ return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, diff --git a/linux/drivers/media/video/cx88/cx88-i2c.c b/linux/drivers/media/video/cx88/cx88-i2c.c index 4a17a7579..680a8c889 100644 --- a/linux/drivers/media/video/cx88/cx88-i2c.c +++ b/linux/drivers/media/video/cx88/cx88-i2c.c @@ -97,39 +97,6 @@ static int cx8800_bit_getsda(void *data) /* ----------------------------------------------------------------------- */ -static int attach_inform(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct cx88_core *core = to_core(v4l2_dev); - - 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 v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct cx88_core *core = to_core(v4l2_dev); - - 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, @@ -175,17 +142,17 @@ 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 LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) 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; +#endif 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->v4l2_dev); @@ -224,8 +191,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/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 827168d67..76b16038c 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -429,11 +429,8 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) routes for different inputs. HVR-1300 surely does */ if (core->board.audio_chip && core->board.audio_chip == V4L2_IDENT_WM8775) { - 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, + INPUT(input).audioroute, 0, 0); } /* cx2388's C-ADC is connected to the tuner only. When used with S-Video, that ADC is busy dealing with @@ -1050,11 +1047,8 @@ static int video_open(struct file *file) if (core->board.radio.audioroute) { if(core->board.audio_chip && core->board.audio_chip == V4L2_IDENT_WM8775) { - 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, + core->board.radio.audioroute, 0, 0); } /* "I2S ADC mode" */ core->tvaudio = WW_I2SADC; @@ -1065,7 +1059,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(); @@ -1159,7 +1153,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, tuner, s_standby); return 0; } @@ -1661,7 +1655,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; } @@ -1677,7 +1671,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); @@ -1759,7 +1753,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; } @@ -1793,7 +1787,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; } @@ -2158,12 +2152,31 @@ 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->v4l2_dev, &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. */ + v4l2_i2c_new_probed_subdev_addr(&core->v4l2_dev, + &core->i2c_adap, + "tvaudio", "tvaudio", 0xb0 >> 1); + } switch (core->boardnr) { case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: - case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: + case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + 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); +#else + request_module("rtc-isl1208"); +#endif + } /* break intentionally omitted */ case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: request_module("ir-kbd-i2c"); diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index d70e26000..a34f6ee0c 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -42,7 +42,7 @@ #include <linux/version.h> #include <linux/mutex.h> -#define CX88_VERSION_CODE KERNEL_VERSION(0,0,6) +#define CX88_VERSION_CODE KERNEL_VERSION(0,0,7) #define UNSET (-1U) @@ -332,6 +332,7 @@ struct cx88_core { /* config info -- analog */ struct v4l2_device v4l2_dev; + struct i2c_client *i2c_rtc; unsigned int boardnr; struct cx88_board board; @@ -375,6 +376,17 @@ 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; @@ -637,8 +649,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); /* ----------------------------------------------------------- */ |