drm/exynos: Implement drm_connector directly in dp driver
authorSean Paul <seanpaul@chromium.org>
Thu, 30 Jan 2014 21:19:30 +0000 (16:19 -0500)
committerInki Dae <daeinki@gmail.com>
Sun, 23 Mar 2014 15:36:37 +0000 (00:36 +0900)
This patch implements drm_connector directly in the dp driver, this will
allow us to move away from the exynos_drm_connector layer.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
drivers/gpu/drm/exynos/exynos_dp_core.c
drivers/gpu/drm/exynos/exynos_dp_core.h

index 05ce947e3347ce84ecfbfc35ec442895acccfe01..af2c9d2cfca0676cbed338c39c5f34f694b66f6d 100644 (file)
 #include <video/of_videomode.h>
 
 #include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
 
 #include "exynos_drm_drv.h"
 #include "exynos_dp_core.h"
 
+#define ctx_from_connector(c)  container_of(c, struct exynos_dp_device, \
+                                       connector)
+
 static int exynos_dp_init_dp(struct exynos_dp_device *dp)
 {
        exynos_dp_reset(dp);
@@ -897,21 +902,98 @@ static void exynos_dp_hotplug(struct work_struct *work)
                dev_err(dp->dev, "unable to config video\n");
 }
 
-static bool exynos_dp_display_is_connected(struct exynos_drm_display *display)
+static enum drm_connector_status exynos_dp_detect(
+                               struct drm_connector *connector, bool force)
 {
-       return true;
+       return connector_status_connected;
 }
 
-static void *exynos_dp_get_panel(struct exynos_drm_display *display)
+static void exynos_dp_connector_destroy(struct drm_connector *connector)
 {
-       struct exynos_dp_device *dp = display->ctx;
+}
+
+static struct drm_connector_funcs exynos_dp_connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .detect = exynos_dp_detect,
+       .destroy = exynos_dp_connector_destroy,
+};
+
+static int exynos_dp_get_modes(struct drm_connector *connector)
+{
+       struct exynos_dp_device *dp = ctx_from_connector(connector);
+       struct drm_display_mode *mode;
+
+       mode = drm_mode_create(connector->dev);
+       if (!mode) {
+               DRM_ERROR("failed to create a new display mode.\n");
+               return 0;
+       }
 
-       return &dp->panel;
+       drm_display_mode_from_videomode(&dp->panel.vm, mode);
+       mode->width_mm = dp->panel.width_mm;
+       mode->height_mm = dp->panel.height_mm;
+       connector->display_info.width_mm = mode->width_mm;
+       connector->display_info.height_mm = mode->height_mm;
+
+       mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+       drm_mode_set_name(mode);
+       drm_mode_probed_add(connector, mode);
+
+       return 1;
 }
 
-static int exynos_dp_check_mode(struct exynos_drm_display *display,
+static int exynos_dp_mode_valid(struct drm_connector *connector,
                        struct drm_display_mode *mode)
 {
+       return MODE_OK;
+}
+
+static struct drm_encoder *exynos_dp_best_encoder(
+                       struct drm_connector *connector)
+{
+       struct exynos_dp_device *dp = ctx_from_connector(connector);
+
+       return dp->encoder;
+}
+
+static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = {
+       .get_modes = exynos_dp_get_modes,
+       .mode_valid = exynos_dp_mode_valid,
+       .best_encoder = exynos_dp_best_encoder,
+};
+
+static int exynos_dp_initialize(struct exynos_drm_display *display,
+                               struct drm_device *drm_dev)
+{
+       struct exynos_dp_device *dp = display->ctx;
+
+       dp->drm_dev = drm_dev;
+
+       return 0;
+}
+
+static int exynos_dp_create_connector(struct exynos_drm_display *display,
+                               struct drm_encoder *encoder)
+{
+       struct exynos_dp_device *dp = display->ctx;
+       struct drm_connector *connector = &dp->connector;
+       int ret;
+
+       dp->encoder = encoder;
+       connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+       ret = drm_connector_init(dp->drm_dev, connector,
+                       &exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP);
+       if (ret) {
+               DRM_ERROR("Failed to initialize connector with drm\n");
+               return ret;
+       }
+
+       drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs);
+       drm_sysfs_connector_add(connector);
+       drm_mode_connector_attach_encoder(connector, encoder);
+
        return 0;
 }
 
@@ -983,9 +1065,8 @@ static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
 }
 
 static struct exynos_drm_display_ops exynos_dp_display_ops = {
-       .is_connected = exynos_dp_display_is_connected,
-       .get_panel = exynos_dp_get_panel,
-       .check_mode = exynos_dp_check_mode,
+       .initialize = exynos_dp_initialize,
+       .create_connector = exynos_dp_create_connector,
        .dpms = exynos_dp_dpms,
 };
 
index ccaeadc8ee16fc3dec91972d395e1fea8b3836a1..d6a900d4ee40d1d307a42dc62cf1d72a27da892a 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef _EXYNOS_DP_CORE_H
 #define _EXYNOS_DP_CORE_H
 
+#include <drm/drm_crtc.h>
 #include <drm/exynos_drm.h>
 
 #define DP_TIMEOUT_LOOP_COUNT 100
@@ -144,6 +145,9 @@ struct link_train {
 
 struct exynos_dp_device {
        struct device           *dev;
+       struct drm_device       *drm_dev;
+       struct drm_connector    connector;
+       struct drm_encoder      *encoder;
        struct clk              *clock;
        unsigned int            irq;
        void __iomem            *reg_base;