if (!coredev->media_dev)
                return;
        media_device_unregister(coredev->media_dev);
+       media_device_cleanup(coredev->media_dev);
        kfree(coredev->media_dev);
        coredev->media_dev = NULL;
 #endif
 
 
 
 /**
- * media_device_register - register a media device
+ * media_device_init() - initialize a media device
  * @mdev:      The media device
  *
  * The caller is responsible for initializing the media device before
  * - dev must point to the parent device
  * - model must be filled with the device model name
  */
-int __must_check __media_device_register(struct media_device *mdev,
-                                        struct module *owner)
+void media_device_init(struct media_device *mdev)
 {
-       int ret;
-
-       if (WARN_ON(mdev->dev == NULL || mdev->model[0] == 0))
-               return -EINVAL;
-
        INIT_LIST_HEAD(&mdev->entities);
        INIT_LIST_HEAD(&mdev->interfaces);
        INIT_LIST_HEAD(&mdev->pads);
        spin_lock_init(&mdev->lock);
        mutex_init(&mdev->graph_mutex);
 
+       dev_dbg(mdev->dev, "Media device initialized\n");
+}
+EXPORT_SYMBOL_GPL(media_device_init);
+
+/**
+ * media_device_cleanup() - Cleanup a media device
+ * @mdev:      The media device
+ *
+ */
+void media_device_cleanup(struct media_device *mdev)
+{
+       mutex_destroy(&mdev->graph_mutex);
+}
+EXPORT_SYMBOL_GPL(media_device_cleanup);
+
+/**
+ * __media_device_register() - register a media device
+ * @mdev:      The media device
+ * @owner:     The module owner
+ *
+ * returns zero on success or a negative error code.
+ */
+int __must_check __media_device_register(struct media_device *mdev,
+                                        struct module *owner)
+{
+       int ret;
+
        /* Register the device node. */
        mdev->devnode.fops = &media_device_fops;
        mdev->devnode.parent = mdev->dev;
 
        ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
 unlock:
        mutex_unlock(&fmd->media_dev.graph_mutex);
-       return ret;
+       if (ret < 0)
+               return ret;
+
+       return media_device_register(&fmd->media_dev);
 }
 
 static int fimc_md_probe(struct platform_device *pdev)
                return ret;
        }
 
-       ret = media_device_register(&fmd->media_dev);
-       if (ret < 0) {
-               v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret);
-               goto err_v4l2_dev;
-       }
+       media_device_init(&fmd->media_dev);
 
        ret = fimc_md_get_clocks(fmd);
        if (ret)
 err_m_ent:
        fimc_md_unregister_entities(fmd);
 err_md:
-       media_device_unregister(&fmd->media_dev);
-err_v4l2_dev:
+       media_device_cleanup(&fmd->media_dev);
        v4l2_device_unregister(&fmd->v4l2_dev);
        return ret;
 }
        fimc_md_unregister_entities(fmd);
        fimc_md_pipelines_free(fmd);
        media_device_unregister(&fmd->media_dev);
+       media_device_cleanup(&fmd->media_dev);
        fimc_md_put_clocks(fmd);
 
        return 0;
 
 
        v4l2_device_unregister(&isp->v4l2_dev);
        media_device_unregister(&isp->media_dev);
+       media_device_cleanup(&isp->media_dev);
 }
 
 static int isp_link_entity(
                sizeof(isp->media_dev.model));
        isp->media_dev.hw_revision = isp->revision;
        isp->media_dev.link_notify = isp_pipeline_link_notify;
-       ret = media_device_register(&isp->media_dev);
-       if (ret < 0) {
-               dev_err(isp->dev, "%s: Media device registration failed (%d)\n",
-                       __func__, ret);
-               return ret;
-       }
+       media_device_init(&isp->media_dev);
 
        isp->v4l2_dev.mdev = &isp->media_dev;
        ret = v4l2_device_register(isp->dev, &isp->v4l2_dev);
                }
        }
 
-       return v4l2_device_register_subdev_nodes(v4l2_dev);
+       ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
+       if (ret < 0)
+               return ret;
+
+       return media_device_register(&isp->media_dev);
 }
 
 /*
 
 /*
  * Media device
  */
-static int camif_media_dev_register(struct camif_dev *camif)
+static int camif_media_dev_init(struct camif_dev *camif)
 {
        struct media_device *md = &camif->media_dev;
        struct v4l2_device *v4l2_dev = &camif->v4l2_dev;
        if (ret < 0)
                return ret;
 
-       ret = media_device_register(md);
-       if (ret < 0)
-               v4l2_device_unregister(v4l2_dev);
+       media_device_init(md);
 
        return ret;
 }
                goto err_alloc;
        }
 
