V4L/DVB (11300): cx88: convert to v4l2_subdev.
authorHans Verkuil <hverkuil@xs4all.nl>
Sun, 29 Mar 2009 11:26:01 +0000 (08:26 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 30 Mar 2009 15:43:48 +0000 (12:43 -0300)
Convert cx88 to use v4l2_subdev since the old i2c autoprobing mechanism
will be removed.

Added code to explicitly load tvaudio where needed. Also fix the rtc-isl1208
support: since that driver no longer supports autoprobing it has to be
loaded using the new i2c API.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-core.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h

index 484df54..44eacfb 100644 (file)
@@ -915,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);
@@ -970,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;
 }
index 348f6ef..c226fff 100644 (file)
@@ -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,
@@ -2985,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:
@@ -3010,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;
        }
 
@@ -3020,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) {
@@ -3029,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) {
@@ -3045,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);
 }
 
 /* ------------------------------------------------------------------ */
@@ -3202,8 +3204,30 @@ 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) {
+               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) {
+                       enum v4l2_i2c_tuner_type type =
+                               has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
+
+                       v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner",
+                               "tuner", v4l2_i2c_tuner_addrs(type));
+               } else {
+                       v4l2_i2c_new_subdev(&core->i2c_adap,
+                               "tuner", "tuner", core->board.tuner_addr);
+               }
+       }
 
        cx88_card_setup(core);
        cx88_ir_init(core, pci);
index 17c7dad..f2fb9f3 100644 (file)
@@ -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;
@@ -1059,8 +1059,11 @@ 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--;
index 08346fa..4ff4d9f 100644 (file)
@@ -1168,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,
index 4a17a75..996b4ed 100644 (file)
@@ -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,11 @@ 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->v4l2_dev);
@@ -224,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
index 5b0fbc6..434237a 100644 (file)
@@ -431,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
@@ -827,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;
@@ -839,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();
 
@@ -933,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;
 }
@@ -1395,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;
 }
@@ -1411,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);
@@ -1493,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;
 }
 
@@ -1527,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;
 }
@@ -1884,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");
index 890018c..9a43fdf 100644 (file)
@@ -328,6 +328,7 @@ struct cx88_core {
 
        /* config info -- analog */
        struct v4l2_device         v4l2_dev;
+       struct i2c_client          *i2c_rtc;
        unsigned int               boardnr;
        struct cx88_board          board;
 
@@ -371,6 +372,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;
 
@@ -616,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);
 
 
 /* ----------------------------------------------------------- */