devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/8] Initial Allwinner Display Engine 2.0 Support
@ 2017-03-16 20:47 Icenowy Zheng
  2017-03-16 20:47 ` [PATCH v2 1/8] dt-bindings: add binding for the Allwinner DE2 CCU Icenowy Zheng
                   ` (7 more replies)
  0 siblings, 8 replies; 12+ messages in thread
From: Icenowy Zheng @ 2017-03-16 20:47 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, Icenowy Zheng, linux-clk,
	linux-arm-kernel

This patchset is the initial patchset for Allwinner DE2 support.

It contains the support of clocks in DE2 and the mixers in DE2.

The SoC used to develop this patchset is V3s, as V3s is the simplest
one of the SoCs that have DE2.
(Allwinner V3s features only one mixer, although its clock control
unit contains support for second mixer's clock; and its only video
output is RGB LCD, which is already supported in our TCON driver)

The last patch is only a testing patch, it shouldn't be merged; and
for the patch to be really usable, the RFC fix of the TCON driver [1]
is needed.

No HDMI, TV encoder or other internal bridges' support is included
in this patchset, which makes it currently not usable on H3.

Thanks to Jean-Francois Moine and Jernej Skrabec for their efforts
to discover the internal of DE2!

[1] https://lists.freedesktop.org/archives/dri-devel/2016-December/126264.html

Icenowy Zheng (8):
  dt-bindings: add binding for the Allwinner DE2 CCU
  clk: sunxi-ng: add support for DE2 CCU
  dt-bindings: add bindings for DE2 on V3s SoC
  drm/sun4i: add support for sun8i DE2 mixers and display engines
  drm/sun4i: tcon: add support for V3s TCON
  ARM: dts: sun8i: add DE2 nodes for V3s SoC
  ARM: dts: sun8i: add pinmux for LCD pins of V3s SoC
  ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero

 .../devicetree/bindings/clock/sun8i-de2.txt        |  31 ++
 .../bindings/display/sunxi/sun4i-drm.txt           |  37 +-
 arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts      |  36 ++
 arch/arm/boot/dts/sun8i-v3s.dtsi                   |  96 +++++
 drivers/clk/sunxi-ng/Kconfig                       |   5 +
 drivers/clk/sunxi-ng/Makefile                      |   1 +
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c               | 204 +++++++++++
 drivers/clk/sunxi-ng/ccu-sun8i-de2.h               |  28 ++
 drivers/gpu/drm/sun4i/Kconfig                      |   9 +
 drivers/gpu/drm/sun4i/Makefile                     |   3 +-
 drivers/gpu/drm/sun4i/sun4i_crtc.c                 |  14 +-
 drivers/gpu/drm/sun4i/sun4i_crtc.h                 |   2 +
 drivers/gpu/drm/sun4i/sun4i_drv.c                  |   4 +-
 drivers/gpu/drm/sun4i/sun4i_drv.h                  |   1 +
 drivers/gpu/drm/sun4i/sun4i_layer.c                |  94 ++++-
 drivers/gpu/drm/sun4i/sun4i_layer.h                |   3 +
 drivers/gpu/drm/sun4i/sun4i_tcon.c                 |   7 +-
 drivers/gpu/drm/sun4i/sun8i_mixer.c                | 385 +++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_mixer.h                | 166 +++++++++
 include/dt-bindings/clock/sun8i-de2.h              |  54 +++
 include/dt-bindings/reset/sun8i-de2.h              |  50 +++
 21 files changed, 1203 insertions(+), 27 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h
 create mode 100644 include/dt-bindings/clock/sun8i-de2.h
 create mode 100644 include/dt-bindings/reset/sun8i-de2.h

-- 
2.12.0

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v2 1/8] dt-bindings: add binding for the Allwinner DE2 CCU
  2017-03-16 20:47 [PATCH v2 0/8] Initial Allwinner Display Engine 2.0 Support Icenowy Zheng
@ 2017-03-16 20:47 ` Icenowy Zheng
  2017-03-20  9:55   ` Maxime Ripard
  2017-03-16 20:47 ` [PATCH v2 2/8] clk: sunxi-ng: add support for " Icenowy Zheng
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 12+ messages in thread
From: Icenowy Zheng @ 2017-03-16 20:47 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, Icenowy Zheng, linux-clk,
	linux-arm-kernel

Allwinner "Display Engine 2.0" contains some clock controls in it.

Add them as a clock driver, and make a device tree binding.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 .../devicetree/bindings/clock/sun8i-de2.txt        | 31 ++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt

diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
new file mode 100644
index 000000000000..c19496f037a4
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
@@ -0,0 +1,31 @@
+Allwinner Display Engine 2.0 Clock Control Binding
+--------------------------------------------------
+
+Required properties :
+- compatible: must contain one of the following compatibles:
+		- "allwinner,sun8i-a83t-de2-clk"
+		- "allwinner,sun50i-a64-de2-clk"
+		- "allwinner,sun50i-h5-de2-clk"
+
+- reg: Must contain the registers base address and length
+- clocks: phandle to the clocks feeding the display engine subsystem.
+	  Three are needed:
+  - "mod": the display engine module clock
+  - "bus": the bus clock for the whole display engine subsystem
+- clock-names: Must contain the clock names described just above
+- resets: phandle to the reset control for the display engine subsystem.
+- #clock-cells : must contain 1
+- #reset-cells : must contain 1
+
+Example:
+de2_clocks: clock@01000000 {
+	compatible = "allwinner,sun50i-a64-de2-clk";
+	reg = <0x01000000 0x1c>;
+	clocks = <&ccu CLK_DE>,
+		 <&ccu CLK_BUS_DE>;
+	clock-names = "mod",
+		      "bus";
+	resets = <&ccu RST_BUS_DE>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 2/8] clk: sunxi-ng: add support for DE2 CCU
  2017-03-16 20:47 [PATCH v2 0/8] Initial Allwinner Display Engine 2.0 Support Icenowy Zheng
  2017-03-16 20:47 ` [PATCH v2 1/8] dt-bindings: add binding for the Allwinner DE2 CCU Icenowy Zheng
@ 2017-03-16 20:47 ` Icenowy Zheng
  2017-03-16 20:47 ` [PATCH v2 3/8] dt-bindings: add bindings for DE2 on V3s SoC Icenowy Zheng
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Icenowy Zheng @ 2017-03-16 20:47 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, Icenowy Zheng, linux-clk,
	linux-arm-kernel

The "Display Engine 2.0" in Allwinner newer SoCs contains a clock
management unit for its subunits, like the DE CCU in A80.

Add a sunxi-ng style driver for it.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes in v2:
- Rename sunxi-de2-ccu to sun8i-de2-ccu.

 drivers/clk/sunxi-ng/Kconfig          |   5 +
 drivers/clk/sunxi-ng/Makefile         |   1 +
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c  | 204 ++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun8i-de2.h  |  28 +++++
 include/dt-bindings/clock/sun8i-de2.h |  54 +++++++++
 include/dt-bindings/reset/sun8i-de2.h |  50 +++++++++
 6 files changed, 342 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.h
 create mode 100644 include/dt-bindings/clock/sun8i-de2.h
 create mode 100644 include/dt-bindings/reset/sun8i-de2.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index 213cf64e4fab..6f921f45c487 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -139,6 +139,11 @@ config SUN8I_V3S_CCU
 	default MACH_SUN8I
 	depends on MACH_SUN8I || COMPILE_TEST
 
+config SUN8I_DE2_CCU
+	bool "Support for the Allwinner SoCs DE2 CCU"
+	select SUNXI_CCU_DIV
+	select SUNXI_CCU_GATE
+
 config SUN9I_A80_CCU
 	bool "Support for the Allwinner A80 CCU"
 	select SUNXI_CCU_DIV
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 6feaac0c5600..8bf3afaefde4 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_SUN8I_A23_CCU)	+= ccu-sun8i-a23.o
 obj-$(CONFIG_SUN8I_A33_CCU)	+= ccu-sun8i-a33.o
 obj-$(CONFIG_SUN8I_H3_CCU)	+= ccu-sun8i-h3.o
 obj-$(CONFIG_SUN8I_V3S_CCU)	+= ccu-sun8i-v3s.o
