This patch makes the link with DRM/KMS interface by initializing the drm
plane/crtc/encoder/connector and adding the drm plane/crtc/encoder/
connector helper.

This patch is compatible with different hisilicon platform such as Hikey
series of boards and other series of boards.

Signed-off-by: Xinliang Liu <xinliang.liu at linaro.org>
Signed-off-by: Xinwei Kong <kong.kongxinwei at hisilicon.com>
Signed-off-by: Andy Green <andy.green at linaro.org>
Signed-off-by: Jiwen Qi <qijiwen at hisilicon.com>
Signed-off-by: Yu Gong <gongyu at hisilicon.com>
---
 drivers/gpu/drm/hisilicon/Makefile             |   4 +
 drivers/gpu/drm/hisilicon/hisi_ade.c           |  44 +++++
 drivers/gpu/drm/hisilicon/hisi_ade_reg.h       |  27 +++
 drivers/gpu/drm/hisilicon/hisi_drm_connector.c |  90 ++++++++++
 drivers/gpu/drm/hisilicon/hisi_drm_connector.h |  25 +++
 drivers/gpu/drm/hisilicon/hisi_drm_crtc.c      | 179 ++++++++++++++++++
 drivers/gpu/drm/hisilicon/hisi_drm_crtc.h      |  45 +++++
 drivers/gpu/drm/hisilicon/hisi_drm_drv.h       |  36 ++++
 drivers/gpu/drm/hisilicon/hisi_drm_dsi.c       |  13 ++
 drivers/gpu/drm/hisilicon/hisi_drm_encoder.c   |  65 +++++++
 drivers/gpu/drm/hisilicon/hisi_drm_encoder.h   |  22 +++
 drivers/gpu/drm/hisilicon/hisi_drm_plane.c     | 240 +++++++++++++++++++++++++
 drivers/gpu/drm/hisilicon/hisi_drm_plane.h     |  51 ++++++
 13 files changed, 841 insertions(+)
 create mode 100644 drivers/gpu/drm/hisilicon/hisi_ade_reg.h
 create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_connector.c
 create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_connector.h
 create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_crtc.c
 create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_crtc.h
 create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_drv.h
 create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_encoder.c
 create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_encoder.h
 create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_plane.c
 create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_plane.h

diff --git a/drivers/gpu/drm/hisilicon/Makefile 
b/drivers/gpu/drm/hisilicon/Makefile
index 3f042fd..aa522f8 100644
--- a/drivers/gpu/drm/hisilicon/Makefile
+++ b/drivers/gpu/drm/hisilicon/Makefile
@@ -1,6 +1,10 @@
 hisi-drm-y := hisi_drm_drv.o \
              hisi_ade.o \
              hisi_drm_dsi.o \
+             hisi_drm_plane.o \
+             hisi_drm_crtc.o \
+             hisi_drm_encoder.o \
+             hisi_drm_connector.o \
              hisi_drm_fb.o \

 obj-$(CONFIG_DRM_HISI) += hisi-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hisi_ade.c 
b/drivers/gpu/drm/hisilicon/hisi_ade.c
index 9b58d20..148ed2f 100644
--- a/drivers/gpu/drm/hisilicon/hisi_ade.c
+++ b/drivers/gpu/drm/hisilicon/hisi_ade.c
@@ -15,6 +15,16 @@

 #include <drm/drm_gem_cma_helper.h>

