V4L/DVB (11297): cx23885: convert to v4l2_subdev.
authorHans Verkuil <hverkuil@xs4all.nl>
Sun, 29 Mar 2009 09:53:29 +0000 (06:53 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 30 Mar 2009 15:43:48 +0000 (12:43 -0300)
Convert this driver to v4l2_subdev. Note that currently the only card with
analog support in this driver is the HVR-1800. The analog tuner support in
this driver is limited to what is needed for this board. When analog support
is added for other cards, then the tuner load code will probably have to be
expanded to take care of those boards. For example, there is currently no
support for either radio tuners or tda9887 demods.

I'd like to thank Steven Toth for testing this on his HVR-1800.

Tested-by: Steven Toth <stoth@linuxtv.org>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/cx23885/cx23885-417.c
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/cx23885/cx23885-core.c
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx23885/cx23885-i2c.c
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx23885/cx23885.h

index 9e57c33b5496f54cde12adbf847eafda4462448c..6f5df90af93ef2a89f2c4bc48bf0c64640b89dea 100644 (file)
@@ -1251,8 +1251,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
        if (0 != t->index)
                return -EINVAL;
        strcpy(t->name, "Television");
-       cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t);
-       cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t);
+       call_all(dev, tuner, g_tuner, t);
 
        dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
 
@@ -1269,7 +1268,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
                return -EINVAL;
 
        /* Update the A/V core */
-       cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_TUNER, t);
+       call_all(dev, tuner, s_tuner, t);
 
        return 0;
 }
@@ -1285,8 +1284,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
        f->type = V4L2_TUNER_ANALOG_TV;
        f->frequency = dev->freq;
 
-       /* Assumption that tuner is always on bus 1 */
-       cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f);
+       call_all(dev, tuner, g_frequency, f);
 
        return 0;
 }
@@ -1313,8 +1311,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
                return -EINVAL;
        dev->freq = f->frequency;
 
-       /* Assumption that tuner is always on bus 1 */
-       cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f);
+       call_all(dev, tuner, s_frequency, f);
 
        cx23885_initialize_codec(dev);
 
@@ -1328,7 +1325,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
        struct cx23885_dev *dev = fh->dev;
 
        /* Update the A/V core */
-       cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, ctl);
+       call_all(dev, core, s_ctrl, ctl);
        return 0;
 }
 
@@ -1524,12 +1521,7 @@ static int vidioc_log_status(struct file *file, void *priv)
        printk(KERN_INFO
                "%s/2: ============  START LOG STATUS  ============\n",
               dev->name);
-       cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_LOG_STATUS,
-               NULL);
-       cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_LOG_STATUS,
-               NULL);
-       cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_LOG_STATUS,
-               NULL);
+       call_all(dev, core, log_status);
        cx2341x_log_status(&dev->mpeg_params, name);
        printk(KERN_INFO
                "%s/2: =============  END LOG STATUS  =============\n",
index 08cd793cd151522f463e92ffa843f2b4858b8d9b..5e4b7e790d9498f6235bd612696c38d4cb975669 100644 (file)
@@ -739,7 +739,9 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
        case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
        case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
-               request_module("cx25840");
+               dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->i2c_bus[2].i2c_adap,
+                               "cx25840", "cx25840", 0x88 >> 1);
+               v4l2_subdev_call(dev->sd_cx25840, core, init, 0);
                break;
        }
 
index 548279225d736d079aa8499c66a22f9591982b32..dc7fff22cfdd5a0218547faf50036e0d1383915f 100644 (file)
@@ -875,7 +875,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
        cx23885_i2c_register(&dev->i2c_bus[1]);
        cx23885_i2c_register(&dev->i2c_bus[2]);
        cx23885_card_setup(dev);
-       cx23885_call_i2c_clients(&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
+       call_all(dev, core, s_standby, 0);
        cx23885_ir_init(dev);
 
        if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
index 8d731fffad586fb6dff5b7b0f6bbe786ea221f1f..d43c7439676781fb35508d78ac05a3c76156dbf6 100644 (file)
@@ -673,7 +673,7 @@ static int dvb_register(struct cx23885_tsport *port)
        fe0->dvb.frontend->callback = cx23885_tuner_callback;
 
        /* Put the analog decoder in standby to keep it quiet */
-       cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL);
+       call_all(dev, core, s_standby, 0);
 
        if (fe0->dvb.frontend->ops.analog_ops.standby)
                fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend);