+obj-$(CONFIG_SUN8I_DE2_CCU)	+= ccu-sun8i-de2.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80-de.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80-usb.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
new file mode 100644
index 000000000000..43d7bd15e38b
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include "ccu_common.h"
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_reset.h"
+
+#include "ccu-sun8i-de2.h"
+
+static SUNXI_CCU_GATE(bus_mixer0_clk,	"bus-mixer0",	"bus-de",
+		      0x04, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_mixer1_clk,	"bus-mixer1",	"bus-de",
+		      0x04, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_wb_clk,	"bus-wb",	"bus-de",
+		      0x04, BIT(2), 0);
+
+static SUNXI_CCU_GATE(mixer0_clk,	"mixer0",	"mixer0-div",
+		      0x00, BIT(0), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(mixer1_clk,	"mixer1",	"mixer1-div",
+		      0x00, BIT(1), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(wb_clk,		"wb",		"wb-div",
+		      0x00, BIT(2), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4,
+		   CLK_SET_RATE_PARENT);
+
+static struct ccu_common *sunxi_de2_clks[] = {
+	&mixer0_clk.common,
+	&mixer1_clk.common,
+	&wb_clk.common,
+
+	&bus_mixer0_clk.common,
+	&bus_mixer1_clk.common,
+	&bus_wb_clk.common,
+
+	&mixer0_div_clk.common,
+	&mixer1_div_clk.common,
+	&wb_div_clk.common,
+};
+
+static struct clk_hw_onecell_data sunxi_de2_hw_clks = {
+	.hws	= {
+		[CLK_MIXER0]		= &mixer0_clk.common.hw,
+		[CLK_MIXER1]		= &mixer1_clk.common.hw,
+		[CLK_WB]		= &wb_clk.common.hw,
+
+		[CLK_BUS_MIXER0]	= &bus_mixer0_clk.common.hw,
+		[CLK_BUS_MIXER1]	= &bus_mixer1_clk.common.hw,
+		[CLK_BUS_WB]		= &bus_wb_clk.common.hw,
+
+		[CLK_MIXER0_DIV]	= &mixer1_div_clk.common.hw,
+		[CLK_MIXER1_DIV]	= &mixer0_div_clk.common.hw,
+		[CLK_WB_DIV]		= &wb_div_clk.common.hw,
+	},
+	.num	= CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun8i_a83t_de2_resets[] = {
+	[RST_MIXER0]	= { 0x08, BIT(0) },
+	/*
+	 * For A83T, H3 and R40, mixer1 reset line is shared with wb, so
+	 * only RST_WB is exported here.
+	 */
+	[RST_WB]	= { 0x08, BIT(2) },
+};
+
+static struct ccu_reset_map sun50i_a64_de2_resets[] = {
+	[RST_MIXER0]	= { 0x08, BIT(0) },
+	[RST_MIXER1]	= { 0x08, BIT(1) },
+	[RST_WB]	= { 0x08, BIT(2) },
+};
+
+static const struct sunxi_ccu_desc sun8i_a83t_de2_clk_desc = {
+	.ccu_clks	= sunxi_de2_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sunxi_de2_clks),
+
+	.hw_clks	= &sunxi_de2_hw_clks,
+
+	.resets		= sun8i_a83t_de2_resets,
+	.num_resets	= ARRAY_SIZE(sun8i_a83t_de2_resets),
+};
+
+static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = {
+	.ccu_clks	= sunxi_de2_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sunxi_de2_clks),
+
+	.hw_clks	= &sunxi_de2_hw_clks,
+
+	.resets		= sun50i_a64_de2_resets,
+	.num_resets	= ARRAY_SIZE(sun50i_a64_de2_resets),
+};
+
+static int sunxi_de2_clk_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct clk *bus_clk;
+	struct reset_control *rstc;
+	void __iomem *reg;
+	const struct sunxi_ccu_desc *ccu_desc;
+	int ret;
+
+	ccu_desc = of_device_get_match_data(&pdev->dev);
+	if (!ccu_desc)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	reg = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	bus_clk = devm_clk_get(&pdev->dev, "bus");
+	if (IS_ERR(bus_clk)) {
+		ret = PTR_ERR(bus_clk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Couldn't get bus clk: %d\n", ret);
+		return ret;
+	}
+
+	rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+	if (IS_ERR(rstc)) {
+		ret = PTR_ERR(bus_clk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev,
+				"Couldn't get reset control: %d\n", ret);
+		return ret;
+	}
+
+	/* The bus clock needs to be enabled for us to access the registers */
+	ret = clk_prepare_enable(bus_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret);
+		return ret;
+	}
+
+	/* The reset control needs to be asserted for the controls to work */
+	ret = reset_control_deassert(rstc);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Couldn't deassert reset control: %d\n", ret);
+		goto err_disable_clk;
+	}
+
+	ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc);
+	if (ret)
+		goto err_assert_reset;
+
+	return 0;
+
+err_assert_reset:
+	reset_control_assert(rstc);
+err_disable_clk:
+	clk_disable_unprepare(bus_clk);
+	return ret;
+}
+
+static const struct of_device_id sunxi_de2_clk_ids[] = {
+	{
+		.compatible = "allwinner,sun8i-a83t-de2-clk",
+		.data = &sun8i_a83t_de2_clk_desc,
+	},
+	{
+		.compatible = "allwinner,sun50i-h5-de2-clk",
+		.data = &sun50i_a64_de2_clk_desc,
+	},
+	/*
+	 * The Allwinner A64 SoC needs some bit to be poke in syscon to make
+	 * DE2 really working.
+	 * So there's currently no A64 compatible here.
+	 * H5 shares the same reset line with A64, so here H5 is using the
+	 * clock description of A64.
+	 */
+	{ }
+};
+
+static struct platform_driver sunxi_de2_clk_driver = {
+	.probe	= sunxi_de2_clk_probe,
+	.driver	= {
+		.name	= "sunxi-de2-clks",
+		.of_match_table	= sunxi_de2_clk_ids,
+	},
+};
+builtin_platform_driver(sunxi_de2_clk_driver);
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.h b/drivers/clk/sunxi-ng/ccu-sun8i-de2.h
new file mode 100644
index 000000000000..ab8bcd4ba3a5
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_SUN8I_DE2_H_
+#define _CCU_SUN8I_DE2_H_
+
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/reset/sun8i-de2.h>
+
+/* Intermediary clock dividers are not exported */
+#define CLK_MIXER0_DIV	3
+#define CLK_MIXER1_DIV	4
+#define CLK_WB_DIV	5
+
+#define CLK_NUMBER	(CLK_WB + 1)
+
+#endif /* _CCU_SUN8I_DE2_H_ */
diff --git a/include/dt-bindings/clock/sun8i-de2.h b/include/dt-bindings/clock/sun8i-de2.h
new file mode 100644
index 000000000000..5fbc954d78e8
--- /dev/null
+++ b/include/dt-bindings/clock/sun8i-de2.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_SUN8I_DE2_H_
+#define _DT_BINDINGS_CLOCK_SUN8I_DE2_H_
+
+#define CLK_BUS_MIXER0		0
+#define CLK_BUS_MIXER1		1
+#define CLK_BUS_WB		2
+
+#define CLK_MIXER0		6
+#define CLK_MIXER1		7
+#define CLK_WB			8
+
+#endif /* _DT_BINDINGS_CLOCK_SUN8I_DE2_H_ */
diff --git a/include/dt-bindings/reset/sun8i-de2.h b/include/dt-bindings/reset/sun8i-de2.h
new file mode 100644
index 000000000000..b45eba4e28c8
--- /dev/null
+++ b/include/dt-bindings/reset/sun8i-de2.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_RESET_SUN8I_DE2_H_
+#define _DT_BINDINGS_RESET_SUN8I_DE2_H_
+
+#define RST_MIXER0	0
+#define RST_MIXER1	1
+#define RST_WB		2
+
+#endif /* _DT_BINDINGS_RESET_SUN8I_DE2_H_ */
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 3/8] dt-bindings: add bindings for DE2 on V3s SoC
  2017-03-16 20:47 [PATCH v2 0/8] Initial Allwinner Display Engine 2.0 Support Icenowy Zheng
  2017-03-16 20:47 ` [PATCH v2 1/8] dt-bindings: add binding for the Allwinner DE2 CCU Icenowy Zheng
  2017-03-16 20:47 ` [PATCH v2 2/8] clk: sunxi-ng: add support for " Icenowy Zheng