-       ret = camif_media_dev_register(camif);
+       ret = camif_media_dev_init(camif);
        if (ret < 0)
                goto err_mdev;
 
                goto err_unlock;
 
        mutex_unlock(&camif->media_dev.graph_mutex);
+
+       ret = media_device_register(&camif->media_dev);
+       if (ret < 0)
+               goto err_sens;
+
        pm_runtime_put(dev);
        return 0;
 
 err_sens:
        v4l2_device_unregister(&camif->v4l2_dev);
        media_device_unregister(&camif->media_dev);
+       media_device_cleanup(&camif->media_dev);
        camif_unregister_media_entities(camif);
 err_mdev:
        vb2_dma_contig_cleanup_ctx(camif->alloc_ctx);
        struct s3c_camif_plat_data *pdata = &camif->pdata;
 
        media_device_unregister(&camif->media_dev);
+       media_device_cleanup(&camif->media_dev);
        camif_unregister_media_entities(camif);
        v4l2_device_unregister(&camif->v4l2_dev);
 
 
 
        v4l2_device_unregister(&vsp1->v4l2_dev);
        media_device_unregister(&vsp1->media_dev);
+       media_device_cleanup(&vsp1->media_dev);
 }
 
 static int vsp1_create_entities(struct vsp1_device *vsp1)
        strlcpy(mdev->model, "VSP1", sizeof(mdev->model));
        snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
                 dev_name(mdev->dev));
-       ret = media_device_register(mdev);
-       if (ret < 0) {
-               dev_err(vsp1->dev, "media device registration failed (%d)\n",
-                       ret);
-               return ret;
-       }
+       media_device_init(mdev);
 
        vdev->mdev = mdev;
        ret = v4l2_device_register(vsp1->dev, vdev);
        }
 
        ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev);
+       if (ret < 0)
+               goto done;
+
+       ret = media_device_register(mdev);
 
 done:
        if (ret < 0)
 
        if (ret < 0)
                dev_err(xdev->dev, "failed to register subdev nodes\n");
 
-       return ret;
+       return media_device_register(&xdev->media_dev);
 }
 
 static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier,
 {
        v4l2_device_unregister(&xdev->v4l2_dev);
        media_device_unregister(&xdev->media_dev);
+       media_device_cleanup(&xdev->media_dev);
 }
 
 static int xvip_composite_v4l2_init(struct xvip_composite_device *xdev)
                sizeof(xdev->media_dev.model));
        xdev->media_dev.hw_revision = 0;
 
-       ret = media_device_register(&xdev->media_dev);
-       if (ret < 0) {
-               dev_err(xdev->dev, "media device registration failed (%d)\n",
-                       ret);
-               return ret;
-       }
+       media_device_init(&xdev->media_dev);
 
        xdev->v4l2_dev.mdev = &xdev->media_dev;
        ret = v4l2_device_register(xdev->dev, &xdev->v4l2_dev);
        if (ret < 0) {
                dev_err(xdev->dev, "V4L2 device registration failed (%d)\n",
                        ret);
-               media_device_unregister(&xdev->media_dev);
+               media_device_cleanup(&xdev->media_dev);
                return ret;
        }
 
 
 #ifdef CONFIG_MEDIA_CONTROLLER
        if (dev->media_dev) {
                media_device_unregister(dev->media_dev);
+               media_device_cleanup(dev->media_dev);
                kfree(dev->media_dev);
                dev->media_dev = NULL;
        }
        au0828_usb_release(dev);
 }
 
