OSDN Git Service

[media] cx231xx: add media controller support
authorMauro Carvalho Chehab <mchehab@osg.samsung.com>
Thu, 1 Jan 2015 14:37:17 +0000 (11:37 -0300)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Fri, 13 Feb 2015 23:10:12 +0000 (21:10 -0200)
Let's add media controller support for this driver and register it
for both V4L and DVB.

The media controller on this driver is not mandatory, as it can fully
work without it. So, if the media controller register fails, just print
an error message, but proceed with device registering.

Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/usb/cx231xx/cx231xx-cards.c
drivers/media/usb/cx231xx/cx231xx-dvb.c
drivers/media/usb/cx231xx/cx231xx.h

index da03733..d357e8c 100644 (file)
@@ -912,9 +912,6 @@ static inline void cx231xx_set_model(struct cx231xx *dev)
  */
 void cx231xx_pre_card_setup(struct cx231xx *dev)
 {
-
-       cx231xx_set_model(dev);
-
        dev_info(dev->dev, "Identified as %s (card=%d)\n",
                dev->board.name, dev->model);
 
@@ -1092,6 +1089,17 @@ void cx231xx_config_i2c(struct cx231xx *dev)
        call_all(dev, video, s_stream, 1);
 }
 
+static void cx231xx_unregister_media_device(struct cx231xx *dev)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+       if (dev->media_dev) {
+               media_device_unregister(dev->media_dev);
+               kfree(dev->media_dev);
+               dev->media_dev = NULL;
+       }
+#endif
+}
+
 /*
  * cx231xx_realease_resources()
  * unregisters the v4l2,i2c and usb devices
@@ -1099,6 +1107,8 @@ void cx231xx_config_i2c(struct cx231xx *dev)
 */
 void cx231xx_release_resources(struct cx231xx *dev)
 {
+       cx231xx_unregister_media_device(dev);
+
        cx231xx_release_analog_resources(dev);
 
        cx231xx_remove_from_devlist(dev);
@@ -1117,6 +1127,38 @@ void cx231xx_release_resources(struct cx231xx *dev)
        clear_bit(dev->devno, &cx231xx_devused);
 }
 
+static void cx231xx_media_device_register(struct cx231xx *dev,
+                                         struct usb_device *udev)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+       struct media_device *mdev;
+       int ret;
+
+       mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+       if (!mdev)
+               return;
+
+       mdev->dev = dev->dev;
+       strlcpy(mdev->model, dev->board.name, sizeof(mdev->model));
+       if (udev->serial)
+               strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
+       strcpy(mdev->bus_info, udev->devpath);
+       mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
+       mdev->driver_version = LINUX_VERSION_CODE;
+
+       ret = media_device_register(mdev);
+       if (ret) {
+               dev_err(dev->dev,
+                       "Couldn't create a media device. Error: %d\n",
+                       ret);
+               kfree(mdev);
+               return;
+       }
+
+       dev->media_dev = mdev;
+#endif
+}
+
 /*
  * cx231xx_init_dev()
  * allocates and inits the device structs, registers i2c bus and v4l device
@@ -1225,10 +1267,8 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev,
        }
 
        retval = cx231xx_register_analog_devices(dev);
-       if (retval) {
-               cx231xx_release_analog_resources(dev);
+       if (retval)
                goto err_analog;
-       }
 
        cx231xx_ir_init(dev);
 
@@ -1236,6 +1276,8 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev,
 
        return 0;
 err_analog:
+       cx231xx_unregister_media_device(dev);
+       cx231xx_release_analog_resources(dev);
        cx231xx_remove_from_devlist(dev);
 err_dev_init:
        cx231xx_dev_uninit(dev);
@@ -1438,6 +1480,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
        dev->video_mode.alt = -1;
        dev->dev = d;
 
+       cx231xx_set_model(dev);
+
        dev->interface_count++;
        /* reset gpio dir and value */
        dev->gpio_dir = 0;
@@ -1502,7 +1546,11 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
        /* save our data pointer in this interface device */
        usb_set_intfdata(interface, dev);
 
+       /* Register the media controller */
+       cx231xx_media_device_register(dev, udev);
+
        /* Create v4l2 device */
+       dev->v4l2_dev.mdev = dev->media_dev;
        retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
        if (retval) {
                dev_err(d, "v4l2_device_register failed\n");
index dd600b9..bb7e766 100644 (file)
@@ -455,6 +455,7 @@ static int register_dvb(struct cx231xx_dvb *dvb,
 
        mutex_init(&dvb->lock);
 
+
        /* register adapter */
        result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
                                      adapter_nr);
@@ -464,6 +465,9 @@ static int register_dvb(struct cx231xx_dvb *dvb,
                       dev->name, result);
                goto fail_adapter;
        }
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+       dvb->adapter.mdev = dev->media_dev;
+#endif
 
        /* Ensure all frontends negotiate bus access */
        dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl;
index 6d6f3ee..af9d6c4 100644 (file)
@@ -658,6 +658,10 @@ struct cx231xx {
        struct video_device *vbi_dev;
        struct video_device *radio_dev;
 
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       struct media_device *media_dev;
+#endif
+
        unsigned char eedata[256];
 
        struct cx231xx_video_mode video_mode;