@ 2017-03-16 20:47 ` Icenowy Zheng
  2017-03-20  9:56   ` Maxime Ripard
  2017-03-16 20:47 ` [PATCH v2 4/8] drm/sun4i: add support for sun8i DE2 mixers and display engines Icenowy Zheng
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 12+ messages in thread
From: Icenowy Zheng @ 2017-03-16 20:47 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, Icenowy Zheng, linux-clk,
	linux-arm-kernel

Allwinner V3s SoC have a display engine which have a different pipeline
with older SoCs.

Add document for it (new compatibles and the new "mixer" part).

The paragraph of TCON is also refactored, for furtherly add TCONs in
A83T/H3/A64/H5 that have only a channel 1 (used for HDMI or TV Encoder).

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 .../bindings/display/sunxi/sun4i-drm.txt           | 37 +++++++++++++++++++---
 1 file changed, 33 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index b82c00449468..2c293247c41d 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -31,11 +31,11 @@ Required properties:
    * allwinner,sun6i-a31-tcon
    * allwinner,sun6i-a31s-tcon
    * allwinner,sun8i-a33-tcon
+   * allwinner,sun8i-v3s-tcon
  - reg: base address and size of memory-mapped region
  - interrupts: interrupt associated to this IP
- - clocks: phandles to the clocks feeding the TCON. Three are needed:
+ - clocks: phandles to the clocks feeding the TCON
    - 'ahb': the interface clocks
-   - 'tcon-ch0': The clock driving the TCON channel 0
  - resets: phandles to the reset controllers driving the encoder
    - "lcd": the reset line for the TCON channel 0
 
@@ -52,7 +52,12 @@ Required properties:
   second the block connected to the TCON channel 1 (usually the TV
   encoder)
 
-On SoCs other than the A33, there is one more clock required:
+On TCONs that have a channel 0 (currently all TCONs supported), there
+is one more clock required:
+   - 'tcon-ch0': The clock driving the TCON channel 0
+
+On TCONs that have a channel 1 (currently all TCONs except the ones in
+A33 and V3s), there is one more clock required:
    - 'tcon-ch1': The clock driving the TCON channel 1
 
 DRC
@@ -137,6 +142,26 @@ Required properties:
   Documentation/devicetree/bindings/media/video-interfaces.txt. The
   first port should be the input endpoints, the second one the outputs
 
+Display Engine 2.0 Mixer
+------------------------
+
+The DE2 mixer have many functionalities, currently only layer blending is
+supported.
+
+Required properties:
+  - compatible: value must be one of:
+    * allwinner,sun8i-v3s-de2-mixer
+  - reg: base address and size of the memory-mapped region.
+  - clocks: phandles to the clocks feeding the frontend and backend
+    * bus: the backend interface clock
+    * ram: the backend DRAM clock
+  - clock-names: the clock names mentioned above
+  - resets: phandles to the reset controllers driving the backend
+
+- ports: A ports node with endpoint definitions as defined in
+  Documentation/devicetree/bindings/media/video-interfaces.txt. The
+  first port should be the input endpoints, the second one the output
+
 
 Display Engine Pipeline
 -----------------------
@@ -151,9 +176,13 @@ Required properties:
     * allwinner,sun6i-a31-display-engine
     * allwinner,sun6i-a31s-display-engine
     * allwinner,sun8i-a33-display-engine
+    * allwinner,sun8i-v3s-display-engine
 
   - allwinner,pipelines: list of phandle to the display engine
-    frontends available.
+    pipeline entry point. For SoCs with original DE (currently
+    all SoCs supported by display engine except V3s), this
+    phandle should be a display frontend or backend; for SoCs
+    with DE2, this phandle should be a mixer.
 
 Example:
 
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 4/8] drm/sun4i: add support for sun8i DE2 mixers and display engines
  2017-03-16 20:47 [PATCH v2 0/8] Initial Allwinner Display Engine 2.0 Support Icenowy Zheng
                   ` (2 preceding siblings ...)
  2017-03-16 20:47 ` [PATCH v2 3/8] dt-bindings: add bindings for DE2 on V3s SoC Icenowy Zheng
@ 2017-03-16 20:47 ` Icenowy Zheng
  2017-03-20 10:26   ` Maxime Ripard
  2017-03-16 20:47 ` [PATCH v2 5/8] drm/sun4i: tcon: add support for V3s TCON Icenowy Zheng
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 12+ messages in thread
From: Icenowy Zheng @ 2017-03-16 20:47 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, Icenowy Zheng, linux-clk,
	linux-arm-kernel

Allwinner have a new "Display Engine 2.0" in there new SoCs, which comes
in a new "Display Engine" (mixers instead of old backends and
frontends).

Add support for the mixer on Allwinner V3s SoC; it's the simplest one.