-static void au0828_media_device_register(struct au0828_dev *dev,
-                                         struct usb_device *udev)
+static void au0828_media_device_init(struct au0828_dev *dev,
+                                    struct usb_device *udev)
 {
 #ifdef CONFIG_MEDIA_CONTROLLER
        struct media_device *mdev;
-       int ret;
 
        mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
        if (!mdev)
        mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
        mdev->driver_version = LINUX_VERSION_CODE;
 
-       ret = media_device_register(mdev);
-       if (ret) {
-               pr_err(
-                       "Couldn't create a media device. Error: %d\n",
-                       ret);
-               kfree(mdev);
-               return;
-       }
+       media_device_init(mdev);
 
        dev->media_dev = mdev;
 #endif
        dev->boardnr = id->driver_info;
        dev->board = au0828_boards[dev->boardnr];
 
-       /* Register the media controller */
-       au0828_media_device_register(dev, usbdev);
+       /* Initialize the media controller */
+       au0828_media_device_init(dev, usbdev);
 
 #ifdef CONFIG_VIDEO_AU0828_V4L2
        dev->v4l2_dev.release = au0828_usb_v4l2_release;
        if (retval) {
                pr_err("%s() au0282_dev_register failed to create graph\n",
                       __func__);
-               au0828_usb_disconnect(interface);
+               goto done;
        }
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+       retval = media_device_register(dev->media_dev);
+#endif
+
+done:
+       if (retval < 0)
+               au0828_usb_disconnect(interface);
+
        return retval;
 }
 
 
 #ifdef CONFIG_MEDIA_CONTROLLER
        if (dev->media_dev) {
                media_device_unregister(dev->media_dev);
+               media_device_cleanup(dev->media_dev);
                kfree(dev->media_dev);
                dev->media_dev = NULL;
        }
        clear_bit(dev->devno, &cx231xx_devused);
 }
 
-static void cx231xx_media_device_register(struct cx231xx *dev,
-                                         struct usb_device *udev)
+static void cx231xx_media_device_init(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)
        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;
-       }
+       media_device_init(mdev);
 
        dev->media_dev = mdev;
 #endif
        /* save our data pointer in this interface device */
        usb_set_intfdata(interface, dev);
 
-       /* Register the media controller */
-       cx231xx_media_device_register(dev, udev);
+       /* Initialize the media controller */
+       cx231xx_media_device_init(dev, udev);
 
        /* Create v4l2 device */
 #ifdef CONFIG_MEDIA_CONTROLLER
        request_modules(dev);
 
        retval = cx231xx_create_media_graph(dev);
-       if (retval < 0) {
-               cx231xx_release_resources(dev);
-       }
+       if (retval < 0)
+               goto done;
+
+#ifdef CONFIG_MEDIA_CONTROLLER
+       retval = media_device_register(dev->media_dev);
+#endif
 
+done:
+       if (retval < 0)
+               cx231xx_release_resources(dev);
        return retval;
+
 err_video_alt:
        /* cx231xx_uninit_dev: */
        cx231xx_close_extension(dev);
 
        return ret;
 }
 
-static void dvb_usbv2_media_device_register(struct dvb_usb_adapter *adap)
+static void dvb_usbv2_media_device_init(struct dvb_usb_adapter *adap)
 {
 #ifdef CONFIG_MEDIA_CONTROLLER_DVB
        struct media_device *mdev;
        struct dvb_usb_device *d = adap_to_d(adap);
        struct usb_device *udev = d->udev;
-       int ret;
 
        mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
        if (!mdev)
        mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
        mdev->driver_version = LINUX_VERSION_CODE;
 
-       ret = media_device_register(mdev);
-       if (ret) {
-               dev_err(&d->udev->dev,
-                       "Couldn't create a media device. Error: %d\n",
-                       ret);
-               kfree(mdev);
-               return;
-       }
+       media_device_init(mdev);
 
        dvb_register_media_controller(&adap->dvb_adap, mdev);
 
        dev_info(&d->udev->dev, "media controller created\n");
+#endif
+}
 
+static void dvb_usbv2_media_device_register(struct dvb_usb_adapter *adap)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+       media_device_register(adap->dvb_adap.mdev);
 #endif
 }
 
                return;
 
        media_device_unregister(adap->dvb_adap.mdev);
+       media_device_cleanup(adap->dvb_adap.mdev);
        kfree(adap->dvb_adap.mdev);
        adap->dvb_adap.mdev = NULL;
 
 
        adap->dvb_adap.priv = adap;
 
