]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/gpu/drm/exynos/exynos_drm_core.c
drm/exynos: add component framework support
[mirror_ubuntu-artful-kernel.git] / drivers / gpu / drm / exynos / exynos_drm_core.c
index 1bef6dc774782efe81b4b2839c9fa09e9f264b4e..4c9f972eaa0771c0b2d9c5ff0f5480da3dc1e93d 100644 (file)
 
 #include <drm/drmP.h>
 #include "exynos_drm_drv.h"
+#include "exynos_drm_crtc.h"
 #include "exynos_drm_encoder.h"
-#include "exynos_drm_connector.h"
 #include "exynos_drm_fbdev.h"
 
 static LIST_HEAD(exynos_drm_subdrv_list);
 
-static int exynos_drm_create_enc_conn(struct drm_device *dev,
-                                       struct exynos_drm_subdrv *subdrv)
+int exynos_drm_create_enc_conn(struct drm_device *dev,
+                                       struct exynos_drm_display *display)
 {
        struct drm_encoder *encoder;
-       struct drm_connector *connector;
        int ret;
+       unsigned long possible_crtcs = 0;
 
-       subdrv->manager->dev = subdrv->dev;
+       ret = exynos_drm_crtc_get_pipe_from_type(dev, display->type);
+       if (ret < 0)
+               return ret;
+
+       possible_crtcs |= 1 << ret;
 
        /* create and initialize a encoder for this sub driver. */
-       encoder = exynos_drm_encoder_create(dev, subdrv->manager,
-                       (1 << MAX_CRTC) - 1);
+       encoder = exynos_drm_encoder_create(dev, display, possible_crtcs);
        if (!encoder) {
                DRM_ERROR("failed to create encoder\n");
                return -EFAULT;
        }
 
-       /*
-        * create and initialize a connector for this sub driver and
-        * attach the encoder created above to the connector.
-        */
-       connector = exynos_drm_connector_create(dev, encoder);
-       if (!connector) {
-               DRM_ERROR("failed to create connector\n");
-               ret = -EFAULT;
+       display->encoder = encoder;
+
+       ret = display->ops->create_connector(display, encoder);
+       if (ret) {
+               DRM_ERROR("failed to create connector ret = %d\n", ret);
                goto err_destroy_encoder;
        }
 
-       subdrv->encoder = encoder;
-       subdrv->connector = connector;
-
        return 0;
 
 err_destroy_encoder:
@@ -58,97 +55,59 @@ err_destroy_encoder:
        return ret;
 }
 
-static void exynos_drm_destroy_enc_conn(struct exynos_drm_subdrv *subdrv)
+int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
 {
-       if (subdrv->encoder) {
-               struct drm_encoder *encoder = subdrv->encoder;
-               encoder->funcs->destroy(encoder);
-               subdrv->encoder = NULL;
-       }
-
-       if (subdrv->connector) {
-               struct drm_connector *connector = subdrv->connector;
-               connector->funcs->destroy(connector);
-               subdrv->connector = NULL;
-       }
-}
+       if (!subdrv)
+               return -EINVAL;
 
-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;
-       }
+       list_add_tail(&subdrv->list, &exynos_drm_subdrv_list);
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register);
 
-static void exynos_drm_subdrv_remove(struct drm_device *dev,
-                                     struct exynos_drm_subdrv *subdrv)
+int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
 {
-       if (subdrv->remove)
-               subdrv->remove(dev, subdrv->dev);
+       if (!subdrv)
+               return -EINVAL;
+
+       list_del(&subdrv->list);
+
+       return 0;
 }
+EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister);
 
-int exynos_drm_device_register(struct drm_device *dev)
+int exynos_drm_device_subdrv_probe(struct drm_device *dev)
 {
        struct exynos_drm_subdrv *subdrv, *n;
-       unsigned int fine_cnt = 0;
        int err;
 
        if (!dev)
                return -EINVAL;
 
        list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) {
-               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;
+               if (subdrv->probe) {
+                       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.
+                        */
+                       err = subdrv->probe(dev, subdrv->dev);
+                       if (err) {
+                               DRM_DEBUG("exynos drm subdrv probe failed.\n");
+                               list_del(&subdrv->list);
+                               continue;
+                       }
                }
-
-               fine_cnt++;
        }
 
-       if (!fine_cnt)
-               return -EINVAL;
-
        return 0;
 }
-EXPORT_SYMBOL_GPL(exynos_drm_device_register);
+EXPORT_SYMBOL_GPL(exynos_drm_device_subdrv_probe);
 
-int exynos_drm_device_unregister(struct drm_device *dev)
+int exynos_drm_device_subdrv_remove(struct drm_device *dev)
 {
        struct exynos_drm_subdrv *subdrv;
 
@@ -158,35 +117,13 @@ int exynos_drm_device_unregister(struct drm_device *dev)
        }
 
        list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
-               exynos_drm_subdrv_remove(dev, subdrv);
-               exynos_drm_destroy_enc_conn(subdrv);
+               if (subdrv->remove)
+                       subdrv->remove(dev, subdrv->dev);
        }
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(exynos_drm_device_unregister);
-
-int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
-{
-       if (!subdrv)
-               return -EINVAL;
-
-       list_add_tail(&subdrv->list, &exynos_drm_subdrv_list);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register);
-
-int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
-{
-       if (!subdrv)
-               return -EINVAL;
-
-       list_del(&subdrv->list);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister);
+EXPORT_SYMBOL_GPL(exynos_drm_device_subdrv_remove);
 
 int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
 {