Currently a lot of functions are still missing -- more investigations
are needed to gain enough infomation for them.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes in v2:
- Rebase on current linux-next (with Chen-Yu's some refactors)
- Removed currently broken overlay plane.

 drivers/gpu/drm/sun4i/Kconfig       |   9 +
 drivers/gpu/drm/sun4i/Makefile      |   3 +-
 drivers/gpu/drm/sun4i/sun4i_crtc.c  |  14 +-
 drivers/gpu/drm/sun4i/sun4i_crtc.h  |   2 +
 drivers/gpu/drm/sun4i/sun4i_drv.c   |   1 +
 drivers/gpu/drm/sun4i/sun4i_drv.h   |   1 +
 drivers/gpu/drm/sun4i/sun4i_layer.c |  94 +++++++--
 drivers/gpu/drm/sun4i/sun4i_layer.h |   3 +
 drivers/gpu/drm/sun4i/sun4i_tcon.c  |   2 +-
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 385 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 166 ++++++++++++++++
 11 files changed, 658 insertions(+), 22 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index a4b357db8856..0fa989f955e7 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -12,3 +12,12 @@ config DRM_SUN4I
 	  Choose this option if you have an Allwinner SoC with a
 	  Display Engine. If M is selected the module will be called
 	  sun4i-drm.
+
+config DRM_SUN4I_DE2
+	bool "Support Display Engine 2.0"
+	depends on DRM_SUN4I
+	default MACH_SUN8I
+	select SUN8I_DE2_CCU
+	help
+	  Choose this option if you have an Allwinner SoC with a
+	  "Display Engine 2.0".
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 59b757350a1f..3e7e2b2eb386 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -1,5 +1,7 @@
 sun4i-drm-y += sun4i_drv.o
 sun4i-drm-y += sun4i_framebuffer.o
+sun4i-drm-y += sun4i_backend.o
+sun4i-drm-$(CONFIG_DRM_SUN4I_DE2) += sun8i_mixer.o
 
 sun4i-tcon-y += sun4i_tcon.o
 sun4i-tcon-y += sun4i_rgb.o
@@ -8,6 +10,5 @@ sun4i-tcon-y += sun4i_crtc.o
 sun4i-tcon-y += sun4i_layer.o
 
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
-obj-$(CONFIG_DRM_SUN4I)		+= sun4i_backend.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 3c876c3a356a..bf2aa0ffd35c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -26,8 +26,8 @@
 #include <video/videomode.h>
 
 #include "sun4i_backend.h"
+#include "sun8i_mixer.h"
 #include "sun4i_crtc.h"
-#include "sun4i_drv.h"
 #include "sun4i_layer.h"
 #include "sun4i_tcon.h"
 
@@ -56,7 +56,10 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	DRM_DEBUG_DRIVER("Committing plane changes\n");
 
-	sun4i_backend_commit(scrtc->backend);
+	if (scrtc->backend)
+		sun4i_backend_commit(scrtc->backend);
+	else if (scrtc->mixer)
+		sun8i_mixer_commit(scrtc->mixer);
 
 	if (event) {
 		crtc->state->event = NULL;
@@ -136,6 +139,7 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = {
 
 struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 				   struct sun4i_backend *backend,
+				   struct sun8i_mixer *mixer,
 				   struct sun4i_tcon *tcon)
 {
 	struct sun4i_crtc *scrtc;
@@ -146,10 +150,14 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 	if (!scrtc)
 		return ERR_PTR(-ENOMEM);
 	scrtc->backend = backend;
+	scrtc->mixer = mixer;
 	scrtc->tcon = tcon;
 
 	/* Create our layers */
-	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
+	if (backend)
+		scrtc->layers = sun4i_layers_init(drm, backend);
+	else if (mixer)
+		scrtc->layers = sun8i_layers_init(drm, mixer);
 	if (IS_ERR(scrtc->layers)) {
 		dev_err(drm->dev, "Couldn't create the planes\n");
 		return NULL;
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
index 230cb8f0d601..5783579e9c3c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
@@ -18,6 +18,7 @@ struct sun4i_crtc {
 	struct drm_pending_vblank_event	*event;
 
 	struct sun4i_backend		*backend;
+	struct sun8i_mixer		*mixer;
 	struct sun4i_tcon		*tcon;
 	struct sun4i_layer		**layers;
 };
@@ -29,6 +30,7 @@ static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
 
 struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 				   struct sun4i_backend *backend,
+				   struct sun8i_mixer *mixer,
 				   struct sun4i_tcon *tcon);
 
 #endif /* _SUN4I_CRTC_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 767bbadcc85d..e78b8aaa4019 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -304,6 +304,7 @@ static const struct of_device_id sun4i_drv_of_table[] = {
 	{ .compatible = "allwinner,sun6i-a31-display-engine" },
 	{ .compatible = "allwinner,sun6i-a31s-display-engine" },
 	{ .compatible = "allwinner,sun8i-a33-display-engine" },
+	{ .compatible = "allwinner,sun8i-v3s-display-engine" },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_drv_of_table);
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h
index 5df50126ff52..00506b99816a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.h
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.h
@@ -18,6 +18,7 @@
 
 struct sun4i_drv {
 	struct sun4i_backend	*backend;
+	struct sun8i_mixer	*mixer;
 	struct sun4i_tcon	*tcon;
 
 	struct drm_fbdev_cma	*fbdev;
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index f26bde5b9117..356253142c60 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -16,49 +16,63 @@
 #include <drm/drmP.h>
 
 #include "sun4i_backend.h"
+#include "sun8i_mixer.h"
 #include "sun4i_layer.h"
 
 struct sun4i_plane_desc {
 	       enum drm_plane_type     type;
+	       /* Pipe is not used in sun8i-mixer */
 	       u8                      pipe;
 	       const uint32_t          *formats;
 	       uint32_t                nformats;
 };
 
-static int sun4i_backend_layer_atomic_check(struct drm_plane *plane,
+static int sun4i_layer_atomic_check(struct drm_plane *plane,
 					    struct drm_plane_state *state)
 {
 	return 0;
 }
 
-static void sun4i_backend_layer_atomic_disable(struct drm_plane *plane,
+static void sun4i_layer_atomic_disable(struct drm_plane *plane,
 					       struct drm_plane_state *old_state)
 {
 	struct sun4i_layer *layer = plane_to_sun4i_layer(plane);
 	struct sun4i_backend *backend = layer->backend;
+	struct sun8i_mixer *mixer = layer->mixer;
 
-	sun4i_backend_layer_enable(backend, layer->id, false);
+	if (backend)
+		sun4i_backend_layer_enable(backend, layer->id, false);
+	else if (mixer)
+		sun8i_mixer_layer_enable(mixer, layer->id, false);
 }
 
-static void sun4i_backend_layer_atomic_update(struct drm_plane *plane,
+static void sun4i_layer_atomic_update(struct drm_plane *plane,
 					      struct drm_plane_state *old_state)
 {
 	struct sun4i_layer *layer = plane_to_sun4i_layer(plane);
 	struct sun4i_backend *backend = layer->backend;
-
-	sun4i_backend_update_layer_coord(backend, layer->id, plane);
-	sun4i_backend_update_layer_formats(backend, layer->id, plane);
-	sun4i_backend_update_layer_buffer(backend, layer->id, plane);
-	sun4i_backend_layer_enable(backend, layer->id, true);
+	struct sun8i_mixer *mixer = layer->mixer;
+
+	if (backend) {
+		sun4i_backend_update_layer_coord(backend, layer->id, plane);
+		sun4i_backend_update_layer_formats(backend, layer->id, plane);
+		sun4i_backend_update_layer_buffer(backend, layer->id, plane);
+		sun4i_backend_layer_enable(backend, layer->id, true);
+	} else if (mixer) {
+		sun8i_mixer_update_layer_coord(mixer, layer->id, plane);
+		sun8i_mixer_update_layer_formats(mixer, layer->id, plane);
+		sun8i_mixer_update_layer_buffer(mixer, layer->id, plane);
+		sun8i_mixer_layer_enable(mixer, layer->id, true);
+	}
 }
 
-static struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = {
-	.atomic_check	= sun4i_backend_layer_atomic_check,
-	.atomic_disable	= sun4i_backend_layer_atomic_disable,
-	.atomic_update	= sun4i_backend_layer_atomic_update,
+static struct drm_plane_helper_funcs sun4i_layer_helper_funcs = {
+	.atomic_check	= sun4i_layer_atomic_check,
+	.atomic_disable	= sun4i_layer_atomic_disable,
+	.atomic_update	= sun4i_layer_atomic_update,
 };
 
-static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
+static const struct drm_plane_funcs sun4i_layer_funcs = {
 	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
 	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
 	.destroy		= drm_plane_cleanup,
@@ -85,6 +99,12 @@ static const uint32_t sun4i_backend_layer_formats_overlay[] = {
 	DRM_FORMAT_XRGB8888,
 };
 
+static const uint32_t sun8i_mixer_layer_formats[] = {
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_XRGB8888,
+};
+
 static const struct sun4i_plane_desc sun4i_backend_planes[] = {
 	{
 		.type = DRM_PLANE_TYPE_PRIMARY,
@@ -100,8 +120,18 @@ static const struct sun4i_plane_desc sun4i_backend_planes[] = {
 	},
 };
 
+static const struct sun4i_plane_desc sun8i_mixer_planes[] = {
+	{
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.formats = sun8i_mixer_layer_formats,
+		.nformats = ARRAY_SIZE(sun8i_mixer_layer_formats),
+	},
+	/* TODO: add support for more planes */
+};
+
 static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 						struct sun4i_backend *backend,
+						struct sun8i_mixer *mixer,
 						const struct sun4i_plane_desc *plane)
 {
 	struct sun4i_layer *layer;
@@ -113,7 +143,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 
 	/* possible crtcs are set later */
 	ret = drm_universal_plane_init(drm, &layer->plane, 0,
-				       &sun4i_backend_layer_funcs,
+				       &sun4i_layer_funcs,
 				       plane->formats, plane->nformats,
 				       plane->type, NULL);
 	if (ret) {
@@ -122,8 +152,9 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 	}
 
 	drm_plane_helper_add(&layer->plane,
-			     &sun4i_backend_layer_helper_funcs);
+			     &sun4i_layer_helper_funcs);
 	layer->backend = backend;
+	layer->mixer = mixer;
 
 	return layer;
 }
@@ -164,7 +195,7 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
 		const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i];
 		struct sun4i_layer *layer;
 
-		layer = sun4i_layer_init_one(drm, backend, plane);
+		layer = sun4i_layer_init_one(drm, backend, NULL, plane);
 		if (IS_ERR(layer)) {
 			dev_err(drm->dev, "Couldn't initialize %s plane\n",
 				i ? "overlay" : "primary");
@@ -183,3 +214,32 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
 
 	return layers;
 }
+
+struct sun4i_layer **sun8i_layers_init(struct drm_device *drm,
+				       struct sun8i_mixer *mixer)
+{
+	struct sun4i_layer **layers;
+	int i;
+
+	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
+			      sizeof(**layers), GFP_KERNEL);
+	if (!layers)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
+		const struct sun4i_plane_desc *plane = &sun8i_mixer_planes[i];
+		struct sun4i_layer *layer = layers[i];
+
+		layer = sun4i_layer_init_one(drm, NULL, mixer, plane);
+		if (IS_ERR(layer)) {
+			dev_err(drm->dev, "Couldn't initialize %s plane\n",
+				i ? "overlay" : "primary");
+			return ERR_CAST(layer);
+		};
+
+		layer->id = i;
+		layers[i] = layer;
+	};
+
+	return layers;
+}
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 4be1f0919df2..6d01215f9726 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -17,6 +17,7 @@ struct sun4i_layer {
 	struct drm_plane	plane;
 	struct sun4i_drv	*drv;
 	struct sun4i_backend	*backend;
+	struct sun8i_mixer	*mixer;
 	int			id;
 };
 
@@ -28,5 +29,7 @@ plane_to_sun4i_layer(struct drm_plane *plane)
 
 struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
 				       struct sun4i_backend *backend);
+struct sun4i_layer **sun8i_layers_init(struct drm_device *drm,
+				       struct sun8i_mixer *mixer);
 
 #endif /* _SUN4I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 3ced0b1cef6e..f4f7283f7cb2 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -528,7 +528,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		goto err_free_dotclock;
 	}
 
-	tcon->crtc = sun4i_crtc_init(drm, drv->backend, tcon);
+	tcon->crtc = sun4i_crtc_init(drm, drv->backend, drv->mixer, tcon);
 	if (IS_ERR(tcon->crtc)) {
 		dev_err(dev, "Couldn't create our CRTC\n");
 		ret = PTR_ERR(tcon->crtc);
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
new file mode 100644
index 000000000000..6fdc1a0c5d5a
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * Based on sun4i_backend.c, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include <linux/component.h>
+#include <linux/reset.h>
+#include <linux/of_device.h>
+
+#include "sun8i_mixer.h"
+#include "sun4i_drv.h"
+
+void sun8i_mixer_commit(struct sun8i_mixer *mixer)
+{
+	DRM_DEBUG_DRIVER("Committing changes\n");
+
+	regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_DBUFF,
+		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
+}
+EXPORT_SYMBOL(sun8i_mixer_commit);
+
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
+				int layer, bool enable)
+{
+	u32 val;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+
+	DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", layer, chan);
+
+	if (enable)
+		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
+	else
+		val = 0;
+
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
+
+	/* Set the alpha configuration */
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
+}
+EXPORT_SYMBOL(sun8i_mixer_layer_enable);
+
+static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
+					     u32 format, u32 *mode)
+{
+	if ((plane->type == DRM_PLANE_TYPE_PRIMARY) &&
+	    (format == DRM_FORMAT_ARGB8888))
+		format = DRM_FORMAT_XRGB8888;
+
+	switch (format) {
+	case DRM_FORMAT_ARGB8888:
+		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888;
+		break;
+
+	case DRM_FORMAT_XRGB8888:
+		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888;
+		break;
+
+	case DRM_FORMAT_RGB888:
+		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
+				     int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int i;
+
+	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
+
+	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
+		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
+				 state->crtc_w, state->crtc_h);
+		regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_SIZE,
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+		DRM_DEBUG_DRIVER("Updating blender size\n");
+		for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
+			regmap_write(mixer->regs,
+				     SUN8I_MIXER_BLEND_ATTR_INSIZE(i),
+				     SUN8I_MIXER_SIZE(state->crtc_w,
+						      state->crtc_h));
+		regmap_write(mixer->regs, SUN8I_MIXER_BLEND_OUTSIZE,
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+		DRM_DEBUG_DRIVER("Updating channel size\n");
+		regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+	}
+
+	/* Set the line width */
+	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
+		     fb->pitches[0]);
+
+	/* Set height and width */
+	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
+			 state->crtc_w, state->crtc_h);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
+		     SUN8I_MIXER_SIZE(state->crtc_w, state->crtc_h));
+
+	/* Set base coordinates */
+	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
+			 state->crtc_x, state->crtc_y);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
+		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_coord);
+
+int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
+				       int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	bool interlaced = false;
+	u32 val;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int ret;
+
+	if (plane->state->crtc)
+		interlaced = plane->state->crtc->state->adjusted_mode.flags
+			& DRM_MODE_FLAG_INTERLACE;
+
+	regmap_update_bits(mixer->regs, SUN8I_MIXER_BLEND_OUTCTL,
+			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED,
+			   interlaced ?
+			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED : 0);
+
+	DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
+			 interlaced ? "on" : "off");
+
+	ret = sun8i_mixer_drm_format_to_layer(plane, fb->format->format,
+						&val);
+	if (ret) {
+		DRM_DEBUG_DRIVER("Invalid format\n");
+		return ret;
+	}
+
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_formats);
+
+int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
+				      int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_gem_cma_object *gem;
+	dma_addr_t paddr;
+	uint32_t paddr_u32;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int bpp;
+
+	/* Get the physical address of the buffer in memory */
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+	DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
+
+	/* Compute the start of the displayed memory */
+	bpp = fb->format->cpp[0];
+	paddr = gem->paddr + fb->offsets[0];
+	paddr += (state->src_x >> 16) * bpp;
+	paddr += (state->src_y >> 16) * fb->pitches[0];
+
+	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
+
+	paddr_u32 = (uint32_t) paddr;
+
+	regmap_write(mixer->regs,
+		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
+		     paddr_u32);
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_buffer);
+
+static struct regmap_config sun8i_mixer_regmap_config = {
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+	.max_register	= 0xbffc, /* guessed */
+};
+
+static int sun8i_mixer_bind(struct device *dev, struct device *master,
+			      void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = data;
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun8i_mixer *mixer;
+	struct resource *res;
+	void __iomem *regs;
+	int i, ret;
+
+	mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
+	if (!mixer)
+		return -ENOMEM;
+	dev_set_drvdata(dev, mixer);
+	drv->mixer = mixer;
+
+	mixer->cfg = of_device_get_match_data(dev);
+	if (!mixer->cfg)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	mixer->regs = devm_regmap_init_mmio(dev, regs,
+					      &sun8i_mixer_regmap_config);
+	if (IS_ERR(mixer->regs)) {
+		dev_err(dev, "Couldn't create the mixer regmap\n");
+		return PTR_ERR(mixer->regs);
+	}
+
+	mixer->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(mixer->reset)) {
+		dev_err(dev, "Couldn't get our reset line\n");
+		return PTR_ERR(mixer->reset);
+	}
+
+	ret = reset_control_deassert(mixer->reset);
+	if (ret) {
+		dev_err(dev, "Couldn't deassert our reset line\n");
+		return ret;
+	}
+
+	mixer->bus_clk = devm_clk_get(dev, "bus");
+	if (IS_ERR(mixer->bus_clk)) {
+		dev_err(dev, "Couldn't get the mixer bus clock\n");
+		ret = PTR_ERR(mixer->bus_clk);
+		goto err_assert_reset;
+	}
+	clk_prepare_enable(mixer->bus_clk);
+
+	mixer->mod_clk = devm_clk_get(dev, "mod");
+	if (IS_ERR(mixer->mod_clk)) {
+		dev_err(dev, "Couldn't get the mixer module clock\n");
+		ret = PTR_ERR(mixer->mod_clk);
+		goto err_disable_bus_clk;
+	}
+	clk_prepare_enable(mixer->mod_clk);
+
+	/* Reset the registers */
+	for (i = 0x0; i < 0x20000; i += 4)
+		regmap_write(mixer->regs, i, 0);
+
+	/* Enable the mixer */
+	regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_CTL,
+		     SUN8I_MIXER_GLOBAL_CTL_RT_EN);
+
+	/* Initialize blender */
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
+		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_PREMULTIPLY,
+		     SUN8I_MIXER_BLEND_PREMULTIPLY_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_BKCOLOR,
+		     SUN8I_MIXER_BLEND_BKCOLOR_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(0),
+		     SUN8I_MIXER_BLEND_MODE_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(1),
+		     SUN8I_MIXER_BLEND_MODE_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_CK_CTL,
+		     SUN8I_MIXER_BLEND_CK_CTL_DEF);
+
+	for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
+		regmap_write(mixer->regs,
+			     SUN8I_MIXER_BLEND_ATTR_FCOLOR(i),
+			     SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF);
+
+	/* Select the first UI channel */
+	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n",
+			 mixer->cfg->vi_num);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_ROUTE,
+		     mixer->cfg->vi_num);
+
+	return 0;
+
+	clk_disable_unprepare(mixer->mod_clk);
+err_disable_bus_clk:
+	clk_disable_unprepare(mixer->bus_clk);
+err_assert_reset:
+	reset_control_assert(mixer->reset);
+	return ret;
+}
+
+static void sun8i_mixer_unbind(struct device *dev, struct device *master,
+				 void *data)
+{
+	struct sun8i_mixer *mixer = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(mixer->mod_clk);
+	clk_disable_unprepare(mixer->bus_clk);
+	reset_control_assert(mixer->reset);
+}
+
+static const struct component_ops sun8i_mixer_ops = {
+	.bind	= sun8i_mixer_bind,
+	.unbind	= sun8i_mixer_unbind,
+};
+
+static int sun8i_mixer_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &sun8i_mixer_ops);
+}
+
+static int sun8i_mixer_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &sun8i_mixer_ops);
+
+	return 0;
+}
+
+static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
+	.vi_num = 2,
+	.ui_num = 1,
+};
+
+static const struct of_device_id sun8i_mixer_of_table[] = {
+	{
+		.compatible = "allwinner,sun8i-v3s-de2-mixer",
+		.data = &sun8i_v3s_mixer_cfg
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);
+
+static struct platform_driver sun8i_mixer_platform_driver = {
+	.probe		= sun8i_mixer_probe,
+	.remove		= sun8i_mixer_remove,
+	.driver		= {
+		.name		= "sun8i-mixer",
+		.of_match_table	= sun8i_mixer_of_table,
+	},
+};
+module_platform_driver(sun8i_mixer_platform_driver);
+
+MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.xyz>");
+MODULE_DESCRIPTION("Allwinner DE2 Mixer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
new file mode 100644
index 000000000000..97184c328bdf
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN8I_MIXER_H_
+#define _SUN8I_MIXER_H_
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include "sun4i_layer.h"
+
+#define SUN8I_MIXER_MAX_CHAN_COUNT		4
+
+#define SUN8I_MIXER_SIZE(w, h)			(((h) - 1) << 16 | ((w) - 1))
+#define SUN8I_MIXER_COORD(x, y)			((y) << 16 | (x))
+
+#define SUN8I_MIXER_GLOBAL_CTL			0x0
+#define SUN8I_MIXER_GLOBAL_STATUS		0x4
+#define SUN8I_MIXER_GLOBAL_DBUFF		0x8
+#define SUN8I_MIXER_GLOBAL_SIZE			0xc
+
+#define SUN8I_MIXER_GLOBAL_CTL_RT_EN		0x1
+
+#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE		0x1
+
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL		0x1000
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x)	(0x1004 + 0x10 * (x) + 0x0)
+#define SUN8I_MIXER_BLEND_ATTR_INSIZE(x)	(0x1004 + 0x10 * (x) + 0x4)
+#define SUN8I_MIXER_BLEND_ATTR_OFFSET(x)	(0x1004 + 0x10 * (x) + 0x8)
+#define SUN8I_MIXER_BLEND_ROUTE			0x1080
+#define SUN8I_MIXER_BLEND_PREMULTIPLY		0x1084
+#define SUN8I_MIXER_BLEND_BKCOLOR		0x1088
+#define SUN8I_MIXER_BLEND_OUTSIZE		0x108c
+#define SUN8I_MIXER_BLEND_MODE(x)		(0x1090 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_CK_CTL		0x10b0
+#define SUN8I_MIXER_BLEND_CK_CFG		0x10b4
+#define SUN8I_MIXER_BLEND_CK_MAX(x)		(0x10c0 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_CK_MIN(x)		(0x10e0 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_OUTCTL		0x10fc
+
+/* The following numbers are some still unknown magic numbers */
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF	0xff000000
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF	0x00000101
+#define SUN8I_MIXER_BLEND_PREMULTIPLY_DEF	0x0
+#define SUN8I_MIXER_BLEND_BKCOLOR_DEF		0xff000000
+#define SUN8I_MIXER_BLEND_MODE_DEF		0x03010301
+#define SUN8I_MIXER_BLEND_CK_CTL_DEF		0x0
+
+#define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED	BIT(1)
+
+/*
+ * VI channels are not used now, but the support of them may be introduced in
+ * the future.
+ */
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
+#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
+#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
+#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
+#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
+#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
+#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x80)
+#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x84)
+#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x2000 + 0x1000 * (ch) + 0x88)
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN		BIT(0)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK	GENMASK(2, 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK	GENMASK(11, 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK	GENMASK(31, 24)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF	(1 << 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888	(0 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888	(4 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888	(8 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF	(0xff << 24)
+
+/*
+ * These sun-engines are still unknown now, the EN registers are here only to
+ * be used to disable these sub-engines.
+ */
+#define SUN8I_MIXER_VSU_EN			0x20000
+#define SUN8I_MIXER_GSU1_EN			0x30000
+#define SUN8I_MIXER_GSU2_EN			0x40000
+#define SUN8I_MIXER_GSU3_EN			0x50000
+#define SUN8I_MIXER_FCE_EN			0xa0000
+#define SUN8I_MIXER_BWS_EN			0xa2000
+#define SUN8I_MIXER_LTI_EN			0xa4000
+#define SUN8I_MIXER_PEAK_EN			0xa6000
+#define SUN8I_MIXER_ASE_EN			0xa8000
+#define SUN8I_MIXER_FCC_EN			0xaa000
+#define SUN8I_MIXER_DCSC_EN			0xb0000
+
+struct sun8i_mixer_cfg {
+	int		vi_num;
+	int		ui_num;
+};
+
+struct sun8i_mixer {
+	struct regmap			*regs;
+
+	const struct sun8i_mixer_cfg	*cfg;
+
+	struct reset_control		*reset;
+
+	struct clk			*bus_clk;
+	struct clk			*mod_clk;
+};
+
+#if defined CONFIG_DRM_SUN4I_DE2
+void sun8i_mixer_commit(struct sun8i_mixer *mixer);
+
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
+				int layer, bool enable);
+int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
+				     int layer, struct drm_plane *plane);
+int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
+				       int layer, struct drm_plane *plane);
+int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
+				      int layer, struct drm_plane *plane);
+#else /* DRM_SUN4I_DE2 */
+static inline void sun8i_mixer_commit(struct sun8i_mixer *mixer)
+{
+}
+
+static inline void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
+					    int layer, bool enable)
+{
+}
+
+static inline int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
+						 int layer,
+						 struct drm_plane *plane)
+{
+	return -ENOENT;
+}
+
+static inline int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
+						   int layer,
+						   struct drm_plane *plane)
+{
+	return -ENOENT;
+}
+
+static inline int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
+						  int layer,
+						  struct drm_plane *plane)
+{
+	return -ENOENT;
+}
+#endif
+
+#endif /* _SUN8I_MIXER_H_ */
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 5/8] drm/sun4i: tcon: add support for V3s TCON
  2017-03-16 20:47 [PATCH v2 0/8] Initial Allwinner Display Engine 2.0 Support Icenowy Zheng
                   ` (3 preceding siblings ...)
  2017-03-16 20:47 ` [PATCH v2 4/8] drm/sun4i: add support for sun8i DE2 mixers and display engines Icenowy Zheng