+#include "hisi_drm_plane.h"
+#include "hisi_drm_crtc.h"
+#include "hisi_ade_reg.h"
+
+#define PRIMARY_CH      (ADE_CH1)
+
+struct ade_crtc {
+       struct hisi_crtc base;
+};
+
 struct ade_hardware_context {
        void __iomem  *base;
        void __iomem  *media_base;
@@ -30,6 +40,8 @@ struct ade_hardware_context {
 };

 struct hisi_ade {
+       struct ade_crtc acrtc;
+       struct hisi_plane hplane[ADE_CH_NUM];
        struct ade_hardware_context ctx;
 };

@@ -99,6 +111,38 @@ static int ade_dts_parse(struct platform_device *pdev,

 static int ade_bind(struct device *dev, struct device *master, void *data)
 {
+       struct hisi_ade *ade = dev_get_drvdata(dev);
+       struct ade_hardware_context *ctx = &ade->ctx;
+       struct hisi_crtc *hcrtc = &ade->acrtc.base;
+       struct drm_device *drm_dev = (struct drm_device *)data;
+       struct hisi_plane *hplane;
+       enum drm_plane_type type;
+       int ret;
+       int i;
+
+       /*
+        * plane init
+        * TODO: Now only support primary plane, overlay planes
+        * need to do.
+        */
+       for (i = 0; i < 1; i++) {
+               hplane = &ade->hplane[i];
+               hplane->ch = i;
+               hplane->ctx = ctx;
+               type = i == PRIMARY_CH ? DRM_PLANE_TYPE_PRIMARY :
+                       DRM_PLANE_TYPE_OVERLAY;
+
+               ret = hisi_drm_plane_init(drm_dev, hplane, type);
+               if (ret)
+                       return ret;
+       }
+
+       /* crtc init */
+       hcrtc->ctx = ctx;
+       ret = hisi_drm_crtc_init(drm_dev, hcrtc, &ade->hplane[PRIMARY_CH].base);
+       if (ret)
+               return ret;
+
        return 0;
 }

diff --git a/drivers/gpu/drm/hisilicon/hisi_ade_reg.h 
b/drivers/gpu/drm/hisilicon/hisi_ade_reg.h
new file mode 100644
index 0000000..bdf3c3b
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hisi_ade_reg.h
@@ -0,0 +1,27 @@
+/*
+ * Hisilicon Terminal SoCs drm driver
+ *
+ * Copyright (c) 2014-2015 Hisilicon Limited.
+ * Author: Xinwei Kong <kong.kongxinwei at hisilicon.com> for hisilicon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __HISI_ADE_REG_H__
+#define __HISI_ADE_REG_H__
+
+enum ade_channel {
+       ADE_CH1 = 0,    /* channel 1 for primary plane */
+       ADE_CH2,
+       ADE_CH3,
+       ADE_CH4,
+       ADE_CH5,
+       ADE_CH6,
+       ADE_DISP,
+       ADE_CH_NUM
+};
+
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_connector.c 
b/drivers/gpu/drm/hisilicon/hisi_drm_connector.c
new file mode 100644
index 0000000..62efdc7
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hisi_drm_connector.c
@@ -0,0 +1,90 @@
+/*
+ * Hisilicon Terminal SoCs drm driver
+ *
+ * Copyright (c) 2014-2015 Hisilicon Limited.
+ * Author: Xinwei Kong <kong.kongxinwei at hisilicon.com> for hisilicon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "hisi_drm_encoder.h"
+#include "hisi_drm_connector.h"
+
+#define to_hisi_connector(connector) \
+       container_of(connector, struct hisi_connector, connector)
+
+int hisi_drm_connector_mode_valid(struct drm_connector *connector,
+                                 struct drm_display_mode *mode)
+{
+       int ret = MODE_OK;
+
+       return ret;
+}
+
+struct drm_encoder *
+hisi_drm_best_encoder(struct drm_connector *connector)
+{
+       struct hisi_connector *hconnector = to_hisi_connector(connector);
+       struct drm_encoder *encoder = hconnector->encoder;
+
+       return encoder;
+}
+
+int hisi_drm_get_modes(struct drm_connector *connector)
+{
+       int count = 0;
+
+       return count;
+}
+
+static struct drm_connector_helper_funcs hisi_drm_connector_helper_funcs = {
+       .get_modes = hisi_drm_get_modes,
+       .best_encoder =  hisi_drm_best_encoder,
+       .mode_valid = hisi_drm_connector_mode_valid,
+};
+
+void hisi_drm_connector_destroy(struct drm_connector *connector)
+{
+       drm_connector_unregister(connector);
+       drm_connector_cleanup(connector);
+}
+
+enum drm_connector_status
+hisi_drm_detect(struct drm_connector *connector, bool force)
+{
+       enum drm_connector_status status = connector_status_unknown;
+
+       return status;
+}
+
+static struct drm_connector_funcs hisi_drm_connector_funcs = {
+       .dpms = drm_atomic_helper_connector_dpms,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .detect = hisi_drm_detect,
+       .destroy = hisi_drm_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,
+};
+
+void hisi_drm_connector_init(struct drm_device *dev,
+                            struct drm_encoder *encoder,
+                            struct drm_connector *connector)
+{
+       connector->polled = DRM_CONNECTOR_POLL_HPD;
+       connector->dpms = DRM_MODE_DPMS_OFF;
+       drm_connector_init(encoder->dev, connector, &hisi_drm_connector_funcs,
+                          DRM_MODE_CONNECTOR_HDMIA);
+       drm_connector_helper_add(connector, &hisi_drm_connector_helper_funcs);
+       drm_connector_register(connector);
+       drm_mode_connector_attach_encoder(connector, encoder);
+
+       drm_mode_config_reset(dev);
+}
diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_connector.h 
b/drivers/gpu/drm/hisilicon/hisi_drm_connector.h
new file mode 100644
index 0000000..114391c
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hisi_drm_connector.h
@@ -0,0 +1,25 @@
+/*
+ * Hisilicon Terminal SoCs drm driver
+ *
+ * Copyright (c) 2014-2015 Hisilicon Limited.
+ * Author: Xinwei Kong <kong.kongxinwei at hisilicon.com> for hisilicon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __HISI_DRM_CONNECTOR_H__
+#define __HISI_DRM_CONNECTOR_H__
+
+struct hisi_connector {
+       struct drm_connector connector;
+       struct drm_encoder *encoder;
+};
+
+void hisi_drm_connector_init(struct drm_device *dev,
+                            struct drm_encoder *encoder,
+                            struct drm_connector *connector);
+
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_crtc.c 
b/drivers/gpu/drm/hisilicon/hisi_drm_crtc.c
new file mode 100644
index 0000000..ad13614
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hisi_drm_crtc.c
@@ -0,0 +1,179 @@
+/*
+ * Hisilicon Terminal SoCs drm driver
+ *
+ * Copyright (c) 2014-2015 Hisilicon Limited.
+ * Author: Xinwei Kong <kong.kongxinwei at hisilicon.com> for hisilicon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "hisi_drm_drv.h"
+#include "hisi_drm_crtc.h"
+
+static void  hisi_drm_crtc_enable(struct drm_crtc *crtc)
+{
+}
+
+static void hisi_drm_crtc_disable(struct drm_crtc *crtc)
+{
+}
+
+static void hisi_drm_crtc_mode_prepare(struct drm_crtc *crtc)
+{
+}
+
+static bool hisi_drm_crtc_mode_fixup(struct drm_crtc *crtc,
+                                    const struct drm_display_mode *mode,
+                                    struct drm_display_mode *adj_mode)
+{
+       bool ret = true;
+
+       return ret;
+}
+
+static void hisi_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+}
+
+static void hisi_crtc_atomic_begin(struct drm_crtc *crtc)
+{
+}
+
+static void hisi_crtc_atomic_flush(struct drm_crtc *crtc)
+{
+}
+
+static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
+       .enable         = hisi_drm_crtc_enable,
+       .disable        = hisi_drm_crtc_disable,
+       .prepare        = hisi_drm_crtc_mode_prepare,
+       .mode_fixup     = hisi_drm_crtc_mode_fixup,
+       .mode_set_nofb  = hisi_drm_crtc_mode_set_nofb,
+       .atomic_begin   = hisi_crtc_atomic_begin,
+       .atomic_flush   = hisi_crtc_atomic_flush,
+};
+
+static void hisi_drm_crtc_destroy(struct drm_crtc *c)
+{
+       drm_crtc_cleanup(c);
+}
+
+static void hisi_crtc_atomic_reset(struct drm_crtc *crtc)
+{
+       struct hisi_crtc_state *state;
+
+       if (crtc->state)
+               kfree(to_hisi_crtc_state(crtc->state));
+
+       state = kzalloc(sizeof(*state), GFP_KERNEL);
+       if (!state)
+               return;
+
+       /* set to default value */
+       state->comp_type = COMPOSITION_UNKNOWN;
+
+       crtc->state = &state->base;
+       crtc->state->crtc = crtc;
+}
+
+static struct drm_crtc_state *
+hisi_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
+{
+       struct hisi_crtc_state *state;
+       struct hisi_crtc_state *copy;
+
+       if (WARN_ON(!crtc->state))
+               return NULL;
+
+       state = to_hisi_crtc_state(crtc->state);
+       copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
+       if (!copy)
+               return NULL;
+
+       __drm_atomic_helper_crtc_duplicate_state(crtc, &copy->base);
+
+       return &copy->base;
+}
+
+static void hisi_crtc_atomic_destroy_state(struct drm_crtc *crtc,
+                                          struct drm_crtc_state *state)
+{
+       __drm_atomic_helper_crtc_destroy_state(crtc, state);
+       kfree(to_hisi_crtc_state(state));
+}
+
+static int hisi_crtc_atomic_set_property(struct drm_crtc *crtc,
+                                        struct drm_crtc_state *state,
+                                        struct drm_property *property,
+                                        uint64_t val)
+{
+       struct hisi_drm_private *priv = crtc->dev->dev_private;
+       struct hisi_crtc_state *hstate = to_hisi_crtc_state(state);
+
+       if (property == priv->comp_type_prop)
+               hstate->comp_type = val;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static int hisi_crtc_atomic_get_property(struct drm_crtc *crtc,
+                                        const struct drm_crtc_state *state,
+                                        struct drm_property *property,
+                                        uint64_t *val)
+{
+       struct hisi_drm_private *priv = crtc->dev->dev_private;
+       struct hisi_crtc_state *hstate = to_hisi_crtc_state(state);
+
+       if (property == priv->comp_type_prop)
+               *val =  hstate->comp_type;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static const struct drm_crtc_funcs crtc_funcs = {
+       .destroy        = hisi_drm_crtc_destroy,
+       .set_config     = drm_atomic_helper_set_config,
+       .page_flip      = drm_atomic_helper_page_flip,
+       .reset          = hisi_crtc_atomic_reset,
+       .set_property = drm_atomic_helper_crtc_set_property,
+       .atomic_duplicate_state = hisi_crtc_atomic_duplicate_state,
+       .atomic_destroy_state   = hisi_crtc_atomic_destroy_state,
+       .atomic_set_property = hisi_crtc_atomic_set_property,
+       .atomic_get_property = hisi_crtc_atomic_get_property,
+};
+
+int hisi_drm_crtc_init(struct drm_device *dev,
+                      struct hisi_crtc *hcrtc,
+                      struct drm_plane *plane)
+{
+       struct hisi_crtc_ops *ops = hcrtc->ops;
+       int ret;
+
+       ret = drm_crtc_init_with_planes(dev, &hcrtc->base, plane,
+                                       NULL, &crtc_funcs);
+       if (ret) {
+               DRM_ERROR("failed to init crtc.\n");
+               return ret;
+       }
+
+       drm_crtc_helper_add(&hcrtc->base, &crtc_helper_funcs);
+
+       if (ops->install_properties) {
+               ret = ops->install_properties(dev, hcrtc);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_crtc.h 
b/drivers/gpu/drm/hisilicon/hisi_drm_crtc.h
new file mode 100644
index 0000000..989cb1f
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hisi_drm_crtc.h
@@ -0,0 +1,45 @@
+/*
+ * Hisilicon Terminal SoCs drm driver
+ *
+ * Copyright (c) 2014-2015 Hisilicon Limited.
+ * Author: Xinwei Kong <kong.kongxinwei at hisilicon.com> for hisilicon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __HISI_DRM_CRTC_H__
+#define __HISI_DRM_CRTC_H__
+
+#define to_hisi_crtc_state(state) \
+               container_of(state, struct hisi_crtc_state, base)
+
+enum composotion_type {
+       COMPOSITION_UNKNOWN     = 0,
+       COMPOSITION_GLES        = 1,
+       COMPOSITION_HWC         = 2,
+       COMPOSITION_MIXED       = 3
+};
+
+struct hisi_crtc {
+       struct drm_crtc base;
+       void *ops;
+       void *ctx;
+};
+
+struct hisi_crtc_ops {
+       int (*install_properties)(struct drm_device *dev,
+                                 struct hisi_crtc *hcrtc);
+};
+
+struct hisi_crtc_state {
+       struct drm_crtc_state base;
+       u8 comp_type;
+};
+
+int hisi_drm_crtc_init(struct drm_device *dev, struct hisi_crtc *crtc,
+                      struct drm_plane *plane);
+
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_drv.h 
b/drivers/gpu/drm/hisilicon/hisi_drm_drv.h
new file mode 100644
index 0000000..0b96357
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hisi_drm_drv.h
@@ -0,0 +1,36 @@
+/*
+ * Hisilicon Terminal SoCs drm driver
+ *
+ * Copyright (c) 2014-2015 Hisilicon Limited.
+ * Author:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __HISI_DRM_DRV_H__
+#define __HISI_DRM_DRV_H__
+
+struct hisi_drm_private {
+       struct hisi_drm_fbdev   *fbdev;
+
+       /* plane properties */
+       struct drm_property *zpos_prop;
+       struct drm_property *alpha_prop;
+       struct drm_property *blend_prop;
+
+       /*
+       * read only capabilities properties
+       * 0: unsupport
+       * 1: support
+       */
+       struct drm_property *cap_scl_prop;
+       struct drm_property *cap_rot_prop;
+
+       /* crtc properties */
+       struct drm_property *comp_type_prop;
+};
+
+#endif /* __HISI_DRM_DRV_H__ */
diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c 
b/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
index a8dbaad..046fd8e 100644
--- a/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
@@ -16,9 +16,15 @@
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_encoder_slave.h>

+#include "hisi_drm_encoder.h"
+#include "hisi_drm_connector.h"
+
 #define DSI_24BITS_1               (5)

 struct hisi_dsi {
+       struct hisi_encoder hisi_encoder;
+       struct hisi_connector hisi_connector;
+
        u32 lanes;
        u32 format;
        u32 date_enable_pol;
@@ -39,8 +45,15 @@ struct hisi_dsi_context {
 static int hisi_dsi_bind(struct device *dev, struct device *master,
                         void *data)
 {
+       struct hisi_dsi_context *ctx = dev_get_drvdata(dev);
        int ret = 0;

+       ctx->dev = data;
+
+       hisi_drm_encoder_init(ctx->dev, &ctx->dsi.hisi_encoder.base.base);
+
+       hisi_drm_connector_init(ctx->dev, &ctx->dsi.hisi_encoder.base.base,
+                               &ctx->dsi.hisi_connector.connector);
        return ret;
 }

diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_encoder.c 
b/drivers/gpu/drm/hisilicon/hisi_drm_encoder.c
new file mode 100644
index 0000000..89fc73d
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hisi_drm_encoder.c
@@ -0,0 +1,65 @@
+/*
+ * Hisilicon Terminal SoCs drm driver
+ *
+ * Copyright (c) 2014-2015 Hisilicon Limited.
+ * Author: Xinwei Kong <kong.kongxinwei at hisilicon.com> for hisilicon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder_slave.h>
+
+#include "hisi_drm_encoder.h"
+
+void hisi_drm_encoder_disable(struct drm_encoder *encoder)
+{
+}
+
+void hisi_drm_encoder_enable(struct drm_encoder *encoder)
+{
+}
+
+void hisi_drm_encoder_mode_set(struct drm_encoder *encoder,
+                              struct drm_display_mode *mode,
+                              struct drm_display_mode *adjusted_mode)
+{
+}
+
+bool
+hisi_drm_encoder_mode_fixup(struct drm_encoder *encoder,
+                           const struct drm_display_mode *mode,
+                           struct drm_display_mode *adjusted_mode)
+{
+       bool ret = true;
+
+       return ret;
+}
+
+void hisi_drm_encoder_destroy(struct drm_encoder *encoder)
+{
+}
+
+static struct drm_encoder_helper_funcs hisi_encoder_helper_funcs = {
+       .mode_fixup     = hisi_drm_encoder_mode_fixup,
+       .mode_set       = hisi_drm_encoder_mode_set,
+       .enable         = hisi_drm_encoder_enable,
+       .disable        = hisi_drm_encoder_disable
+};
+
+static struct drm_encoder_funcs hisi_encoder_funcs = {
+       .destroy = hisi_drm_encoder_destroy
+};
+
+void hisi_drm_encoder_init(struct drm_device *dev,
+                          struct drm_encoder *encoder)
+{
+       encoder->possible_crtcs = 1;
+
+       drm_encoder_init(dev, encoder, &hisi_encoder_funcs,
+                        DRM_MODE_ENCODER_TMDS);
+       drm_encoder_helper_add(encoder, &hisi_encoder_helper_funcs);
+}
diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_encoder.h 
b/drivers/gpu/drm/hisilicon/hisi_drm_encoder.h
new file mode 100644
index 0000000..31c04e4
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hisi_drm_encoder.h
@@ -0,0 +1,22 @@
+/*
+ * Hisilicon Terminal SoCs drm driver
+ *
+ * Copyright (c) 2014-2015 Hisilicon Limited.
+ * Author: Xinwei Kong <kong.kongxinwei at hisilicon.com> for hisilicon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __HISI_DRM_ENCODER_H__
+#define __HISI_DRM_ENCODER_H__
+
+struct hisi_encoder {
+       struct drm_encoder_slave base;
+};
+
+void hisi_drm_encoder_init(struct drm_device *dev, struct drm_encoder 
*encoder);
+
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_plane.c 
b/drivers/gpu/drm/hisilicon/hisi_drm_plane.c
new file mode 100644
index 0000000..af040b6
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hisi_drm_plane.c
@@ -0,0 +1,240 @@
+/*
+ * Hisilicon Terminal SoCs drm driver
+ *
+ * Copyright (c) 2014-2015 Hisilicon Limited.
+ * Author: Xinwei Kong <kong.kongxinwei at hisilicon.com> for hisilicon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_atomic.h>
+
+#include "hisi_drm_drv.h"
+#include "hisi_drm_plane.h"
+
+#define to_hisi_plane(plane) \
+               container_of(plane, struct hisi_plane, base)
+
+static void hisi_plane_atomic_disable(struct drm_plane *plane,
+                                     struct drm_plane_state *old_state)
+{
+}
+
+static void hisi_plane_atomic_update(struct drm_plane *plane,
+                                    struct drm_plane_state *old_state)
+{
+}
+
+int hisi_plane_atomic_check(struct drm_plane *plane,
+                           struct drm_plane_state *state)
+{
+       struct drm_framebuffer *fb = state->fb;
+       struct drm_crtc *crtc = state->crtc;
+       struct drm_crtc_state *crtc_state;
+       u32 src_x = state->src_x >> 16;
+       u32 src_y = state->src_y >> 16;
+       u32 src_w = state->src_w >> 16;
+       u32 src_h = state->src_h >> 16;
+       u32 crtc_w = state->crtc_w;
+       u32 crtc_h = state->crtc_h;
+       int crtc_x = state->crtc_x;
+       int crtc_y = state->crtc_y;
+
+       if (!crtc || !fb)
+               return 0;
+
+       if (state->rotation != BIT(DRM_ROTATE_0)) {
+               DRM_ERROR("Rotation not support!!!\n");
+               return -EINVAL;
+       }
+
+       crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
+       if (IS_ERR(crtc_state))
+               return PTR_ERR(crtc_state);
+
+       if (src_w != crtc_w || src_h != crtc_h) {
+               DRM_ERROR("Scale not support!!!\n");
+               return -EINVAL;
+       }
+
+       if (src_x + src_w > fb->width ||
+           src_y + src_h > fb->height)
+               return -EINVAL;
+
+       if (crtc_x < 0 || crtc_y < 0)
+               return -EINVAL;
+
+       if (crtc_x + crtc_w > crtc_state->adjusted_mode.hdisplay ||
+           crtc_y + crtc_h > crtc_state->adjusted_mode.vdisplay)
+               return -EINVAL;
+
+       return 0;
+}
+
+void hisi_plane_cleanup_fb(struct drm_plane *plane,
+                          struct drm_framebuffer *fb,
+                          const struct drm_plane_state *old_state)
+{
+}
+
+int hisi_plane_prepare_fb(struct drm_plane *p,
+                         struct drm_framebuffer *fb,
+                         const struct drm_plane_state *new_state)
+{
+       return 0;
+}
+
+static const struct drm_plane_helper_funcs hisi_plane_helper_funcs = {
+       .prepare_fb = hisi_plane_prepare_fb,
+       .cleanup_fb = hisi_plane_cleanup_fb,
+       .atomic_check = hisi_plane_atomic_check,
+       .atomic_update = hisi_plane_atomic_update,
+       .atomic_disable = hisi_plane_atomic_disable,
+};
+
+void hisi_plane_destroy(struct drm_plane *plane)
+{
+       drm_plane_cleanup(plane);
+}
+
+static void hisi_plane_atomic_reset(struct drm_plane *plane)
+{
+       struct hisi_plane_state *state;
+
+       if (plane->state && plane->state->fb)
+               drm_framebuffer_unreference(plane->state->fb);
+
+       if (plane->state)
+               kfree(to_hisi_plane_state(plane->state));
+
+       state = kzalloc(sizeof(*state), GFP_KERNEL);
+       if (!state)
+               return;
+
+       /* set to default value */
+       state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 :
+               drm_plane_index(plane);
+       state->base.rotation = BIT(DRM_ROTATE_0);
+       state->alpha = 255;
+       state->blend = ALPHA_BLENDING_NONE;
+
+       plane->state = &state->base;
+       plane->state->plane = plane;
+}
+
+static struct drm_plane_state *
+hisi_plane_atomic_duplicate_state(struct drm_plane *plane)
+{
+       struct hisi_plane_state *hstate;
+       struct hisi_plane_state *copy;
+
+       if (WARN_ON(!plane->state))
+               return NULL;
+
+       hstate = to_hisi_plane_state(plane->state);
+       copy = kmemdup(hstate, sizeof(*hstate), GFP_KERNEL);
+       if (!copy)
+               return NULL;
+
+       __drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
+
+       return &copy->base;
+}
+
+static void hisi_plane_atomic_destroy_state(struct drm_plane *plane,
+                                           struct drm_plane_state *state)
+{
+       __drm_atomic_helper_plane_destroy_state(plane, state);
+       kfree(to_hisi_plane_state(state));
+}
+
+static int hisi_plane_atomic_set_property(struct drm_plane *plane,
+                                         struct drm_plane_state *state,
+                                         struct drm_property *property,
+                                         uint64_t val)
+{
+       struct hisi_drm_private *priv = plane->dev->dev_private;
+       struct hisi_plane_state *hstate = to_hisi_plane_state(state);
+
+       if (property == priv->zpos_prop)
+               hstate->zpos = val;
+       else if (property == priv->alpha_prop)
+               hstate->alpha = val;
+       else if (property == priv->blend_prop)
+               hstate->blend = val;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static int hisi_plane_atomic_get_property(struct drm_plane *plane,
+                                         const struct drm_plane_state *state,
+                                         struct drm_property *property,
+                                         uint64_t *val)
+{
+       struct hisi_drm_private *priv = plane->dev->dev_private;
+       const struct hisi_plane_state *hstate = to_hisi_plane_state(state);
+
+       if (property == priv->zpos_prop)
+               *val = hstate->zpos;
+       else if (property == priv->alpha_prop)
+               *val = hstate->alpha;
+       else if (property == priv->blend_prop)
+               *val = hstate->blend;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static struct drm_plane_funcs hisi_plane_funcs = {
+       .update_plane   = drm_atomic_helper_update_plane,
+       .disable_plane  = drm_atomic_helper_disable_plane,
+       .set_property = drm_atomic_helper_plane_set_property,
+       .destroy = hisi_plane_destroy,
+       .reset = hisi_plane_atomic_reset,
+       .atomic_duplicate_state = hisi_plane_atomic_duplicate_state,
+       .atomic_destroy_state = hisi_plane_atomic_destroy_state,
+       .atomic_set_property = hisi_plane_atomic_set_property,
+       .atomic_get_property = hisi_plane_atomic_get_property,
+};
+
+int hisi_drm_plane_init(struct drm_device *dev,
+                       struct hisi_plane *hplane,
+                       enum drm_plane_type type)
+{
+       struct hisi_plane_funcs *ops = hplane->ops;
+       const u32 *fmts;
+       u32 fmts_cnt;
+       int ret = 0;
+
+       /* get  properties */
+       fmts_cnt = ops->get_properties(hplane->ch, &fmts);
+       if (ret)
+               return ret;
+       ret = drm_universal_plane_init(dev, &hplane->base, 1,
+                                      &hisi_plane_funcs,
+                                      fmts, fmts_cnt, type);
+       if (ret) {
+               DRM_ERROR("fail to init plane, ch: %d\n", hplane->ch);
+               return ret;
+       }
+
+       drm_plane_helper_add(&hplane->base, &hisi_plane_helper_funcs);
+
+       /* install overlay plane properties */
+       if (type == DRM_PLANE_TYPE_OVERLAY && ops->install_properties) {
+               ret = ops->install_properties(dev, hplane);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_plane.h 
b/drivers/gpu/drm/hisilicon/hisi_drm_plane.h
new file mode 100644
index 0000000..70ee845
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hisi_drm_plane.h
@@ -0,0 +1,51 @@
+/*
+ * Hisilicon Terminal SoCs drm driver
+ *
+ * Copyright (c) 2014-2015 Hisilicon Limited.
+ * Author: Xinwei Kong <kong.kongxinwei at hisilicon.com> for hisilicon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __HISI_DRM_PLANE_H__
+#define __HISI_DRM_PLANE_H__
+
+#define to_hisi_plane_state(s)  container_of(s, struct hisi_plane_state, base)
+
+enum {
+       /* no blending */
+       ALPHA_BLENDING_NONE     = 0x0100,
+       /* ONE / ONE_MINUS_SRC_ALPHA */
+       ALPHA_BLENDING_PREMULT  = 0x0105,
+       /* SRC_ALPHA / ONE_MINUS_SRC_ALPHA */
+       ALPHA_BLENDING_COVERAGE = 0x0405
+};
+
+struct hisi_plane {
+       struct drm_plane base;
+       void *ops;
+       void *ctx;
+       u8 ch; /* channel or pipe */
+};
+
+struct hisi_plane_funcs {
+       u32 (*get_properties)(u8 ch, const u32 **formats);
+       int (*install_properties)(struct drm_device *dev,
+                                 struct hisi_plane *hplane);
+};
+
+int hisi_drm_plane_init(struct drm_device *dev, struct hisi_plane *hplane,
+                       enum drm_plane_type type);
+
+/* plane structs  */
+struct hisi_plane_state {
+       struct drm_plane_state base;
+       u8 zpos;  /* z order */
+       u8 alpha; /* Alpha value applied to the whole plane */
+       u32 blend; /* blending cases: none, premult and coverage */
+};
+
+#endif
-- 
1.9.1


Reply via email to