These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / exynos / exynos_drm_dpi.c
index 37678cf..c748b87 100644 (file)
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_panel.h>
+#include <drm/drm_atomic_helper.h>
 
 #include <linux/regulator/consumer.h>
 
 #include <video/of_videomode.h>
 #include <video/videomode.h>
 
-#include "exynos_drm_drv.h"
+#include "exynos_drm_crtc.h"
 
 struct exynos_dpi {
-       struct exynos_drm_display display;
+       struct drm_encoder encoder;
        struct device *dev;
        struct device_node *panel_node;
 
        struct drm_panel *panel;
        struct drm_connector connector;
-       struct drm_encoder *encoder;
 
        struct videomode *vm;
-       int dpms_mode;
 };
 
 #define connector_to_dpi(c) container_of(c, struct exynos_dpi, connector)
 
-static inline struct exynos_dpi *display_to_dpi(struct exynos_drm_display *d)
+static inline struct exynos_dpi *encoder_to_dpi(struct drm_encoder *e)
 {
-       return container_of(d, struct exynos_dpi, display);
+       return container_of(e, struct exynos_dpi, encoder);
 }
 
 static enum drm_connector_status
@@ -59,10 +58,13 @@ static void exynos_dpi_connector_destroy(struct drm_connector *connector)
 }
 
 static struct drm_connector_funcs exynos_dpi_connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
+       .dpms = drm_atomic_helper_connector_dpms,
        .detect = exynos_dpi_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .destroy = exynos_dpi_connector_destroy,