@ 2017-03-16 20:47 ` Icenowy Zheng
  2017-03-16 20:47 ` [PATCH v2 6/8] ARM: dts: sun8i: add DE2 nodes for V3s SoC Icenowy Zheng
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Icenowy Zheng @ 2017-03-16 20:47 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, Icenowy Zheng, linux-clk,
	linux-arm-kernel

Allwinner V3s SoC features a TCON without channel 1.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 drivers/gpu/drm/sun4i/sun4i_drv.c  | 3 ++-
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 5 +++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index e78b8aaa4019..aad6a1a4664c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -186,7 +186,8 @@ static bool sun4i_drv_node_is_tcon(struct device_node *node)
 	return of_device_is_compatible(node, "allwinner,sun5i-a13-tcon") ||
 		of_device_is_compatible(node, "allwinner,sun6i-a31-tcon") ||
 		of_device_is_compatible(node, "allwinner,sun6i-a31s-tcon") ||
-		of_device_is_compatible(node, "allwinner,sun8i-a33-tcon");
+		of_device_is_compatible(node, "allwinner,sun8i-a33-tcon") ||
+		of_device_is_compatible(node, "allwinner,sun8i-v3s-tcon");
 }
 
 static int compare_of(struct device *dev, void *data)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index f4f7283f7cb2..110e432b766d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -613,11 +613,16 @@ static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
 	/* nothing is supported */
 };
 