index 969b7ebbc82720ce83476d8de94b02188b5a8cdc..3421bd12056a95ee58a4604ca380354f4ccb444c 100644 (file)
@@ -268,65 +268,6 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap,
        return retval;
 }
 
-static int attach_inform(struct i2c_client *client)
-{
-       struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter);
-       struct cx23885_dev *dev = to_cx23885(v4l2_dev);
-       struct tuner_setup tun_setup;
-
-       dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
-               client->driver->driver.name, client->addr, client->name);
-
-       if (!client->driver->command)
-               return 0;
-
-       if (dev->tuner_type != UNSET) {
-
-               dprintk(1, "%s  (tuner) i2c attach [addr=0x%x,client=%s]\n",
-                       client->driver->driver.name, client->addr,
-                       client->name);
-
-               if ((dev->tuner_addr == ADDR_UNSET) ||
-                       (dev->tuner_addr == client->addr)) {
-
-                       dprintk(1, "%s (tuner || addr UNSET)\n",
-                               client->driver->driver.name);
-
-                       dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
-                               client->driver->driver.name,
-                               client->addr, client->name);
-
-                       tun_setup.mode_mask = T_ANALOG_TV;
-                       tun_setup.type = dev->tuner_type;
-                       tun_setup.addr = dev->tuner_addr;
-
-                       client->driver->command(client, TUNER_SET_TYPE_ADDR,
-                               &tun_setup);
-               }
-       }
-
-       return 0;
-}
-
-static int detach_inform(struct i2c_client *client)
-{
-       struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter);
-       struct cx23885_dev *dev = to_cx23885(v4l2_dev);
-
-       dprintk(1, "i2c detach [client=%s]\n", client->name);
-
-       return 0;
-}
-
-void cx23885_call_i2c_clients(struct cx23885_i2c *bus,
-                             unsigned int cmd, void *arg)
-{
-       if (bus->i2c_rc != 0)
-               return;
-
-       i2c_clients_command(&bus->i2c_adap, cmd, arg);
-}
-
 static u32 cx23885_functionality(struct i2c_adapter *adap)
 {
        return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
@@ -344,9 +285,6 @@ static struct i2c_adapter cx23885_i2c_adap_template = {
        .owner             = THIS_MODULE,
        .id                = I2C_HW_B_CX23885,
        .algo              = &cx23885_i2c_algo_template,
-       .class             = I2C_CLASS_TV_ANALOG,
-       .client_register   = attach_inform,
-       .client_unregister = detach_inform,
 };
 
 static struct i2c_client cx23885_i2c_client_template = {
@@ -410,8 +348,11 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
 
        if (0 == bus->i2c_rc) {
                dprintk(1, "%s: i2c bus %d registered\n", dev->name, bus->nr);
-               if (i2c_scan)
+               if (i2c_scan) {
+                       printk(KERN_INFO "%s: scan bus %d:\n",
+                                       dev->name, bus->nr);
                        do_i2c_scan(dev->name, &bus->i2c_client);
+               }
        } else
                printk(KERN_WARNING "%s: i2c bus %d register FAILED\n",
                        dev->name, bus->nr);
index 1596f4ff3dfee24b2b6e231506c0db1423cdad69..f0ac62c5dc83f398ee9b310fc8bff3069226ce1f 100644 (file)
@@ -299,11 +299,7 @@ static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
 
        dev->tvnorm = norm;
 
-       /* Tell the analog tuner/demods */
-       cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_STD, &norm);
-
-       /* Tell the internal A/V decoder */
-       cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_STD, &norm);
+       call_all(dev, tuner, s_std, norm);
 
        return 0;
 }
@@ -410,8 +406,7 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
        route.input = INPUT(input)->vmux;
 
        /* Tell the internal A/V decoder */
