[PATCH RFC 3/8] drm: hisilicon: Add the link to DRM/KMS interface

Xinwei Kong kong.kongxinwei at hisilicon.com
Tue Sep 15 02:37:09 PDT 2015


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




More information about the dri-devel mailing list