+static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
+	/* nothing is supported */
+};
+
 static const struct of_device_id sun4i_tcon_of_table[] = {
 	{ .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
 	{ .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
 	{ .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
 	{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
+	{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 6/8] ARM: dts: sun8i: add DE2 nodes for V3s SoC
  2017-03-16 20:47 [PATCH v2 0/8] Initial Allwinner Display Engine 2.0 Support Icenowy Zheng
                   ` (4 preceding siblings ...)
  2017-03-16 20:47 ` [PATCH v2 5/8] drm/sun4i: tcon: add support for V3s TCON Icenowy Zheng
@ 2017-03-16 20:47 ` Icenowy Zheng
  2017-03-16 20:47 ` [PATCH v2 7/8] ARM: dts: sun8i: add pinmux for LCD pins of " Icenowy Zheng
  2017-03-16 20:47 ` [PATCH v2 8/8] ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero Icenowy Zheng
  7 siblings, 0 replies; 12+ messages in thread
From: Icenowy Zheng @ 2017-03-16 20:47 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, Icenowy Zheng, linux-clk,
	linux-arm-kernel

Allwinner V3s SoC features a "Display Engine 2.0" with only one TCON
which have RGB LCD output.

Add device nodes for it as well as the TCON.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 arch/arm/boot/dts/sun8i-v3s.dtsi | 87 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
index 71075969e5e6..3b29f11ad46a 100644
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -41,6 +41,10 @@
  */
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun8i-v3s-ccu.h>
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/reset/sun8i-v3s-ccu.h>
+#include <dt-bindings/reset/sun8i-de2.h>
 
 / {
 	#address-cells = <1>;
@@ -59,6 +63,12 @@
 		};
 	};
 
+	de: display-engine {
+		compatible = "allwinner,sun8i-v3s-display-engine";
+		allwinner,pipelines = <&de2_mixer0>;
+		status = "disabled";
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
@@ -93,6 +103,83 @@
 		#size-cells = <1>;
 		ranges;
 
+		de2_clocks: clock@01000000 {
+			compatible = "allwinner,sun50i-h5-de2-clk";
+			reg = <0x01000000 0x1c>;
+			clocks = <&ccu CLK_DE>,
+				 <&ccu CLK_BUS_DE>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&ccu RST_BUS_DE>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		de2_mixer0: mixer@01100000 {
+			compatible = "allwinner,sun8i-v3s-de2-mixer";
+			reg = <0x01100000 0x100000>;
+			clocks = <&de2_clocks CLK_MIXER0>,
+				 <&de2_clocks CLK_BUS_MIXER0>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&de2_clocks RST_MIXER0>;
+			assigned-clocks = <&de2_clocks CLK_MIXER0>;
+			assigned-clock-rates = <150000000>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				mixer0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					mixer0_out_tcon0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&tcon0_in_mixer0>;
+					};
+				};
+			};
+		};
+
+		tcon0: lcd-controller@01c0c000 {
+			compatible = "allwinner,sun8i-v3s-tcon";
+			reg = <0x01c0c000 0x1000>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_TCON0>,
+				 <&ccu CLK_TCON0>;
+			clock-names = "ahb",
+				      "tcon-ch0";
+			clock-output-names = "tcon-pixel-clock";
+			resets = <&ccu RST_BUS_TCON0>;
+			reset-names = "lcd";
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon0_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					tcon0_in_mixer0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&mixer0_out_tcon0>;
+					};
+				};
+
+				tcon0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+			};
+		};
+
+
 		mmc0: mmc@01c0f000 {
 			compatible = "allwinner,sun7i-a20-mmc";
 			reg = <0x01c0f000 0x1000>;
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 7/8] ARM: dts: sun8i: add pinmux for LCD pins of V3s SoC
  2017-03-16 20:47 [PATCH v2 0/8] Initial Allwinner Display Engine 2.0 Support Icenowy Zheng
                   ` (5 preceding siblings ...)
  2017-03-16 20:47 ` [PATCH v2 6/8] ARM: dts: sun8i: add DE2 nodes for V3s SoC Icenowy Zheng
@ 2017-03-16 20:47 ` Icenowy Zheng
  2017-03-16 20:47 ` [PATCH v2 8/8] ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero Icenowy Zheng
  7 siblings, 0 replies; 12+ messages in thread
From: Icenowy Zheng @ 2017-03-16 20:47 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, Icenowy Zheng, linux-clk,
	linux-arm-kernel

Allwinner V3s SoC features a set of pins that have functionality of RGB
LCD, the pins are at different pin ban than other SoCs.

Add pinctrl node for them.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 arch/arm/boot/dts/sun8i-v3s.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
index 3b29f11ad46a..f19258bb821b 100644
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -297,6 +297,15 @@
 				function = "i2c0";
 			};
 
+			lcd_rgb666_pins: lcd_rgb666@0 {
+				pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+				       "PE5", "PE6", "PE7", "PE8", "PE9",
+				       "PE10", "PE11", "PE12", "PE13", "PE14",
+				       "PE15", "PE16", "PE17", "PE18", "PE19",
+				       "PE23", "PE24";
+				function = "lcd";
+			};
+
 			uart0_pins_a: uart0@0 {
 				pins = "PB8", "PB9";
 				function = "uart0";
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 8/8] ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero
  2017-03-16 20:47 [PATCH v2 0/8] Initial Allwinner Display Engine 2.0 Support Icenowy Zheng
                   ` (6 preceding siblings ...)
  2017-03-16 20:47 ` [PATCH v2 7/8] ARM: dts: sun8i: add pinmux for LCD pins of " Icenowy Zheng
@ 2017-03-16 20:47 ` Icenowy Zheng
  7 siblings, 0 replies; 12+ messages in thread
From: Icenowy Zheng @ 2017-03-16 20:47 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, Icenowy Zheng, linux-clk,
	linux-arm-kernel

A 480x272 QiaoDian QD43003C0-40-7LED panel is available from Lichee Pi.

This commit connects this panel to Lichee Pi Zero.

Lichee Pi also provides a 800x480 panel without accurate model number,
so do not merge this patch. It will finally come as device tree overlay.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts | 36 +++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
index 387fc2aa546d..7ae72bf63cd0 100644
--- a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
+++ b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
@@ -75,6 +75,28 @@
 			gpios = <&pio 6 2 GPIO_ACTIVE_LOW>; /* PG2 */
 		};
 	};
+
+	panel: panel {
+		compatible = "qiaodian,qd43003c0-40", "simple-panel";
+		enable-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* Should be backlight */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			panel_input: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&tcon0_out_lcd>;
+			};
+		};
+	};
+};
+
+&de {
+	status = "okay";
 };
 
 &mmc0 {
@@ -86,6 +108,20 @@
 	status = "okay";
 };
 