+       .reset = drm_atomic_helper_connector_reset,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 static int exynos_dpi_get_modes(struct drm_connector *connector)
@@ -95,7 +97,7 @@ exynos_dpi_best_encoder(struct drm_connector *connector)
 {
        struct exynos_dpi *ctx = connector_to_dpi(connector);
 
-       return ctx->encoder;
+       return &ctx->encoder;
 }
 
 static struct drm_connector_helper_funcs exynos_dpi_connector_helper_funcs = {
@@ -103,15 +105,12 @@ static struct drm_connector_helper_funcs exynos_dpi_connector_helper_funcs = {
        .best_encoder = exynos_dpi_best_encoder,
 };
 
-static int exynos_dpi_create_connector(struct exynos_drm_display *display,
-                                      struct drm_encoder *encoder)
+static int exynos_dpi_create_connector(struct drm_encoder *encoder)
 {
-       struct exynos_dpi *ctx = display_to_dpi(display);
+       struct exynos_dpi *ctx = encoder_to_dpi(encoder);
        struct drm_connector *connector = &ctx->connector;
        int ret;
 
-       ctx->encoder = encoder;
-
        connector->polled = DRM_CONNECTOR_POLL_HPD;
 
        ret = drm_connector_init(encoder->dev, connector,
@@ -129,46 +128,48 @@ static int exynos_dpi_create_connector(struct exynos_drm_display *display,
        return 0;
 }
 
-static void exynos_dpi_poweron(struct exynos_dpi *ctx)
+static bool exynos_dpi_mode_fixup(struct drm_encoder *encoder,
+                                 const struct drm_display_mode *mode,
+                                 struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+static void exynos_dpi_mode_set(struct drm_encoder *encoder,
+                               struct drm_display_mode *mode,
+                               struct drm_display_mode *adjusted_mode)
+{
+}
+
+static void exynos_dpi_enable(struct drm_encoder *encoder)
 {
+       struct exynos_dpi *ctx = encoder_to_dpi(encoder);
+
        if (ctx->panel) {
                drm_panel_prepare(ctx->panel);
                drm_panel_enable(ctx->panel);
        }
 }
 
-static void exynos_dpi_poweroff(struct exynos_dpi *ctx)
+static void exynos_dpi_disable(struct drm_encoder *encoder)
 {
+       struct exynos_dpi *ctx = encoder_to_dpi(encoder);
+
        if (ctx->panel) {
                drm_panel_disable(ctx->panel);
                drm_panel_unprepare(ctx->panel);
        }
 }
 
-static void exynos_dpi_dpms(struct exynos_drm_display *display, int mode)
-{
-       struct exynos_dpi *ctx = display_to_dpi(display);
-
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-               if (ctx->dpms_mode != DRM_MODE_DPMS_ON)
-                               exynos_dpi_poweron(ctx);
-                       break;
-       case DRM_MODE_DPMS_STANDBY:
-       case DRM_MODE_DPMS_SUSPEND:
-       case DRM_MODE_DPMS_OFF:
-               if (ctx->dpms_mode == DRM_MODE_DPMS_ON)
-                       exynos_dpi_poweroff(ctx);
-               break;
-       default:
-               break;
-       }
-       ctx->dpms_mode = mode;
-}
+static struct drm_encoder_helper_funcs exynos_dpi_encoder_helper_funcs = {
+       .mode_fixup = exynos_dpi_mode_fixup,
+       .mode_set = exynos_dpi_mode_set,
+       .enable = exynos_dpi_enable,
+       .disable = exynos_dpi_disable,
+};
 
-static struct exynos_drm_display_ops exynos_dpi_display_ops = {
-       .create_connector = exynos_dpi_create_connector,
-       .dpms = exynos_dpi_dpms
+static struct drm_encoder_funcs exynos_dpi_encoder_funcs = {
+       .destroy = drm_encoder_cleanup,
 };
 
 /* of_* functions will be removed after merge of of_graph patches */
@@ -295,7 +296,34 @@ static int exynos_dpi_parse_dt(struct exynos_dpi *ctx)
        return 0;
 }
 
-struct exynos_drm_display *exynos_dpi_probe(struct device *dev)
+int exynos_dpi_bind(struct drm_device *dev, struct drm_encoder *encoder)
+{
+       int ret;
+
+       ret = exynos_drm_crtc_get_pipe_from_type(dev, EXYNOS_DISPLAY_TYPE_LCD);
+       if (ret < 0)
+               return ret;
+
+       encoder->possible_crtcs = 1 << ret;
+
+       DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
+
+       drm_encoder_init(dev, encoder, &exynos_dpi_encoder_funcs,
+                        DRM_MODE_ENCODER_TMDS);
+
+       drm_encoder_helper_add(encoder, &exynos_dpi_encoder_helper_funcs);
+
+       ret = exynos_dpi_create_connector(encoder);
+       if (ret) {
+               DRM_ERROR("failed to create connector ret = %d\n", ret);
+               drm_encoder_cleanup(encoder);
+               return ret;
+       }
+
+       return 0;
+}
+
+struct drm_encoder *exynos_dpi_probe(struct device *dev)
 {
        struct exynos_dpi *ctx;
        int ret;
@@ -304,50 +332,31 @@ struct exynos_drm_display *exynos_dpi_probe(struct device *dev)
        if (!ctx)
                return ERR_PTR(-ENOMEM);
 
-       ctx->display.type = EXYNOS_DISPLAY_TYPE_LCD;
-       ctx->display.ops = &exynos_dpi_display_ops;
        ctx->dev = dev;
-       ctx->dpms_mode = DRM_MODE_DPMS_OFF;
-
-       ret = exynos_drm_component_add(dev,
-                                       EXYNOS_DEVICE_TYPE_CONNECTOR,
-                                       ctx->display.type);
-       if (ret)
-               return ERR_PTR(ret);
 
        ret = exynos_dpi_parse_dt(ctx);
        if (ret < 0) {
                devm_kfree(dev, ctx);
-               goto err_del_component;
+               return NULL;
        }
 
        if (ctx->panel_node) {
                ctx->panel = of_drm_find_panel(ctx->panel_node);
-               if (!ctx->panel) {
-                       exynos_drm_component_del(dev,
-                                               EXYNOS_DEVICE_TYPE_CONNECTOR);
+               if (!ctx->panel)
                        return ERR_PTR(-EPROBE_DEFER);
-               }
        }
 
-       return &ctx->display;
-
-err_del_component:
-       exynos_drm_component_del(dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
-
-       return NULL;
+       return &ctx->encoder;
 }
 
-int exynos_dpi_remove(struct exynos_drm_display *display)
+int exynos_dpi_remove(struct drm_encoder *encoder)
 {
-       struct exynos_dpi *ctx = display_to_dpi(display);
+       struct exynos_dpi *ctx = encoder_to_dpi(encoder);
 
-       exynos_dpi_dpms(&ctx->display, DRM_MODE_DPMS_OFF);
+       exynos_dpi_disable(&ctx->encoder);
 
        if (ctx->panel)
                drm_panel_detach(ctx->panel);
 
-       exynos_drm_component_del(ctx->dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
-
        return 0;
 }