mwifiex: fix typo in PCIe adapter NULL check
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / exynos / exynos_drm_core.c
index 19bdf0a194eb440c148dac1ea305a8402359894c..94026ad76a775d9cfb826fa65f9e2da74d14660f 100644 (file)
 
 static LIST_HEAD(exynos_drm_subdrv_list);
 
-static int exynos_drm_subdrv_probe(struct drm_device *dev,
+static int exynos_drm_create_enc_conn(struct drm_device *dev,
                                        struct exynos_drm_subdrv *subdrv)
 {
        struct drm_encoder *encoder;
        struct drm_connector *connector;
+       int ret;
 
        DRM_DEBUG_DRIVER("%s\n", __FILE__);
 
-       if (subdrv->probe) {
-               int ret;
-
-               /*
-                * this probe callback would be called by sub driver
-                * after setting of all resources to this sub driver,
-                * such as clock, irq and register map are done or by load()
-                * of exynos drm driver.
-                *
-                * P.S. note that this driver is considered for modularization.
-                */
-               ret = subdrv->probe(dev, subdrv->dev);
-               if (ret)
-                       return ret;
-       }
-
-       if (!subdrv->manager)
-               return 0;
-
        subdrv->manager->dev = subdrv->dev;
 
        /* create and initialize a encoder for this sub driver. */
@@ -78,24 +60,22 @@ static int exynos_drm_subdrv_probe(struct drm_device *dev,
        connector = exynos_drm_connector_create(dev, encoder);
        if (!connector) {
                DRM_ERROR("failed to create connector\n");
-               encoder->funcs->destroy(encoder);
-               return -EFAULT;
+               ret = -EFAULT;
+               goto err_destroy_encoder;
        }
 
        subdrv->encoder = encoder;
        subdrv->connector = connector;
 
        return 0;
+
+err_destroy_encoder:
+       encoder->funcs->destroy(encoder);
+       return ret;
 }
 
-static void exynos_drm_subdrv_remove(struct drm_device *dev,
-                                     struct exynos_drm_subdrv *subdrv)
+static void exynos_drm_destroy_enc_conn(struct exynos_drm_subdrv *subdrv)
 {
-       DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
-       if (subdrv->remove)
-               subdrv->remove(dev);
-
        if (subdrv->encoder) {
                struct drm_encoder *encoder = subdrv->encoder;
                encoder->funcs->destroy(encoder);
@@ -109,9 +89,43 @@ static void exynos_drm_subdrv_remove(struct drm_device *dev,
        }
 }
 
+static int exynos_drm_subdrv_probe(struct drm_device *dev,
+                                       struct exynos_drm_subdrv *subdrv)
+{
+       if (subdrv->probe) {
+               int ret;
+
+               subdrv->drm_dev = dev;
+
+               /*
+                * this probe callback would be called by sub driver
+                * after setting of all resources to this sub driver,
+                * such as clock, irq and register map are done or by load()
+                * of exynos drm driver.
+                *
+                * P.S. note that this driver is considered for modularization.
+                */
+               ret = subdrv->probe(dev, subdrv->dev);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static void exynos_drm_subdrv_remove(struct drm_device *dev,
+                                     struct exynos_drm_subdrv *subdrv)
+{
+       DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+       if (subdrv->remove)
+               subdrv->remove(dev, subdrv->dev);
+}
+
 int exynos_drm_device_register(struct drm_device *dev)
 {
        struct exynos_drm_subdrv *subdrv, *n;
+       unsigned int fine_cnt = 0;
        int err;
 
        DRM_DEBUG_DRIVER("%s\n", __FILE__);
@@ -120,14 +134,36 @@ int exynos_drm_device_register(struct drm_device *dev)
                return -EINVAL;
 
        list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) {
-               subdrv->drm_dev = dev;
                err = exynos_drm_subdrv_probe(dev, subdrv);
                if (err) {
                        DRM_DEBUG("exynos drm subdrv probe failed.\n");
                        list_del(&subdrv->list);
+                       continue;
+               }
+
+               /*
+                * if manager is null then it means that this sub driver
+                * doesn't need encoder and connector.
+                */
+               if (!subdrv->manager) {
+                       fine_cnt++;
+                       continue;
+               }
+
+               err = exynos_drm_create_enc_conn(dev, subdrv);
+               if (err) {
+                       DRM_DEBUG("failed to create encoder and connector.\n");
+                       exynos_drm_subdrv_remove(dev, subdrv);
+                       list_del(&subdrv->list);
+                       continue;
                }
+
+               fine_cnt++;
        }
 
+       if (!fine_cnt)
+               return -EINVAL;
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(exynos_drm_device_register);
@@ -143,8 +179,10 @@ int exynos_drm_device_unregister(struct drm_device *dev)
                return -EINVAL;
        }
 
-       list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list)
+       list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
                exynos_drm_subdrv_remove(dev, subdrv);
+               exynos_drm_destroy_enc_conn(subdrv);
+       }
 
        return 0;
 }