+&tcon0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd_rgb666_pins>;
+	status = "okay";
+
+};
+
+&tcon0_out {
+	tcon0_out_lcd: endpoint@0 {
+		reg = <0>;
+		remote-endpoint = <&panel_input>;
+	};
+};
+
 &uart0 {
 	pinctrl-0 = <&uart0_pins_a>;
 	pinctrl-names = "default";
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 1/8] dt-bindings: add binding for the Allwinner DE2 CCU
  2017-03-16 20:47 ` [PATCH v2 1/8] dt-bindings: add binding for the Allwinner DE2 CCU Icenowy Zheng
@ 2017-03-20  9:55   ` Maxime Ripard
  0 siblings, 0 replies; 12+ messages in thread
From: Maxime Ripard @ 2017-03-20  9:55 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: devicetree, Jernej Skrabec, linux-kernel, dri-devel, Chen-Yu Tsai,
	Rob Herring, linux-clk, linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 1889 bytes --]

On Fri, Mar 17, 2017 at 04:47:41AM +0800, Icenowy Zheng wrote:
> Allwinner "Display Engine 2.0" contains some clock controls in it.
> 
> Add them as a clock driver, and make a device tree binding.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
>  .../devicetree/bindings/clock/sun8i-de2.txt        | 31 ++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
> new file mode 100644
> index 000000000000..c19496f037a4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
> @@ -0,0 +1,31 @@
> +Allwinner Display Engine 2.0 Clock Control Binding
> +--------------------------------------------------
> +
> +Required properties :
> +- compatible: must contain one of the following compatibles:
> +		- "allwinner,sun8i-a83t-de2-clk"
> +		- "allwinner,sun50i-a64-de2-clk"
> +		- "allwinner,sun50i-h5-de2-clk"
> +
> +- reg: Must contain the registers base address and length
> +- clocks: phandle to the clocks feeding the display engine subsystem.
> +	  Three are needed:
> +  - "mod": the display engine module clock
> +  - "bus": the bus clock for the whole display engine subsystem
> +- clock-names: Must contain the clock names described just above
> +- resets: phandle to the reset control for the display engine subsystem.
> +- #clock-cells : must contain 1
> +- #reset-cells : must contain 1
> +
> +Example:
> +de2_clocks: clock@01000000 {
> +	compatible = "allwinner,sun50i-a64-de2-clk";
> +	reg = <0x01000000 0x1c>;

Please use the full size of the memory area allocated to that device.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 3/8] dt-bindings: add bindings for DE2 on V3s SoC
  2017-03-16 20:47 ` [PATCH v2 3/8] dt-bindings: add bindings for DE2 on V3s SoC Icenowy Zheng
@ 2017-03-20  9:56   ` Maxime Ripard
  0 siblings, 0 replies; 12+ messages in thread
From: Maxime Ripard @ 2017-03-20  9:56 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: devicetree, Jernej Skrabec, linux-kernel, dri-devel, Chen-Yu Tsai,
	Rob Herring, linux-clk, linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 3949 bytes --]

On Fri, Mar 17, 2017 at 04:47:43AM +0800, Icenowy Zheng wrote:
> Allwinner V3s SoC have a display engine which have a different pipeline
> with older SoCs.
> 
> Add document for it (new compatibles and the new "mixer" part).
> 
> The paragraph of TCON is also refactored, for furtherly add TCONs in
> A83T/H3/A64/H5 that have only a channel 1 (used for HDMI or TV Encoder).
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
>  .../bindings/display/sunxi/sun4i-drm.txt           | 37 +++++++++++++++++++---
>  1 file changed, 33 insertions(+), 4 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> index b82c00449468..2c293247c41d 100644
> --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> @@ -31,11 +31,11 @@ Required properties:
>     * allwinner,sun6i-a31-tcon
>     * allwinner,sun6i-a31s-tcon
>     * allwinner,sun8i-a33-tcon
> +   * allwinner,sun8i-v3s-tcon
>   - reg: base address and size of memory-mapped region
>   - interrupts: interrupt associated to this IP
> - - clocks: phandles to the clocks feeding the TCON. Three are needed:
> + - clocks: phandles to the clocks feeding the TCON
>     - 'ahb': the interface clocks
> -   - 'tcon-ch0': The clock driving the TCON channel 0
>   - resets: phandles to the reset controllers driving the encoder
>     - "lcd": the reset line for the TCON channel 0
>  
> @@ -52,7 +52,12 @@ Required properties:
>    second the block connected to the TCON channel 1 (usually the TV
>    encoder)
>  
> -On SoCs other than the A33, there is one more clock required:
> +On TCONs that have a channel 0 (currently all TCONs supported), there
> +is one more clock required:
> +   - 'tcon-ch0': The clock driving the TCON channel 0
> +
> +On TCONs that have a channel 1 (currently all TCONs except the ones in
> +A33 and V3s), there is one more clock required:
>     - 'tcon-ch1': The clock driving the TCON channel 1
>  
>  DRC
> @@ -137,6 +142,26 @@ Required properties:
>    Documentation/devicetree/bindings/media/video-interfaces.txt. The
>    first port should be the input endpoints, the second one the outputs
>  
> +Display Engine 2.0 Mixer
> +------------------------
> +
> +The DE2 mixer have many functionalities, currently only layer blending is
> +supported.
> +
> +Required properties:
> +  - compatible: value must be one of:
> +    * allwinner,sun8i-v3s-de2-mixer
> +  - reg: base address and size of the memory-mapped region.
> +  - clocks: phandles to the clocks feeding the frontend and backend
> +    * bus: the backend interface clock
> +    * ram: the backend DRAM clock
> +  - clock-names: the clock names mentioned above
> +  - resets: phandles to the reset controllers driving the backend
> +
> +- ports: A ports node with endpoint definitions as defined in
> +  Documentation/devicetree/bindings/media/video-interfaces.txt. The
> +  first port should be the input endpoints, the second one the output
> +
>  
>  Display Engine Pipeline
>  -----------------------
> @@ -151,9 +176,13 @@ Required properties:
>      * allwinner,sun6i-a31-display-engine
>      * allwinner,sun6i-a31s-display-engine
>      * allwinner,sun8i-a33-display-engine
> +    * allwinner,sun8i-v3s-display-engine
>  
>    - allwinner,pipelines: list of phandle to the display engine
> -    frontends available.
> +    pipeline entry point. For SoCs with original DE (currently
> +    all SoCs supported by display engine except V3s), this
> +    phandle should be a display frontend or backend; for SoCs
> +    with DE2, this phandle should be a mixer.

In the old ones, this should never be the backend.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 4/8] drm/sun4i: add support for sun8i DE2 mixers and display engines
  2017-03-16 20:47 ` [PATCH v2 4/8] drm/sun4i: add support for sun8i DE2 mixers and display engines Icenowy Zheng
@ 2017-03-20 10:26   ` Maxime Ripard
  0 siblings, 0 replies; 12+ messages in thread