-       cx23885_call_i2c_clients(&dev->i2c_bus[2],
-               VIDIOC_INT_S_VIDEO_ROUTING, &route);
+       v4l2_subdev_call(dev->sd_cx25840, video, s_routing, &route);
 
        return 0;
 }
@@ -887,7 +882,7 @@ static int cx23885_get_control(struct cx23885_dev *dev,
        struct v4l2_control *ctl)
 {
        dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
-       cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl);
+       call_all(dev, core, g_ctrl, ctl);
        return 0;
 }
 
@@ -1001,7 +996,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        fh->vidq.field = f->fmt.pix.field;
        dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
                fh->width, fh->height, fh->vidq.field);
-       cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_FMT, f);
+       call_all(dev, video, s_fmt, f);
        return 0;
 }
 
@@ -1281,7 +1276,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
        f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
        f->frequency = dev->freq;
 
-       cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f);
+       call_all(dev, tuner, g_frequency, f);
 
        return 0;
 }
@@ -1296,7 +1291,7 @@ static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
        mutex_lock(&dev->lock);
        dev->freq = f->frequency;
 
-       cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f);
+       call_all(dev, tuner, s_frequency, f);
 
        /* When changing channels it is required to reset TVAUDIO */
        msleep(10);
@@ -1330,7 +1325,7 @@ static int vidioc_g_register(struct file *file, void *fh,
        if (!v4l2_chip_match_host(&reg->match))
                return -EINVAL;
 
-       cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_G_REGISTER, reg);
+       call_all(dev, core, g_register, reg);
 
        return 0;
 }
@@ -1343,7 +1338,7 @@ static int vidioc_s_register(struct file *file, void *fh,
        if (!v4l2_chip_match_host(&reg->match))
                return -EINVAL;
 
-       cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_S_REGISTER, reg);
+       call_all(dev, core, s_register, reg);
 
        return 0;
 }
@@ -1524,6 +1519,26 @@ int cx23885_video_register(struct cx23885_dev *dev)
        /* Don't enable VBI yet */
        cx_set(PCI_INT_MSK, 1);
 
+       if (TUNER_ABSENT != dev->tuner_type) {
+               struct v4l2_subdev *sd = NULL;
+
+               if (dev->tuner_addr)
+                       sd = v4l2_i2c_new_subdev(&dev->i2c_bus[1].i2c_adap,
+                               "tuner", "tuner", dev->tuner_addr);
+               else
+                       sd = v4l2_i2c_new_probed_subdev(&dev->i2c_bus[1].i2c_adap,
+                               "tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_TV));
+               if (sd) {
+                       struct tuner_setup tun_setup;
+
+                       tun_setup.mode_mask = T_ANALOG_TV;
+                       tun_setup.type = dev->tuner_type;
+                       tun_setup.addr = v4l2_i2c_subdev_addr(sd);
+
+                       v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup);
+               }
+       }
+
 
        /* register v4l devices */
        dev->video_dev = cx23885_vdev_init(dev, dev->pci,
index ba57643f11983df6e05e9b65e88eea1828d2c186..02d980a29962381474a7aea6c34ba2b95792e304 100644 (file)
@@ -323,6 +323,7 @@ struct cx23885_dev {
        unsigned int               radio_type;
        unsigned char              radio_addr;
        unsigned int               has_radio;
+       struct v4l2_subdev         *sd_cx25840;
 
        /* V4l */
        u32                        freq;
@@ -348,6 +349,9 @@ static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev)
        return container_of(v4l2_dev, struct cx23885_dev, v4l2_dev);
 }
 
+#define call_all(dev, o, f, args...) \
+       v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
+
 extern struct list_head cx23885_devlist;
 
 #define SRAM_CH01  0 /* Video A */
@@ -464,8 +468,6 @@ extern struct videobuf_queue_ops cx23885_vbi_qops;
 /* cx23885-i2c.c                                                */
 extern int cx23885_i2c_register(struct cx23885_i2c *bus);
 extern int cx23885_i2c_unregister(struct cx23885_i2c *bus);
-extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd,
-                                    void *arg);
 extern void cx23885_av_clk(struct cx23885_dev *dev, int enable);
 
 /* ----------------------------------------------------------- */