-       dvb_usbv2_media_device_register(adap);
+       dvb_usbv2_media_device_init(adap);
 
        if (d->props->read_mac_address) {
                ret = d->props->read_mac_address(adap,
        if (ret < 0)
                goto err_dvb_unregister_frontend;
 
+       dvb_usbv2_media_device_register(adap);
+
        return 0;
 
 err_dvb_unregister_frontend:
 
        return dvb_usb_ctrl_feed(dvbdmxfeed, 0);
 }
 
-static void dvb_usb_media_device_register(struct dvb_usb_adapter *adap)
+static void dvb_usb_media_device_init(struct dvb_usb_adapter *adap)
 {
 #ifdef CONFIG_MEDIA_CONTROLLER_DVB
        struct media_device *mdev;
        struct dvb_usb_device *d = adap->dev;
        struct usb_device *udev = d->udev;
-       int ret;
 
        mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
        if (!mdev)
        mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
        mdev->driver_version = LINUX_VERSION_CODE;
 
-       ret = media_device_register(mdev);
-       if (ret) {
-               dev_err(&d->udev->dev,
-                       "Couldn't create a media device. Error: %d\n",
-                       ret);
-               kfree(mdev);
-               return;
-       }
+       media_device_init(mdev);
+
        dvb_register_media_controller(&adap->dvb_adap, mdev);
 
        dev_info(&d->udev->dev, "media controller created\n");
 #endif
 }
 
+static void dvb_usb_media_device_register(struct dvb_usb_adapter *adap)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+       media_device_register(adap->dvb_adap.mdev);
+#endif
+}
+
 static void dvb_usb_media_device_unregister(struct dvb_usb_adapter *adap)
 {
 #ifdef CONFIG_MEDIA_CONTROLLER_DVB
                return;
 
        media_device_unregister(adap->dvb_adap.mdev);
+       media_device_cleanup(adap->dvb_adap.mdev);
        kfree(adap->dvb_adap.mdev);
        adap->dvb_adap.mdev = NULL;
 #endif
        }
        adap->dvb_adap.priv = adap;
 
-       dvb_usb_media_device_register(adap);
+       dvb_usb_media_device_init(adap);
 
        if (adap->dev->props.read_mac_address) {
                if (adap->dev->props.read_mac_address(adap->dev, adap->dvb_adap.proposed_mac) == 0)
 
        ret = dvb_create_media_graph(&adap->dvb_adap);
 
+       dvb_usb_media_device_register(adap);
+
        return ret;
 }
 
 
        mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
        mdev->driver_version = LINUX_VERSION_CODE;
 
+       media_device_init(mdev);
+
        ret = media_device_register(mdev);
        if (ret) {
-               pr_err("Couldn't create a media device. Error: %d\n",
-                       ret);
+               media_device_cleanup(mdev);
                kfree(mdev);
                return NULL;
        }
 
 #ifdef CONFIG_MEDIA_CONTROLLER
        if (media_devnode_is_registered(&dev->mdev.devnode))
                media_device_unregister(&dev->mdev);
+       media_device_cleanup(&dev->mdev);
 #endif
 
        list_for_each_safe(p, n, &dev->chains) {
                        "linux-uvc-devel mailing list.\n");
        }
 
-       /* Register the media and V4L2 devices. */
+       /* Initialize the media device and register the V4L2 device. */
 #ifdef CONFIG_MEDIA_CONTROLLER
        dev->mdev.dev = &intf->dev;
        strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
        strcpy(dev->mdev.bus_info, udev->devpath);
        dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
        dev->mdev.driver_version = LINUX_VERSION_CODE;
-       if (media_device_register(&dev->mdev) < 0)
-               goto error;
+       media_device_init(&dev->mdev);
 
        dev->vdev.mdev = &dev->mdev;
 #endif
        if (uvc_register_chains(dev) < 0)
                goto error;
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+       /* Register the media device node */
+       if (media_device_register(&dev->mdev) < 0)
+               goto error;
+#endif
        /* Save our data pointer in the interface data. */
        usb_set_intfdata(intf, dev);
 
 
 /* media_devnode to media_device */
 #define to_media_device(node) container_of(node, struct media_device, devnode)
 
+/**
+ * media_device_init() - Initializes a media device element
+ *
+ * @mdev:      pointer to struct &media_device
+ *
+ * This function initializes the media device prior to its registration.
+ * The media device initialization and registration is split in two functions
+ * to avoid race conditions and make the media device available to user-space
+ * before the media graph has been completed.
+ *
+ * So drivers need to first initialize the media device, register any entity
+ * within the media device, create pad to pad links and then finally register
+ * the media device by calling media_device_register() as a final step.
+ */
+void media_device_init(struct media_device *mdev);
+
+/**
+ * media_device_cleanup() - Cleanups a media device element
+ *
+ * @mdev:      pointer to struct &media_device
+ *
+ * This function that will destroy the graph_mutex that is
+ * initialized in media_device_init().
+ */
+void media_device_cleanup(struct media_device *mdev);
+
 /**
  * __media_device_register() - Registers a media device element
  *