From: Maxime Ripard @ 2017-03-20 10:26 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: devicetree, Jernej Skrabec, linux-kernel, dri-devel, Chen-Yu Tsai,
	Rob Herring, linux-clk, linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 7663 bytes --]

Hi,

On Fri, Mar 17, 2017 at 04:47:44AM +0800, Icenowy Zheng wrote:
> Allwinner have a new "Display Engine 2.0" in there new SoCs, which comes
> in a new "Display Engine" (mixers instead of old backends and
> frontends).
> 
> Add support for the mixer on Allwinner V3s SoC; it's the simplest one.
> 
> Currently a lot of functions are still missing -- more investigations
> are needed to gain enough infomation for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
> Changes in v2:
> - Rebase on current linux-next (with Chen-Yu's some refactors)
> - Removed currently broken overlay plane.
> 
>  drivers/gpu/drm/sun4i/Kconfig       |   9 +
>  drivers/gpu/drm/sun4i/Makefile      |   3 +-
>  drivers/gpu/drm/sun4i/sun4i_crtc.c  |  14 +-
>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |   2 +
>  drivers/gpu/drm/sun4i/sun4i_drv.c   |   1 +
>  drivers/gpu/drm/sun4i/sun4i_drv.h   |   1 +
>  drivers/gpu/drm/sun4i/sun4i_layer.c |  94 +++++++--
>  drivers/gpu/drm/sun4i/sun4i_layer.h |   3 +
>  drivers/gpu/drm/sun4i/sun4i_tcon.c  |   2 +-
>  drivers/gpu/drm/sun4i/sun8i_mixer.c | 385 ++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/sun4i/sun8i_mixer.h | 166 ++++++++++++++++
>  11 files changed, 658 insertions(+), 22 deletions(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h
> 
> diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
> index a4b357db8856..0fa989f955e7 100644
> --- a/drivers/gpu/drm/sun4i/Kconfig
> +++ b/drivers/gpu/drm/sun4i/Kconfig
> @@ -12,3 +12,12 @@ config DRM_SUN4I
>  	  Choose this option if you have an Allwinner SoC with a
>  	  Display Engine. If M is selected the module will be called
>  	  sun4i-drm.
> +
> +config DRM_SUN4I_DE2
> +	bool "Support Display Engine 2.0"
> +	depends on DRM_SUN4I
> +	default MACH_SUN8I
> +	select SUN8I_DE2_CCU
> +	help
> +	  Choose this option if you have an Allwinner SoC with a
> +	  "Display Engine 2.0".
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index 59b757350a1f..3e7e2b2eb386 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -1,5 +1,7 @@
>  sun4i-drm-y += sun4i_drv.o
>  sun4i-drm-y += sun4i_framebuffer.o
> +sun4i-drm-y += sun4i_backend.o
> +sun4i-drm-$(CONFIG_DRM_SUN4I_DE2) += sun8i_mixer.o
>  
>  sun4i-tcon-y += sun4i_tcon.o
>  sun4i-tcon-y += sun4i_rgb.o
> @@ -8,6 +10,5 @@ sun4i-tcon-y += sun4i_crtc.o
>  sun4i-tcon-y += sun4i_layer.o
>  
>  obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
> -obj-$(CONFIG_DRM_SUN4I)		+= sun4i_backend.o
>  obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
>  obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> index 3c876c3a356a..bf2aa0ffd35c 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> @@ -26,8 +26,8 @@
>  #include <video/videomode.h>
>  
>  #include "sun4i_backend.h"
> +#include "sun8i_mixer.h"
>  #include "sun4i_crtc.h"
> -#include "sun4i_drv.h"
>  #include "sun4i_layer.h"
>  #include "sun4i_tcon.h"
>  
> @@ -56,7 +56,10 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
>  
>  	DRM_DEBUG_DRIVER("Committing plane changes\n");
>  
> -	sun4i_backend_commit(scrtc->backend);
> +	if (scrtc->backend)
> +		sun4i_backend_commit(scrtc->backend);
> +	else if (scrtc->mixer)
> +		sun8i_mixer_commit(scrtc->mixer);

As I told you already, you should be using functions pointers and just
call whatever is stored in that pointer

>  	if (event) {
>  		crtc->state->event = NULL;
> @@ -136,6 +139,7 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = {
>  
>  struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  				   struct sun4i_backend *backend,
> +				   struct sun8i_mixer *mixer,
>  				   struct sun4i_tcon *tcon)
>  {
>  	struct sun4i_crtc *scrtc;
> @@ -146,10 +150,14 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	if (!scrtc)
>  		return ERR_PTR(-ENOMEM);
>  	scrtc->backend = backend;
> +	scrtc->mixer = mixer;
>  	scrtc->tcon = tcon;
>  
>  	/* Create our layers */
> -	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
> +	if (backend)
> +		scrtc->layers = sun4i_layers_init(drm, backend);
> +	else if (mixer)
> +		scrtc->layers = sun8i_layers_init(drm, mixer);

Same thing here.

>  	if (IS_ERR(scrtc->layers)) {
>  		dev_err(drm->dev, "Couldn't create the planes\n");
>  		return NULL;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
> index 230cb8f0d601..5783579e9c3c 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
> @@ -18,6 +18,7 @@ struct sun4i_crtc {
>  	struct drm_pending_vblank_event	*event;
>  
>  	struct sun4i_backend		*backend;
> +	struct sun8i_mixer		*mixer;
>  	struct sun4i_tcon		*tcon;
>  	struct sun4i_layer		**layers;
>  };
> @@ -29,6 +30,7 @@ static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
>  
>  struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  				   struct sun4i_backend *backend,
> +				   struct sun8i_mixer *mixer,
>  				   struct sun4i_tcon *tcon);
>  
>  #endif /* _SUN4I_CRTC_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
> index 767bbadcc85d..e78b8aaa4019 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_drv.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
> @@ -304,6 +304,7 @@ static const struct of_device_id sun4i_drv_of_table[] = {
>  	{ .compatible = "allwinner,sun6i-a31-display-engine" },
>  	{ .compatible = "allwinner,sun6i-a31s-display-engine" },
>  	{ .compatible = "allwinner,sun8i-a33-display-engine" },
> +	{ .compatible = "allwinner,sun8i-v3s-display-engine" },
>  	{ }
>  };
>  MODULE_DEVICE_TABLE(of, sun4i_drv_of_table);
> diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h
> index 5df50126ff52..00506b99816a 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_drv.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_drv.h
> @@ -18,6 +18,7 @@
>  
>  struct sun4i_drv {
>  	struct sun4i_backend	*backend;
> +	struct sun8i_mixer	*mixer;

I don't think you need to store the mixer pointer both in the CRTC and
the main structure.

>  	struct sun4i_tcon	*tcon;
>  
>  	struct drm_fbdev_cma	*fbdev;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
> index f26bde5b9117..356253142c60 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
> @@ -16,49 +16,63 @@
>  #include <drm/drmP.h>
>  
>  #include "sun4i_backend.h"
> +#include "sun8i_mixer.h"
>  #include "sun4i_layer.h"
>  
>  struct sun4i_plane_desc {
>  	       enum drm_plane_type     type;
> +	       /* Pipe is not used in sun8i-mixer */
>  	       u8                      pipe;
>  	       const uint32_t          *formats;
>  	       uint32_t                nformats;
>  };
>  
> -static int sun4i_backend_layer_atomic_check(struct drm_plane *plane,
> +static int sun4i_layer_atomic_check(struct drm_plane *plane,
>  					    struct drm_plane_state *state)
>  {
>  	return 0;
>  }

And there's no reason to share the layers code. The formats supported
are likely to be different, the constraints will be, and there's no
code to share at all, since the registers are not the same.

Just create a new one.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-03-20 10:26 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-03-16 20:47 [PATCH v2 0/8] Initial Allwinner Display Engine 2.0 Support Icenowy Zheng
2017-03-16 20:47 ` [PATCH v2 1/8] dt-bindings: add binding for the Allwinner DE2 CCU Icenowy Zheng
2017-03-20  9:55   ` Maxime Ripard
2017-03-16 20:47 ` [PATCH v2 2/8] clk: sunxi-ng: add support for " Icenowy Zheng
2017-03-16 20:47 ` [PATCH v2 3/8] dt-bindings: add bindings for DE2 on V3s SoC Icenowy Zheng
2017-03-20  9:56   ` Maxime Ripard
2017-03-16 20:47 ` [PATCH v2 4/8] drm/sun4i: add support for sun8i DE2 mixers and display engines Icenowy Zheng
2017-03-20 10:26   ` Maxime Ripard
2017-03-16 20:47 ` [PATCH v2 5/8] drm/sun4i: tcon: add support for V3s TCON Icenowy Zheng
2017-03-16 20:47 ` [PATCH v2 6/8] ARM: dts: sun8i: add DE2 nodes for V3s SoC Icenowy Zheng
2017-03-16 20:47 ` [PATCH v2 7/8] ARM: dts: sun8i: add pinmux for LCD pins of " Icenowy Zheng
2017-03-16 20:47 ` [PATCH v2 8/8] ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero Icenowy Zheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).