drm/exynos: separated subdrv_probe function into two parts.
authorInki Dae <inki.dae@samsung.com>
Fri, 17 Aug 2012 04:23:25 +0000 (13:23 +0900)
committerInki Dae <inki.dae@samsung.com>
Thu, 4 Oct 2012 01:05:59 +0000 (10:05 +0900)
Changelog v2:
fixed the issue that when sub driver is probed, no kms drivers such as
fimd or hdmi are failed. no kms drivers have no manager so if manager is
null then encoder and connector creation should be ignored.

Changelog v1:
this patch separates exynos_drm_subdrv_probe function into sub driver's probe call
and encoder/connector creation so that exynos drm core module can take exception
when some operation was failed properly.

Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
drivers/gpu/drm/exynos/exynos_drm_core.c

index 80cba2f413f4d07fc43c903eb91889768db5c930..7b0432b7a3645e8228c0c53b17a444cff3e299bc 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, subdrv->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;
 }