All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/23] drm/sun4i: Add A83t LVDS support
@ 2017-10-17  9:06 ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

Hi,

Here is an attempt at supporting the LVDS output in our DRM driver. This
has been tested on the A83T (with DE2), but since everything is basically
in the TCON, it should also be usable on the older SoCs with minor
modifications.

This was the occasion to refactor a bunch of things. The most notable ones
would be the documentation, and split of the UI layers in the mixer code,
and the switch to kfifo for our endpoint parsing code in the driver that
fixes an issue introduced by the switch to BFS.

Let me know what you think,
Maxime

Maxime Ripard (23):
  drm/sun4i: Implement endpoint parsing using kfifo
  drm/sun4i: Realign Makefile padding and reorder it
  drm/sun4i: tcon: Make tcon_set_mux mode argument const
  drm/sun4i: tcon: Make tcon_get_clk_delay mode argument const
  drm/sun4i: tcon: Don't rely on encoders to enable the TCON
  drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
  drm/sun4i: tcon: Move out the tcon0 common setup
  dt-bindings: panel: lvds: Document power-supply property
  drm/panel: lvds: Add support for the power-supply property
  clk: sunxi-ng: Add A83T display clocks
  drm/sun4i: Rename layers to UI planes
  drm/sun4i: sun8i: properly support UI channels
  drm/sun4i: Reorder and document DE2 mixer registers
  drm/sun4i: Create minimal multipliers and dividers
  drm/sun4i: Add LVDS support
  drm/sun4i: Add A83T support
  arm: dts: sun8i: a83t: Add display pipeline
  arm: dts: sun8i: a83t: Enable the PWM
  arm: dts: sun8i: a83t: Add LVDS pins group
  arm: dts: sun8i: a83t: Add the PWM pin group
  arm: dts: sun8i: a711: Add regulator support
  arm: dts: sun8i: a711: Enable USB OTG
  arm: dts: sun8i: a711: Enable the LCD

 Documentation/devicetree/bindings/display/panel/panel-common.txt |   6 +-
 Documentation/devicetree/bindings/display/panel/panel-lvds.txt   |   1 +-
 Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt    |   3 +-
 arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts                        | 232 +++++++++++++++++++++++++++++++++++++++++++++++++--
 arch/arm/boot/dts/sun8i-a83t.dtsi                                | 100 ++++++++++++++++++++++-
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c                             |  21 +++--
 drivers/gpu/drm/panel/panel-lvds.c                               |  23 +++++-
 drivers/gpu/drm/sun4i/Makefile                                   |  29 +++---
 drivers/gpu/drm/sun4i/sun4i_crtc.c                               |  32 ++++++-
 drivers/gpu/drm/sun4i/sun4i_dotclock.c                           |  10 +-
 drivers/gpu/drm/sun4i/sun4i_drv.c                                |  73 +++-------------
 drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c                       |   1 +-
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c                           |  15 +---
 drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c                      |   1 +-
 drivers/gpu/drm/sun4i/sun4i_lvds.c                               | 183 ++++++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_lvds.h                               |  18 ++++-
 drivers/gpu/drm/sun4i/sun4i_rgb.c                                |  29 +------
 drivers/gpu/drm/sun4i/sun4i_tcon.c                               | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
 drivers/gpu/drm/sun4i/sun4i_tcon.h                               |  50 +++++++----
 drivers/gpu/drm/sun4i/sun4i_tv.c                                 |  12 +---
 drivers/gpu/drm/sun4i/sun8i_layer.c                              | 134 +------------------------------
 drivers/gpu/drm/sun4i/sun8i_layer.h                              |  36 +--------
 drivers/gpu/drm/sun4i/sun8i_mixer.c                              |  81 ++++++++----------
 drivers/gpu/drm/sun4i/sun8i_mixer.h                              | 101 ++++++++++++----------
 drivers/gpu/drm/sun4i/sun8i_ui.c                                 | 136 ++++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun8i_ui.h                                 |  37 ++++++++-
 26 files changed, 1212 insertions(+), 478 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.h

base-commit: 5ffd95d0dc16c6491631b6ca19403c96fd3db5d5
-- 
git-series 0.9.1

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

* [PATCH 00/23] drm/sun4i: Add A83t LVDS support
@ 2017-10-17  9:06 ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Here is an attempt at supporting the LVDS output in our DRM driver. This
has been tested on the A83T (with DE2), but since everything is basically
in the TCON, it should also be usable on the older SoCs with minor
modifications.

This was the occasion to refactor a bunch of things. The most notable ones
would be the documentation, and split of the UI layers in the mixer code,
and the switch to kfifo for our endpoint parsing code in the driver that
fixes an issue introduced by the switch to BFS.

Let me know what you think,
Maxime

Maxime Ripard (23):
  drm/sun4i: Implement endpoint parsing using kfifo
  drm/sun4i: Realign Makefile padding and reorder it
  drm/sun4i: tcon: Make tcon_set_mux mode argument const
  drm/sun4i: tcon: Make tcon_get_clk_delay mode argument const
  drm/sun4i: tcon: Don't rely on encoders to enable the TCON
  drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
  drm/sun4i: tcon: Move out the tcon0 common setup
  dt-bindings: panel: lvds: Document power-supply property
  drm/panel: lvds: Add support for the power-supply property
  clk: sunxi-ng: Add A83T display clocks
  drm/sun4i: Rename layers to UI planes
  drm/sun4i: sun8i: properly support UI channels
  drm/sun4i: Reorder and document DE2 mixer registers
  drm/sun4i: Create minimal multipliers and dividers
  drm/sun4i: Add LVDS support
  drm/sun4i: Add A83T support
  arm: dts: sun8i: a83t: Add display pipeline
  arm: dts: sun8i: a83t: Enable the PWM
  arm: dts: sun8i: a83t: Add LVDS pins group
  arm: dts: sun8i: a83t: Add the PWM pin group
  arm: dts: sun8i: a711: Add regulator support
  arm: dts: sun8i: a711: Enable USB OTG
  arm: dts: sun8i: a711: Enable the LCD

 Documentation/devicetree/bindings/display/panel/panel-common.txt |   6 +-
 Documentation/devicetree/bindings/display/panel/panel-lvds.txt   |   1 +-
 Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt    |   3 +-
 arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts                        | 232 +++++++++++++++++++++++++++++++++++++++++++++++++--
 arch/arm/boot/dts/sun8i-a83t.dtsi                                | 100 ++++++++++++++++++++++-
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c                             |  21 +++--
 drivers/gpu/drm/panel/panel-lvds.c                               |  23 +++++-
 drivers/gpu/drm/sun4i/Makefile                                   |  29 +++---
 drivers/gpu/drm/sun4i/sun4i_crtc.c                               |  32 ++++++-
 drivers/gpu/drm/sun4i/sun4i_dotclock.c                           |  10 +-
 drivers/gpu/drm/sun4i/sun4i_drv.c                                |  73 +++-------------
 drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c                       |   1 +-
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c                           |  15 +---
 drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c                      |   1 +-
 drivers/gpu/drm/sun4i/sun4i_lvds.c                               | 183 ++++++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_lvds.h                               |  18 ++++-
 drivers/gpu/drm/sun4i/sun4i_rgb.c                                |  29 +------
 drivers/gpu/drm/sun4i/sun4i_tcon.c                               | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
 drivers/gpu/drm/sun4i/sun4i_tcon.h                               |  50 +++++++----
 drivers/gpu/drm/sun4i/sun4i_tv.c                                 |  12 +---
 drivers/gpu/drm/sun4i/sun8i_layer.c                              | 134 +------------------------------
 drivers/gpu/drm/sun4i/sun8i_layer.h                              |  36 +--------
 drivers/gpu/drm/sun4i/sun8i_mixer.c                              |  81 ++++++++----------
 drivers/gpu/drm/sun4i/sun8i_mixer.h                              | 101 ++++++++++++----------
 drivers/gpu/drm/sun4i/sun8i_ui.c                                 | 136 ++++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun8i_ui.h                                 |  37 ++++++++-
 26 files changed, 1212 insertions(+), 478 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.h

base-commit: 5ffd95d0dc16c6491631b6ca19403c96fd3db5d5
-- 
git-series 0.9.1

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

* [PATCH 00/23] drm/sun4i: Add A83t LVDS support
@ 2017-10-17  9:06 ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

Hi,

Here is an attempt at supporting the LVDS output in our DRM driver. This
has been tested on the A83T (with DE2), but since everything is basically
in the TCON, it should also be usable on the older SoCs with minor
modifications.

This was the occasion to refactor a bunch of things. The most notable ones
would be the documentation, and split of the UI layers in the mixer code,
and the switch to kfifo for our endpoint parsing code in the driver that
fixes an issue introduced by the switch to BFS.

Let me know what you think,
Maxime

Maxime Ripard (23):
  drm/sun4i: Implement endpoint parsing using kfifo
  drm/sun4i: Realign Makefile padding and reorder it
  drm/sun4i: tcon: Make tcon_set_mux mode argument const
  drm/sun4i: tcon: Make tcon_get_clk_delay mode argument const
  drm/sun4i: tcon: Don't rely on encoders to enable the TCON
  drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
  drm/sun4i: tcon: Move out the tcon0 common setup
  dt-bindings: panel: lvds: Document power-supply property
  drm/panel: lvds: Add support for the power-supply property
  clk: sunxi-ng: Add A83T display clocks
  drm/sun4i: Rename layers to UI planes
  drm/sun4i: sun8i: properly support UI channels
  drm/sun4i: Reorder and document DE2 mixer registers
  drm/sun4i: Create minimal multipliers and dividers
  drm/sun4i: Add LVDS support
  drm/sun4i: Add A83T support
  arm: dts: sun8i: a83t: Add display pipeline
  arm: dts: sun8i: a83t: Enable the PWM
  arm: dts: sun8i: a83t: Add LVDS pins group
  arm: dts: sun8i: a83t: Add the PWM pin group
  arm: dts: sun8i: a711: Add regulator support
  arm: dts: sun8i: a711: Enable USB OTG
  arm: dts: sun8i: a711: Enable the LCD

 Documentation/devicetree/bindings/display/panel/panel-common.txt |   6 +-
 Documentation/devicetree/bindings/display/panel/panel-lvds.txt   |   1 +-
 Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt    |   3 +-
 arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts                        | 232 +++++++++++++++++++++++++++++++++++++++++++++++++--
 arch/arm/boot/dts/sun8i-a83t.dtsi                                | 100 ++++++++++++++++++++++-
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c                             |  21 +++--
 drivers/gpu/drm/panel/panel-lvds.c                               |  23 +++++-
 drivers/gpu/drm/sun4i/Makefile                                   |  29 +++---
 drivers/gpu/drm/sun4i/sun4i_crtc.c                               |  32 ++++++-
 drivers/gpu/drm/sun4i/sun4i_dotclock.c                           |  10 +-
 drivers/gpu/drm/sun4i/sun4i_drv.c                                |  73 +++-------------
 drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c                       |   1 +-
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c                           |  15 +---
 drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c                      |   1 +-
 drivers/gpu/drm/sun4i/sun4i_lvds.c                               | 183 ++++++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_lvds.h                               |  18 ++++-
 drivers/gpu/drm/sun4i/sun4i_rgb.c                                |  29 +------
 drivers/gpu/drm/sun4i/sun4i_tcon.c                               | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
 drivers/gpu/drm/sun4i/sun4i_tcon.h                               |  50 +++++++----
 drivers/gpu/drm/sun4i/sun4i_tv.c                                 |  12 +---
 drivers/gpu/drm/sun4i/sun8i_layer.c                              | 134 +------------------------------
 drivers/gpu/drm/sun4i/sun8i_layer.h                              |  36 +--------
 drivers/gpu/drm/sun4i/sun8i_mixer.c                              |  81 ++++++++----------
 drivers/gpu/drm/sun4i/sun8i_mixer.h                              | 101 ++++++++++++----------
 drivers/gpu/drm/sun4i/sun8i_ui.c                                 | 136 ++++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun8i_ui.h                                 |  37 ++++++++-
 26 files changed, 1212 insertions(+), 478 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.h

base-commit: 5ffd95d0dc16c6491631b6ca19403c96fd3db5d5
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 01/23] drm/sun4i: Implement endpoint parsing using kfifo
  2017-10-17  9:06 ` Maxime Ripard
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

The commit da82b8785eeb ("drm/sun4i: add components in breadth first
traversal order") implemented a breadth first traversal of our device tree
nodes graph. However, it was relying on the kernel linked lists, and those
are not really safe for addition.

Indeed, in a single pipeline stage, your first stage (ie, the mixer or
fronted) will be queued, and it will be the final iteration of that list as
far as list_for_each_entry_safe is concerned. Then, during that final
iteration, we'll queue another element (the TCON or the backend) that
list_for_each_entry_safe will not account for, and we will leave the loop
without having iterated over all the elements. And since we won't have
built our components list properly, the DRM driver will be left
non-functional.

We can instead use a kfifo to queue and enqueue components in-order, as was
the original intention. This also has the benefit of removing any dynamic
allocation, making the error handling path simpler too. The only thing
we're losing is the ability to tell whether an element has already been
queued, but that was only needed to remove spurious logs, and therefore
purely cosmetic.

This means that this commit effectively reverses e8afb7b67fba ("drm/sun4i:
don't add components that are already in the queue").

Fixes: da82b8785eeb ("drm/sun4i: add components in breadth first traversal order")
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_drv.c | 71 +++++---------------------------
 1 file changed, 13 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index b5879d4620d8..a27efad9bc76 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/component.h>
+#include <linux/kfifo.h>
 #include <linux/of_graph.h>
 #include <linux/of_reserved_mem.h>
 
@@ -222,29 +223,15 @@ static int compare_of(struct device *dev, void *data)
  * matching system handles this for us.
  */
 struct endpoint_list {
-	struct device_node *node;
-	struct list_head list;
+	DECLARE_KFIFO(fifo, struct device_node *, 16);
 };
 
-static bool node_is_in_list(struct list_head *endpoints,
-			    struct device_node *node)
-{
-	struct endpoint_list *endpoint;
-
-	list_for_each_entry(endpoint, endpoints, list)
-		if (endpoint->node == node)
-			return true;
-
-	return false;
-}
-
 static int sun4i_drv_add_endpoints(struct device *dev,
-				   struct list_head *endpoints,
+				   struct endpoint_list *list,
 				   struct component_match **match,
 				   struct device_node *node)
 {
 	struct device_node *port, *ep, *remote;
-	struct endpoint_list *endpoint;
 	int count = 0;
 
 	/*
@@ -304,19 +291,7 @@ static int sun4i_drv_add_endpoints(struct device *dev,
 			}
 		}
 
-		/* skip downstream node if it is already in the queue */
-		if (node_is_in_list(endpoints, remote))
-			continue;
-
-		/* Add downstream nodes to the queue */
-		endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
-		if (!endpoint) {
-			of_node_put(remote);
-			return -ENOMEM;
-		}
-
-		endpoint->node = remote;
-		list_add_tail(&endpoint->list, endpoints);
+		kfifo_put(&list->fifo, remote);
 	}
 
 	return count;
@@ -325,10 +300,11 @@ static int sun4i_drv_add_endpoints(struct device *dev,
 static int sun4i_drv_probe(struct platform_device *pdev)
 {
 	struct component_match *match = NULL;
-	struct device_node *np = pdev->dev.of_node;
-	struct endpoint_list *endpoint, *endpoint_temp;
+	struct device_node *np = pdev->dev.of_node, *endpoint;
+	struct endpoint_list list;
 	int i, ret, count = 0;
-	LIST_HEAD(endpoints);
+
+	INIT_KFIFO(list.fifo);
 
 	for (i = 0;; i++) {
 		struct device_node *pipeline = of_parse_phandle(np,
@@ -337,31 +313,19 @@ static int sun4i_drv_probe(struct platform_device *pdev)
 		if (!pipeline)
 			break;
 
-		endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
-		if (!endpoint) {
-			ret = -ENOMEM;
-			goto err_free_endpoints;
-		}
-
-		endpoint->node = pipeline;
-		list_add_tail(&endpoint->list, &endpoints);
+		kfifo_put(&list.fifo, pipeline);
 	}
 
-	list_for_each_entry_safe(endpoint, endpoint_temp, &endpoints, list) {
+	while (kfifo_get(&list.fifo, &endpoint)) {
 		/* process this endpoint */
-		ret = sun4i_drv_add_endpoints(&pdev->dev, &endpoints, &match,
-					      endpoint->node);
+		ret = sun4i_drv_add_endpoints(&pdev->dev, &list, &match,
+					      endpoint);
 
 		/* sun4i_drv_add_endpoints can fail to allocate memory */
 		if (ret < 0)
-			goto err_free_endpoints;
+			return ret;
 
 		count += ret;
-
-		/* delete and cleanup the current entry */
-		list_del(&endpoint->list);
-		of_node_put(endpoint->node);
-		kfree(endpoint);
 	}
 
 	if (count)
@@ -370,15 +334,6 @@ static int sun4i_drv_probe(struct platform_device *pdev)
 						       match);
 	else
 		return 0;
-
-err_free_endpoints:
-	list_for_each_entry_safe(endpoint, endpoint_temp, &endpoints, list) {
-		list_del(&endpoint->list);
-		of_node_put(endpoint->node);
-		kfree(endpoint);
-	}
-
-	return ret;
 }
 
 static int sun4i_drv_remove(struct platform_device *pdev)
-- 
git-series 0.9.1

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

* [PATCH 01/23] drm/sun4i: Implement endpoint parsing using kfifo
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

The commit da82b8785eeb ("drm/sun4i: add components in breadth first
traversal order") implemented a breadth first traversal of our device tree
nodes graph. However, it was relying on the kernel linked lists, and those
are not really safe for addition.

Indeed, in a single pipeline stage, your first stage (ie, the mixer or
fronted) will be queued, and it will be the final iteration of that list as
far as list_for_each_entry_safe is concerned. Then, during that final
iteration, we'll queue another element (the TCON or the backend) that
list_for_each_entry_safe will not account for, and we will leave the loop
without having iterated over all the elements. And since we won't have
built our components list properly, the DRM driver will be left
non-functional.

We can instead use a kfifo to queue and enqueue components in-order, as was
the original intention. This also has the benefit of removing any dynamic
allocation, making the error handling path simpler too. The only thing
we're losing is the ability to tell whether an element has already been
queued, but that was only needed to remove spurious logs, and therefore
purely cosmetic.

This means that this commit effectively reverses e8afb7b67fba ("drm/sun4i:
don't add components that are already in the queue").

Fixes: da82b8785eeb ("drm/sun4i: add components in breadth first traversal order")
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_drv.c | 71 +++++---------------------------
 1 file changed, 13 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index b5879d4620d8..a27efad9bc76 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/component.h>
+#include <linux/kfifo.h>
 #include <linux/of_graph.h>
 #include <linux/of_reserved_mem.h>
 
@@ -222,29 +223,15 @@ static int compare_of(struct device *dev, void *data)
  * matching system handles this for us.
  */
 struct endpoint_list {
-	struct device_node *node;
-	struct list_head list;
+	DECLARE_KFIFO(fifo, struct device_node *, 16);
 };
 
-static bool node_is_in_list(struct list_head *endpoints,
-			    struct device_node *node)
-{
-	struct endpoint_list *endpoint;
-
-	list_for_each_entry(endpoint, endpoints, list)
-		if (endpoint->node == node)
-			return true;
-
-	return false;
-}
-
 static int sun4i_drv_add_endpoints(struct device *dev,
-				   struct list_head *endpoints,
+				   struct endpoint_list *list,
 				   struct component_match **match,
 				   struct device_node *node)
 {
 	struct device_node *port, *ep, *remote;
-	struct endpoint_list *endpoint;
 	int count = 0;
 
 	/*
@@ -304,19 +291,7 @@ static int sun4i_drv_add_endpoints(struct device *dev,
 			}
 		}
 
-		/* skip downstream node if it is already in the queue */
-		if (node_is_in_list(endpoints, remote))
-			continue;
-
-		/* Add downstream nodes to the queue */
-		endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
-		if (!endpoint) {
-			of_node_put(remote);
-			return -ENOMEM;
-		}
-
-		endpoint->node = remote;
-		list_add_tail(&endpoint->list, endpoints);
+		kfifo_put(&list->fifo, remote);
 	}
 
 	return count;
@@ -325,10 +300,11 @@ static int sun4i_drv_add_endpoints(struct device *dev,
 static int sun4i_drv_probe(struct platform_device *pdev)
 {
 	struct component_match *match = NULL;
-	struct device_node *np = pdev->dev.of_node;
-	struct endpoint_list *endpoint, *endpoint_temp;
+	struct device_node *np = pdev->dev.of_node, *endpoint;
+	struct endpoint_list list;
 	int i, ret, count = 0;
-	LIST_HEAD(endpoints);
+
+	INIT_KFIFO(list.fifo);
 
 	for (i = 0;; i++) {
 		struct device_node *pipeline = of_parse_phandle(np,
@@ -337,31 +313,19 @@ static int sun4i_drv_probe(struct platform_device *pdev)
 		if (!pipeline)
 			break;
 
-		endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
-		if (!endpoint) {
-			ret = -ENOMEM;
-			goto err_free_endpoints;
-		}
-
-		endpoint->node = pipeline;
-		list_add_tail(&endpoint->list, &endpoints);
+		kfifo_put(&list.fifo, pipeline);
 	}
 
-	list_for_each_entry_safe(endpoint, endpoint_temp, &endpoints, list) {
+	while (kfifo_get(&list.fifo, &endpoint)) {
 		/* process this endpoint */
-		ret = sun4i_drv_add_endpoints(&pdev->dev, &endpoints, &match,
-					      endpoint->node);
+		ret = sun4i_drv_add_endpoints(&pdev->dev, &list, &match,
+					      endpoint);
 
 		/* sun4i_drv_add_endpoints can fail to allocate memory */
 		if (ret < 0)
-			goto err_free_endpoints;
+			return ret;
 
 		count += ret;
-
-		/* delete and cleanup the current entry */
-		list_del(&endpoint->list);
-		of_node_put(endpoint->node);
-		kfree(endpoint);
 	}
 
 	if (count)
@@ -370,15 +334,6 @@ static int sun4i_drv_probe(struct platform_device *pdev)
 						       match);
 	else
 		return 0;
-
-err_free_endpoints:
-	list_for_each_entry_safe(endpoint, endpoint_temp, &endpoints, list) {
-		list_del(&endpoint->list);
-		of_node_put(endpoint->node);
-		kfree(endpoint);
-	}
-
-	return ret;
 }
 
 static int sun4i_drv_remove(struct platform_device *pdev)
-- 
git-series 0.9.1

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

* [PATCH 01/23] drm/sun4i: Implement endpoint parsing using kfifo
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The commit da82b8785eeb ("drm/sun4i: add components in breadth first
traversal order") implemented a breadth first traversal of our device tree
nodes graph. However, it was relying on the kernel linked lists, and those
are not really safe for addition.

Indeed, in a single pipeline stage, your first stage (ie, the mixer or
fronted) will be queued, and it will be the final iteration of that list as
far as list_for_each_entry_safe is concerned. Then, during that final
iteration, we'll queue another element (the TCON or the backend) that
list_for_each_entry_safe will not account for, and we will leave the loop
without having iterated over all the elements. And since we won't have
built our components list properly, the DRM driver will be left
non-functional.

We can instead use a kfifo to queue and enqueue components in-order, as was
the original intention. This also has the benefit of removing any dynamic
allocation, making the error handling path simpler too. The only thing
we're losing is the ability to tell whether an element has already been
queued, but that was only needed to remove spurious logs, and therefore
purely cosmetic.

This means that this commit effectively reverses e8afb7b67fba ("drm/sun4i:
don't add components that are already in the queue").

Fixes: da82b8785eeb ("drm/sun4i: add components in breadth first traversal order")
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_drv.c | 71 +++++---------------------------
 1 file changed, 13 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index b5879d4620d8..a27efad9bc76 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/component.h>
+#include <linux/kfifo.h>
 #include <linux/of_graph.h>
 #include <linux/of_reserved_mem.h>
 
@@ -222,29 +223,15 @@ static int compare_of(struct device *dev, void *data)
  * matching system handles this for us.
  */
 struct endpoint_list {
-	struct device_node *node;
-	struct list_head list;
+	DECLARE_KFIFO(fifo, struct device_node *, 16);
 };
 
-static bool node_is_in_list(struct list_head *endpoints,
-			    struct device_node *node)
-{
-	struct endpoint_list *endpoint;
-
-	list_for_each_entry(endpoint, endpoints, list)
-		if (endpoint->node == node)
-			return true;
-
-	return false;
-}
-
 static int sun4i_drv_add_endpoints(struct device *dev,
-				   struct list_head *endpoints,
+				   struct endpoint_list *list,
 				   struct component_match **match,
 				   struct device_node *node)
 {
 	struct device_node *port, *ep, *remote;
-	struct endpoint_list *endpoint;
 	int count = 0;
 
 	/*
@@ -304,19 +291,7 @@ static int sun4i_drv_add_endpoints(struct device *dev,
 			}
 		}
 
-		/* skip downstream node if it is already in the queue */
-		if (node_is_in_list(endpoints, remote))
-			continue;
-
-		/* Add downstream nodes to the queue */
-		endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
-		if (!endpoint) {
-			of_node_put(remote);
-			return -ENOMEM;
-		}
-
-		endpoint->node = remote;
-		list_add_tail(&endpoint->list, endpoints);
+		kfifo_put(&list->fifo, remote);
 	}
 
 	return count;
@@ -325,10 +300,11 @@ static int sun4i_drv_add_endpoints(struct device *dev,
 static int sun4i_drv_probe(struct platform_device *pdev)
 {
 	struct component_match *match = NULL;
-	struct device_node *np = pdev->dev.of_node;
-	struct endpoint_list *endpoint, *endpoint_temp;
+	struct device_node *np = pdev->dev.of_node, *endpoint;
+	struct endpoint_list list;
 	int i, ret, count = 0;
-	LIST_HEAD(endpoints);
+
+	INIT_KFIFO(list.fifo);
 
 	for (i = 0;; i++) {
 		struct device_node *pipeline = of_parse_phandle(np,
@@ -337,31 +313,19 @@ static int sun4i_drv_probe(struct platform_device *pdev)
 		if (!pipeline)
 			break;
 
-		endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
-		if (!endpoint) {
-			ret = -ENOMEM;
-			goto err_free_endpoints;
-		}
-
-		endpoint->node = pipeline;
-		list_add_tail(&endpoint->list, &endpoints);
+		kfifo_put(&list.fifo, pipeline);
 	}
 
-	list_for_each_entry_safe(endpoint, endpoint_temp, &endpoints, list) {
+	while (kfifo_get(&list.fifo, &endpoint)) {
 		/* process this endpoint */
-		ret = sun4i_drv_add_endpoints(&pdev->dev, &endpoints, &match,
-					      endpoint->node);
+		ret = sun4i_drv_add_endpoints(&pdev->dev, &list, &match,
+					      endpoint);
 
 		/* sun4i_drv_add_endpoints can fail to allocate memory */
 		if (ret < 0)
-			goto err_free_endpoints;
+			return ret;
 
 		count += ret;
-
-		/* delete and cleanup the current entry */
-		list_del(&endpoint->list);
-		of_node_put(endpoint->node);
-		kfree(endpoint);
 	}
 
 	if (count)
@@ -370,15 +334,6 @@ static int sun4i_drv_probe(struct platform_device *pdev)
 						       match);
 	else
 		return 0;
-
-err_free_endpoints:
-	list_for_each_entry_safe(endpoint, endpoint_temp, &endpoints, list) {
-		list_del(&endpoint->list);
-		of_node_put(endpoint->node);
-		kfree(endpoint);
-	}
-
-	return ret;
 }
 
 static int sun4i_drv_remove(struct platform_device *pdev)
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 02/23] drm/sun4i: Realign Makefile padding and reorder it
  2017-10-17  9:06 ` Maxime Ripard
  (?)
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

Some options were not padded as they should, and the order in the Makefile
was chaotic. Fix that.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/Makefile | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 43c753cafc88..af18b70ba5ed 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -1,24 +1,24 @@
-sun4i-drm-y += sun4i_drv.o
-sun4i-drm-y += sun4i_framebuffer.o
+sun4i-backend-y			+= sun4i_backend.o sun4i_layer.o
 
-sun4i-drm-hdmi-y += sun4i_hdmi_enc.o
-sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o
-sun4i-drm-hdmi-y += sun4i_hdmi_ddc_clk.o
-sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o
+sun4i-drm-y			+= sun4i_drv.o
+sun4i-drm-y			+= sun4i_framebuffer.o
 
-sun4i-tcon-y += sun4i_tcon.o
-sun4i-tcon-y += sun4i_rgb.o
-sun4i-tcon-y += sun4i_dotclock.o
-sun4i-tcon-y += sun4i_crtc.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_enc.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_i2c.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_ddc_clk.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_tmds_clk.o
 
-sun4i-backend-y += sun4i_backend.o sun4i_layer.o
+sun4i-tcon-y			+= sun4i_tcon.o
+sun4i-tcon-y			+= sun4i_rgb.o
+sun4i-tcon-y			+= sun4i_dotclock.o
+sun4i-tcon-y			+= sun4i_crtc.o
 
-sun8i-mixer-y += sun8i_mixer.o sun8i_layer.o
+sun8i-mixer-y			+= sun8i_mixer.o sun8i_layer.o
 
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
 
-obj-$(CONFIG_DRM_SUN4I_BACKEND)		+= sun4i-backend.o
+obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
 obj-$(CONFIG_DRM_SUN4I_HDMI)	+= sun4i-drm-hdmi.o
-obj-$(CONFIG_DRM_SUN8I_MIXER)		+= sun8i-mixer.o
+obj-$(CONFIG_DRM_SUN8I_MIXER)	+= sun8i-mixer.o
-- 
git-series 0.9.1

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

* [PATCH 02/23] drm/sun4i: Realign Makefile padding and reorder it
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

Some options were not padded as they should, and the order in the Makefile
was chaotic. Fix that.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/Makefile | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 43c753cafc88..af18b70ba5ed 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -1,24 +1,24 @@
-sun4i-drm-y += sun4i_drv.o
-sun4i-drm-y += sun4i_framebuffer.o
+sun4i-backend-y			+= sun4i_backend.o sun4i_layer.o
 
-sun4i-drm-hdmi-y += sun4i_hdmi_enc.o
-sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o
-sun4i-drm-hdmi-y += sun4i_hdmi_ddc_clk.o
-sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o
+sun4i-drm-y			+= sun4i_drv.o
+sun4i-drm-y			+= sun4i_framebuffer.o
 
-sun4i-tcon-y += sun4i_tcon.o
-sun4i-tcon-y += sun4i_rgb.o
-sun4i-tcon-y += sun4i_dotclock.o
-sun4i-tcon-y += sun4i_crtc.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_enc.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_i2c.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_ddc_clk.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_tmds_clk.o
 
-sun4i-backend-y += sun4i_backend.o sun4i_layer.o
+sun4i-tcon-y			+= sun4i_tcon.o
+sun4i-tcon-y			+= sun4i_rgb.o
+sun4i-tcon-y			+= sun4i_dotclock.o
+sun4i-tcon-y			+= sun4i_crtc.o
 
-sun8i-mixer-y += sun8i_mixer.o sun8i_layer.o
+sun8i-mixer-y			+= sun8i_mixer.o sun8i_layer.o
 
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
 
-obj-$(CONFIG_DRM_SUN4I_BACKEND)		+= sun4i-backend.o
+obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
 obj-$(CONFIG_DRM_SUN4I_HDMI)	+= sun4i-drm-hdmi.o
-obj-$(CONFIG_DRM_SUN8I_MIXER)		+= sun8i-mixer.o
+obj-$(CONFIG_DRM_SUN8I_MIXER)	+= sun8i-mixer.o
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 02/23] drm/sun4i: Realign Makefile padding and reorder it
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

Some options were not padded as they should, and the order in the Makefile
was chaotic. Fix that.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/Makefile | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 43c753cafc88..af18b70ba5ed 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -1,24 +1,24 @@
-sun4i-drm-y += sun4i_drv.o
-sun4i-drm-y += sun4i_framebuffer.o
+sun4i-backend-y			+= sun4i_backend.o sun4i_layer.o
 
-sun4i-drm-hdmi-y += sun4i_hdmi_enc.o
-sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o
-sun4i-drm-hdmi-y += sun4i_hdmi_ddc_clk.o
-sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o
+sun4i-drm-y			+= sun4i_drv.o
+sun4i-drm-y			+= sun4i_framebuffer.o
 
-sun4i-tcon-y += sun4i_tcon.o
-sun4i-tcon-y += sun4i_rgb.o
-sun4i-tcon-y += sun4i_dotclock.o
-sun4i-tcon-y += sun4i_crtc.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_enc.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_i2c.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_ddc_clk.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_tmds_clk.o
 
-sun4i-backend-y += sun4i_backend.o sun4i_layer.o
+sun4i-tcon-y			+= sun4i_tcon.o
+sun4i-tcon-y			+= sun4i_rgb.o
+sun4i-tcon-y			+= sun4i_dotclock.o
+sun4i-tcon-y			+= sun4i_crtc.o
 
-sun8i-mixer-y += sun8i_mixer.o sun8i_layer.o
+sun8i-mixer-y			+= sun8i_mixer.o sun8i_layer.o
 
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
 
-obj-$(CONFIG_DRM_SUN4I_BACKEND)		+= sun4i-backend.o
+obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
 obj-$(CONFIG_DRM_SUN4I_HDMI)	+= sun4i-drm-hdmi.o
-obj-$(CONFIG_DRM_SUN8I_MIXER)		+= sun8i-mixer.o
+obj-$(CONFIG_DRM_SUN8I_MIXER)	+= sun8i-mixer.o
-- 
git-series 0.9.1

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

* [PATCH 02/23] drm/sun4i: Realign Makefile padding and reorder it
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

Some options were not padded as they should, and the order in the Makefile
was chaotic. Fix that.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/Makefile | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 43c753cafc88..af18b70ba5ed 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -1,24 +1,24 @@
-sun4i-drm-y += sun4i_drv.o
-sun4i-drm-y += sun4i_framebuffer.o
+sun4i-backend-y			+= sun4i_backend.o sun4i_layer.o
 
-sun4i-drm-hdmi-y += sun4i_hdmi_enc.o
-sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o
-sun4i-drm-hdmi-y += sun4i_hdmi_ddc_clk.o
-sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o
+sun4i-drm-y			+= sun4i_drv.o
+sun4i-drm-y			+= sun4i_framebuffer.o
 
-sun4i-tcon-y += sun4i_tcon.o
-sun4i-tcon-y += sun4i_rgb.o
-sun4i-tcon-y += sun4i_dotclock.o
-sun4i-tcon-y += sun4i_crtc.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_enc.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_i2c.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_ddc_clk.o
+sun4i-drm-hdmi-y		+= sun4i_hdmi_tmds_clk.o
 
-sun4i-backend-y += sun4i_backend.o sun4i_layer.o
+sun4i-tcon-y			+= sun4i_tcon.o
+sun4i-tcon-y			+= sun4i_rgb.o
+sun4i-tcon-y			+= sun4i_dotclock.o
+sun4i-tcon-y			+= sun4i_crtc.o
 
-sun8i-mixer-y += sun8i_mixer.o sun8i_layer.o
+sun8i-mixer-y			+= sun8i_mixer.o sun8i_layer.o
 
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
 
-obj-$(CONFIG_DRM_SUN4I_BACKEND)		+= sun4i-backend.o
+obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
 obj-$(CONFIG_DRM_SUN4I_HDMI)	+= sun4i-drm-hdmi.o
-obj-$(CONFIG_DRM_SUN8I_MIXER)		+= sun8i-mixer.o
+obj-$(CONFIG_DRM_SUN8I_MIXER)	+= sun8i-mixer.o
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 03/23] drm/sun4i: tcon: Make tcon_set_mux mode argument const
  2017-10-17  9:06 ` Maxime Ripard
  (?)
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

The drm_display_mode pointer can be mark const, so let's do it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 6 +++---
 drivers/gpu/drm/sun4i/sun4i_tcon.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 68751b999877..54e1796d2953 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -134,7 +134,7 @@ static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)
 }
 
 void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
-			struct drm_encoder *encoder)
+			const struct drm_encoder *encoder)
 {
 	int ret = -ENOTSUPP;
 
@@ -783,7 +783,7 @@ static int sun4i_tcon_remove(struct platform_device *pdev)
 
 /* platform specific TCON muxing callbacks */
 static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon,
-				  struct drm_encoder *encoder)
+				  const struct drm_encoder *encoder)
 {
 	u32 val;
 
@@ -799,7 +799,7 @@ static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon,
 }
 
 static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
-			      struct drm_encoder *encoder)
+			      const struct drm_encoder *encoder)
 {
 	struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev);
 	u32 shift;
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index d9e1357cc8ae..d81c6e20efe6 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -152,7 +152,7 @@ struct sun4i_tcon_quirks {
 	bool	needs_de_be_mux; /* sun6i needs mux to select backend */
 
 	/* callback to handle tcon muxing options */
-	int	(*set_mux)(struct sun4i_tcon *, struct drm_encoder *);
+	int	(*set_mux)(struct sun4i_tcon *, const struct drm_encoder *);
 };
 
 struct sun4i_tcon {
-- 
git-series 0.9.1

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

* [PATCH 03/23] drm/sun4i: tcon: Make tcon_set_mux mode argument const
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The drm_display_mode pointer can be mark const, so let's do it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 6 +++---
 drivers/gpu/drm/sun4i/sun4i_tcon.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 68751b999877..54e1796d2953 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -134,7 +134,7 @@ static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)
 }
 
 void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
-			struct drm_encoder *encoder)
+			const struct drm_encoder *encoder)
 {
 	int ret = -ENOTSUPP;
 
@@ -783,7 +783,7 @@ static int sun4i_tcon_remove(struct platform_device *pdev)
 
 /* platform specific TCON muxing callbacks */
 static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon,
-				  struct drm_encoder *encoder)
+				  const struct drm_encoder *encoder)
 {
 	u32 val;
 
@@ -799,7 +799,7 @@ static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon,
 }
 
 static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
-			      struct drm_encoder *encoder)
+			      const struct drm_encoder *encoder)
 {
 	struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev);
 	u32 shift;
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index d9e1357cc8ae..d81c6e20efe6 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -152,7 +152,7 @@ struct sun4i_tcon_quirks {
 	bool	needs_de_be_mux; /* sun6i needs mux to select backend */
 
 	/* callback to handle tcon muxing options */
-	int	(*set_mux)(struct sun4i_tcon *, struct drm_encoder *);
+	int	(*set_mux)(struct sun4i_tcon *, const struct drm_encoder *);
 };
 
 struct sun4i_tcon {
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 03/23] drm/sun4i: tcon: Make tcon_set_mux mode argument const
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

The drm_display_mode pointer can be mark const, so let's do it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 6 +++---
 drivers/gpu/drm/sun4i/sun4i_tcon.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 68751b999877..54e1796d2953 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -134,7 +134,7 @@ static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)
 }
 
 void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
-			struct drm_encoder *encoder)
+			const struct drm_encoder *encoder)
 {
 	int ret = -ENOTSUPP;
 
@@ -783,7 +783,7 @@ static int sun4i_tcon_remove(struct platform_device *pdev)
 
 /* platform specific TCON muxing callbacks */
 static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon,
-				  struct drm_encoder *encoder)
+				  const struct drm_encoder *encoder)
 {
 	u32 val;
 
@@ -799,7 +799,7 @@ static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon,
 }
 
 static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
-			      struct drm_encoder *encoder)
+			      const struct drm_encoder *encoder)
 {
 	struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev);
 	u32 shift;
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index d9e1357cc8ae..d81c6e20efe6 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -152,7 +152,7 @@ struct sun4i_tcon_quirks {
 	bool	needs_de_be_mux; /* sun6i needs mux to select backend */
 
 	/* callback to handle tcon muxing options */
-	int	(*set_mux)(struct sun4i_tcon *, struct drm_encoder *);
+	int	(*set_mux)(struct sun4i_tcon *, const struct drm_encoder *);
 };
 
 struct sun4i_tcon {
-- 
git-series 0.9.1

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

* [PATCH 03/23] drm/sun4i: tcon: Make tcon_set_mux mode argument const
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The drm_display_mode pointer can be mark const, so let's do it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 6 +++---
 drivers/gpu/drm/sun4i/sun4i_tcon.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 68751b999877..54e1796d2953 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -134,7 +134,7 @@ static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)
 }
 
 void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
-			struct drm_encoder *encoder)
+			const struct drm_encoder *encoder)
 {
 	int ret = -ENOTSUPP;
 
@@ -783,7 +783,7 @@ static int sun4i_tcon_remove(struct platform_device *pdev)
 
 /* platform specific TCON muxing callbacks */
 static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon,
-				  struct drm_encoder *encoder)
+				  const struct drm_encoder *encoder)
 {
 	u32 val;
 
@@ -799,7 +799,7 @@ static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon,
 }
 
 static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
-			      struct drm_encoder *encoder)
+			      const struct drm_encoder *encoder)
 {
 	struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev);
 	u32 shift;
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index d9e1357cc8ae..d81c6e20efe6 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -152,7 +152,7 @@ struct sun4i_tcon_quirks {
 	bool	needs_de_be_mux; /* sun6i needs mux to select backend */
 
 	/* callback to handle tcon muxing options */
-	int	(*set_mux)(struct sun4i_tcon *, struct drm_encoder *);
+	int	(*set_mux)(struct sun4i_tcon *, const struct drm_encoder *);
 };
 
 struct sun4i_tcon {
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 04/23] drm/sun4i: tcon: Make tcon_get_clk_delay mode argument const
  2017-10-17  9:06 ` Maxime Ripard
  (?)
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

The drm_display_mode pointer can be mark const, so let's do it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 54e1796d2953..9b5b21ad8378 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -146,7 +146,7 @@ void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
 }
 EXPORT_SYMBOL(sun4i_tcon_set_mux);
 
-static int sun4i_tcon_get_clk_delay(struct drm_display_mode *mode,
+static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 				    int channel)
 {
 	int delay = mode->vtotal - mode->vdisplay;
-- 
git-series 0.9.1

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

* [PATCH 04/23] drm/sun4i: tcon: Make tcon_get_clk_delay mode argument const
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The drm_display_mode pointer can be mark const, so let's do it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 54e1796d2953..9b5b21ad8378 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -146,7 +146,7 @@ void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
 }
 EXPORT_SYMBOL(sun4i_tcon_set_mux);
 
-static int sun4i_tcon_get_clk_delay(struct drm_display_mode *mode,
+static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 				    int channel)
 {
 	int delay = mode->vtotal - mode->vdisplay;
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 04/23] drm/sun4i: tcon: Make tcon_get_clk_delay mode argument const
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

The drm_display_mode pointer can be mark const, so let's do it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 54e1796d2953..9b5b21ad8378 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -146,7 +146,7 @@ void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
 }
 EXPORT_SYMBOL(sun4i_tcon_set_mux);
 
-static int sun4i_tcon_get_clk_delay(struct drm_display_mode *mode,
+static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 				    int channel)
 {
 	int delay = mode->vtotal - mode->vdisplay;
-- 
git-series 0.9.1

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

* [PATCH 04/23] drm/sun4i: tcon: Make tcon_get_clk_delay mode argument const
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The drm_display_mode pointer can be mark const, so let's do it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 54e1796d2953..9b5b21ad8378 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -146,7 +146,7 @@ void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
 }
 EXPORT_SYMBOL(sun4i_tcon_set_mux);
 
-static int sun4i_tcon_get_clk_delay(struct drm_display_mode *mode,
+static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 				    int channel)
 {
 	int delay = mode->vtotal - mode->vdisplay;
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 05/23] drm/sun4i: tcon: Don't rely on encoders to enable the TCON
  2017-10-17  9:06 ` Maxime Ripard
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

So far, we've required all the TCON-connected encoders to call the TCON
enable and disable functions.

This was made this way because in the RGB/LVDS case, the TCON is the CRTC
and the encoder. However, in all the other cases (HDMI, TV, DSI, etc.), we
have another encoder down the road that needs to be programmed.

We also needed to know which channel the encoder is connected to, which is
encoder-specific.

The CRTC's enable and disable callbacks can work just fine for our use
case, and we can get the channel to use just by looking at the type of
encoder, since that is fixed. Implement those callbacks, which will
remove some of the encoder boilerplate.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_crtc.c     | 22 ++++++-
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c |  8 +--
 drivers/gpu/drm/sun4i/sun4i_rgb.c      | 14 +---
 drivers/gpu/drm/sun4i/sun4i_tcon.c     | 87 ++++++++++++---------------
 drivers/gpu/drm/sun4i/sun4i_tcon.h     | 10 +---
 drivers/gpu/drm/sun4i/sun4i_tv.c       |  6 +--
 6 files changed, 67 insertions(+), 80 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index d097c6f93ad0..e86baa3746af 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -30,6 +30,22 @@
 #include "sunxi_engine.h"
 #include "sun4i_tcon.h"
 
+/*
+ * While this isn't really working in the DRM theory, in practice we
+ * can only ever have one encoder per TCON since we have a mux in our
+ * TCON.
+ */
+static struct drm_encoder *sun4i_crtc_get_encoder(struct drm_crtc *crtc)
+{
+	struct drm_encoder *encoder;
+
+	drm_for_each_encoder(encoder, crtc->dev)
+		if (encoder->crtc == crtc)
+			return encoder;
+
+	return NULL;
+}
+
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
 				    struct drm_crtc_state *old_state)
 {
@@ -72,11 +88,12 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
 static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc,
 				      struct drm_crtc_state *old_state)
 {
+	struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
 	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
 
 	DRM_DEBUG_DRIVER("Disabling the CRTC\n");
 
-	sun4i_tcon_disable(scrtc->tcon);
+	sun4i_tcon_set_status(scrtc->tcon, encoder, false);
 
 	if (crtc->state->event && !crtc->state->active) {
 		spin_lock_irq(&crtc->dev->event_lock);
@@ -90,11 +107,12 @@ static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc,
 static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
 				     struct drm_crtc_state *old_state)
 {
+	struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
 	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
 
 	DRM_DEBUG_DRIVER("Enabling the CRTC\n");
 
-	sun4i_tcon_enable(scrtc->tcon);
+	sun4i_tcon_set_status(scrtc->tcon, encoder, true);
 }
 
 static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 6ca6e6a74c4a..482bf03d55c1 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -86,8 +86,6 @@ static int sun4i_hdmi_atomic_check(struct drm_encoder *encoder,
 static void sun4i_hdmi_disable(struct drm_encoder *encoder)
 {
 	struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 	u32 val;
 
 	DRM_DEBUG_DRIVER("Disabling the HDMI Output\n");
@@ -95,22 +93,16 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
 	val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
 	val &= ~SUN4I_HDMI_VID_CTRL_ENABLE;
 	writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
-
-	sun4i_tcon_channel_disable(tcon, 1);
 }
 
 static void sun4i_hdmi_enable(struct drm_encoder *encoder)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 	u32 val = 0;
 
 	DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
 
-	sun4i_tcon_channel_enable(tcon, 1);
-
 	sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
 	val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
 	val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index 7cd7090ad63a..a7f297ed40c1 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -134,13 +134,10 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
 
 	DRM_DEBUG_DRIVER("Enabling RGB output\n");
 
-	if (!IS_ERR(tcon->panel))
+	if (!IS_ERR(tcon->panel)) {
 		drm_panel_prepare(tcon->panel);
-
-	sun4i_tcon_channel_enable(tcon, 0);
-
-	if (!IS_ERR(tcon->panel))
 		drm_panel_enable(tcon->panel);
+	}
 }
 
 static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
@@ -150,13 +147,10 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
 
 	DRM_DEBUG_DRIVER("Disabling RGB output\n");
 
-	if (!IS_ERR(tcon->panel))
+	if (!IS_ERR(tcon->panel)) {
 		drm_panel_disable(tcon->panel);
-
-	sun4i_tcon_channel_disable(tcon, 0);
-
-	if (!IS_ERR(tcon->panel))
 		drm_panel_unprepare(tcon->panel);
+	}
 }
 
 static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 9b5b21ad8378..964cf22a1ced 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -35,66 +35,61 @@
 #include "sun4i_tcon.h"
 #include "sunxi_engine.h"
 
-void sun4i_tcon_disable(struct sun4i_tcon *tcon)
+static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
+					  bool enabled)
 {
-	DRM_DEBUG_DRIVER("Disabling TCON\n");
+	struct clk *clk;
 
-	/* Disable the TCON */
-	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
-			   SUN4I_TCON_GCTL_TCON_ENABLE, 0);
-}
-EXPORT_SYMBOL(sun4i_tcon_disable);
-
-void sun4i_tcon_enable(struct sun4i_tcon *tcon)
-{
-	DRM_DEBUG_DRIVER("Enabling TCON\n");
-
-	/* Enable the TCON */
-	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
-			   SUN4I_TCON_GCTL_TCON_ENABLE,
-			   SUN4I_TCON_GCTL_TCON_ENABLE);
-}
-EXPORT_SYMBOL(sun4i_tcon_enable);
-
-void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel)
-{
-	DRM_DEBUG_DRIVER("Disabling TCON channel %d\n", channel);
-
-	/* Disable the TCON's channel */
-	if (channel == 0) {
+	switch (channel) {
+	case 0:
 		regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
-				   SUN4I_TCON0_CTL_TCON_ENABLE, 0);
-		clk_disable_unprepare(tcon->dclk);
+				   SUN4I_TCON0_CTL_TCON_ENABLE,
+				   enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0);
+		clk = tcon->dclk;
+		break;
+	case 1:
+		WARN_ON(!tcon->quirks->has_channel_1);
+		regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
+				   SUN4I_TCON1_CTL_TCON_ENABLE,
+				   enabled ? SUN4I_TCON1_CTL_TCON_ENABLE : 0);
+		clk = tcon->sclk1;
+		break;
+	default:
+		DRM_WARN("Unknown channel... doing nothing\n");
 		return;
 	}
 
-	WARN_ON(!tcon->quirks->has_channel_1);
-	regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
-			   SUN4I_TCON1_CTL_TCON_ENABLE, 0);
-	clk_disable_unprepare(tcon->sclk1);
+	if (enabled)
+		clk_prepare_enable(clk);
+	else
+		clk_disable_unprepare(clk);
 }
-EXPORT_SYMBOL(sun4i_tcon_channel_disable);
 
-void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel)
+void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
+			   const struct drm_encoder *encoder,
+			   bool enabled)
 {
-	DRM_DEBUG_DRIVER("Enabling TCON channel %d\n", channel);
+	int channel;
 
-	/* Enable the TCON's channel */
-	if (channel == 0) {
-		regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
-				   SUN4I_TCON0_CTL_TCON_ENABLE,
-				   SUN4I_TCON0_CTL_TCON_ENABLE);
-		clk_prepare_enable(tcon->dclk);
+	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_NONE:
+		channel = 0;
+		break;
+	case DRM_MODE_ENCODER_TMDS:
+	case DRM_MODE_ENCODER_TVDAC:
+		channel = 1;
+		break;
+	default:
+		DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
 		return;
 	}
 
-	WARN_ON(!tcon->quirks->has_channel_1);
-	regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
-			   SUN4I_TCON1_CTL_TCON_ENABLE,
-			   SUN4I_TCON1_CTL_TCON_ENABLE);
-	clk_prepare_enable(tcon->sclk1);
+	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
+			   SUN4I_TCON_GCTL_TCON_ENABLE,
+			   enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
+
+	sun4i_tcon_channel_set_status(tcon, channel, enabled);
 }
-EXPORT_SYMBOL(sun4i_tcon_channel_enable);
 
 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable)
 {
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index d81c6e20efe6..03f983927baa 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -190,15 +190,9 @@ struct sun4i_tcon {
 struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
 struct drm_panel *sun4i_tcon_find_panel(struct device_node *node);
 
-/* Global Control */
-void sun4i_tcon_disable(struct sun4i_tcon *tcon);
-void sun4i_tcon_enable(struct sun4i_tcon *tcon);
-
-/* Channel Control */
-void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel);
-void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel);
-
 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
+void sun4i_tcon_set_status(struct sun4i_tcon *crtc,
+			   const struct drm_encoder *encoder, bool enable);
 
 /* Mode Related Controls */
 void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 050cfd43c7a0..2e27ff9fc58f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -345,12 +345,9 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
 {
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
 	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 
 	DRM_DEBUG_DRIVER("Disabling the TV Output\n");
 
-	sun4i_tcon_channel_disable(tcon, 1);
-
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
 			   0);
@@ -362,7 +359,6 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
 {
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
 	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 
 	DRM_DEBUG_DRIVER("Enabling the TV Output\n");
 
@@ -371,8 +367,6 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
 			   SUN4I_TVE_EN_ENABLE);
-
-	sun4i_tcon_channel_enable(tcon, 1);
 }
 
 static void sun4i_tv_mode_set(struct drm_encoder *encoder,
-- 
git-series 0.9.1

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

* [PATCH 05/23] drm/sun4i: tcon: Don't rely on encoders to enable the TCON
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

So far, we've required all the TCON-connected encoders to call the TCON
enable and disable functions.

This was made this way because in the RGB/LVDS case, the TCON is the CRTC
and the encoder. However, in all the other cases (HDMI, TV, DSI, etc.), we
have another encoder down the road that needs to be programmed.

We also needed to know which channel the encoder is connected to, which is
encoder-specific.

The CRTC's enable and disable callbacks can work just fine for our use
case, and we can get the channel to use just by looking at the type of
encoder, since that is fixed. Implement those callbacks, which will
remove some of the encoder boilerplate.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_crtc.c     | 22 ++++++-
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c |  8 +--
 drivers/gpu/drm/sun4i/sun4i_rgb.c      | 14 +---
 drivers/gpu/drm/sun4i/sun4i_tcon.c     | 87 ++++++++++++---------------
 drivers/gpu/drm/sun4i/sun4i_tcon.h     | 10 +---
 drivers/gpu/drm/sun4i/sun4i_tv.c       |  6 +--
 6 files changed, 67 insertions(+), 80 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index d097c6f93ad0..e86baa3746af 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -30,6 +30,22 @@
 #include "sunxi_engine.h"
 #include "sun4i_tcon.h"
 
+/*
+ * While this isn't really working in the DRM theory, in practice we
+ * can only ever have one encoder per TCON since we have a mux in our
+ * TCON.
+ */
+static struct drm_encoder *sun4i_crtc_get_encoder(struct drm_crtc *crtc)
+{
+	struct drm_encoder *encoder;
+
+	drm_for_each_encoder(encoder, crtc->dev)
+		if (encoder->crtc == crtc)
+			return encoder;
+
+	return NULL;
+}
+
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
 				    struct drm_crtc_state *old_state)
 {
@@ -72,11 +88,12 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
 static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc,
 				      struct drm_crtc_state *old_state)
 {
+	struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
 	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
 
 	DRM_DEBUG_DRIVER("Disabling the CRTC\n");
 
-	sun4i_tcon_disable(scrtc->tcon);
+	sun4i_tcon_set_status(scrtc->tcon, encoder, false);
 
 	if (crtc->state->event && !crtc->state->active) {
 		spin_lock_irq(&crtc->dev->event_lock);
@@ -90,11 +107,12 @@ static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc,
 static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
 				     struct drm_crtc_state *old_state)
 {
+	struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
 	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
 
 	DRM_DEBUG_DRIVER("Enabling the CRTC\n");
 
-	sun4i_tcon_enable(scrtc->tcon);
+	sun4i_tcon_set_status(scrtc->tcon, encoder, true);
 }
 
 static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 6ca6e6a74c4a..482bf03d55c1 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -86,8 +86,6 @@ static int sun4i_hdmi_atomic_check(struct drm_encoder *encoder,
 static void sun4i_hdmi_disable(struct drm_encoder *encoder)
 {
 	struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 	u32 val;
 
 	DRM_DEBUG_DRIVER("Disabling the HDMI Output\n");
@@ -95,22 +93,16 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
 	val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
 	val &= ~SUN4I_HDMI_VID_CTRL_ENABLE;
 	writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
-
-	sun4i_tcon_channel_disable(tcon, 1);
 }
 
 static void sun4i_hdmi_enable(struct drm_encoder *encoder)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 	u32 val = 0;
 
 	DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
 
-	sun4i_tcon_channel_enable(tcon, 1);
-
 	sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
 	val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
 	val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index 7cd7090ad63a..a7f297ed40c1 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -134,13 +134,10 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
 
 	DRM_DEBUG_DRIVER("Enabling RGB output\n");
 
-	if (!IS_ERR(tcon->panel))
+	if (!IS_ERR(tcon->panel)) {
 		drm_panel_prepare(tcon->panel);
-
-	sun4i_tcon_channel_enable(tcon, 0);
-
-	if (!IS_ERR(tcon->panel))
 		drm_panel_enable(tcon->panel);
+	}
 }
 
 static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
@@ -150,13 +147,10 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
 
 	DRM_DEBUG_DRIVER("Disabling RGB output\n");
 
-	if (!IS_ERR(tcon->panel))
+	if (!IS_ERR(tcon->panel)) {
 		drm_panel_disable(tcon->panel);
-
-	sun4i_tcon_channel_disable(tcon, 0);
-
-	if (!IS_ERR(tcon->panel))
 		drm_panel_unprepare(tcon->panel);
+	}
 }
 
 static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 9b5b21ad8378..964cf22a1ced 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -35,66 +35,61 @@
 #include "sun4i_tcon.h"
 #include "sunxi_engine.h"
 
-void sun4i_tcon_disable(struct sun4i_tcon *tcon)
+static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
+					  bool enabled)
 {
-	DRM_DEBUG_DRIVER("Disabling TCON\n");
+	struct clk *clk;
 
-	/* Disable the TCON */
-	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
-			   SUN4I_TCON_GCTL_TCON_ENABLE, 0);
-}
-EXPORT_SYMBOL(sun4i_tcon_disable);
-
-void sun4i_tcon_enable(struct sun4i_tcon *tcon)
-{
-	DRM_DEBUG_DRIVER("Enabling TCON\n");
-
-	/* Enable the TCON */
-	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
-			   SUN4I_TCON_GCTL_TCON_ENABLE,
-			   SUN4I_TCON_GCTL_TCON_ENABLE);
-}
-EXPORT_SYMBOL(sun4i_tcon_enable);
-
-void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel)
-{
-	DRM_DEBUG_DRIVER("Disabling TCON channel %d\n", channel);
-
-	/* Disable the TCON's channel */
-	if (channel == 0) {
+	switch (channel) {
+	case 0:
 		regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
-				   SUN4I_TCON0_CTL_TCON_ENABLE, 0);
-		clk_disable_unprepare(tcon->dclk);
+				   SUN4I_TCON0_CTL_TCON_ENABLE,
+				   enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0);
+		clk = tcon->dclk;
+		break;
+	case 1:
+		WARN_ON(!tcon->quirks->has_channel_1);
+		regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
+				   SUN4I_TCON1_CTL_TCON_ENABLE,
+				   enabled ? SUN4I_TCON1_CTL_TCON_ENABLE : 0);
+		clk = tcon->sclk1;
+		break;
+	default:
+		DRM_WARN("Unknown channel... doing nothing\n");
 		return;
 	}
 
-	WARN_ON(!tcon->quirks->has_channel_1);
-	regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
-			   SUN4I_TCON1_CTL_TCON_ENABLE, 0);
-	clk_disable_unprepare(tcon->sclk1);
+	if (enabled)
+		clk_prepare_enable(clk);
+	else
+		clk_disable_unprepare(clk);
 }
-EXPORT_SYMBOL(sun4i_tcon_channel_disable);
 
-void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel)
+void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
+			   const struct drm_encoder *encoder,
+			   bool enabled)
 {
-	DRM_DEBUG_DRIVER("Enabling TCON channel %d\n", channel);
+	int channel;
 
-	/* Enable the TCON's channel */
-	if (channel == 0) {
-		regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
-				   SUN4I_TCON0_CTL_TCON_ENABLE,
-				   SUN4I_TCON0_CTL_TCON_ENABLE);
-		clk_prepare_enable(tcon->dclk);
+	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_NONE:
+		channel = 0;
+		break;
+	case DRM_MODE_ENCODER_TMDS:
+	case DRM_MODE_ENCODER_TVDAC:
+		channel = 1;
+		break;
+	default:
+		DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
 		return;
 	}
 
-	WARN_ON(!tcon->quirks->has_channel_1);
-	regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
-			   SUN4I_TCON1_CTL_TCON_ENABLE,
-			   SUN4I_TCON1_CTL_TCON_ENABLE);
-	clk_prepare_enable(tcon->sclk1);
+	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
+			   SUN4I_TCON_GCTL_TCON_ENABLE,
+			   enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
+
+	sun4i_tcon_channel_set_status(tcon, channel, enabled);
 }
-EXPORT_SYMBOL(sun4i_tcon_channel_enable);
 
 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable)
 {
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index d81c6e20efe6..03f983927baa 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -190,15 +190,9 @@ struct sun4i_tcon {
 struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
 struct drm_panel *sun4i_tcon_find_panel(struct device_node *node);
 
-/* Global Control */
-void sun4i_tcon_disable(struct sun4i_tcon *tcon);
-void sun4i_tcon_enable(struct sun4i_tcon *tcon);
-
-/* Channel Control */
-void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel);
-void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel);
-
 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
+void sun4i_tcon_set_status(struct sun4i_tcon *crtc,
+			   const struct drm_encoder *encoder, bool enable);
 
 /* Mode Related Controls */
 void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 050cfd43c7a0..2e27ff9fc58f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -345,12 +345,9 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
 {
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
 	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 
 	DRM_DEBUG_DRIVER("Disabling the TV Output\n");
 
-	sun4i_tcon_channel_disable(tcon, 1);
-
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
 			   0);
@@ -362,7 +359,6 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
 {
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
 	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 
 	DRM_DEBUG_DRIVER("Enabling the TV Output\n");
 
@@ -371,8 +367,6 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
 			   SUN4I_TVE_EN_ENABLE);
-
-	sun4i_tcon_channel_enable(tcon, 1);
 }
 
 static void sun4i_tv_mode_set(struct drm_encoder *encoder,
-- 
git-series 0.9.1

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

* [PATCH 05/23] drm/sun4i: tcon: Don't rely on encoders to enable the TCON
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

So far, we've required all the TCON-connected encoders to call the TCON
enable and disable functions.

This was made this way because in the RGB/LVDS case, the TCON is the CRTC
and the encoder. However, in all the other cases (HDMI, TV, DSI, etc.), we
have another encoder down the road that needs to be programmed.

We also needed to know which channel the encoder is connected to, which is
encoder-specific.

The CRTC's enable and disable callbacks can work just fine for our use
case, and we can get the channel to use just by looking at the type of
encoder, since that is fixed. Implement those callbacks, which will
remove some of the encoder boilerplate.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_crtc.c     | 22 ++++++-
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c |  8 +--
 drivers/gpu/drm/sun4i/sun4i_rgb.c      | 14 +---
 drivers/gpu/drm/sun4i/sun4i_tcon.c     | 87 ++++++++++++---------------
 drivers/gpu/drm/sun4i/sun4i_tcon.h     | 10 +---
 drivers/gpu/drm/sun4i/sun4i_tv.c       |  6 +--
 6 files changed, 67 insertions(+), 80 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index d097c6f93ad0..e86baa3746af 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -30,6 +30,22 @@
 #include "sunxi_engine.h"
 #include "sun4i_tcon.h"
 
+/*
+ * While this isn't really working in the DRM theory, in practice we
+ * can only ever have one encoder per TCON since we have a mux in our
+ * TCON.
+ */
+static struct drm_encoder *sun4i_crtc_get_encoder(struct drm_crtc *crtc)
+{
+	struct drm_encoder *encoder;
+
+	drm_for_each_encoder(encoder, crtc->dev)
+		if (encoder->crtc == crtc)
+			return encoder;
+
+	return NULL;
+}
+
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
 				    struct drm_crtc_state *old_state)
 {
@@ -72,11 +88,12 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
 static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc,
 				      struct drm_crtc_state *old_state)
 {
+	struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
 	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
 
 	DRM_DEBUG_DRIVER("Disabling the CRTC\n");
 
-	sun4i_tcon_disable(scrtc->tcon);
+	sun4i_tcon_set_status(scrtc->tcon, encoder, false);
 
 	if (crtc->state->event && !crtc->state->active) {
 		spin_lock_irq(&crtc->dev->event_lock);
@@ -90,11 +107,12 @@ static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc,
 static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
 				     struct drm_crtc_state *old_state)
 {
+	struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
 	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
 
 	DRM_DEBUG_DRIVER("Enabling the CRTC\n");
 
-	sun4i_tcon_enable(scrtc->tcon);
+	sun4i_tcon_set_status(scrtc->tcon, encoder, true);
 }
 
 static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 6ca6e6a74c4a..482bf03d55c1 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -86,8 +86,6 @@ static int sun4i_hdmi_atomic_check(struct drm_encoder *encoder,
 static void sun4i_hdmi_disable(struct drm_encoder *encoder)
 {
 	struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 	u32 val;
 
 	DRM_DEBUG_DRIVER("Disabling the HDMI Output\n");
@@ -95,22 +93,16 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
 	val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
 	val &= ~SUN4I_HDMI_VID_CTRL_ENABLE;
 	writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
-
-	sun4i_tcon_channel_disable(tcon, 1);
 }
 
 static void sun4i_hdmi_enable(struct drm_encoder *encoder)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 	u32 val = 0;
 
 	DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
 
-	sun4i_tcon_channel_enable(tcon, 1);
-
 	sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
 	val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
 	val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index 7cd7090ad63a..a7f297ed40c1 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -134,13 +134,10 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
 
 	DRM_DEBUG_DRIVER("Enabling RGB output\n");
 
-	if (!IS_ERR(tcon->panel))
+	if (!IS_ERR(tcon->panel)) {
 		drm_panel_prepare(tcon->panel);
-
-	sun4i_tcon_channel_enable(tcon, 0);
-
-	if (!IS_ERR(tcon->panel))
 		drm_panel_enable(tcon->panel);
+	}
 }
 
 static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
@@ -150,13 +147,10 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
 
 	DRM_DEBUG_DRIVER("Disabling RGB output\n");
 
-	if (!IS_ERR(tcon->panel))
+	if (!IS_ERR(tcon->panel)) {
 		drm_panel_disable(tcon->panel);
-
-	sun4i_tcon_channel_disable(tcon, 0);
-
-	if (!IS_ERR(tcon->panel))
 		drm_panel_unprepare(tcon->panel);
+	}
 }
 
 static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 9b5b21ad8378..964cf22a1ced 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -35,66 +35,61 @@
 #include "sun4i_tcon.h"
 #include "sunxi_engine.h"
 
-void sun4i_tcon_disable(struct sun4i_tcon *tcon)
+static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
+					  bool enabled)
 {
-	DRM_DEBUG_DRIVER("Disabling TCON\n");
+	struct clk *clk;
 
-	/* Disable the TCON */
-	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
-			   SUN4I_TCON_GCTL_TCON_ENABLE, 0);
-}
-EXPORT_SYMBOL(sun4i_tcon_disable);
-
-void sun4i_tcon_enable(struct sun4i_tcon *tcon)
-{
-	DRM_DEBUG_DRIVER("Enabling TCON\n");
-
-	/* Enable the TCON */
-	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
-			   SUN4I_TCON_GCTL_TCON_ENABLE,
-			   SUN4I_TCON_GCTL_TCON_ENABLE);
-}
-EXPORT_SYMBOL(sun4i_tcon_enable);
-
-void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel)
-{
-	DRM_DEBUG_DRIVER("Disabling TCON channel %d\n", channel);
-
-	/* Disable the TCON's channel */
-	if (channel == 0) {
+	switch (channel) {
+	case 0:
 		regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
-				   SUN4I_TCON0_CTL_TCON_ENABLE, 0);
-		clk_disable_unprepare(tcon->dclk);
+				   SUN4I_TCON0_CTL_TCON_ENABLE,
+				   enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0);
+		clk = tcon->dclk;
+		break;
+	case 1:
+		WARN_ON(!tcon->quirks->has_channel_1);
+		regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
+				   SUN4I_TCON1_CTL_TCON_ENABLE,
+				   enabled ? SUN4I_TCON1_CTL_TCON_ENABLE : 0);
+		clk = tcon->sclk1;
+		break;
+	default:
+		DRM_WARN("Unknown channel... doing nothing\n");
 		return;
 	}
 
-	WARN_ON(!tcon->quirks->has_channel_1);
-	regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
-			   SUN4I_TCON1_CTL_TCON_ENABLE, 0);
-	clk_disable_unprepare(tcon->sclk1);
+	if (enabled)
+		clk_prepare_enable(clk);
+	else
+		clk_disable_unprepare(clk);
 }
-EXPORT_SYMBOL(sun4i_tcon_channel_disable);
 
-void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel)
+void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
+			   const struct drm_encoder *encoder,
+			   bool enabled)
 {
-	DRM_DEBUG_DRIVER("Enabling TCON channel %d\n", channel);
+	int channel;
 
-	/* Enable the TCON's channel */
-	if (channel == 0) {
-		regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
-				   SUN4I_TCON0_CTL_TCON_ENABLE,
-				   SUN4I_TCON0_CTL_TCON_ENABLE);
-		clk_prepare_enable(tcon->dclk);
+	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_NONE:
+		channel = 0;
+		break;
+	case DRM_MODE_ENCODER_TMDS:
+	case DRM_MODE_ENCODER_TVDAC:
+		channel = 1;
+		break;
+	default:
+		DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
 		return;
 	}
 
-	WARN_ON(!tcon->quirks->has_channel_1);
-	regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
-			   SUN4I_TCON1_CTL_TCON_ENABLE,
-			   SUN4I_TCON1_CTL_TCON_ENABLE);
-	clk_prepare_enable(tcon->sclk1);
+	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
+			   SUN4I_TCON_GCTL_TCON_ENABLE,
+			   enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
+
+	sun4i_tcon_channel_set_status(tcon, channel, enabled);
 }
-EXPORT_SYMBOL(sun4i_tcon_channel_enable);
 
 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable)
 {
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index d81c6e20efe6..03f983927baa 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -190,15 +190,9 @@ struct sun4i_tcon {
 struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
 struct drm_panel *sun4i_tcon_find_panel(struct device_node *node);
 
-/* Global Control */
-void sun4i_tcon_disable(struct sun4i_tcon *tcon);
-void sun4i_tcon_enable(struct sun4i_tcon *tcon);
-
-/* Channel Control */
-void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel);
-void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel);
-
 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
+void sun4i_tcon_set_status(struct sun4i_tcon *crtc,
+			   const struct drm_encoder *encoder, bool enable);
 
 /* Mode Related Controls */
 void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 050cfd43c7a0..2e27ff9fc58f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -345,12 +345,9 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
 {
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
 	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 
 	DRM_DEBUG_DRIVER("Disabling the TV Output\n");
 
-	sun4i_tcon_channel_disable(tcon, 1);
-
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
 			   0);
@@ -362,7 +359,6 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
 {
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
 	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 
 	DRM_DEBUG_DRIVER("Enabling the TV Output\n");
 
@@ -371,8 +367,6 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
 			   SUN4I_TVE_EN_ENABLE);
-
-	sun4i_tcon_channel_enable(tcon, 1);
 }
 
 static void sun4i_tv_mode_set(struct drm_encoder *encoder,
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 06/23] drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
  2017-10-17  9:06 ` Maxime Ripard
  (?)
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

Just like we did for the TCON enable and disable, for historical reasons we
used to rely on the encoders calling the TCON mode_set function, while the
CRTC has a callback for that.

Let's implement it in order to reduce the boilerplate code.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_crtc.c          | 10 +++++++-
 drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c  |  1 +-
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c      |  7 +-----
 drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c |  1 +-
 drivers/gpu/drm/sun4i/sun4i_rgb.c           | 15 +-----------
 drivers/gpu/drm/sun4i/sun4i_tcon.c          | 31 +++++++++++++++++-----
 drivers/gpu/drm/sun4i/sun4i_tcon.h          | 11 ++------
 drivers/gpu/drm/sun4i/sun4i_tv.c            |  6 +----
 8 files changed, 37 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index e86baa3746af..5decae0069d0 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -115,11 +115,21 @@ static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
 	sun4i_tcon_set_status(scrtc->tcon, encoder, true);
 }
 
+static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+	struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
+	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
+
+	sun4i_tcon_mode_set(scrtc->tcon, encoder, mode);
+}
+
 static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
 	.atomic_begin	= sun4i_crtc_atomic_begin,
 	.atomic_flush	= sun4i_crtc_atomic_flush,
 	.atomic_enable	= sun4i_crtc_atomic_enable,
 	.atomic_disable	= sun4i_crtc_atomic_disable,
+	.mode_set_nofb	= sun4i_crtc_mode_set_nofb,
 };
 
 static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
index 04f85b1cf922..e826da34e919 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
@@ -13,7 +13,6 @@
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
 
-#include "sun4i_tcon.h"
 #include "sun4i_hdmi.h"
 
 struct sun4i_ddc {
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 482bf03d55c1..d2eb0a60e568 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -30,7 +30,6 @@
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
 #include "sun4i_hdmi.h"
-#include "sun4i_tcon.h"
 
 static inline struct sun4i_hdmi *
 drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
@@ -120,15 +119,9 @@ static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *adjusted_mode)
 {
 	struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 	unsigned int x, y;
 	u32 val;
 
-	sun4i_tcon1_mode_set(tcon, mode);
-	sun4i_tcon_set_mux(tcon, 1, encoder);
-
-	clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
 	clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
 	clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
index 1b6b37aefc38..dc332ea56f6c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
@@ -12,7 +12,6 @@
 
 #include <linux/clk-provider.h>
 
-#include "sun4i_tcon.h"
 #include "sun4i_hdmi.h"
 
 struct sun4i_tmds {
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index a7f297ed40c1..832f8f9bc47f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -153,22 +153,7 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
 	}
 }
 
-static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
-				       struct drm_display_mode *mode,
-				       struct drm_display_mode *adjusted_mode)
-{
-	struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
-	struct sun4i_tcon *tcon = rgb->tcon;
-
-	sun4i_tcon0_mode_set(tcon, mode);
-	sun4i_tcon_set_mux(tcon, 0, encoder);
-
-	/* FIXME: This seems to be board specific */
-	clk_set_phase(tcon->dclk, 120);
-}
-
 static struct drm_encoder_helper_funcs sun4i_rgb_enc_helper_funcs = {
-	.mode_set	= sun4i_rgb_encoder_mode_set,
 	.disable	= sun4i_rgb_encoder_disable,
 	.enable		= sun4i_rgb_encoder_enable,
 };
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 964cf22a1ced..7ecd4f7c8411 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -139,7 +139,6 @@ void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
 	DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
 			 encoder->name, encoder->crtc->name, ret);
 }
-EXPORT_SYMBOL(sun4i_tcon_set_mux);
 
 static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 				    int channel)
@@ -159,8 +158,8 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 	return delay;
 }
 
-void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode)
+static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
+				 struct drm_display_mode *mode)
 {
 	unsigned int bp, hsync, vsync;
 	u8 clk_delay;
@@ -233,10 +232,9 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
 	/* Enable the output on the pins */
 	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
 }
-EXPORT_SYMBOL(sun4i_tcon0_mode_set);
 
-void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode)
+static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
+				 const struct drm_display_mode *mode)
 {
 	unsigned int bp, hsync, vsync, vtotal;
 	u8 clk_delay;
@@ -324,7 +322,26 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
 			   SUN4I_TCON_GCTL_IOMAP_MASK,
 			   SUN4I_TCON_GCTL_IOMAP_TCON1);
 }
-EXPORT_SYMBOL(sun4i_tcon1_mode_set);
+
+void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
+			 const struct drm_encoder *encoder,
+			 const struct drm_display_mode *mode)
+{
+	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_NONE:
+		sun4i_tcon0_mode_set(tcon, mode);
+		sun4i_tcon_set_mux(tcon, 0, encoder);
+		break;
+	case DRM_MODE_ENCODER_TVDAC:
+	case DRM_MODE_ENCODER_TMDS:
+		sun4i_tcon1_mode_set(tcon, mode);
+		sun4i_tcon_set_mux(tcon, 1, encoder);
+		break;
+	default:
+		DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
+	}
+}
+EXPORT_SYMBOL(sun4i_tcon_mode_set);
 
 static void sun4i_tcon_finish_page_flip(struct drm_device *dev,
 					struct sun4i_crtc *scrtc)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 03f983927baa..f61bf6d83b4a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -191,15 +191,10 @@ struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
 struct drm_panel *sun4i_tcon_find_panel(struct device_node *node);
 
 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
+void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
+			 const struct drm_encoder *encoder,
+			 const struct drm_display_mode *mode);
 void sun4i_tcon_set_status(struct sun4i_tcon *crtc,
 			   const struct drm_encoder *encoder, bool enable);
 
-/* Mode Related Controls */
-void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
-			struct drm_encoder *encoder);
-void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode);
-void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode);
-
 #endif /* __SUN4I_TCON_H__ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 2e27ff9fc58f..b070d522ed8d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -24,7 +24,6 @@
 
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
-#include "sun4i_tcon.h"
 #include "sunxi_engine.h"
 
 #define SUN4I_TVE_EN_REG		0x000
@@ -374,13 +373,8 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder,
 			      struct drm_display_mode *adjusted_mode)
 {
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
-	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 	const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode);
 
-	sun4i_tcon1_mode_set(tcon, mode);
-	sun4i_tcon_set_mux(tcon, 1, encoder);
-
 	/* Enable and map the DAC to the output */
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_DAC_MAP_MASK,
-- 
git-series 0.9.1

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

* [PATCH 06/23] drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

Just like we did for the TCON enable and disable, for historical reasons we
used to rely on the encoders calling the TCON mode_set function, while the
CRTC has a callback for that.

Let's implement it in order to reduce the boilerplate code.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_crtc.c          | 10 +++++++-
 drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c  |  1 +-
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c      |  7 +-----
 drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c |  1 +-
 drivers/gpu/drm/sun4i/sun4i_rgb.c           | 15 +-----------
 drivers/gpu/drm/sun4i/sun4i_tcon.c          | 31 +++++++++++++++++-----
 drivers/gpu/drm/sun4i/sun4i_tcon.h          | 11 ++------
 drivers/gpu/drm/sun4i/sun4i_tv.c            |  6 +----
 8 files changed, 37 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index e86baa3746af..5decae0069d0 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -115,11 +115,21 @@ static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
 	sun4i_tcon_set_status(scrtc->tcon, encoder, true);
 }
 
+static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+	struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
+	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
+
+	sun4i_tcon_mode_set(scrtc->tcon, encoder, mode);
+}
+
 static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
 	.atomic_begin	= sun4i_crtc_atomic_begin,
 	.atomic_flush	= sun4i_crtc_atomic_flush,
 	.atomic_enable	= sun4i_crtc_atomic_enable,
 	.atomic_disable	= sun4i_crtc_atomic_disable,
+	.mode_set_nofb	= sun4i_crtc_mode_set_nofb,
 };
 
 static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
index 04f85b1cf922..e826da34e919 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
@@ -13,7 +13,6 @@
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
 
-#include "sun4i_tcon.h"
 #include "sun4i_hdmi.h"
 
 struct sun4i_ddc {
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 482bf03d55c1..d2eb0a60e568 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -30,7 +30,6 @@
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
 #include "sun4i_hdmi.h"
-#include "sun4i_tcon.h"
 
 static inline struct sun4i_hdmi *
 drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
@@ -120,15 +119,9 @@ static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *adjusted_mode)
 {
 	struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 	unsigned int x, y;
 	u32 val;
 
-	sun4i_tcon1_mode_set(tcon, mode);
-	sun4i_tcon_set_mux(tcon, 1, encoder);
-
-	clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
 	clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
 	clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
index 1b6b37aefc38..dc332ea56f6c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
@@ -12,7 +12,6 @@
 
 #include <linux/clk-provider.h>
 
-#include "sun4i_tcon.h"
 #include "sun4i_hdmi.h"
 
 struct sun4i_tmds {
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index a7f297ed40c1..832f8f9bc47f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -153,22 +153,7 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
 	}
 }
 
-static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
-				       struct drm_display_mode *mode,
-				       struct drm_display_mode *adjusted_mode)
-{
-	struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
-	struct sun4i_tcon *tcon = rgb->tcon;
-
-	sun4i_tcon0_mode_set(tcon, mode);
-	sun4i_tcon_set_mux(tcon, 0, encoder);
-
-	/* FIXME: This seems to be board specific */
-	clk_set_phase(tcon->dclk, 120);
-}
-
 static struct drm_encoder_helper_funcs sun4i_rgb_enc_helper_funcs = {
-	.mode_set	= sun4i_rgb_encoder_mode_set,
 	.disable	= sun4i_rgb_encoder_disable,
 	.enable		= sun4i_rgb_encoder_enable,
 };
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 964cf22a1ced..7ecd4f7c8411 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -139,7 +139,6 @@ void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
 	DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
 			 encoder->name, encoder->crtc->name, ret);
 }
-EXPORT_SYMBOL(sun4i_tcon_set_mux);
 
 static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 				    int channel)
@@ -159,8 +158,8 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 	return delay;
 }
 
-void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode)
+static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
+				 struct drm_display_mode *mode)
 {
 	unsigned int bp, hsync, vsync;
 	u8 clk_delay;
@@ -233,10 +232,9 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
 	/* Enable the output on the pins */
 	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
 }
-EXPORT_SYMBOL(sun4i_tcon0_mode_set);
 
-void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode)
+static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
+				 const struct drm_display_mode *mode)
 {
 	unsigned int bp, hsync, vsync, vtotal;
 	u8 clk_delay;
@@ -324,7 +322,26 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
 			   SUN4I_TCON_GCTL_IOMAP_MASK,
 			   SUN4I_TCON_GCTL_IOMAP_TCON1);
 }
-EXPORT_SYMBOL(sun4i_tcon1_mode_set);
+
+void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
+			 const struct drm_encoder *encoder,
+			 const struct drm_display_mode *mode)
+{
+	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_NONE:
+		sun4i_tcon0_mode_set(tcon, mode);
+		sun4i_tcon_set_mux(tcon, 0, encoder);
+		break;
+	case DRM_MODE_ENCODER_TVDAC:
+	case DRM_MODE_ENCODER_TMDS:
+		sun4i_tcon1_mode_set(tcon, mode);
+		sun4i_tcon_set_mux(tcon, 1, encoder);
+		break;
+	default:
+		DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
+	}
+}
+EXPORT_SYMBOL(sun4i_tcon_mode_set);
 
 static void sun4i_tcon_finish_page_flip(struct drm_device *dev,
 					struct sun4i_crtc *scrtc)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 03f983927baa..f61bf6d83b4a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -191,15 +191,10 @@ struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
 struct drm_panel *sun4i_tcon_find_panel(struct device_node *node);
 
 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
+void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
+			 const struct drm_encoder *encoder,
+			 const struct drm_display_mode *mode);
 void sun4i_tcon_set_status(struct sun4i_tcon *crtc,
 			   const struct drm_encoder *encoder, bool enable);
 
-/* Mode Related Controls */
-void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
-			struct drm_encoder *encoder);
-void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode);
-void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode);
-
 #endif /* __SUN4I_TCON_H__ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 2e27ff9fc58f..b070d522ed8d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -24,7 +24,6 @@
 
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
-#include "sun4i_tcon.h"
 #include "sunxi_engine.h"
 
 #define SUN4I_TVE_EN_REG		0x000
@@ -374,13 +373,8 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder,
 			      struct drm_display_mode *adjusted_mode)
 {
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
-	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 	const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode);
 
-	sun4i_tcon1_mode_set(tcon, mode);
-	sun4i_tcon_set_mux(tcon, 1, encoder);
-
 	/* Enable and map the DAC to the output */
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_DAC_MAP_MASK,
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 06/23] drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

Just like we did for the TCON enable and disable, for historical reasons we
used to rely on the encoders calling the TCON mode_set function, while the
CRTC has a callback for that.

Let's implement it in order to reduce the boilerplate code.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_crtc.c          | 10 +++++++-
 drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c  |  1 +-
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c      |  7 +-----
 drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c |  1 +-
 drivers/gpu/drm/sun4i/sun4i_rgb.c           | 15 +-----------
 drivers/gpu/drm/sun4i/sun4i_tcon.c          | 31 +++++++++++++++++-----
 drivers/gpu/drm/sun4i/sun4i_tcon.h          | 11 ++------
 drivers/gpu/drm/sun4i/sun4i_tv.c            |  6 +----
 8 files changed, 37 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index e86baa3746af..5decae0069d0 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -115,11 +115,21 @@ static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
 	sun4i_tcon_set_status(scrtc->tcon, encoder, true);
 }
 
+static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+	struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
+	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
+
+	sun4i_tcon_mode_set(scrtc->tcon, encoder, mode);
+}
+
 static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
 	.atomic_begin	= sun4i_crtc_atomic_begin,
 	.atomic_flush	= sun4i_crtc_atomic_flush,
 	.atomic_enable	= sun4i_crtc_atomic_enable,
 	.atomic_disable	= sun4i_crtc_atomic_disable,
+	.mode_set_nofb	= sun4i_crtc_mode_set_nofb,
 };
 
 static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
index 04f85b1cf922..e826da34e919 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
@@ -13,7 +13,6 @@
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
 
-#include "sun4i_tcon.h"
 #include "sun4i_hdmi.h"
 
 struct sun4i_ddc {
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 482bf03d55c1..d2eb0a60e568 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -30,7 +30,6 @@
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
 #include "sun4i_hdmi.h"
-#include "sun4i_tcon.h"
 
 static inline struct sun4i_hdmi *
 drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
@@ -120,15 +119,9 @@ static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *adjusted_mode)
 {
 	struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 	unsigned int x, y;
 	u32 val;
 
-	sun4i_tcon1_mode_set(tcon, mode);
-	sun4i_tcon_set_mux(tcon, 1, encoder);
-
-	clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
 	clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
 	clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
index 1b6b37aefc38..dc332ea56f6c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
@@ -12,7 +12,6 @@
 
 #include <linux/clk-provider.h>
 
-#include "sun4i_tcon.h"
 #include "sun4i_hdmi.h"
 
 struct sun4i_tmds {
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index a7f297ed40c1..832f8f9bc47f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -153,22 +153,7 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
 	}
 }
 
-static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
-				       struct drm_display_mode *mode,
-				       struct drm_display_mode *adjusted_mode)
-{
-	struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
-	struct sun4i_tcon *tcon = rgb->tcon;
-
-	sun4i_tcon0_mode_set(tcon, mode);
-	sun4i_tcon_set_mux(tcon, 0, encoder);
-
-	/* FIXME: This seems to be board specific */
-	clk_set_phase(tcon->dclk, 120);
-}
-
 static struct drm_encoder_helper_funcs sun4i_rgb_enc_helper_funcs = {
-	.mode_set	= sun4i_rgb_encoder_mode_set,
 	.disable	= sun4i_rgb_encoder_disable,
 	.enable		= sun4i_rgb_encoder_enable,
 };
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 964cf22a1ced..7ecd4f7c8411 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -139,7 +139,6 @@ void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
 	DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
 			 encoder->name, encoder->crtc->name, ret);
 }
-EXPORT_SYMBOL(sun4i_tcon_set_mux);
 
 static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 				    int channel)
@@ -159,8 +158,8 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 	return delay;
 }
 
-void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode)
+static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
+				 struct drm_display_mode *mode)
 {
 	unsigned int bp, hsync, vsync;
 	u8 clk_delay;
@@ -233,10 +232,9 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
 	/* Enable the output on the pins */
 	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
 }
-EXPORT_SYMBOL(sun4i_tcon0_mode_set);
 
-void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode)
+static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
+				 const struct drm_display_mode *mode)
 {
 	unsigned int bp, hsync, vsync, vtotal;
 	u8 clk_delay;
@@ -324,7 +322,26 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
 			   SUN4I_TCON_GCTL_IOMAP_MASK,
 			   SUN4I_TCON_GCTL_IOMAP_TCON1);
 }
-EXPORT_SYMBOL(sun4i_tcon1_mode_set);
+
+void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
+			 const struct drm_encoder *encoder,
+			 const struct drm_display_mode *mode)
+{
+	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_NONE:
+		sun4i_tcon0_mode_set(tcon, mode);
+		sun4i_tcon_set_mux(tcon, 0, encoder);
+		break;
+	case DRM_MODE_ENCODER_TVDAC:
+	case DRM_MODE_ENCODER_TMDS:
+		sun4i_tcon1_mode_set(tcon, mode);
+		sun4i_tcon_set_mux(tcon, 1, encoder);
+		break;
+	default:
+		DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
+	}
+}
+EXPORT_SYMBOL(sun4i_tcon_mode_set);
 
 static void sun4i_tcon_finish_page_flip(struct drm_device *dev,
 					struct sun4i_crtc *scrtc)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 03f983927baa..f61bf6d83b4a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -191,15 +191,10 @@ struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
 struct drm_panel *sun4i_tcon_find_panel(struct device_node *node);
 
 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
+void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
+			 const struct drm_encoder *encoder,
+			 const struct drm_display_mode *mode);
 void sun4i_tcon_set_status(struct sun4i_tcon *crtc,
 			   const struct drm_encoder *encoder, bool enable);
 
-/* Mode Related Controls */
-void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
-			struct drm_encoder *encoder);
-void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode);
-void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode);
-
 #endif /* __SUN4I_TCON_H__ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 2e27ff9fc58f..b070d522ed8d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -24,7 +24,6 @@
 
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
-#include "sun4i_tcon.h"
 #include "sunxi_engine.h"
 
 #define SUN4I_TVE_EN_REG		0x000
@@ -374,13 +373,8 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder,
 			      struct drm_display_mode *adjusted_mode)
 {
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
-	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 	const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode);
 
-	sun4i_tcon1_mode_set(tcon, mode);
-	sun4i_tcon_set_mux(tcon, 1, encoder);
-
 	/* Enable and map the DAC to the output */
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_DAC_MAP_MASK,
-- 
git-series 0.9.1

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

* [PATCH 06/23] drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

Just like we did for the TCON enable and disable, for historical reasons we
used to rely on the encoders calling the TCON mode_set function, while the
CRTC has a callback for that.

Let's implement it in order to reduce the boilerplate code.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_crtc.c          | 10 +++++++-
 drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c  |  1 +-
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c      |  7 +-----
 drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c |  1 +-
 drivers/gpu/drm/sun4i/sun4i_rgb.c           | 15 +-----------
 drivers/gpu/drm/sun4i/sun4i_tcon.c          | 31 +++++++++++++++++-----
 drivers/gpu/drm/sun4i/sun4i_tcon.h          | 11 ++------
 drivers/gpu/drm/sun4i/sun4i_tv.c            |  6 +----
 8 files changed, 37 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index e86baa3746af..5decae0069d0 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -115,11 +115,21 @@ static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
 	sun4i_tcon_set_status(scrtc->tcon, encoder, true);
 }
 
+static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+	struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
+	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
+
+	sun4i_tcon_mode_set(scrtc->tcon, encoder, mode);
+}
+
 static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
 	.atomic_begin	= sun4i_crtc_atomic_begin,
 	.atomic_flush	= sun4i_crtc_atomic_flush,
 	.atomic_enable	= sun4i_crtc_atomic_enable,
 	.atomic_disable	= sun4i_crtc_atomic_disable,
+	.mode_set_nofb	= sun4i_crtc_mode_set_nofb,
 };
 
 static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
index 04f85b1cf922..e826da34e919 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
@@ -13,7 +13,6 @@
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
 
-#include "sun4i_tcon.h"
 #include "sun4i_hdmi.h"
 
 struct sun4i_ddc {
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 482bf03d55c1..d2eb0a60e568 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -30,7 +30,6 @@
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
 #include "sun4i_hdmi.h"
-#include "sun4i_tcon.h"
 
 static inline struct sun4i_hdmi *
 drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
@@ -120,15 +119,9 @@ static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *adjusted_mode)
 {
 	struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 	unsigned int x, y;
 	u32 val;
 
-	sun4i_tcon1_mode_set(tcon, mode);
-	sun4i_tcon_set_mux(tcon, 1, encoder);
-
-	clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
 	clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
 	clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
index 1b6b37aefc38..dc332ea56f6c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
@@ -12,7 +12,6 @@
 
 #include <linux/clk-provider.h>
 
-#include "sun4i_tcon.h"
 #include "sun4i_hdmi.h"
 
 struct sun4i_tmds {
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index a7f297ed40c1..832f8f9bc47f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -153,22 +153,7 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
 	}
 }
 
-static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
-				       struct drm_display_mode *mode,
-				       struct drm_display_mode *adjusted_mode)
-{
-	struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
-	struct sun4i_tcon *tcon = rgb->tcon;
-
-	sun4i_tcon0_mode_set(tcon, mode);
-	sun4i_tcon_set_mux(tcon, 0, encoder);
-
-	/* FIXME: This seems to be board specific */
-	clk_set_phase(tcon->dclk, 120);
-}
-
 static struct drm_encoder_helper_funcs sun4i_rgb_enc_helper_funcs = {
-	.mode_set	= sun4i_rgb_encoder_mode_set,
 	.disable	= sun4i_rgb_encoder_disable,
 	.enable		= sun4i_rgb_encoder_enable,
 };
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 964cf22a1ced..7ecd4f7c8411 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -139,7 +139,6 @@ void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
 	DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
 			 encoder->name, encoder->crtc->name, ret);
 }
-EXPORT_SYMBOL(sun4i_tcon_set_mux);
 
 static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 				    int channel)
@@ -159,8 +158,8 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 	return delay;
 }
 
-void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode)
+static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
+				 struct drm_display_mode *mode)
 {
 	unsigned int bp, hsync, vsync;
 	u8 clk_delay;
@@ -233,10 +232,9 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
 	/* Enable the output on the pins */
 	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
 }
-EXPORT_SYMBOL(sun4i_tcon0_mode_set);
 
-void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode)
+static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
+				 const struct drm_display_mode *mode)
 {
 	unsigned int bp, hsync, vsync, vtotal;
 	u8 clk_delay;
@@ -324,7 +322,26 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
 			   SUN4I_TCON_GCTL_IOMAP_MASK,
 			   SUN4I_TCON_GCTL_IOMAP_TCON1);
 }
-EXPORT_SYMBOL(sun4i_tcon1_mode_set);
+
+void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
+			 const struct drm_encoder *encoder,
+			 const struct drm_display_mode *mode)
+{
+	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_NONE:
+		sun4i_tcon0_mode_set(tcon, mode);
+		sun4i_tcon_set_mux(tcon, 0, encoder);
+		break;
+	case DRM_MODE_ENCODER_TVDAC:
+	case DRM_MODE_ENCODER_TMDS:
+		sun4i_tcon1_mode_set(tcon, mode);
+		sun4i_tcon_set_mux(tcon, 1, encoder);
+		break;
+	default:
+		DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
+	}
+}
+EXPORT_SYMBOL(sun4i_tcon_mode_set);
 
 static void sun4i_tcon_finish_page_flip(struct drm_device *dev,
 					struct sun4i_crtc *scrtc)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 03f983927baa..f61bf6d83b4a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -191,15 +191,10 @@ struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
 struct drm_panel *sun4i_tcon_find_panel(struct device_node *node);
 
 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
+void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
+			 const struct drm_encoder *encoder,
+			 const struct drm_display_mode *mode);
 void sun4i_tcon_set_status(struct sun4i_tcon *crtc,
 			   const struct drm_encoder *encoder, bool enable);
 
-/* Mode Related Controls */
-void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
-			struct drm_encoder *encoder);
-void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode);
-void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
-			  struct drm_display_mode *mode);
-
 #endif /* __SUN4I_TCON_H__ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 2e27ff9fc58f..b070d522ed8d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -24,7 +24,6 @@
 
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
-#include "sun4i_tcon.h"
 #include "sunxi_engine.h"
 
 #define SUN4I_TVE_EN_REG		0x000
@@ -374,13 +373,8 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder,
 			      struct drm_display_mode *adjusted_mode)
 {
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
-	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-	struct sun4i_tcon *tcon = crtc->tcon;
 	const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode);
 
-	sun4i_tcon1_mode_set(tcon, mode);
-	sun4i_tcon_set_mux(tcon, 1, encoder);
-
 	/* Enable and map the DAC to the output */
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_DAC_MAP_MASK,
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 07/23] drm/sun4i: tcon: Move out the tcon0 common setup
  2017-10-17  9:06 ` Maxime Ripard
  (?)
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

Some channel0 setup has to be done, no matter what the output interface is
(RGB, CPU, LVDS). Move that code into a common function in order to avoid
duplication.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 7ecd4f7c8411..f69bcdf11cb8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -158,15 +158,26 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 	return delay;
 }
 
-static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
-				 struct drm_display_mode *mode)
+static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
+					const struct drm_display_mode *mode)
+{
+	/* Configure the dot clock */
+	clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
+	/* Set the resolution */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+		     SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
+}
+
+static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
+				     const struct drm_display_mode *mode)
 {
 	unsigned int bp, hsync, vsync;
 	u8 clk_delay;
 	u32 val = 0;
 
-	/* Configure the dot clock */
-	clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+	sun4i_tcon0_mode_set_common(tcon, mode);
 
 	/* Adjust clock delay */
 	clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
@@ -174,11 +185,6 @@ static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
 			   SUN4I_TCON0_CTL_CLK_DELAY_MASK,
 			   SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
 
-	/* Set the resolution */
-	regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
-		     SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
-		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
-
 	/*
 	 * This is called a backporch in the register documentation,
 	 * but it really is the back porch + hsync
@@ -329,7 +335,7 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
 {
 	switch (encoder->encoder_type) {
 	case DRM_MODE_ENCODER_NONE:
-		sun4i_tcon0_mode_set(tcon, mode);
+		sun4i_tcon0_mode_set_rgb(tcon, mode);
 		sun4i_tcon_set_mux(tcon, 0, encoder);
 		break;
 	case DRM_MODE_ENCODER_TVDAC:
-- 
git-series 0.9.1

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

* [PATCH 07/23] drm/sun4i: tcon: Move out the tcon0 common setup
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

Some channel0 setup has to be done, no matter what the output interface is
(RGB, CPU, LVDS). Move that code into a common function in order to avoid
duplication.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 7ecd4f7c8411..f69bcdf11cb8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -158,15 +158,26 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 	return delay;
 }
 
-static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
-				 struct drm_display_mode *mode)
+static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
+					const struct drm_display_mode *mode)
+{
+	/* Configure the dot clock */
+	clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
+	/* Set the resolution */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+		     SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
+}
+
+static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
+				     const struct drm_display_mode *mode)
 {
 	unsigned int bp, hsync, vsync;
 	u8 clk_delay;
 	u32 val = 0;
 
-	/* Configure the dot clock */
-	clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+	sun4i_tcon0_mode_set_common(tcon, mode);
 
 	/* Adjust clock delay */
 	clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
@@ -174,11 +185,6 @@ static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
 			   SUN4I_TCON0_CTL_CLK_DELAY_MASK,
 			   SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
 
-	/* Set the resolution */
-	regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
-		     SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
-		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
-
 	/*
 	 * This is called a backporch in the register documentation,
 	 * but it really is the back porch + hsync
@@ -329,7 +335,7 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
 {
 	switch (encoder->encoder_type) {
 	case DRM_MODE_ENCODER_NONE:
-		sun4i_tcon0_mode_set(tcon, mode);
+		sun4i_tcon0_mode_set_rgb(tcon, mode);
 		sun4i_tcon_set_mux(tcon, 0, encoder);
 		break;
 	case DRM_MODE_ENCODER_TVDAC:
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 07/23] drm/sun4i: tcon: Move out the tcon0 common setup
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

Some channel0 setup has to be done, no matter what the output interface is
(RGB, CPU, LVDS). Move that code into a common function in order to avoid
duplication.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 7ecd4f7c8411..f69bcdf11cb8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -158,15 +158,26 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 	return delay;
 }
 
-static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
-				 struct drm_display_mode *mode)
+static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
+					const struct drm_display_mode *mode)
+{
+	/* Configure the dot clock */
+	clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
+	/* Set the resolution */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+		     SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
+}
+
+static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
+				     const struct drm_display_mode *mode)
 {
 	unsigned int bp, hsync, vsync;
 	u8 clk_delay;
 	u32 val = 0;
 
-	/* Configure the dot clock */
-	clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+	sun4i_tcon0_mode_set_common(tcon, mode);
 
 	/* Adjust clock delay */
 	clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
@@ -174,11 +185,6 @@ static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
 			   SUN4I_TCON0_CTL_CLK_DELAY_MASK,
 			   SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
 
-	/* Set the resolution */
-	regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
-		     SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
-		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
-
 	/*
 	 * This is called a backporch in the register documentation,
 	 * but it really is the back porch + hsync
@@ -329,7 +335,7 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
 {
 	switch (encoder->encoder_type) {
 	case DRM_MODE_ENCODER_NONE:
-		sun4i_tcon0_mode_set(tcon, mode);
+		sun4i_tcon0_mode_set_rgb(tcon, mode);
 		sun4i_tcon_set_mux(tcon, 0, encoder);
 		break;
 	case DRM_MODE_ENCODER_TVDAC:
-- 
git-series 0.9.1

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

* [PATCH 07/23] drm/sun4i: tcon: Move out the tcon0 common setup
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

Some channel0 setup has to be done, no matter what the output interface is
(RGB, CPU, LVDS). Move that code into a common function in order to avoid
duplication.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 7ecd4f7c8411..f69bcdf11cb8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -158,15 +158,26 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
 	return delay;
 }
 
-static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
-				 struct drm_display_mode *mode)
+static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
+					const struct drm_display_mode *mode)
+{
+	/* Configure the dot clock */
+	clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
+	/* Set the resolution */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+		     SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
+}
+
+static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
+				     const struct drm_display_mode *mode)
 {
 	unsigned int bp, hsync, vsync;
 	u8 clk_delay;
 	u32 val = 0;
 
-	/* Configure the dot clock */
-	clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+	sun4i_tcon0_mode_set_common(tcon, mode);
 
 	/* Adjust clock delay */
 	clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
@@ -174,11 +185,6 @@ static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
 			   SUN4I_TCON0_CTL_CLK_DELAY_MASK,
 			   SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
 
-	/* Set the resolution */
-	regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
-		     SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
-		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
-
 	/*
 	 * This is called a backporch in the register documentation,
 	 * but it really is the back porch + hsync
@@ -329,7 +335,7 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
 {
 	switch (encoder->encoder_type) {
 	case DRM_MODE_ENCODER_NONE:
-		sun4i_tcon0_mode_set(tcon, mode);
+		sun4i_tcon0_mode_set_rgb(tcon, mode);
 		sun4i_tcon_set_mux(tcon, 0, encoder);
 		break;
 	case DRM_MODE_ENCODER_TVDAC:
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 08/23] dt-bindings: panel: lvds: Document power-supply property
  2017-10-17  9:06 ` Maxime Ripard
  (?)
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

The power-supply property is used be a vast majority of panels, including
panel-simple. Let's document it as a common property

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/display/panel/panel-common.txt | 6 ++++++
 Documentation/devicetree/bindings/display/panel/panel-lvds.txt   | 1 +
 2 files changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/panel/panel-common.txt b/Documentation/devicetree/bindings/display/panel/panel-common.txt
index ec52c472c845..125ea68052af 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-common.txt
+++ b/Documentation/devicetree/bindings/display/panel/panel-common.txt
@@ -78,6 +78,12 @@ used for panels that implement compatible control signals.
   while active. Active high reset signals can be supported by inverting the
   GPIO specifier polarity flag.
 
+Power
+-----
+
+- power-supply: many display panels need an additional power supply in
+  order to be fully powered-up. For such panels, power-supply contains
+  a phandle to the regulator powering the panel.
 
 Backlight
 ---------
diff --git a/Documentation/devicetree/bindings/display/panel/panel-lvds.txt b/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
index b938269f841e..250850a2150b 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
+++ b/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
@@ -32,6 +32,7 @@ Optional properties:
 - label: See panel-common.txt.
 - gpios: See panel-common.txt.
 - backlight: See panel-common.txt.
+- power-supply: See panel-common.txt.
 - data-mirror: If set, reverse the bit order described in the data mappings
   below on all data lanes, transmitting bits for slots 6 to 0 instead of
   0 to 6.
-- 
git-series 0.9.1

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

* [PATCH 08/23] dt-bindings: panel: lvds: Document power-supply property
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The power-supply property is used be a vast majority of panels, including
panel-simple. Let's document it as a common property

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/display/panel/panel-common.txt | 6 ++++++
 Documentation/devicetree/bindings/display/panel/panel-lvds.txt   | 1 +
 2 files changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/panel/panel-common.txt b/Documentation/devicetree/bindings/display/panel/panel-common.txt
index ec52c472c845..125ea68052af 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-common.txt
+++ b/Documentation/devicetree/bindings/display/panel/panel-common.txt
@@ -78,6 +78,12 @@ used for panels that implement compatible control signals.
   while active. Active high reset signals can be supported by inverting the
   GPIO specifier polarity flag.
 
+Power
+-----
+
+- power-supply: many display panels need an additional power supply in
+  order to be fully powered-up. For such panels, power-supply contains
+  a phandle to the regulator powering the panel.
 
 Backlight
 ---------
diff --git a/Documentation/devicetree/bindings/display/panel/panel-lvds.txt b/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
index b938269f841e..250850a2150b 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
+++ b/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
@@ -32,6 +32,7 @@ Optional properties:
 - label: See panel-common.txt.
 - gpios: See panel-common.txt.
 - backlight: See panel-common.txt.
+- power-supply: See panel-common.txt.
 - data-mirror: If set, reverse the bit order described in the data mappings
   below on all data lanes, transmitting bits for slots 6 to 0 instead of
   0 to 6.
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 08/23] dt-bindings: panel: lvds: Document power-supply property
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

The power-supply property is used be a vast majority of panels, including
panel-simple. Let's document it as a common property

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/display/panel/panel-common.txt | 6 ++++++
 Documentation/devicetree/bindings/display/panel/panel-lvds.txt   | 1 +
 2 files changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/panel/panel-common.txt b/Documentation/devicetree/bindings/display/panel/panel-common.txt
index ec52c472c845..125ea68052af 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-common.txt
+++ b/Documentation/devicetree/bindings/display/panel/panel-common.txt
@@ -78,6 +78,12 @@ used for panels that implement compatible control signals.
   while active. Active high reset signals can be supported by inverting the
   GPIO specifier polarity flag.
 
+Power
+-----
+
+- power-supply: many display panels need an additional power supply in
+  order to be fully powered-up. For such panels, power-supply contains
+  a phandle to the regulator powering the panel.
 
 Backlight
 ---------
diff --git a/Documentation/devicetree/bindings/display/panel/panel-lvds.txt b/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
index b938269f841e..250850a2150b 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
+++ b/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
@@ -32,6 +32,7 @@ Optional properties:
 - label: See panel-common.txt.
 - gpios: See panel-common.txt.
 - backlight: See panel-common.txt.
+- power-supply: See panel-common.txt.
 - data-mirror: If set, reverse the bit order described in the data mappings
   below on all data lanes, transmitting bits for slots 6 to 0 instead of
   0 to 6.
-- 
git-series 0.9.1

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

* [PATCH 08/23] dt-bindings: panel: lvds: Document power-supply property
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The power-supply property is used be a vast majority of panels, including
panel-simple. Let's document it as a common property

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/display/panel/panel-common.txt | 6 ++++++
 Documentation/devicetree/bindings/display/panel/panel-lvds.txt   | 1 +
 2 files changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/panel/panel-common.txt b/Documentation/devicetree/bindings/display/panel/panel-common.txt
index ec52c472c845..125ea68052af 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-common.txt
+++ b/Documentation/devicetree/bindings/display/panel/panel-common.txt
@@ -78,6 +78,12 @@ used for panels that implement compatible control signals.
   while active. Active high reset signals can be supported by inverting the
   GPIO specifier polarity flag.
 
+Power
+-----
+
+- power-supply: many display panels need an additional power supply in
+  order to be fully powered-up. For such panels, power-supply contains
+  a phandle to the regulator powering the panel.
 
 Backlight
 ---------
diff --git a/Documentation/devicetree/bindings/display/panel/panel-lvds.txt b/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
index b938269f841e..250850a2150b 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
+++ b/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
@@ -32,6 +32,7 @@ Optional properties:
 - label: See panel-common.txt.
 - gpios: See panel-common.txt.
 - backlight: See panel-common.txt.
+- power-supply: See panel-common.txt.
 - data-mirror: If set, reverse the bit order described in the data mappings
   below on all data lanes, transmitting bits for slots 6 to 0 instead of
   0 to 6.
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 09/23] drm/panel: lvds: Add support for the power-supply property
  2017-10-17  9:06 ` Maxime Ripard
  (?)
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

A significant number of panels need to power up a regulator in order to
operate properly. Add support for the power-supply property to enable and
disable such a regulator whenever needed.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/panel/panel-lvds.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-lvds.c b/drivers/gpu/drm/panel/panel-lvds.c
index e2d57c01200b..57e38a9e7ab4 100644
--- a/drivers/gpu/drm/panel/panel-lvds.c
+++ b/drivers/gpu/drm/panel/panel-lvds.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 
 #include <drm/drmP.h>
@@ -39,6 +40,7 @@ struct panel_lvds {
 	bool data_mirror;
 
 	struct backlight_device *backlight;
+	struct regulator *supply;
 
 	struct gpio_desc *enable_gpio;
 	struct gpio_desc *reset_gpio;
@@ -69,6 +71,9 @@ static int panel_lvds_unprepare(struct drm_panel *panel)
 	if (lvds->enable_gpio)
 		gpiod_set_value_cansleep(lvds->enable_gpio, 0);
 
+	if (lvds->supply)
+		regulator_disable(lvds->supply);
+
 	return 0;
 }
 
@@ -76,6 +81,17 @@ static int panel_lvds_prepare(struct drm_panel *panel)
 {
 	struct panel_lvds *lvds = to_panel_lvds(panel);
 
+	if (lvds->supply) {
+		int err;
+
+		err = regulator_enable(lvds->supply);
+		if (err < 0) {
+			dev_err(lvds->dev, "failed to enable supply: %d\n",
+				err);
+			return err;
+		}
+	}
+
 	if (lvds->enable_gpio)
 		gpiod_set_value_cansleep(lvds->enable_gpio, 1);
 
@@ -196,6 +212,13 @@ static int panel_lvds_probe(struct platform_device *pdev)
 	if (ret < 0)
 		return ret;
 
+	lvds->supply = devm_regulator_get_optional(lvds->dev, "power");
+	if (IS_ERR(lvds->supply)) {
+		ret = PTR_ERR(lvds->supply);
+		dev_err(lvds->dev, "failed to request regulator: %d\n", ret);
+		return ret;
+	}
+
 	/* Get GPIOs and backlight controller. */
 	lvds->enable_gpio = devm_gpiod_get_optional(lvds->dev, "enable",
 						     GPIOD_OUT_LOW);
-- 
git-series 0.9.1

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

* [PATCH 09/23] drm/panel: lvds: Add support for the power-supply property
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

A significant number of panels need to power up a regulator in order to
operate properly. Add support for the power-supply property to enable and
disable such a regulator whenever needed.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/panel/panel-lvds.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-lvds.c b/drivers/gpu/drm/panel/panel-lvds.c
index e2d57c01200b..57e38a9e7ab4 100644
--- a/drivers/gpu/drm/panel/panel-lvds.c
+++ b/drivers/gpu/drm/panel/panel-lvds.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 
 #include <drm/drmP.h>
@@ -39,6 +40,7 @@ struct panel_lvds {
 	bool data_mirror;
 
 	struct backlight_device *backlight;
+	struct regulator *supply;
 
 	struct gpio_desc *enable_gpio;
 	struct gpio_desc *reset_gpio;
@@ -69,6 +71,9 @@ static int panel_lvds_unprepare(struct drm_panel *panel)
 	if (lvds->enable_gpio)
 		gpiod_set_value_cansleep(lvds->enable_gpio, 0);
 
+	if (lvds->supply)
+		regulator_disable(lvds->supply);
+
 	return 0;
 }
 
@@ -76,6 +81,17 @@ static int panel_lvds_prepare(struct drm_panel *panel)
 {
 	struct panel_lvds *lvds = to_panel_lvds(panel);
 
+	if (lvds->supply) {
+		int err;
+
+		err = regulator_enable(lvds->supply);
+		if (err < 0) {
+			dev_err(lvds->dev, "failed to enable supply: %d\n",
+				err);
+			return err;
+		}
+	}
+
 	if (lvds->enable_gpio)
 		gpiod_set_value_cansleep(lvds->enable_gpio, 1);
 
@@ -196,6 +212,13 @@ static int panel_lvds_probe(struct platform_device *pdev)
 	if (ret < 0)
 		return ret;
 
+	lvds->supply = devm_regulator_get_optional(lvds->dev, "power");
+	if (IS_ERR(lvds->supply)) {
+		ret = PTR_ERR(lvds->supply);
+		dev_err(lvds->dev, "failed to request regulator: %d\n", ret);
+		return ret;
+	}
+
 	/* Get GPIOs and backlight controller. */
 	lvds->enable_gpio = devm_gpiod_get_optional(lvds->dev, "enable",
 						     GPIOD_OUT_LOW);
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 09/23] drm/panel: lvds: Add support for the power-supply property
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

A significant number of panels need to power up a regulator in order to
operate properly. Add support for the power-supply property to enable and
disable such a regulator whenever needed.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/panel/panel-lvds.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-lvds.c b/drivers/gpu/drm/panel/panel-lvds.c
index e2d57c01200b..57e38a9e7ab4 100644
--- a/drivers/gpu/drm/panel/panel-lvds.c
+++ b/drivers/gpu/drm/panel/panel-lvds.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 
 #include <drm/drmP.h>
@@ -39,6 +40,7 @@ struct panel_lvds {
 	bool data_mirror;
 
 	struct backlight_device *backlight;
+	struct regulator *supply;
 
 	struct gpio_desc *enable_gpio;
 	struct gpio_desc *reset_gpio;
@@ -69,6 +71,9 @@ static int panel_lvds_unprepare(struct drm_panel *panel)
 	if (lvds->enable_gpio)
 		gpiod_set_value_cansleep(lvds->enable_gpio, 0);
 
+	if (lvds->supply)
+		regulator_disable(lvds->supply);
+
 	return 0;
 }
 
@@ -76,6 +81,17 @@ static int panel_lvds_prepare(struct drm_panel *panel)
 {
 	struct panel_lvds *lvds = to_panel_lvds(panel);
 
+	if (lvds->supply) {
+		int err;
+
+		err = regulator_enable(lvds->supply);
+		if (err < 0) {
+			dev_err(lvds->dev, "failed to enable supply: %d\n",
+				err);
+			return err;
+		}
+	}
+
 	if (lvds->enable_gpio)
 		gpiod_set_value_cansleep(lvds->enable_gpio, 1);
 
@@ -196,6 +212,13 @@ static int panel_lvds_probe(struct platform_device *pdev)
 	if (ret < 0)
 		return ret;
 
+	lvds->supply = devm_regulator_get_optional(lvds->dev, "power");
+	if (IS_ERR(lvds->supply)) {
+		ret = PTR_ERR(lvds->supply);
+		dev_err(lvds->dev, "failed to request regulator: %d\n", ret);
+		return ret;
+	}
+
 	/* Get GPIOs and backlight controller. */
 	lvds->enable_gpio = devm_gpiod_get_optional(lvds->dev, "enable",
 						     GPIOD_OUT_LOW);
-- 
git-series 0.9.1

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

* [PATCH 09/23] drm/panel: lvds: Add support for the power-supply property
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

A significant number of panels need to power up a regulator in order to
operate properly. Add support for the power-supply property to enable and
disable such a regulator whenever needed.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/panel/panel-lvds.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-lvds.c b/drivers/gpu/drm/panel/panel-lvds.c
index e2d57c01200b..57e38a9e7ab4 100644
--- a/drivers/gpu/drm/panel/panel-lvds.c
+++ b/drivers/gpu/drm/panel/panel-lvds.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 
 #include <drm/drmP.h>
@@ -39,6 +40,7 @@ struct panel_lvds {
 	bool data_mirror;
 
 	struct backlight_device *backlight;
+	struct regulator *supply;
 
 	struct gpio_desc *enable_gpio;
 	struct gpio_desc *reset_gpio;
@@ -69,6 +71,9 @@ static int panel_lvds_unprepare(struct drm_panel *panel)
 	if (lvds->enable_gpio)
 		gpiod_set_value_cansleep(lvds->enable_gpio, 0);
 
+	if (lvds->supply)
+		regulator_disable(lvds->supply);
+
 	return 0;
 }
 
@@ -76,6 +81,17 @@ static int panel_lvds_prepare(struct drm_panel *panel)
 {
 	struct panel_lvds *lvds = to_panel_lvds(panel);
 
+	if (lvds->supply) {
+		int err;
+
+		err = regulator_enable(lvds->supply);
+		if (err < 0) {
+			dev_err(lvds->dev, "failed to enable supply: %d\n",
+				err);
+			return err;
+		}
+	}
+
 	if (lvds->enable_gpio)
 		gpiod_set_value_cansleep(lvds->enable_gpio, 1);
 
@@ -196,6 +212,13 @@ static int panel_lvds_probe(struct platform_device *pdev)
 	if (ret < 0)
 		return ret;
 
+	lvds->supply = devm_regulator_get_optional(lvds->dev, "power");
+	if (IS_ERR(lvds->supply)) {
+		ret = PTR_ERR(lvds->supply);
+		dev_err(lvds->dev, "failed to request regulator: %d\n", ret);
+		return ret;
+	}
+
 	/* Get GPIOs and backlight controller. */
 	lvds->enable_gpio = devm_gpiod_get_optional(lvds->dev, "enable",
 						     GPIOD_OUT_LOW);
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 10/23] clk: sunxi-ng: Add A83T display clocks
  2017-10-17  9:06 ` Maxime Ripard
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

Unfortunately, the A83t display clocks are not children of the de clock,
since that clocks doesn't exist at all on the A83t.

For now, they are orphans, so let's move them to their true, existing,
parent.

Fixes: 763c5bd045b1 ("clk: sunxi-ng: add support for DE2 CCU")
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
index 5cdaf52669e4..5cc9d9952121 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
@@ -41,11 +41,16 @@ static SUNXI_CCU_GATE(wb_clk,		"wb",		"wb-div",
 
 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 SUNXI_CCU_M(mixer0_div_a83_clk, "mixer0-div", "pll-de", 0x0c, 0, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(mixer1_div_a83_clk, "mixer1-div", "pll-de", 0x0c, 4, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(wb_div_a83_clk, "wb-div", "pll-de", 0x0c, 8, 4,
+		   CLK_SET_RATE_PARENT);
+
 static struct ccu_common *sun8i_a83t_de2_clks[] = {
 	&mixer0_clk.common,
 	&mixer1_clk.common,
@@ -55,9 +60,9 @@ static struct ccu_common *sun8i_a83t_de2_clks[] = {
 	&bus_mixer1_clk.common,
 	&bus_wb_clk.common,
 
-	&mixer0_div_clk.common,
-	&mixer1_div_clk.common,
-	&wb_div_clk.common,
+	&mixer0_div_a83_clk.common,
+	&mixer1_div_a83_clk.common,
+	&wb_div_a83_clk.common,
 };
 
 static struct ccu_common *sun8i_v3s_de2_clks[] = {
@@ -81,9 +86,9 @@ static struct clk_hw_onecell_data sun8i_a83t_de2_hw_clks = {
 		[CLK_BUS_MIXER1]	= &bus_mixer1_clk.common.hw,
 		[CLK_BUS_WB]		= &bus_wb_clk.common.hw,
 
-		[CLK_MIXER0_DIV]	= &mixer0_div_clk.common.hw,
-		[CLK_MIXER1_DIV]	= &mixer1_div_clk.common.hw,
-		[CLK_WB_DIV]		= &wb_div_clk.common.hw,
+		[CLK_MIXER0_DIV]	= &mixer0_div_a83_clk.common.hw,
+		[CLK_MIXER1_DIV]	= &mixer1_div_a83_clk.common.hw,
+		[CLK_WB_DIV]		= &wb_div_a83_clk.common.hw,
 	},
 	.num	= CLK_NUMBER,
 };
-- 
git-series 0.9.1

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

* [PATCH 10/23] clk: sunxi-ng: Add A83T display clocks
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

Unfortunately, the A83t display clocks are not children of the de clock,
since that clocks doesn't exist at all on the A83t.

For now, they are orphans, so let's move them to their true, existing,
parent.

Fixes: 763c5bd045b1 ("clk: sunxi-ng: add support for DE2 CCU")
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
index 5cdaf52669e4..5cc9d9952121 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
@@ -41,11 +41,16 @@ static SUNXI_CCU_GATE(wb_clk,		"wb",		"wb-div",
 
 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 SUNXI_CCU_M(mixer0_div_a83_clk, "mixer0-div", "pll-de", 0x0c, 0, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(mixer1_div_a83_clk, "mixer1-div", "pll-de", 0x0c, 4, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(wb_div_a83_clk, "wb-div", "pll-de", 0x0c, 8, 4,
+		   CLK_SET_RATE_PARENT);
+
 static struct ccu_common *sun8i_a83t_de2_clks[] = {
 	&mixer0_clk.common,
 	&mixer1_clk.common,
@@ -55,9 +60,9 @@ static struct ccu_common *sun8i_a83t_de2_clks[] = {
 	&bus_mixer1_clk.common,
 	&bus_wb_clk.common,
 
-	&mixer0_div_clk.common,
-	&mixer1_div_clk.common,
-	&wb_div_clk.common,
+	&mixer0_div_a83_clk.common,
+	&mixer1_div_a83_clk.common,
+	&wb_div_a83_clk.common,
 };
 
 static struct ccu_common *sun8i_v3s_de2_clks[] = {
@@ -81,9 +86,9 @@ static struct clk_hw_onecell_data sun8i_a83t_de2_hw_clks = {
 		[CLK_BUS_MIXER1]	= &bus_mixer1_clk.common.hw,
 		[CLK_BUS_WB]		= &bus_wb_clk.common.hw,
 
-		[CLK_MIXER0_DIV]	= &mixer0_div_clk.common.hw,
-		[CLK_MIXER1_DIV]	= &mixer1_div_clk.common.hw,
-		[CLK_WB_DIV]		= &wb_div_clk.common.hw,
+		[CLK_MIXER0_DIV]	= &mixer0_div_a83_clk.common.hw,
+		[CLK_MIXER1_DIV]	= &mixer1_div_a83_clk.common.hw,
+		[CLK_WB_DIV]		= &wb_div_a83_clk.common.hw,
 	},
 	.num	= CLK_NUMBER,
 };
-- 
git-series 0.9.1

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

* [PATCH 10/23] clk: sunxi-ng: Add A83T display clocks
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

Unfortunately, the A83t display clocks are not children of the de clock,
since that clocks doesn't exist at all on the A83t.

For now, they are orphans, so let's move them to their true, existing,
parent.

Fixes: 763c5bd045b1 ("clk: sunxi-ng: add support for DE2 CCU")
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
index 5cdaf52669e4..5cc9d9952121 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
@@ -41,11 +41,16 @@ static SUNXI_CCU_GATE(wb_clk,		"wb",		"wb-div",
 
 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 SUNXI_CCU_M(mixer0_div_a83_clk, "mixer0-div", "pll-de", 0x0c, 0, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(mixer1_div_a83_clk, "mixer1-div", "pll-de", 0x0c, 4, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(wb_div_a83_clk, "wb-div", "pll-de", 0x0c, 8, 4,
+		   CLK_SET_RATE_PARENT);
+
 static struct ccu_common *sun8i_a83t_de2_clks[] = {
 	&mixer0_clk.common,
 	&mixer1_clk.common,
@@ -55,9 +60,9 @@ static struct ccu_common *sun8i_a83t_de2_clks[] = {
 	&bus_mixer1_clk.common,
 	&bus_wb_clk.common,
 
-	&mixer0_div_clk.common,
-	&mixer1_div_clk.common,
-	&wb_div_clk.common,
+	&mixer0_div_a83_clk.common,
+	&mixer1_div_a83_clk.common,
+	&wb_div_a83_clk.common,
 };
 
 static struct ccu_common *sun8i_v3s_de2_clks[] = {
@@ -81,9 +86,9 @@ static struct clk_hw_onecell_data sun8i_a83t_de2_hw_clks = {
 		[CLK_BUS_MIXER1]	= &bus_mixer1_clk.common.hw,
 		[CLK_BUS_WB]		= &bus_wb_clk.common.hw,
 
-		[CLK_MIXER0_DIV]	= &mixer0_div_clk.common.hw,
-		[CLK_MIXER1_DIV]	= &mixer1_div_clk.common.hw,
-		[CLK_WB_DIV]		= &wb_div_clk.common.hw,
+		[CLK_MIXER0_DIV]	= &mixer0_div_a83_clk.common.hw,
+		[CLK_MIXER1_DIV]	= &mixer1_div_a83_clk.common.hw,
+		[CLK_WB_DIV]		= &wb_div_a83_clk.common.hw,
 	},
 	.num	= CLK_NUMBER,
 };
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 11/23] drm/sun4i: Rename layers to UI planes
  2017-10-17  9:06 ` Maxime Ripard
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

The currently supported planes for DE2 are actually only UI planes, and the
VI planes will differ both in terms of code and features.

It will make sense to support them in a separate file, so let's make sure
we don't create a confusing file name.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/Makefile      |   2 +-
 drivers/gpu/drm/sun4i/sun8i_layer.c | 134 +-----------------------------
 drivers/gpu/drm/sun4i/sun8i_layer.h |  36 +--------
 drivers/gpu/drm/sun4i/sun8i_mixer.c |   4 +-
 drivers/gpu/drm/sun4i/sun8i_ui.c    | 134 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun8i_ui.h    |  36 ++++++++-
 6 files changed, 173 insertions(+), 173 deletions(-)
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.h

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index af18b70ba5ed..cfba2c07519c 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -13,7 +13,7 @@ sun4i-tcon-y			+= sun4i_rgb.o
 sun4i-tcon-y			+= sun4i_dotclock.o
 sun4i-tcon-y			+= sun4i_crtc.o
 
-sun8i-mixer-y			+= sun8i_mixer.o sun8i_layer.o
+sun8i-mixer-y			+= sun8i_mixer.o sun8i_ui.o
 
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c
deleted file mode 100644
index 23810ff72684..000000000000
--- a/drivers/gpu/drm/sun4i/sun8i_layer.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
- *
- * Based on sun4i_layer.h, which is:
- *   Copyright (C) 2015 Free Electrons
- *   Copyright (C) 2015 NextThing Co
- *
- *   Maxime Ripard <maxime.ripard@free-electrons.com>
- *
- * 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/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
-#include <drm/drmP.h>
-
-#include "sun8i_layer.h"
-#include "sun8i_mixer.h"
-
-struct sun8i_plane_desc {
-	       enum drm_plane_type     type;
-	       const uint32_t          *formats;
-	       uint32_t                nformats;
-};
-
-static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane,
-					       struct drm_plane_state *old_state)
-{
-	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
-	struct sun8i_mixer *mixer = layer->mixer;
-
-	sun8i_mixer_layer_enable(mixer, layer->id, false);
-}
-
-static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
-					      struct drm_plane_state *old_state)
-{
-	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
-	struct sun8i_mixer *mixer = layer->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 sun8i_mixer_layer_helper_funcs = {
-	.atomic_disable	= sun8i_mixer_layer_atomic_disable,
-	.atomic_update	= sun8i_mixer_layer_atomic_update,
-};
-
-static const struct drm_plane_funcs sun8i_mixer_layer_funcs = {
-	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
-	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
-	.destroy		= drm_plane_cleanup,
-	.disable_plane		= drm_atomic_helper_disable_plane,
-	.reset			= drm_atomic_helper_plane_reset,
-	.update_plane		= drm_atomic_helper_update_plane,
-};
-
-static const uint32_t sun8i_mixer_layer_formats[] = {
-	DRM_FORMAT_RGB888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_XRGB8888,
-};
-
-static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
-	{
-		.type = DRM_PLANE_TYPE_PRIMARY,
-		.formats = sun8i_mixer_layer_formats,
-		.nformats = ARRAY_SIZE(sun8i_mixer_layer_formats),
-	},
-};
-
-static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
-						struct sun8i_mixer *mixer,
-						const struct sun8i_plane_desc *plane)
-{
-	struct sun8i_layer *layer;
-	int ret;
-
-	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
-	if (!layer)
-		return ERR_PTR(-ENOMEM);
-
-	/* possible crtcs are set later */
-	ret = drm_universal_plane_init(drm, &layer->plane, 0,
-				       &sun8i_mixer_layer_funcs,
-				       plane->formats, plane->nformats,
-				       NULL, plane->type, NULL);
-	if (ret) {
-		dev_err(drm->dev, "Couldn't initialize layer\n");
-		return ERR_PTR(ret);
-	}
-
-	drm_plane_helper_add(&layer->plane,
-			     &sun8i_mixer_layer_helper_funcs);
-	layer->mixer = mixer;
-
-	return layer;
-}
-
-struct drm_plane **sun8i_layers_init(struct drm_device *drm,
-				     struct sunxi_engine *engine)
-{
-	struct drm_plane **planes;
-	struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
-	int i;
-
-	planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
-			      sizeof(*planes), GFP_KERNEL);
-	if (!planes)
-		return ERR_PTR(-ENOMEM);
-
-	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
-		const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
-		struct sun8i_layer *layer;
-
-		layer = sun8i_layer_init_one(drm, 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;
-		planes[i] = &layer->plane;
-	};
-
-	return planes;
-}
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.h b/drivers/gpu/drm/sun4i/sun8i_layer.h
deleted file mode 100644
index e5eccd27cff0..000000000000
--- a/drivers/gpu/drm/sun4i/sun8i_layer.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
- *
- * Based on sun4i_layer.h, which is:
- *   Copyright (C) 2015 Free Electrons
- *   Copyright (C) 2015 NextThing Co
- *
- *   Maxime Ripard <maxime.ripard@free-electrons.com>
- *
- * 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_LAYER_H_
-#define _SUN8I_LAYER_H_
-
-struct sunxi_engine;
-
-struct sun8i_layer {
-	struct drm_plane	plane;
-	struct sun4i_drv	*drv;
-	struct sun8i_mixer	*mixer;
-	int			id;
-};
-
-static inline struct sun8i_layer *
-plane_to_sun8i_layer(struct drm_plane *plane)
-{
-	return container_of(plane, struct sun8i_layer, plane);
-}
-
-struct drm_plane **sun8i_layers_init(struct drm_device *drm,
-				     struct sunxi_engine *engine);
-#endif /* _SUN8I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index cb193c5f1686..1955b2a36ac5 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -26,7 +26,7 @@
 
 #include "sun4i_drv.h"
 #include "sun8i_mixer.h"
-#include "sun8i_layer.h"
+#include "sun8i_ui.h"
 #include "sunxi_engine.h"
 
 static void sun8i_mixer_commit(struct sunxi_engine *engine)
@@ -228,7 +228,7 @@ int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
 
 static const struct sunxi_engine_ops sun8i_engine_ops = {
 	.commit		= sun8i_mixer_commit,
-	.layers_init	= sun8i_layers_init,
+	.layers_init	= sun8i_ui_init,
 };
 
 static struct regmap_config sun8i_mixer_regmap_config = {
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.c b/drivers/gpu/drm/sun4i/sun8i_ui.c
new file mode 100644
index 000000000000..077099ef565a
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_ui.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
+ *
+ * Based on sun4i_layer.h, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ *   Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * 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/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "sun8i_ui.h"
+#include "sun8i_mixer.h"
+
+struct sun8i_plane_desc {
+	       enum drm_plane_type     type;
+	       const uint32_t          *formats;
+	       uint32_t                nformats;
+};
+
+static void sun8i_mixer_ui_atomic_disable(struct drm_plane *plane,
+					  struct drm_plane_state *old_state)
+{
+	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
+	struct sun8i_mixer *mixer = ui->mixer;
+
+	sun8i_mixer_layer_enable(mixer, ui->id, false);
+}
+
+static void sun8i_mixer_ui_atomic_update(struct drm_plane *plane,
+					 struct drm_plane_state *old_state)
+{
+	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
+	struct sun8i_mixer *mixer = ui->mixer;
+
+	sun8i_mixer_update_layer_coord(mixer, ui->id, plane);
+	sun8i_mixer_update_layer_formats(mixer, ui->id, plane);
+	sun8i_mixer_update_layer_buffer(mixer, ui->id, plane);
+	sun8i_mixer_layer_enable(mixer, ui->id, true);
+}
+
+static struct drm_plane_helper_funcs sun8i_mixer_ui_helper_funcs = {
+	.atomic_disable	= sun8i_mixer_ui_atomic_disable,
+	.atomic_update	= sun8i_mixer_ui_atomic_update,
+};
+
+static const struct drm_plane_funcs sun8i_mixer_ui_funcs = {
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
+	.destroy		= drm_plane_cleanup,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.reset			= drm_atomic_helper_plane_reset,
+	.update_plane		= drm_atomic_helper_update_plane,
+};
+
+static const uint32_t sun8i_mixer_ui_formats[] = {
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XRGB8888,
+};
+
+static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
+	{
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.formats = sun8i_mixer_ui_formats,
+		.nformats = ARRAY_SIZE(sun8i_mixer_ui_formats),
+	},
+};
+
+static struct sun8i_ui *sun8i_ui_init_one(struct drm_device *drm,
+					  struct sun8i_mixer *mixer,
+					  const struct sun8i_plane_desc *plane)
+{
+	struct sun8i_ui *ui;
+	int ret;
+
+	ui = devm_kzalloc(drm->dev, sizeof(*ui), GFP_KERNEL);
+	if (!ui)
+		return ERR_PTR(-ENOMEM);
+
+	/* possible crtcs are set later */
+	ret = drm_universal_plane_init(drm, &ui->plane, 0,
+				       &sun8i_mixer_ui_funcs,
+				       plane->formats, plane->nformats,
+				       NULL, plane->type, NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialize ui\n");
+		return ERR_PTR(ret);
+	}
+
+	drm_plane_helper_add(&ui->plane,
+			     &sun8i_mixer_ui_helper_funcs);
+	ui->mixer = mixer;
+
+	return ui;
+}
+
+struct drm_plane **sun8i_ui_init(struct drm_device *drm,
+				 struct sunxi_engine *engine)
+{
+	struct drm_plane **planes;
+	struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
+	int i;
+
+	planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
+			      sizeof(*planes), GFP_KERNEL);
+	if (!planes)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
+		const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
+		struct sun8i_ui *ui;
+
+		ui = sun8i_ui_init_one(drm, mixer, plane);
+		if (IS_ERR(ui)) {
+			dev_err(drm->dev, "Couldn't initialize %s plane\n",
+				i ? "overlay" : "primary");
+			return ERR_CAST(ui);
+		};
+
+		ui->id = i;
+		planes[i] = &ui->plane;
+	};
+
+	return planes;
+}
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.h b/drivers/gpu/drm/sun4i/sun8i_ui.h
new file mode 100644
index 000000000000..17dfc92ccc9f
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_ui.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
+ *
+ * Based on sun4i_layer.h, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ *   Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * 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_UI_H_
+#define _SUN8I_UI_H_
+
+struct sunxi_engine;
+
+struct sun8i_ui {
+	struct drm_plane	plane;
+	struct sun4i_drv	*drv;
+	struct sun8i_mixer	*mixer;
+	int			id;
+};
+
+static inline struct sun8i_ui *
+plane_to_sun8i_ui(struct drm_plane *plane)
+{
+	return container_of(plane, struct sun8i_ui, plane);
+}
+
+struct drm_plane **sun8i_ui_init(struct drm_device *drm,
+				 struct sunxi_engine *engine);
+#endif /* _SUN8I_UI_H_ */
-- 
git-series 0.9.1

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

* [PATCH 11/23] drm/sun4i: Rename layers to UI planes
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

The currently supported planes for DE2 are actually only UI planes, and the
VI planes will differ both in terms of code and features.

It will make sense to support them in a separate file, so let's make sure
we don't create a confusing file name.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/Makefile      |   2 +-
 drivers/gpu/drm/sun4i/sun8i_layer.c | 134 +-----------------------------
 drivers/gpu/drm/sun4i/sun8i_layer.h |  36 +--------
 drivers/gpu/drm/sun4i/sun8i_mixer.c |   4 +-
 drivers/gpu/drm/sun4i/sun8i_ui.c    | 134 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun8i_ui.h    |  36 ++++++++-
 6 files changed, 173 insertions(+), 173 deletions(-)
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.h

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index af18b70ba5ed..cfba2c07519c 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -13,7 +13,7 @@ sun4i-tcon-y			+= sun4i_rgb.o
 sun4i-tcon-y			+= sun4i_dotclock.o
 sun4i-tcon-y			+= sun4i_crtc.o
 
-sun8i-mixer-y			+= sun8i_mixer.o sun8i_layer.o
+sun8i-mixer-y			+= sun8i_mixer.o sun8i_ui.o
 
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c
deleted file mode 100644
index 23810ff72684..000000000000
--- a/drivers/gpu/drm/sun4i/sun8i_layer.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
- *
- * Based on sun4i_layer.h, which is:
- *   Copyright (C) 2015 Free Electrons
- *   Copyright (C) 2015 NextThing Co
- *
- *   Maxime Ripard <maxime.ripard@free-electrons.com>
- *
- * 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/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
-#include <drm/drmP.h>
-
-#include "sun8i_layer.h"
-#include "sun8i_mixer.h"
-
-struct sun8i_plane_desc {
-	       enum drm_plane_type     type;
-	       const uint32_t          *formats;
-	       uint32_t                nformats;
-};
-
-static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane,
-					       struct drm_plane_state *old_state)
-{
-	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
-	struct sun8i_mixer *mixer = layer->mixer;
-
-	sun8i_mixer_layer_enable(mixer, layer->id, false);
-}
-
-static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
-					      struct drm_plane_state *old_state)
-{
-	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
-	struct sun8i_mixer *mixer = layer->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 sun8i_mixer_layer_helper_funcs = {
-	.atomic_disable	= sun8i_mixer_layer_atomic_disable,
-	.atomic_update	= sun8i_mixer_layer_atomic_update,
-};
-
-static const struct drm_plane_funcs sun8i_mixer_layer_funcs = {
-	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
-	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
-	.destroy		= drm_plane_cleanup,
-	.disable_plane		= drm_atomic_helper_disable_plane,
-	.reset			= drm_atomic_helper_plane_reset,
-	.update_plane		= drm_atomic_helper_update_plane,
-};
-
-static const uint32_t sun8i_mixer_layer_formats[] = {
-	DRM_FORMAT_RGB888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_XRGB8888,
-};
-
-static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
-	{
-		.type = DRM_PLANE_TYPE_PRIMARY,
-		.formats = sun8i_mixer_layer_formats,
-		.nformats = ARRAY_SIZE(sun8i_mixer_layer_formats),
-	},
-};
-
-static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
-						struct sun8i_mixer *mixer,
-						const struct sun8i_plane_desc *plane)
-{
-	struct sun8i_layer *layer;
-	int ret;
-
-	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
-	if (!layer)
-		return ERR_PTR(-ENOMEM);
-
-	/* possible crtcs are set later */
-	ret = drm_universal_plane_init(drm, &layer->plane, 0,
-				       &sun8i_mixer_layer_funcs,
-				       plane->formats, plane->nformats,
-				       NULL, plane->type, NULL);
-	if (ret) {
-		dev_err(drm->dev, "Couldn't initialize layer\n");
-		return ERR_PTR(ret);
-	}
-
-	drm_plane_helper_add(&layer->plane,
-			     &sun8i_mixer_layer_helper_funcs);
-	layer->mixer = mixer;
-
-	return layer;
-}
-
-struct drm_plane **sun8i_layers_init(struct drm_device *drm,
-				     struct sunxi_engine *engine)
-{
-	struct drm_plane **planes;
-	struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
-	int i;
-
-	planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
-			      sizeof(*planes), GFP_KERNEL);
-	if (!planes)
-		return ERR_PTR(-ENOMEM);
-
-	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
-		const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
-		struct sun8i_layer *layer;
-
-		layer = sun8i_layer_init_one(drm, 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;
-		planes[i] = &layer->plane;
-	};
-
-	return planes;
-}
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.h b/drivers/gpu/drm/sun4i/sun8i_layer.h
deleted file mode 100644
index e5eccd27cff0..000000000000
--- a/drivers/gpu/drm/sun4i/sun8i_layer.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
- *
- * Based on sun4i_layer.h, which is:
- *   Copyright (C) 2015 Free Electrons
- *   Copyright (C) 2015 NextThing Co
- *
- *   Maxime Ripard <maxime.ripard@free-electrons.com>
- *
- * 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_LAYER_H_
-#define _SUN8I_LAYER_H_
-
-struct sunxi_engine;
-
-struct sun8i_layer {
-	struct drm_plane	plane;
-	struct sun4i_drv	*drv;
-	struct sun8i_mixer	*mixer;
-	int			id;
-};
-
-static inline struct sun8i_layer *
-plane_to_sun8i_layer(struct drm_plane *plane)
-{
-	return container_of(plane, struct sun8i_layer, plane);
-}
-
-struct drm_plane **sun8i_layers_init(struct drm_device *drm,
-				     struct sunxi_engine *engine);
-#endif /* _SUN8I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index cb193c5f1686..1955b2a36ac5 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -26,7 +26,7 @@
 
 #include "sun4i_drv.h"
 #include "sun8i_mixer.h"
-#include "sun8i_layer.h"
+#include "sun8i_ui.h"
 #include "sunxi_engine.h"
 
 static void sun8i_mixer_commit(struct sunxi_engine *engine)
@@ -228,7 +228,7 @@ int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
 
 static const struct sunxi_engine_ops sun8i_engine_ops = {
 	.commit		= sun8i_mixer_commit,
-	.layers_init	= sun8i_layers_init,
+	.layers_init	= sun8i_ui_init,
 };
 
 static struct regmap_config sun8i_mixer_regmap_config = {
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.c b/drivers/gpu/drm/sun4i/sun8i_ui.c
new file mode 100644
index 000000000000..077099ef565a
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_ui.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
+ *
+ * Based on sun4i_layer.h, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ *   Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * 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/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "sun8i_ui.h"
+#include "sun8i_mixer.h"
+
+struct sun8i_plane_desc {
+	       enum drm_plane_type     type;
+	       const uint32_t          *formats;
+	       uint32_t                nformats;
+};
+
+static void sun8i_mixer_ui_atomic_disable(struct drm_plane *plane,
+					  struct drm_plane_state *old_state)
+{
+	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
+	struct sun8i_mixer *mixer = ui->mixer;
+
+	sun8i_mixer_layer_enable(mixer, ui->id, false);
+}
+
+static void sun8i_mixer_ui_atomic_update(struct drm_plane *plane,
+					 struct drm_plane_state *old_state)
+{
+	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
+	struct sun8i_mixer *mixer = ui->mixer;
+
+	sun8i_mixer_update_layer_coord(mixer, ui->id, plane);
+	sun8i_mixer_update_layer_formats(mixer, ui->id, plane);
+	sun8i_mixer_update_layer_buffer(mixer, ui->id, plane);
+	sun8i_mixer_layer_enable(mixer, ui->id, true);
+}
+
+static struct drm_plane_helper_funcs sun8i_mixer_ui_helper_funcs = {
+	.atomic_disable	= sun8i_mixer_ui_atomic_disable,
+	.atomic_update	= sun8i_mixer_ui_atomic_update,
+};
+
+static const struct drm_plane_funcs sun8i_mixer_ui_funcs = {
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
+	.destroy		= drm_plane_cleanup,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.reset			= drm_atomic_helper_plane_reset,
+	.update_plane		= drm_atomic_helper_update_plane,
+};
+
+static const uint32_t sun8i_mixer_ui_formats[] = {
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XRGB8888,
+};
+
+static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
+	{
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.formats = sun8i_mixer_ui_formats,
+		.nformats = ARRAY_SIZE(sun8i_mixer_ui_formats),
+	},
+};
+
+static struct sun8i_ui *sun8i_ui_init_one(struct drm_device *drm,
+					  struct sun8i_mixer *mixer,
+					  const struct sun8i_plane_desc *plane)
+{
+	struct sun8i_ui *ui;
+	int ret;
+
+	ui = devm_kzalloc(drm->dev, sizeof(*ui), GFP_KERNEL);
+	if (!ui)
+		return ERR_PTR(-ENOMEM);
+
+	/* possible crtcs are set later */
+	ret = drm_universal_plane_init(drm, &ui->plane, 0,
+				       &sun8i_mixer_ui_funcs,
+				       plane->formats, plane->nformats,
+				       NULL, plane->type, NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialize ui\n");
+		return ERR_PTR(ret);
+	}
+
+	drm_plane_helper_add(&ui->plane,
+			     &sun8i_mixer_ui_helper_funcs);
+	ui->mixer = mixer;
+
+	return ui;
+}
+
+struct drm_plane **sun8i_ui_init(struct drm_device *drm,
+				 struct sunxi_engine *engine)
+{
+	struct drm_plane **planes;
+	struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
+	int i;
+
+	planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
+			      sizeof(*planes), GFP_KERNEL);
+	if (!planes)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
+		const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
+		struct sun8i_ui *ui;
+
+		ui = sun8i_ui_init_one(drm, mixer, plane);
+		if (IS_ERR(ui)) {
+			dev_err(drm->dev, "Couldn't initialize %s plane\n",
+				i ? "overlay" : "primary");
+			return ERR_CAST(ui);
+		};
+
+		ui->id = i;
+		planes[i] = &ui->plane;
+	};
+
+	return planes;
+}
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.h b/drivers/gpu/drm/sun4i/sun8i_ui.h
new file mode 100644
index 000000000000..17dfc92ccc9f
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_ui.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
+ *
+ * Based on sun4i_layer.h, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ *   Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * 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_UI_H_
+#define _SUN8I_UI_H_
+
+struct sunxi_engine;
+
+struct sun8i_ui {
+	struct drm_plane	plane;
+	struct sun4i_drv	*drv;
+	struct sun8i_mixer	*mixer;
+	int			id;
+};
+
+static inline struct sun8i_ui *
+plane_to_sun8i_ui(struct drm_plane *plane)
+{
+	return container_of(plane, struct sun8i_ui, plane);
+}
+
+struct drm_plane **sun8i_ui_init(struct drm_device *drm,
+				 struct sunxi_engine *engine);
+#endif /* _SUN8I_UI_H_ */
-- 
git-series 0.9.1

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

* [PATCH 11/23] drm/sun4i: Rename layers to UI planes
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The currently supported planes for DE2 are actually only UI planes, and the
VI planes will differ both in terms of code and features.

It will make sense to support them in a separate file, so let's make sure
we don't create a confusing file name.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/Makefile      |   2 +-
 drivers/gpu/drm/sun4i/sun8i_layer.c | 134 +-----------------------------
 drivers/gpu/drm/sun4i/sun8i_layer.h |  36 +--------
 drivers/gpu/drm/sun4i/sun8i_mixer.c |   4 +-
 drivers/gpu/drm/sun4i/sun8i_ui.c    | 134 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun8i_ui.h    |  36 ++++++++-
 6 files changed, 173 insertions(+), 173 deletions(-)
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.h

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index af18b70ba5ed..cfba2c07519c 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -13,7 +13,7 @@ sun4i-tcon-y			+= sun4i_rgb.o
 sun4i-tcon-y			+= sun4i_dotclock.o
 sun4i-tcon-y			+= sun4i_crtc.o
 
-sun8i-mixer-y			+= sun8i_mixer.o sun8i_layer.o
+sun8i-mixer-y			+= sun8i_mixer.o sun8i_ui.o
 
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c
deleted file mode 100644
index 23810ff72684..000000000000
--- a/drivers/gpu/drm/sun4i/sun8i_layer.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
- *
- * Based on sun4i_layer.h, which is:
- *   Copyright (C) 2015 Free Electrons
- *   Copyright (C) 2015 NextThing Co
- *
- *   Maxime Ripard <maxime.ripard@free-electrons.com>
- *
- * 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/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
-#include <drm/drmP.h>
-
-#include "sun8i_layer.h"
-#include "sun8i_mixer.h"
-
-struct sun8i_plane_desc {
-	       enum drm_plane_type     type;
-	       const uint32_t          *formats;
-	       uint32_t                nformats;
-};
-
-static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane,
-					       struct drm_plane_state *old_state)
-{
-	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
-	struct sun8i_mixer *mixer = layer->mixer;
-
-	sun8i_mixer_layer_enable(mixer, layer->id, false);
-}
-
-static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
-					      struct drm_plane_state *old_state)
-{
-	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
-	struct sun8i_mixer *mixer = layer->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 sun8i_mixer_layer_helper_funcs = {
-	.atomic_disable	= sun8i_mixer_layer_atomic_disable,
-	.atomic_update	= sun8i_mixer_layer_atomic_update,
-};
-
-static const struct drm_plane_funcs sun8i_mixer_layer_funcs = {
-	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
-	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
-	.destroy		= drm_plane_cleanup,
-	.disable_plane		= drm_atomic_helper_disable_plane,
-	.reset			= drm_atomic_helper_plane_reset,
-	.update_plane		= drm_atomic_helper_update_plane,
-};
-
-static const uint32_t sun8i_mixer_layer_formats[] = {
-	DRM_FORMAT_RGB888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_XRGB8888,
-};
-
-static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
-	{
-		.type = DRM_PLANE_TYPE_PRIMARY,
-		.formats = sun8i_mixer_layer_formats,
-		.nformats = ARRAY_SIZE(sun8i_mixer_layer_formats),
-	},
-};
-
-static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
-						struct sun8i_mixer *mixer,
-						const struct sun8i_plane_desc *plane)
-{
-	struct sun8i_layer *layer;
-	int ret;
-
-	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
-	if (!layer)
-		return ERR_PTR(-ENOMEM);
-
-	/* possible crtcs are set later */
-	ret = drm_universal_plane_init(drm, &layer->plane, 0,
-				       &sun8i_mixer_layer_funcs,
-				       plane->formats, plane->nformats,
-				       NULL, plane->type, NULL);
-	if (ret) {
-		dev_err(drm->dev, "Couldn't initialize layer\n");
-		return ERR_PTR(ret);
-	}
-
-	drm_plane_helper_add(&layer->plane,
-			     &sun8i_mixer_layer_helper_funcs);
-	layer->mixer = mixer;
-
-	return layer;
-}
-
-struct drm_plane **sun8i_layers_init(struct drm_device *drm,
-				     struct sunxi_engine *engine)
-{
-	struct drm_plane **planes;
-	struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
-	int i;
-
-	planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
-			      sizeof(*planes), GFP_KERNEL);
-	if (!planes)
-		return ERR_PTR(-ENOMEM);
-
-	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
-		const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
-		struct sun8i_layer *layer;
-
-		layer = sun8i_layer_init_one(drm, 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;
-		planes[i] = &layer->plane;
-	};
-
-	return planes;
-}
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.h b/drivers/gpu/drm/sun4i/sun8i_layer.h
deleted file mode 100644
index e5eccd27cff0..000000000000
--- a/drivers/gpu/drm/sun4i/sun8i_layer.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
- *
- * Based on sun4i_layer.h, which is:
- *   Copyright (C) 2015 Free Electrons
- *   Copyright (C) 2015 NextThing Co
- *
- *   Maxime Ripard <maxime.ripard@free-electrons.com>
- *
- * 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_LAYER_H_
-#define _SUN8I_LAYER_H_
-
-struct sunxi_engine;
-
-struct sun8i_layer {
-	struct drm_plane	plane;
-	struct sun4i_drv	*drv;
-	struct sun8i_mixer	*mixer;
-	int			id;
-};
-
-static inline struct sun8i_layer *
-plane_to_sun8i_layer(struct drm_plane *plane)
-{
-	return container_of(plane, struct sun8i_layer, plane);
-}
-
-struct drm_plane **sun8i_layers_init(struct drm_device *drm,
-				     struct sunxi_engine *engine);
-#endif /* _SUN8I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index cb193c5f1686..1955b2a36ac5 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -26,7 +26,7 @@
 
 #include "sun4i_drv.h"
 #include "sun8i_mixer.h"
-#include "sun8i_layer.h"
+#include "sun8i_ui.h"
 #include "sunxi_engine.h"
 
 static void sun8i_mixer_commit(struct sunxi_engine *engine)
@@ -228,7 +228,7 @@ int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
 
 static const struct sunxi_engine_ops sun8i_engine_ops = {
 	.commit		= sun8i_mixer_commit,
-	.layers_init	= sun8i_layers_init,
+	.layers_init	= sun8i_ui_init,
 };
 
 static struct regmap_config sun8i_mixer_regmap_config = {
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.c b/drivers/gpu/drm/sun4i/sun8i_ui.c
new file mode 100644
index 000000000000..077099ef565a
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_ui.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
+ *
+ * Based on sun4i_layer.h, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ *   Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * 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/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "sun8i_ui.h"
+#include "sun8i_mixer.h"
+
+struct sun8i_plane_desc {
+	       enum drm_plane_type     type;
+	       const uint32_t          *formats;
+	       uint32_t                nformats;
+};
+
+static void sun8i_mixer_ui_atomic_disable(struct drm_plane *plane,
+					  struct drm_plane_state *old_state)
+{
+	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
+	struct sun8i_mixer *mixer = ui->mixer;
+
+	sun8i_mixer_layer_enable(mixer, ui->id, false);
+}
+
+static void sun8i_mixer_ui_atomic_update(struct drm_plane *plane,
+					 struct drm_plane_state *old_state)
+{
+	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
+	struct sun8i_mixer *mixer = ui->mixer;
+
+	sun8i_mixer_update_layer_coord(mixer, ui->id, plane);
+	sun8i_mixer_update_layer_formats(mixer, ui->id, plane);
+	sun8i_mixer_update_layer_buffer(mixer, ui->id, plane);
+	sun8i_mixer_layer_enable(mixer, ui->id, true);
+}
+
+static struct drm_plane_helper_funcs sun8i_mixer_ui_helper_funcs = {
+	.atomic_disable	= sun8i_mixer_ui_atomic_disable,
+	.atomic_update	= sun8i_mixer_ui_atomic_update,
+};
+
+static const struct drm_plane_funcs sun8i_mixer_ui_funcs = {
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
+	.destroy		= drm_plane_cleanup,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.reset			= drm_atomic_helper_plane_reset,
+	.update_plane		= drm_atomic_helper_update_plane,
+};
+
+static const uint32_t sun8i_mixer_ui_formats[] = {
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XRGB8888,
+};
+
+static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
+	{
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.formats = sun8i_mixer_ui_formats,
+		.nformats = ARRAY_SIZE(sun8i_mixer_ui_formats),
+	},
+};
+
+static struct sun8i_ui *sun8i_ui_init_one(struct drm_device *drm,
+					  struct sun8i_mixer *mixer,
+					  const struct sun8i_plane_desc *plane)
+{
+	struct sun8i_ui *ui;
+	int ret;
+
+	ui = devm_kzalloc(drm->dev, sizeof(*ui), GFP_KERNEL);
+	if (!ui)
+		return ERR_PTR(-ENOMEM);
+
+	/* possible crtcs are set later */
+	ret = drm_universal_plane_init(drm, &ui->plane, 0,
+				       &sun8i_mixer_ui_funcs,
+				       plane->formats, plane->nformats,
+				       NULL, plane->type, NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialize ui\n");
+		return ERR_PTR(ret);
+	}
+
+	drm_plane_helper_add(&ui->plane,
+			     &sun8i_mixer_ui_helper_funcs);
+	ui->mixer = mixer;
+
+	return ui;
+}
+
+struct drm_plane **sun8i_ui_init(struct drm_device *drm,
+				 struct sunxi_engine *engine)
+{
+	struct drm_plane **planes;
+	struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
+	int i;
+
+	planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
+			      sizeof(*planes), GFP_KERNEL);
+	if (!planes)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
+		const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
+		struct sun8i_ui *ui;
+
+		ui = sun8i_ui_init_one(drm, mixer, plane);
+		if (IS_ERR(ui)) {
+			dev_err(drm->dev, "Couldn't initialize %s plane\n",
+				i ? "overlay" : "primary");
+			return ERR_CAST(ui);
+		};
+
+		ui->id = i;
+		planes[i] = &ui->plane;
+	};
+
+	return planes;
+}
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.h b/drivers/gpu/drm/sun4i/sun8i_ui.h
new file mode 100644
index 000000000000..17dfc92ccc9f
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_ui.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
+ *
+ * Based on sun4i_layer.h, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ *   Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * 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_UI_H_
+#define _SUN8I_UI_H_
+
+struct sunxi_engine;
+
+struct sun8i_ui {
+	struct drm_plane	plane;
+	struct sun4i_drv	*drv;
+	struct sun8i_mixer	*mixer;
+	int			id;
+};
+
+static inline struct sun8i_ui *
+plane_to_sun8i_ui(struct drm_plane *plane)
+{
+	return container_of(plane, struct sun8i_ui, plane);
+}
+
+struct drm_plane **sun8i_ui_init(struct drm_device *drm,
+				 struct sunxi_engine *engine);
+#endif /* _SUN8I_UI_H_ */
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 12/23] drm/sun4i: sun8i: properly support UI channels
  2017-10-17  9:06 ` Maxime Ripard
  (?)
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

The current code has the wrong macro to get the registers offsets of the
UI-registers, with an off-by-0x1000 error.

It works so far by accident, since the UI channel used everywhere else is
the number of VI planes, which has always been 1 so far, and the offset
between two UI channels is 0x1000.

Let's correct that behaviour by setting the UI chan number in the sun8i_ui
structure, and remove the hardcoded values pretty much everywhere. Once we
have sane values, we can convert the macros to their actual definition.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 50 ++++++++++++------------------
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 32 ++++++++++---------
 drivers/gpu/drm/sun4i/sun8i_ui.c    | 12 ++++---
 drivers/gpu/drm/sun4i/sun8i_ui.h    |  1 +-
 4 files changed, 46 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 1955b2a36ac5..5afe8ef709a5 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -37,14 +37,12 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine)
 		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
 }
 
-void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
-				int layer, bool enable)
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct sun8i_ui *ui,
+			      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);
+	DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", ui->id, ui->chan);
 
 	if (enable)
 		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
@@ -52,16 +50,16 @@ void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
 		val = 0;
 
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
 
 	/* Set the alpha configuration */
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
 }
@@ -90,14 +88,13 @@ static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
 }
 
 int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
-				     int layer, struct drm_plane *plane)
+				   struct sun8i_ui *ui)
 {
+	struct drm_plane *plane = &ui->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;
 
-	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
+	DRM_DEBUG_DRIVER("Updating layer %d\n", ui->id);
 
 	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
 		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
@@ -115,7 +112,7 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
 					      state->crtc_h));
 		DRM_DEBUG_DRIVER("Updating channel size\n");
 		regmap_write(mixer->engine.regs,
-			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
+			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(ui->chan),
 			     SUN8I_MIXER_SIZE(state->crtc_w,
 					      state->crtc_h));
 	}
@@ -123,35 +120,34 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
 	/* Set the line width */
 	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
 	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ui->chan, ui->id),
 		     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->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ui->chan, ui->id),
 		     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->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_COORD(ui->chan, ui->id),
 		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
 
 	return 0;
 }
 
 int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
-				       int layer, struct drm_plane *plane)
+				     struct sun8i_ui *ui)
 {
+	struct drm_plane *plane = &ui->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)
@@ -174,21 +170,20 @@ int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
 	}
 
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
 
 	return 0;
 }
 
 int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
-				      int layer, struct drm_plane *plane)
+				    struct sun8i_ui *ui)
 {
+	struct drm_plane *plane = &ui->plane;
 	struct drm_plane_state *state = plane->state;
 	struct drm_framebuffer *fb = state->fb;
 	struct drm_gem_cma_object *gem;
 	dma_addr_t paddr;
-	/* Currently the first UI channel is used */
-	int chan = mixer->cfg->vi_num;
 	int bpp;
 
 	/* Get the physical address of the buffer in memory */
@@ -220,7 +215,7 @@ int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
 	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
 
 	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ui->chan, ui->id),
 		     lower_32_bits(paddr));
 
 	return 0;
@@ -342,11 +337,8 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 		     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->engine.regs, SUN8I_MIXER_BLEND_ROUTE,
-		     mixer->cfg->vi_num);
-
+	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n", 1);
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE, 1);
 	return 0;
 
 err_disable_bus_clk:
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 4785ac090b8c..20d2ee1c4187 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -61,22 +61,22 @@
  */
 
 #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
 #define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
 #define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
 #define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
 #define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
 #define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
+			(0x3000 + 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)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
+#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 0x80)
+#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 0x84)
+#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x3000 + 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)
@@ -104,6 +104,8 @@
 #define SUN8I_MIXER_FCC_EN			0xaa000
 #define SUN8I_MIXER_DCSC_EN			0xb0000
 
+struct sun8i_ui;
+
 struct sun8i_mixer_cfg {
 	int		vi_num;
 	int		ui_num;
@@ -126,12 +128,12 @@ engine_to_sun8i_mixer(struct sunxi_engine *engine)
 	return container_of(engine, struct sun8i_mixer, engine);
 }
 
-void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
-				int layer, bool enable);
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct sun8i_ui *ui,
+			      bool enable);
 int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
-				     int layer, struct drm_plane *plane);
+				   struct sun8i_ui *ui);
 int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
-				       int layer, struct drm_plane *plane);
+				     struct sun8i_ui *ui);
 int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
-				      int layer, struct drm_plane *plane);
+				    struct sun8i_ui *ui);
 #endif /* _SUN8I_MIXER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.c b/drivers/gpu/drm/sun4i/sun8i_ui.c
index 077099ef565a..a056bb0c63c7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui.c
@@ -32,7 +32,7 @@ static void sun8i_mixer_ui_atomic_disable(struct drm_plane *plane,
 	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
 	struct sun8i_mixer *mixer = ui->mixer;
 
-	sun8i_mixer_layer_enable(mixer, ui->id, false);
+	sun8i_mixer_layer_enable(mixer, ui, false);
 }
 
 static void sun8i_mixer_ui_atomic_update(struct drm_plane *plane,
@@ -41,10 +41,10 @@ static void sun8i_mixer_ui_atomic_update(struct drm_plane *plane,
 	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
 	struct sun8i_mixer *mixer = ui->mixer;
 
-	sun8i_mixer_update_layer_coord(mixer, ui->id, plane);
-	sun8i_mixer_update_layer_formats(mixer, ui->id, plane);
-	sun8i_mixer_update_layer_buffer(mixer, ui->id, plane);
-	sun8i_mixer_layer_enable(mixer, ui->id, true);
+	sun8i_mixer_update_layer_coord(mixer, ui);
+	sun8i_mixer_update_layer_formats(mixer, ui);
+	sun8i_mixer_update_layer_buffer(mixer, ui);
+	sun8i_mixer_layer_enable(mixer, ui, true);
 }
 
 static struct drm_plane_helper_funcs sun8i_mixer_ui_helper_funcs = {
@@ -126,6 +126,8 @@ struct drm_plane **sun8i_ui_init(struct drm_device *drm,
 			return ERR_CAST(ui);
 		};
 
+		/* TODO: Support several UI channels */
+		ui->chan = 0;
 		ui->id = i;
 		planes[i] = &ui->plane;
 	};
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.h b/drivers/gpu/drm/sun4i/sun8i_ui.h
index 17dfc92ccc9f..3c3185878ad1 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui.h
+++ b/drivers/gpu/drm/sun4i/sun8i_ui.h
@@ -22,6 +22,7 @@ struct sun8i_ui {
 	struct drm_plane	plane;
 	struct sun4i_drv	*drv;
 	struct sun8i_mixer	*mixer;
+	u8			chan;
 	int			id;
 };
 
-- 
git-series 0.9.1

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

* [PATCH 12/23] drm/sun4i: sun8i: properly support UI channels
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The current code has the wrong macro to get the registers offsets of the
UI-registers, with an off-by-0x1000 error.

It works so far by accident, since the UI channel used everywhere else is
the number of VI planes, which has always been 1 so far, and the offset
between two UI channels is 0x1000.

Let's correct that behaviour by setting the UI chan number in the sun8i_ui
structure, and remove the hardcoded values pretty much everywhere. Once we
have sane values, we can convert the macros to their actual definition.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 50 ++++++++++++------------------
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 32 ++++++++++---------
 drivers/gpu/drm/sun4i/sun8i_ui.c    | 12 ++++---
 drivers/gpu/drm/sun4i/sun8i_ui.h    |  1 +-
 4 files changed, 46 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 1955b2a36ac5..5afe8ef709a5 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -37,14 +37,12 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine)
 		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
 }
 
-void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
-				int layer, bool enable)
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct sun8i_ui *ui,
+			      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);
+	DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", ui->id, ui->chan);
 
 	if (enable)
 		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
@@ -52,16 +50,16 @@ void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
 		val = 0;
 
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
 
 	/* Set the alpha configuration */
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
 }
@@ -90,14 +88,13 @@ static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
 }
 
 int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
-				     int layer, struct drm_plane *plane)
+				   struct sun8i_ui *ui)
 {
+	struct drm_plane *plane = &ui->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;
 
-	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
+	DRM_DEBUG_DRIVER("Updating layer %d\n", ui->id);
 
 	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
 		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
@@ -115,7 +112,7 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
 					      state->crtc_h));
 		DRM_DEBUG_DRIVER("Updating channel size\n");
 		regmap_write(mixer->engine.regs,
-			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
+			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(ui->chan),
 			     SUN8I_MIXER_SIZE(state->crtc_w,
 					      state->crtc_h));
 	}
@@ -123,35 +120,34 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
 	/* Set the line width */
 	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
 	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ui->chan, ui->id),
 		     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->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ui->chan, ui->id),
 		     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->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_COORD(ui->chan, ui->id),
 		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
 
 	return 0;
 }
 
 int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
-				       int layer, struct drm_plane *plane)
+				     struct sun8i_ui *ui)
 {
+	struct drm_plane *plane = &ui->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)
@@ -174,21 +170,20 @@ int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
 	}
 
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
 
 	return 0;
 }
 
 int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
-				      int layer, struct drm_plane *plane)
+				    struct sun8i_ui *ui)
 {
+	struct drm_plane *plane = &ui->plane;
 	struct drm_plane_state *state = plane->state;
 	struct drm_framebuffer *fb = state->fb;
 	struct drm_gem_cma_object *gem;
 	dma_addr_t paddr;
-	/* Currently the first UI channel is used */
-	int chan = mixer->cfg->vi_num;
 	int bpp;
 
 	/* Get the physical address of the buffer in memory */
@@ -220,7 +215,7 @@ int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
 	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
 
 	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ui->chan, ui->id),
 		     lower_32_bits(paddr));
 
 	return 0;
@@ -342,11 +337,8 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 		     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->engine.regs, SUN8I_MIXER_BLEND_ROUTE,
-		     mixer->cfg->vi_num);
-
+	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n", 1);
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE, 1);
 	return 0;
 
 err_disable_bus_clk:
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 4785ac090b8c..20d2ee1c4187 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -61,22 +61,22 @@
  */
 
 #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
 #define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
 #define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
 #define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
 #define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
 #define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
+			(0x3000 + 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)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
+#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 0x80)
+#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 0x84)
+#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x3000 + 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)
@@ -104,6 +104,8 @@
 #define SUN8I_MIXER_FCC_EN			0xaa000
 #define SUN8I_MIXER_DCSC_EN			0xb0000
 
+struct sun8i_ui;
+
 struct sun8i_mixer_cfg {
 	int		vi_num;
 	int		ui_num;
@@ -126,12 +128,12 @@ engine_to_sun8i_mixer(struct sunxi_engine *engine)
 	return container_of(engine, struct sun8i_mixer, engine);
 }
 
-void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
-				int layer, bool enable);
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct sun8i_ui *ui,
+			      bool enable);
 int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
-				     int layer, struct drm_plane *plane);
+				   struct sun8i_ui *ui);
 int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
-				       int layer, struct drm_plane *plane);
+				     struct sun8i_ui *ui);
 int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
-				      int layer, struct drm_plane *plane);
+				    struct sun8i_ui *ui);
 #endif /* _SUN8I_MIXER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.c b/drivers/gpu/drm/sun4i/sun8i_ui.c
index 077099ef565a..a056bb0c63c7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui.c
@@ -32,7 +32,7 @@ static void sun8i_mixer_ui_atomic_disable(struct drm_plane *plane,
 	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
 	struct sun8i_mixer *mixer = ui->mixer;
 
-	sun8i_mixer_layer_enable(mixer, ui->id, false);
+	sun8i_mixer_layer_enable(mixer, ui, false);
 }
 
 static void sun8i_mixer_ui_atomic_update(struct drm_plane *plane,
@@ -41,10 +41,10 @@ static void sun8i_mixer_ui_atomic_update(struct drm_plane *plane,
 	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
 	struct sun8i_mixer *mixer = ui->mixer;
 
-	sun8i_mixer_update_layer_coord(mixer, ui->id, plane);
-	sun8i_mixer_update_layer_formats(mixer, ui->id, plane);
-	sun8i_mixer_update_layer_buffer(mixer, ui->id, plane);
-	sun8i_mixer_layer_enable(mixer, ui->id, true);
+	sun8i_mixer_update_layer_coord(mixer, ui);
+	sun8i_mixer_update_layer_formats(mixer, ui);
+	sun8i_mixer_update_layer_buffer(mixer, ui);
+	sun8i_mixer_layer_enable(mixer, ui, true);
 }
 
 static struct drm_plane_helper_funcs sun8i_mixer_ui_helper_funcs = {
@@ -126,6 +126,8 @@ struct drm_plane **sun8i_ui_init(struct drm_device *drm,
 			return ERR_CAST(ui);
 		};
 
+		/* TODO: Support several UI channels */
+		ui->chan = 0;
 		ui->id = i;
 		planes[i] = &ui->plane;
 	};
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.h b/drivers/gpu/drm/sun4i/sun8i_ui.h
index 17dfc92ccc9f..3c3185878ad1 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui.h
+++ b/drivers/gpu/drm/sun4i/sun8i_ui.h
@@ -22,6 +22,7 @@ struct sun8i_ui {
 	struct drm_plane	plane;
 	struct sun4i_drv	*drv;
 	struct sun8i_mixer	*mixer;
+	u8			chan;
 	int			id;
 };
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 12/23] drm/sun4i: sun8i: properly support UI channels
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

The current code has the wrong macro to get the registers offsets of the
UI-registers, with an off-by-0x1000 error.

It works so far by accident, since the UI channel used everywhere else is
the number of VI planes, which has always been 1 so far, and the offset
between two UI channels is 0x1000.

Let's correct that behaviour by setting the UI chan number in the sun8i_ui
structure, and remove the hardcoded values pretty much everywhere. Once we
have sane values, we can convert the macros to their actual definition.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 50 ++++++++++++------------------
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 32 ++++++++++---------
 drivers/gpu/drm/sun4i/sun8i_ui.c    | 12 ++++---
 drivers/gpu/drm/sun4i/sun8i_ui.h    |  1 +-
 4 files changed, 46 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 1955b2a36ac5..5afe8ef709a5 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -37,14 +37,12 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine)
 		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
 }
 
-void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
-				int layer, bool enable)
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct sun8i_ui *ui,
+			      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);
+	DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", ui->id, ui->chan);
 
 	if (enable)
 		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
@@ -52,16 +50,16 @@ void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
 		val = 0;
 
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
 
 	/* Set the alpha configuration */
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
 }
@@ -90,14 +88,13 @@ static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
 }
 
 int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
-				     int layer, struct drm_plane *plane)
+				   struct sun8i_ui *ui)
 {
+	struct drm_plane *plane = &ui->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;
 
-	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
+	DRM_DEBUG_DRIVER("Updating layer %d\n", ui->id);
 
 	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
 		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
@@ -115,7 +112,7 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
 					      state->crtc_h));
 		DRM_DEBUG_DRIVER("Updating channel size\n");
 		regmap_write(mixer->engine.regs,
-			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
+			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(ui->chan),
 			     SUN8I_MIXER_SIZE(state->crtc_w,
 					      state->crtc_h));
 	}
@@ -123,35 +120,34 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
 	/* Set the line width */
 	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
 	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ui->chan, ui->id),
 		     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->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ui->chan, ui->id),
 		     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->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_COORD(ui->chan, ui->id),
 		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
 
 	return 0;
 }
 
 int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
-				       int layer, struct drm_plane *plane)
+				     struct sun8i_ui *ui)
 {
+	struct drm_plane *plane = &ui->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)
@@ -174,21 +170,20 @@ int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
 	}
 
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
 
 	return 0;
 }
 
 int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
-				      int layer, struct drm_plane *plane)
+				    struct sun8i_ui *ui)
 {
+	struct drm_plane *plane = &ui->plane;
 	struct drm_plane_state *state = plane->state;
 	struct drm_framebuffer *fb = state->fb;
 	struct drm_gem_cma_object *gem;
 	dma_addr_t paddr;
-	/* Currently the first UI channel is used */
-	int chan = mixer->cfg->vi_num;
 	int bpp;
 
 	/* Get the physical address of the buffer in memory */
@@ -220,7 +215,7 @@ int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
 	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
 
 	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ui->chan, ui->id),
 		     lower_32_bits(paddr));
 
 	return 0;
@@ -342,11 +337,8 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 		     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->engine.regs, SUN8I_MIXER_BLEND_ROUTE,
-		     mixer->cfg->vi_num);
-
+	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n", 1);
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE, 1);
 	return 0;
 
 err_disable_bus_clk:
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 4785ac090b8c..20d2ee1c4187 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -61,22 +61,22 @@
  */
 
 #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
 #define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
 #define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
 #define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
 #define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
 #define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
+			(0x3000 + 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)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
+#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 0x80)
+#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 0x84)
+#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x3000 + 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)
@@ -104,6 +104,8 @@
 #define SUN8I_MIXER_FCC_EN			0xaa000
 #define SUN8I_MIXER_DCSC_EN			0xb0000
 
+struct sun8i_ui;
+
 struct sun8i_mixer_cfg {
 	int		vi_num;
 	int		ui_num;
@@ -126,12 +128,12 @@ engine_to_sun8i_mixer(struct sunxi_engine *engine)
 	return container_of(engine, struct sun8i_mixer, engine);
 }
 
-void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
-				int layer, bool enable);
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct sun8i_ui *ui,
+			      bool enable);
 int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
-				     int layer, struct drm_plane *plane);
+				   struct sun8i_ui *ui);
 int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
-				       int layer, struct drm_plane *plane);
+				     struct sun8i_ui *ui);
 int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
-				      int layer, struct drm_plane *plane);
+				    struct sun8i_ui *ui);
 #endif /* _SUN8I_MIXER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.c b/drivers/gpu/drm/sun4i/sun8i_ui.c
index 077099ef565a..a056bb0c63c7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui.c
@@ -32,7 +32,7 @@ static void sun8i_mixer_ui_atomic_disable(struct drm_plane *plane,
 	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
 	struct sun8i_mixer *mixer = ui->mixer;
 
-	sun8i_mixer_layer_enable(mixer, ui->id, false);
+	sun8i_mixer_layer_enable(mixer, ui, false);
 }
 
 static void sun8i_mixer_ui_atomic_update(struct drm_plane *plane,
@@ -41,10 +41,10 @@ static void sun8i_mixer_ui_atomic_update(struct drm_plane *plane,
 	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
 	struct sun8i_mixer *mixer = ui->mixer;
 
-	sun8i_mixer_update_layer_coord(mixer, ui->id, plane);
-	sun8i_mixer_update_layer_formats(mixer, ui->id, plane);
-	sun8i_mixer_update_layer_buffer(mixer, ui->id, plane);
-	sun8i_mixer_layer_enable(mixer, ui->id, true);
+	sun8i_mixer_update_layer_coord(mixer, ui);
+	sun8i_mixer_update_layer_formats(mixer, ui);
+	sun8i_mixer_update_layer_buffer(mixer, ui);
+	sun8i_mixer_layer_enable(mixer, ui, true);
 }
 
 static struct drm_plane_helper_funcs sun8i_mixer_ui_helper_funcs = {
@@ -126,6 +126,8 @@ struct drm_plane **sun8i_ui_init(struct drm_device *drm,
 			return ERR_CAST(ui);
 		};
 
+		/* TODO: Support several UI channels */
+		ui->chan = 0;
 		ui->id = i;
 		planes[i] = &ui->plane;
 	};
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.h b/drivers/gpu/drm/sun4i/sun8i_ui.h
index 17dfc92ccc9f..3c3185878ad1 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui.h
+++ b/drivers/gpu/drm/sun4i/sun8i_ui.h
@@ -22,6 +22,7 @@ struct sun8i_ui {
 	struct drm_plane	plane;
 	struct sun4i_drv	*drv;
 	struct sun8i_mixer	*mixer;
+	u8			chan;
 	int			id;
 };
 
-- 
git-series 0.9.1

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

* [PATCH 12/23] drm/sun4i: sun8i: properly support UI channels
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The current code has the wrong macro to get the registers offsets of the
UI-registers, with an off-by-0x1000 error.

It works so far by accident, since the UI channel used everywhere else is
the number of VI planes, which has always been 1 so far, and the offset
between two UI channels is 0x1000.

Let's correct that behaviour by setting the UI chan number in the sun8i_ui
structure, and remove the hardcoded values pretty much everywhere. Once we
have sane values, we can convert the macros to their actual definition.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 50 ++++++++++++------------------
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 32 ++++++++++---------
 drivers/gpu/drm/sun4i/sun8i_ui.c    | 12 ++++---
 drivers/gpu/drm/sun4i/sun8i_ui.h    |  1 +-
 4 files changed, 46 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 1955b2a36ac5..5afe8ef709a5 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -37,14 +37,12 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine)
 		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
 }
 
-void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
-				int layer, bool enable)
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct sun8i_ui *ui,
+			      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);
+	DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", ui->id, ui->chan);
 
 	if (enable)
 		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
@@ -52,16 +50,16 @@ void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
 		val = 0;
 
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
 
 	/* Set the alpha configuration */
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
 }
@@ -90,14 +88,13 @@ static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
 }
 
 int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
-				     int layer, struct drm_plane *plane)
+				   struct sun8i_ui *ui)
 {
+	struct drm_plane *plane = &ui->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;
 
-	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
+	DRM_DEBUG_DRIVER("Updating layer %d\n", ui->id);
 
 	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
 		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
@@ -115,7 +112,7 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
 					      state->crtc_h));
 		DRM_DEBUG_DRIVER("Updating channel size\n");
 		regmap_write(mixer->engine.regs,
-			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
+			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(ui->chan),
 			     SUN8I_MIXER_SIZE(state->crtc_w,
 					      state->crtc_h));
 	}
@@ -123,35 +120,34 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
 	/* Set the line width */
 	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
 	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ui->chan, ui->id),
 		     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->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ui->chan, ui->id),
 		     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->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_COORD(ui->chan, ui->id),
 		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
 
 	return 0;
 }
 
 int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
-				       int layer, struct drm_plane *plane)
+				     struct sun8i_ui *ui)
 {
+	struct drm_plane *plane = &ui->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)
@@ -174,21 +170,20 @@ int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
 	}
 
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
 
 	return 0;
 }
 
 int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
-				      int layer, struct drm_plane *plane)
+				    struct sun8i_ui *ui)
 {
+	struct drm_plane *plane = &ui->plane;
 	struct drm_plane_state *state = plane->state;
 	struct drm_framebuffer *fb = state->fb;
 	struct drm_gem_cma_object *gem;
 	dma_addr_t paddr;
-	/* Currently the first UI channel is used */
-	int chan = mixer->cfg->vi_num;
 	int bpp;
 
 	/* Get the physical address of the buffer in memory */
@@ -220,7 +215,7 @@ int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
 	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
 
 	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ui->chan, ui->id),
 		     lower_32_bits(paddr));
 
 	return 0;
@@ -342,11 +337,8 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 		     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->engine.regs, SUN8I_MIXER_BLEND_ROUTE,
-		     mixer->cfg->vi_num);
-
+	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n", 1);
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE, 1);
 	return 0;
 
 err_disable_bus_clk:
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 4785ac090b8c..20d2ee1c4187 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -61,22 +61,22 @@
  */
 
 #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
 #define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
 #define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
 #define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
 #define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
 #define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
-			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
+			(0x3000 + 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)
+			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
+#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 0x80)
+#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 0x84)
+#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x3000 + 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)
@@ -104,6 +104,8 @@
 #define SUN8I_MIXER_FCC_EN			0xaa000
 #define SUN8I_MIXER_DCSC_EN			0xb0000
 
+struct sun8i_ui;
+
 struct sun8i_mixer_cfg {
 	int		vi_num;
 	int		ui_num;
@@ -126,12 +128,12 @@ engine_to_sun8i_mixer(struct sunxi_engine *engine)
 	return container_of(engine, struct sun8i_mixer, engine);
 }
 
-void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
-				int layer, bool enable);
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct sun8i_ui *ui,
+			      bool enable);
 int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
-				     int layer, struct drm_plane *plane);
+				   struct sun8i_ui *ui);
 int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
-				       int layer, struct drm_plane *plane);
+				     struct sun8i_ui *ui);
 int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
-				      int layer, struct drm_plane *plane);
+				    struct sun8i_ui *ui);
 #endif /* _SUN8I_MIXER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.c b/drivers/gpu/drm/sun4i/sun8i_ui.c
index 077099ef565a..a056bb0c63c7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui.c
@@ -32,7 +32,7 @@ static void sun8i_mixer_ui_atomic_disable(struct drm_plane *plane,
 	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
 	struct sun8i_mixer *mixer = ui->mixer;
 
-	sun8i_mixer_layer_enable(mixer, ui->id, false);
+	sun8i_mixer_layer_enable(mixer, ui, false);
 }
 
 static void sun8i_mixer_ui_atomic_update(struct drm_plane *plane,
@@ -41,10 +41,10 @@ static void sun8i_mixer_ui_atomic_update(struct drm_plane *plane,
 	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
 	struct sun8i_mixer *mixer = ui->mixer;
 
-	sun8i_mixer_update_layer_coord(mixer, ui->id, plane);
-	sun8i_mixer_update_layer_formats(mixer, ui->id, plane);
-	sun8i_mixer_update_layer_buffer(mixer, ui->id, plane);
-	sun8i_mixer_layer_enable(mixer, ui->id, true);
+	sun8i_mixer_update_layer_coord(mixer, ui);
+	sun8i_mixer_update_layer_formats(mixer, ui);
+	sun8i_mixer_update_layer_buffer(mixer, ui);
+	sun8i_mixer_layer_enable(mixer, ui, true);
 }
 
 static struct drm_plane_helper_funcs sun8i_mixer_ui_helper_funcs = {
@@ -126,6 +126,8 @@ struct drm_plane **sun8i_ui_init(struct drm_device *drm,
 			return ERR_CAST(ui);
 		};
 
+		/* TODO: Support several UI channels */
+		ui->chan = 0;
 		ui->id = i;
 		planes[i] = &ui->plane;
 	};
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.h b/drivers/gpu/drm/sun4i/sun8i_ui.h
index 17dfc92ccc9f..3c3185878ad1 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui.h
+++ b/drivers/gpu/drm/sun4i/sun8i_ui.h
@@ -22,6 +22,7 @@ struct sun8i_ui {
 	struct drm_plane	plane;
 	struct sun4i_drv	*drv;
 	struct sun8i_mixer	*mixer;
+	u8			chan;
 	int			id;
 };
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 13/23] drm/sun4i: Reorder and document DE2 mixer registers
  2017-10-17  9:06 ` Maxime Ripard
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

Some registers values have been hardcoded so far, or were not as
descriptive as supposed to, because of missing information. The various
BSP that poped up since have given us more details, some hopefully we can
be more explicit about things.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 25 ++++----
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 89 ++++++++++++++++--------------
 2 files changed, 63 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 5afe8ef709a5..86c6c24b5105 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -61,7 +61,7 @@ void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct sun8i_ui *ui,
 	regmap_update_bits(mixer->engine.regs,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA(255));
 }
 
 static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
@@ -322,19 +322,20 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 
 	/* Initialize blender */
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
-		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PREMULTIPLY,
-		     SUN8I_MIXER_BLEND_PREMULTIPLY_DEF);
+		     SUN8I_MIXER_BLEND_FCOLOR_CTL_FCOLOR_EN(0) |
+		     SUN8I_MIXER_BLEND_FCOLOR_CTL_EN(0));
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PREMULTIPLY, 0);
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR,
-		     SUN8I_MIXER_BLEND_BKCOLOR_DEF);
+		     SUN8I_MIXER_BLEND_BKCOLOR_ALPHA(255));
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_MODE(0),
-		     SUN8I_MIXER_BLEND_MODE_DEF);
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_CK_CTL,
-		     SUN8I_MIXER_BLEND_CK_CTL_DEF);
-
-	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
-		     SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF);
+		     SUN8I_MIXER_BLEND_MODE_PIXEL_FS(1) |
+		     SUN8I_MIXER_BLEND_MODE_PIXEL_FD(3) |
+		     SUN8I_MIXER_BLEND_MODE_ALPHA_FS(1) |
+		     SUN8I_MIXER_BLEND_MODE_ALPHA_FD(3));
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_CK_CTL, 0);
+
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
+		     SUN8I_MIXER_BLEND_ATTR_FCOLOR_ALPHA(255));
 
 	/* Select the first UI channel */
 	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n", 1);
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 20d2ee1c4187..22877a008e0d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -22,71 +22,82 @@
 #define SUN8I_MIXER_COORD(x, y)			((y) << 16 | (x))
 
 #define SUN8I_MIXER_GLOBAL_CTL			0x0
+#define SUN8I_MIXER_GLOBAL_CTL_RT_EN			BIT(0)
+
 #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			BIT(0)
 
-#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE		0x1
+#define SUN8I_MIXER_GLOBAL_SIZE			0xc
 
 #define SUN8I_MIXER_BLEND_FCOLOR_CTL		0x1000
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL_EN(x)		BIT(8 + (x))
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL_FCOLOR_EN(x)	BIT(x)
+
 #define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x)	(0x1004 + 0x10 * (x) + 0x0)
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR_ALPHA(x)		(((x) & 0xff) << 24)
+
 #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_BKCOLOR_ALPHA(x)		(((x) & 0xff) << 24)
+
 #define SUN8I_MIXER_BLEND_OUTSIZE		0x108c
+
 #define SUN8I_MIXER_BLEND_MODE(x)		(0x1090 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_MODE_ALPHA_FD(x)		(((x) & 0xf) << 24)
+#define SUN8I_MIXER_BLEND_MODE_ALPHA_FS(x)		(((x) & 0xf) << 16)
+#define SUN8I_MIXER_BLEND_MODE_PIXEL_FD(x)		(((x) & 0xf) << 8)
+#define SUN8I_MIXER_BLEND_MODE_PIXEL_FS(x)		((x) & 0xf)
+
 #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)
+#define SUN8I_MIXER_BLEND_OUTCTL		0x10fc
+#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) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
-#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
-#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
-#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
-#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
-#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
-#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
-#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 0x80)
-#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 0x84)
-#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x3000 + 0x1000 * (ch) + 0x88)
+#define SUN8I_MIXER_CHAN(ch)		(0x3000 + 0x1000 * (ch))
+#define SUN8I_MIXER_UI_LAYER(ch, layer)	(SUN8I_MIXER_CHAN(ch) + 0x20 * (layer))
 
-#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(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x00)
 #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)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA(x)			(0xff << 24)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK	GENMASK(11, 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888		(8 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888		(4 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888		(0 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK	GENMASK(2, 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF		(1 << 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN		BIT(0)
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x04)
+#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x08)
+#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x0c)
+#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x10)
+#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x14)
+#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x18)
+
+#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(SUN8I_MIXER_CHAN(ch) + 0x80)
+#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(SUN8I_MIXER_CHAN(ch) + 0x84)
+#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(SUN8I_MIXER_CHAN(ch) + 0x88)
 
 /*
  * These sub-engines are still unknown now, the EN registers are here only to
-- 
git-series 0.9.1

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

* [PATCH 13/23] drm/sun4i: Reorder and document DE2 mixer registers
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

Some registers values have been hardcoded so far, or were not as
descriptive as supposed to, because of missing information. The various
BSP that poped up since have given us more details, some hopefully we can
be more explicit about things.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 25 ++++----
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 89 ++++++++++++++++--------------
 2 files changed, 63 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 5afe8ef709a5..86c6c24b5105 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -61,7 +61,7 @@ void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct sun8i_ui *ui,
 	regmap_update_bits(mixer->engine.regs,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA(255));
 }
 
 static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
@@ -322,19 +322,20 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 
 	/* Initialize blender */
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
-		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PREMULTIPLY,
-		     SUN8I_MIXER_BLEND_PREMULTIPLY_DEF);
+		     SUN8I_MIXER_BLEND_FCOLOR_CTL_FCOLOR_EN(0) |
+		     SUN8I_MIXER_BLEND_FCOLOR_CTL_EN(0));
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PREMULTIPLY, 0);
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR,
-		     SUN8I_MIXER_BLEND_BKCOLOR_DEF);
+		     SUN8I_MIXER_BLEND_BKCOLOR_ALPHA(255));
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_MODE(0),
-		     SUN8I_MIXER_BLEND_MODE_DEF);
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_CK_CTL,
-		     SUN8I_MIXER_BLEND_CK_CTL_DEF);
-
-	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
-		     SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF);
+		     SUN8I_MIXER_BLEND_MODE_PIXEL_FS(1) |
+		     SUN8I_MIXER_BLEND_MODE_PIXEL_FD(3) |
+		     SUN8I_MIXER_BLEND_MODE_ALPHA_FS(1) |
+		     SUN8I_MIXER_BLEND_MODE_ALPHA_FD(3));
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_CK_CTL, 0);
+
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
+		     SUN8I_MIXER_BLEND_ATTR_FCOLOR_ALPHA(255));
 
 	/* Select the first UI channel */
 	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n", 1);
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 20d2ee1c4187..22877a008e0d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -22,71 +22,82 @@
 #define SUN8I_MIXER_COORD(x, y)			((y) << 16 | (x))
 
 #define SUN8I_MIXER_GLOBAL_CTL			0x0
+#define SUN8I_MIXER_GLOBAL_CTL_RT_EN			BIT(0)
+
 #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			BIT(0)
 
-#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE		0x1
+#define SUN8I_MIXER_GLOBAL_SIZE			0xc
 
 #define SUN8I_MIXER_BLEND_FCOLOR_CTL		0x1000
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL_EN(x)		BIT(8 + (x))
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL_FCOLOR_EN(x)	BIT(x)
+
 #define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x)	(0x1004 + 0x10 * (x) + 0x0)
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR_ALPHA(x)		(((x) & 0xff) << 24)
+
 #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_BKCOLOR_ALPHA(x)		(((x) & 0xff) << 24)
+
 #define SUN8I_MIXER_BLEND_OUTSIZE		0x108c
+
 #define SUN8I_MIXER_BLEND_MODE(x)		(0x1090 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_MODE_ALPHA_FD(x)		(((x) & 0xf) << 24)
+#define SUN8I_MIXER_BLEND_MODE_ALPHA_FS(x)		(((x) & 0xf) << 16)
+#define SUN8I_MIXER_BLEND_MODE_PIXEL_FD(x)		(((x) & 0xf) << 8)
+#define SUN8I_MIXER_BLEND_MODE_PIXEL_FS(x)		((x) & 0xf)
+
 #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)
+#define SUN8I_MIXER_BLEND_OUTCTL		0x10fc
+#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) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
-#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
-#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
-#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
-#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
-#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
-#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
-#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 0x80)
-#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 0x84)
-#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x3000 + 0x1000 * (ch) + 0x88)
+#define SUN8I_MIXER_CHAN(ch)		(0x3000 + 0x1000 * (ch))
+#define SUN8I_MIXER_UI_LAYER(ch, layer)	(SUN8I_MIXER_CHAN(ch) + 0x20 * (layer))
 
-#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(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x00)
 #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)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA(x)			(0xff << 24)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK	GENMASK(11, 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888		(8 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888		(4 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888		(0 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK	GENMASK(2, 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF		(1 << 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN		BIT(0)
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x04)
+#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x08)
+#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x0c)
+#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x10)
+#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x14)
+#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x18)
+
+#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(SUN8I_MIXER_CHAN(ch) + 0x80)
+#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(SUN8I_MIXER_CHAN(ch) + 0x84)
+#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(SUN8I_MIXER_CHAN(ch) + 0x88)
 
 /*
  * These sub-engines are still unknown now, the EN registers are here only to
-- 
git-series 0.9.1

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

* [PATCH 13/23] drm/sun4i: Reorder and document DE2 mixer registers
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

Some registers values have been hardcoded so far, or were not as
descriptive as supposed to, because of missing information. The various
BSP that poped up since have given us more details, some hopefully we can
be more explicit about things.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 25 ++++----
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 89 ++++++++++++++++--------------
 2 files changed, 63 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 5afe8ef709a5..86c6c24b5105 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -61,7 +61,7 @@ void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct sun8i_ui *ui,
 	regmap_update_bits(mixer->engine.regs,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA(255));
 }
 
 static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
@@ -322,19 +322,20 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 
 	/* Initialize blender */
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
-		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PREMULTIPLY,
-		     SUN8I_MIXER_BLEND_PREMULTIPLY_DEF);
+		     SUN8I_MIXER_BLEND_FCOLOR_CTL_FCOLOR_EN(0) |
+		     SUN8I_MIXER_BLEND_FCOLOR_CTL_EN(0));
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PREMULTIPLY, 0);
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR,
-		     SUN8I_MIXER_BLEND_BKCOLOR_DEF);
+		     SUN8I_MIXER_BLEND_BKCOLOR_ALPHA(255));
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_MODE(0),
-		     SUN8I_MIXER_BLEND_MODE_DEF);
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_CK_CTL,
-		     SUN8I_MIXER_BLEND_CK_CTL_DEF);
-
-	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
-		     SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF);
+		     SUN8I_MIXER_BLEND_MODE_PIXEL_FS(1) |
+		     SUN8I_MIXER_BLEND_MODE_PIXEL_FD(3) |
+		     SUN8I_MIXER_BLEND_MODE_ALPHA_FS(1) |
+		     SUN8I_MIXER_BLEND_MODE_ALPHA_FD(3));
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_CK_CTL, 0);
+
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
+		     SUN8I_MIXER_BLEND_ATTR_FCOLOR_ALPHA(255));
 
 	/* Select the first UI channel */
 	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n", 1);
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 20d2ee1c4187..22877a008e0d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -22,71 +22,82 @@
 #define SUN8I_MIXER_COORD(x, y)			((y) << 16 | (x))
 
 #define SUN8I_MIXER_GLOBAL_CTL			0x0
+#define SUN8I_MIXER_GLOBAL_CTL_RT_EN			BIT(0)
+
 #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			BIT(0)
 
-#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE		0x1
+#define SUN8I_MIXER_GLOBAL_SIZE			0xc
 
 #define SUN8I_MIXER_BLEND_FCOLOR_CTL		0x1000
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL_EN(x)		BIT(8 + (x))
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL_FCOLOR_EN(x)	BIT(x)
+
 #define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x)	(0x1004 + 0x10 * (x) + 0x0)
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR_ALPHA(x)		(((x) & 0xff) << 24)
+
 #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_BKCOLOR_ALPHA(x)		(((x) & 0xff) << 24)
+
 #define SUN8I_MIXER_BLEND_OUTSIZE		0x108c
+
 #define SUN8I_MIXER_BLEND_MODE(x)		(0x1090 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_MODE_ALPHA_FD(x)		(((x) & 0xf) << 24)
+#define SUN8I_MIXER_BLEND_MODE_ALPHA_FS(x)		(((x) & 0xf) << 16)
+#define SUN8I_MIXER_BLEND_MODE_PIXEL_FD(x)		(((x) & 0xf) << 8)
+#define SUN8I_MIXER_BLEND_MODE_PIXEL_FS(x)		((x) & 0xf)
+
 #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)
+#define SUN8I_MIXER_BLEND_OUTCTL		0x10fc
+#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) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
-#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
-#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
-#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
-#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
-#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
-#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \
-			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
-#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 0x80)
-#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 0x84)
-#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x3000 + 0x1000 * (ch) + 0x88)
+#define SUN8I_MIXER_CHAN(ch)		(0x3000 + 0x1000 * (ch))
+#define SUN8I_MIXER_UI_LAYER(ch, layer)	(SUN8I_MIXER_CHAN(ch) + 0x20 * (layer))
 
-#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(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x00)
 #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)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA(x)			(0xff << 24)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK	GENMASK(11, 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888		(8 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888		(4 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888		(0 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK	GENMASK(2, 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF		(1 << 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN		BIT(0)
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x04)
+#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x08)
+#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x0c)
+#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x10)
+#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x14)
+#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer)	\
+	(SUN8I_MIXER_UI_LAYER(ch, layer) + 0x18)
+
+#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(SUN8I_MIXER_CHAN(ch) + 0x80)
+#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(SUN8I_MIXER_CHAN(ch) + 0x84)
+#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(SUN8I_MIXER_CHAN(ch) + 0x88)
 
 /*
  * These sub-engines are still unknown now, the EN registers are here only to
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 14/23] drm/sun4i: Create minimal multipliers and dividers
  2017-10-17  9:06 ` Maxime Ripard
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

The various outputs the TCON can provide have different constraints on the
dotclock divider. Let's make them configurable by the various mode_set
functions.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_dotclock.c | 10 +++++++---
 drivers/gpu/drm/sun4i/sun4i_tcon.c     |  2 ++
 drivers/gpu/drm/sun4i/sun4i_tcon.h     |  2 ++
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
index d401156490f3..023f39bda633 100644
--- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
+++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
@@ -17,8 +17,9 @@
 #include "sun4i_dotclock.h"
 
 struct sun4i_dclk {
-	struct clk_hw	hw;
-	struct regmap	*regmap;
+	struct clk_hw		hw;
+	struct regmap		*regmap;
+	struct sun4i_tcon	*tcon;
 };
 
 static inline struct sun4i_dclk *hw_to_dclk(struct clk_hw *hw)
@@ -73,11 +74,13 @@ static unsigned long sun4i_dclk_recalc_rate(struct clk_hw *hw,
 static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
 				  unsigned long *parent_rate)
 {
+	struct sun4i_dclk *dclk = hw_to_dclk(hw);
+	struct sun4i_tcon *tcon = dclk->tcon;
 	unsigned long best_parent = 0;
 	u8 best_div = 1;
 	int i;
 
-	for (i = 6; i <= 127; i++) {
+	for (i = tcon->dclk_min_div; i <= tcon->dclk_max_div; i++) {
 		unsigned long ideal = rate * i;
 		unsigned long rounded;
 
@@ -167,6 +170,7 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
 	dclk = devm_kzalloc(dev, sizeof(*dclk), GFP_KERNEL);
 	if (!dclk)
 		return -ENOMEM;
+	dclk->tcon = tcon;
 
 	init.name = clk_name;
 	init.ops = &sun4i_dclk_ops;
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index f69bcdf11cb8..3efa1ab045cd 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -177,6 +177,8 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
 	u8 clk_delay;
 	u32 val = 0;
 
+	tcon->dclk_min_div = 6;
+	tcon->dclk_max_div = 127;
 	sun4i_tcon0_mode_set_common(tcon, mode);
 
 	/* Adjust clock delay */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index f61bf6d83b4a..4141fbd97ddf 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -169,6 +169,8 @@ struct sun4i_tcon {
 
 	/* Pixel clock */
 	struct clk			*dclk;
+	u8				dclk_max_div;
+	u8				dclk_min_div;
 
 	/* Reset control */
 	struct reset_control		*lcd_rst;
-- 
git-series 0.9.1

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

* [PATCH 14/23] drm/sun4i: Create minimal multipliers and dividers
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

The various outputs the TCON can provide have different constraints on the
dotclock divider. Let's make them configurable by the various mode_set
functions.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_dotclock.c | 10 +++++++---
 drivers/gpu/drm/sun4i/sun4i_tcon.c     |  2 ++
 drivers/gpu/drm/sun4i/sun4i_tcon.h     |  2 ++
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
index d401156490f3..023f39bda633 100644
--- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
+++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
@@ -17,8 +17,9 @@
 #include "sun4i_dotclock.h"
 
 struct sun4i_dclk {
-	struct clk_hw	hw;
-	struct regmap	*regmap;
+	struct clk_hw		hw;
+	struct regmap		*regmap;
+	struct sun4i_tcon	*tcon;
 };
 
 static inline struct sun4i_dclk *hw_to_dclk(struct clk_hw *hw)
@@ -73,11 +74,13 @@ static unsigned long sun4i_dclk_recalc_rate(struct clk_hw *hw,
 static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
 				  unsigned long *parent_rate)
 {
+	struct sun4i_dclk *dclk = hw_to_dclk(hw);
+	struct sun4i_tcon *tcon = dclk->tcon;
 	unsigned long best_parent = 0;
 	u8 best_div = 1;
 	int i;
 
-	for (i = 6; i <= 127; i++) {
+	for (i = tcon->dclk_min_div; i <= tcon->dclk_max_div; i++) {
 		unsigned long ideal = rate * i;
 		unsigned long rounded;
 
@@ -167,6 +170,7 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
 	dclk = devm_kzalloc(dev, sizeof(*dclk), GFP_KERNEL);
 	if (!dclk)
 		return -ENOMEM;
+	dclk->tcon = tcon;
 
 	init.name = clk_name;
 	init.ops = &sun4i_dclk_ops;
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index f69bcdf11cb8..3efa1ab045cd 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -177,6 +177,8 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
 	u8 clk_delay;
 	u32 val = 0;
 
+	tcon->dclk_min_div = 6;
+	tcon->dclk_max_div = 127;
 	sun4i_tcon0_mode_set_common(tcon, mode);
 
 	/* Adjust clock delay */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index f61bf6d83b4a..4141fbd97ddf 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -169,6 +169,8 @@ struct sun4i_tcon {
 
 	/* Pixel clock */
 	struct clk			*dclk;
+	u8				dclk_max_div;
+	u8				dclk_min_div;
 
 	/* Reset control */
 	struct reset_control		*lcd_rst;
-- 
git-series 0.9.1

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

* [PATCH 15/23] drm/sun4i: Add LVDS support
  2017-10-17  9:06 ` Maxime Ripard
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

The TCON supports the LVDS interface to output to a panel or a bridge.
Let's add support for it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/Makefile     |   1 +-
 drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 ++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_lvds.h |  18 +++-
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 193 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  25 ++++-
 5 files changed, 419 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index cfba2c07519c..6fee15d016ef 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -10,6 +10,7 @@ sun4i-drm-hdmi-y		+= sun4i_hdmi_tmds_clk.o
 
 sun4i-tcon-y			+= sun4i_tcon.o
 sun4i-tcon-y			+= sun4i_rgb.o
+sun4i-tcon-y			+= sun4i_lvds.o
 sun4i-tcon-y			+= sun4i_dotclock.o
 sun4i-tcon-y			+= sun4i_crtc.o
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
new file mode 100644
index 000000000000..635a3f505ecb
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2015 NextThing Co
+ * Copyright (C) 2015-2017 Free Electrons
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * 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 <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+
+#include "sun4i_crtc.h"
+#include "sun4i_tcon.h"
+#include "sun4i_lvds.h"
+
+struct sun4i_lvds {
+	struct drm_connector	connector;
+	struct drm_encoder	encoder;
+
+	struct sun4i_tcon	*tcon;
+};
+
+static inline struct sun4i_lvds *
+drm_connector_to_sun4i_lvds(struct drm_connector *connector)
+{
+	return container_of(connector, struct sun4i_lvds,
+			    connector);
+}
+
+static inline struct sun4i_lvds *
+drm_encoder_to_sun4i_lvds(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct sun4i_lvds,
+			    encoder);
+}
+
+static int sun4i_lvds_get_modes(struct drm_connector *connector)
+{
+	struct sun4i_lvds *lvds =
+		drm_connector_to_sun4i_lvds(connector);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	return drm_panel_get_modes(tcon->panel);
+}
+
+static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = {
+	.get_modes	= sun4i_lvds_get_modes,
+};
+
+static void
+sun4i_lvds_connector_destroy(struct drm_connector *connector)
+{
+	struct sun4i_lvds *lvds = drm_connector_to_sun4i_lvds(connector);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	drm_panel_detach(tcon->panel);
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs sun4i_lvds_con_funcs = {
+	.fill_modes		= drm_helper_probe_single_connector_modes,
+	.destroy		= sun4i_lvds_connector_destroy,
+	.reset			= drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
+};
+
+static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder)
+{
+	struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	DRM_DEBUG_DRIVER("Enabling LVDS output\n");
+
+	if (!IS_ERR(tcon->panel)) {
+		drm_panel_prepare(tcon->panel);
+		drm_panel_enable(tcon->panel);
+	}
+}
+
+static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder)
+{
+	struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	DRM_DEBUG_DRIVER("Disabling LVDS output\n");
+
+	if (!IS_ERR(tcon->panel)) {
+		drm_panel_disable(tcon->panel);
+		drm_panel_unprepare(tcon->panel);
+	}
+}
+
+static const struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = {
+	.disable	= sun4i_lvds_encoder_disable,
+	.enable		= sun4i_lvds_encoder_enable,
+};
+
+static const struct drm_encoder_funcs sun4i_lvds_enc_funcs = {
+	.destroy	= drm_encoder_cleanup,
+};
+
+int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon)
+{
+	struct drm_encoder *encoder;
+	struct drm_bridge *bridge;
+	struct sun4i_lvds *lvds;
+	int ret;
+
+	lvds = devm_kzalloc(drm->dev, sizeof(*lvds), GFP_KERNEL);
+	if (!lvds)
+		return -ENOMEM;
+	lvds->tcon = tcon;
+	encoder = &lvds->encoder;
+
+	ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
+					  &tcon->panel, &bridge);
+	if (ret) {
+		dev_info(drm->dev, "No panel or bridge found... LVDS output disabled\n");
+		return 0;
+	}
+
+	drm_encoder_helper_add(&lvds->encoder,
+			       &sun4i_lvds_enc_helper_funcs);
+	ret = drm_encoder_init(drm,
+			       &lvds->encoder,
+			       &sun4i_lvds_enc_funcs,
+			       DRM_MODE_ENCODER_LVDS,
+			       NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialise the lvds encoder\n");
+		goto err_out;
+	}
+
+	/* The LVDS encoder can only work with the TCON channel 0 */
+	lvds->encoder.possible_crtcs = BIT(drm_crtc_index(&tcon->crtc->crtc));
+
+	if (tcon->panel) {
+		drm_connector_helper_add(&lvds->connector,
+					 &sun4i_lvds_con_helper_funcs);
+		ret = drm_connector_init(drm, &lvds->connector,
+					 &sun4i_lvds_con_funcs,
+					 DRM_MODE_CONNECTOR_LVDS);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't initialise the lvds connector\n");
+			goto err_cleanup_connector;
+		}
+
+		drm_mode_connector_attach_encoder(&lvds->connector,
+						  &lvds->encoder);
+
+		ret = drm_panel_attach(tcon->panel, &lvds->connector);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't attach our panel\n");
+			goto err_cleanup_connector;
+		}
+	}
+
+	if (bridge) {
+		ret = drm_bridge_attach(encoder, bridge, NULL);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't attach our bridge\n");
+			goto err_cleanup_connector;
+		}
+	}
+
+	return 0;
+
+err_cleanup_connector:
+	drm_encoder_cleanup(&lvds->encoder);
+err_out:
+	return ret;
+}
+EXPORT_SYMBOL(sun4i_lvds_init);
diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.h b/drivers/gpu/drm/sun4i/sun4i_lvds.h
new file mode 100644
index 000000000000..1b8fad4b82c3
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun4i_lvds.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 NextThing Co
+ * Copyright (C) 2015-2017 Free Electrons
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * 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 _SUN4I_LVDS_H_
+#define _SUN4I_LVDS_H_
+
+int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon);
+
+#endif /* _SUN4I_LVDS_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 3efa1ab045cd..6a20a467ee6d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -31,10 +31,52 @@
 #include "sun4i_crtc.h"
 #include "sun4i_dotclock.h"
 #include "sun4i_drv.h"
+#include "sun4i_lvds.h"
 #include "sun4i_rgb.h"
 #include "sun4i_tcon.h"
 #include "sunxi_engine.h"
 
+static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
+{
+	struct drm_connector *connector;
+	struct drm_connector_list_iter iter;
+
+	drm_connector_list_iter_begin(encoder->dev, &iter);
+	drm_for_each_connector_iter(connector, &iter)
+		if (connector->encoder == encoder) {
+			drm_connector_list_iter_end(&iter);
+			return connector;
+		}
+	drm_connector_list_iter_end(&iter);
+
+	return NULL;
+}
+
+static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder)
+{
+	struct drm_connector *connector;
+	struct drm_display_info *info;
+
+	connector = sun4i_tcon_get_connector(encoder);
+	if (!connector)
+		return -EINVAL;
+
+	info = &connector->display_info;
+	if (info->num_bus_formats != 1)
+		return -EINVAL;
+
+	switch (info->bus_formats[0]) {
+	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
+		return 18;
+
+	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
+	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
+		return 24;
+	}
+
+	return -EINVAL;
+}
+
 static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
 					  bool enabled)
 {
@@ -69,9 +111,13 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
 			   const struct drm_encoder *encoder,
 			   bool enabled)
 {
+	bool is_lvds = false;
 	int channel;
 
 	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_LVDS:
+		is_lvds = true;
+		/* Fallthrough */
 	case DRM_MODE_ENCODER_NONE:
 		channel = 0;
 		break;
@@ -84,10 +130,47 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
 		return;
 	}
 
+	if (is_lvds && !enabled)
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
+				   SUN4I_TCON0_LVDS_IF_EN, 0);
+
 	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
 			   SUN4I_TCON_GCTL_TCON_ENABLE,
 			   enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
 
+	if (is_lvds && enabled) {
+		u8 val;
+
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
+				   SUN4I_TCON0_LVDS_IF_EN,
+				   SUN4I_TCON0_LVDS_IF_EN);
+
+		regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+			     SUN4I_TCON0_LVDS_ANA0_C(2) |
+			     SUN4I_TCON0_LVDS_ANA0_V(3) |
+			     SUN4I_TCON0_LVDS_ANA0_PD(2) |
+			     SUN4I_TCON0_LVDS_ANA0_EN_LDO);
+		udelay(2);
+
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+				   SUN4I_TCON0_LVDS_ANA0_EN_MB,
+				   SUN4I_TCON0_LVDS_ANA0_EN_MB);
+		udelay(2);
+
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+				   SUN4I_TCON0_LVDS_ANA0_EN_DRVC,
+				   SUN4I_TCON0_LVDS_ANA0_EN_DRVC);
+
+		if (sun4i_tcon_get_pixel_depth(encoder) == 18)
+			val = 7;
+		else
+			val = 0xf;
+
+		regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+				  SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
+				  SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val));
+	}
+
 	sun4i_tcon_channel_set_status(tcon, channel, enabled);
 }
 
@@ -170,6 +253,78 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
 		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
 }
 
+static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
+				      const struct drm_encoder *encoder,
+				      const struct drm_display_mode *mode)
+{
+	unsigned int bp;
+	u8 clk_delay;
+	u32 reg, val = 0;
+
+	tcon->dclk_min_div = 7;
+	tcon->dclk_max_div = 7;
+	sun4i_tcon0_mode_set_common(tcon, mode);
+
+	/* Adjust clock delay */
+	clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
+	regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
+			   SUN4I_TCON0_CTL_CLK_DELAY_MASK,
+			   SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
+
+	/*
+	 * This is called a backporch in the register documentation,
+	 * but it really is the back porch + hsync
+	 */
+	bp = mode->crtc_htotal - mode->crtc_hsync_start;
+	DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
+			 mode->crtc_htotal, bp);
+
+	/* Set horizontal display timings */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
+		     SUN4I_TCON0_BASIC1_H_TOTAL(0x554) |
+		     SUN4I_TCON0_BASIC1_H_BACKPORCH(0xa0));
+
+	/*
+	 * This is called a backporch in the register documentation,
+	 * but it really is the back porch + hsync
+	 */
+	bp = mode->crtc_vtotal - mode->crtc_vsync_start;
+	DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
+			 mode->crtc_vtotal, bp);
+
+	/* Set vertical display timings */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
+		     SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
+		     SUN4I_TCON0_BASIC2_V_BACKPORCH(0x17));
+
+	reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0 |
+		SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL |
+		SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL;
+	if (sun4i_tcon_get_pixel_depth(encoder) == 24)
+		reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS;
+	else
+		reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
+
+	regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
+
+	/* Setup the polarity of the various signals */
+	if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
+		val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
+
+	if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
+		val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
+
+	regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, 0);
+
+	/* Map output pins to channel 0 */
+	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
+			   SUN4I_TCON_GCTL_IOMAP_MASK,
+			   SUN4I_TCON_GCTL_IOMAP_TCON0);
+
+	/* Enable the output on the pins */
+	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
+}
+
 static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
 				     const struct drm_display_mode *mode)
 {
@@ -336,6 +491,9 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
 			 const struct drm_display_mode *mode)
 {
 	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_LVDS:
+		sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
+		break;
 	case DRM_MODE_ENCODER_NONE:
 		sun4i_tcon0_mode_set_rgb(tcon, mode);
 		sun4i_tcon_set_mux(tcon, 0, encoder);
@@ -667,7 +825,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 	struct drm_device *drm = data;
 	struct sun4i_drv *drv = drm->dev_private;
 	struct sunxi_engine *engine;
+	struct device_node *remote;
 	struct sun4i_tcon *tcon;
+	bool has_lvds;
 	int ret;
 
 	engine = sun4i_tcon_find_engine(drv, dev->of_node);
@@ -698,6 +858,26 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
+	/*
+	 * This can only be made optional since we've had DT nodes
+	 * without the LVDS reset properties.
+	 *
+	 * If the property is missing, just disable LVDS, and print a
+	 * warning.
+	 */
+	tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
+	if (IS_ERR(tcon->lvds_rst)) {
+		dev_err(dev, "Couldn't get our reset line\n");
+		return PTR_ERR(tcon->lvds_rst);
+	} else if (tcon->lvds_rst) {
+		has_lvds = true;
+		reset_control_reset(tcon->lvds_rst);
+	} else {
+		has_lvds = false;
+		dev_warn(dev,
+			 "Missing LVDS reset property, you should consider upgrading your DT\n");
+	}
+
 	ret = sun4i_tcon_init_clocks(dev, tcon);
 	if (ret) {
 		dev_err(dev, "Couldn't init our TCON clocks\n");
@@ -729,7 +909,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		goto err_free_clocks;
 	}
 
-	ret = sun4i_rgb_init(drm, tcon);
+	/*
+	 * If we have an LVDS panel connected to the TCON, we should
+	 * just probe the LVDS connector. Otherwise, just probe RGB as
+	 * we used to.
+	 */
+	remote = of_graph_get_remote_node(dev->of_node, 1, 0);
+	if (has_lvds && of_device_is_compatible(remote, "panel-lvds"))
+		ret = sun4i_lvds_init(drm, tcon);
+	else
+		ret = sun4i_rgb_init(drm, tcon);
+	of_node_put(remote);
+
 	if (ret < 0)
 		goto err_free_clocks;
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 4141fbd97ddf..382689e5396e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -70,7 +70,21 @@
 #define SUN4I_TCON0_TTL2_REG			0x78
 #define SUN4I_TCON0_TTL3_REG			0x7c
 #define SUN4I_TCON0_TTL4_REG			0x80
+
 #define SUN4I_TCON0_LVDS_IF_REG			0x84
+#define SUN4I_TCON0_LVDS_IF_EN				BIT(31)
+#define SUN4I_TCON0_LVDS_IF_BITWIDTH_MASK		BIT(26)
+#define SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS		(1 << 26)
+#define SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS		(0 << 26)
+#define SUN4I_TCON0_LVDS_IF_CLK_SEL_MASK		BIT(20)
+#define SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0		(1 << 20)
+#define SUN4I_TCON0_LVDS_IF_CLK_POL_MASK		BIT(4)
+#define SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL		(1 << 4)
+#define SUN4I_TCON0_LVDS_IF_CLK_POL_INV			(0 << 4)
+#define SUN4I_TCON0_LVDS_IF_DATA_POL_MASK		GENMASK(3, 0)
+#define SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL		(0xf)
+#define SUN4I_TCON0_LVDS_IF_DATA_POL_INV		(0)
+
 #define SUN4I_TCON0_IO_POL_REG			0x88
 #define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase)		((phase & 3) << 28)
 #define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE		BIT(25)
@@ -131,6 +145,16 @@
 #define SUN4I_TCON_CEU_RANGE_G_REG		0x144
 #define SUN4I_TCON_CEU_RANGE_B_REG		0x148
 #define SUN4I_TCON_MUX_CTRL_REG			0x200
+
+#define SUN4I_TCON0_LVDS_ANA0_REG		0x220
+#define SUN4I_TCON0_LVDS_ANA0_EN_MB			BIT(31)
+#define SUN4I_TCON0_LVDS_ANA0_EN_LDO			BIT(30)
+#define SUN4I_TCON0_LVDS_ANA0_EN_DRVC			BIT(24)
+#define SUN4I_TCON0_LVDS_ANA0_EN_DRVD(x)		(((x) & 0xf) << 20)
+#define SUN4I_TCON0_LVDS_ANA0_C(x)			(((x) & 3) << 17)
+#define SUN4I_TCON0_LVDS_ANA0_V(x)			(((x) & 3) << 8)
+#define SUN4I_TCON0_LVDS_ANA0_PD(x)			(((x) & 3) << 4)
+
 #define SUN4I_TCON1_FILL_CTL_REG		0x300
 #define SUN4I_TCON1_FILL_BEG0_REG		0x304
 #define SUN4I_TCON1_FILL_END0_REG		0x308
@@ -174,6 +198,7 @@ struct sun4i_tcon {
 
 	/* Reset control */
 	struct reset_control		*lcd_rst;
+	struct reset_control		*lvds_rst;
 
 	struct drm_panel		*panel;
 
-- 
git-series 0.9.1

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

* [PATCH 15/23] drm/sun4i: Add LVDS support
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

The TCON supports the LVDS interface to output to a panel or a bridge.
Let's add support for it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/Makefile     |   1 +-
 drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 ++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_lvds.h |  18 +++-
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 193 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  25 ++++-
 5 files changed, 419 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index cfba2c07519c..6fee15d016ef 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -10,6 +10,7 @@ sun4i-drm-hdmi-y		+= sun4i_hdmi_tmds_clk.o
 
 sun4i-tcon-y			+= sun4i_tcon.o
 sun4i-tcon-y			+= sun4i_rgb.o
+sun4i-tcon-y			+= sun4i_lvds.o
 sun4i-tcon-y			+= sun4i_dotclock.o
 sun4i-tcon-y			+= sun4i_crtc.o
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
new file mode 100644
index 000000000000..635a3f505ecb
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2015 NextThing Co
+ * Copyright (C) 2015-2017 Free Electrons
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * 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 <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+
+#include "sun4i_crtc.h"
+#include "sun4i_tcon.h"
+#include "sun4i_lvds.h"
+
+struct sun4i_lvds {
+	struct drm_connector	connector;
+	struct drm_encoder	encoder;
+
+	struct sun4i_tcon	*tcon;
+};
+
+static inline struct sun4i_lvds *
+drm_connector_to_sun4i_lvds(struct drm_connector *connector)
+{
+	return container_of(connector, struct sun4i_lvds,
+			    connector);
+}
+
+static inline struct sun4i_lvds *
+drm_encoder_to_sun4i_lvds(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct sun4i_lvds,
+			    encoder);
+}
+
+static int sun4i_lvds_get_modes(struct drm_connector *connector)
+{
+	struct sun4i_lvds *lvds =
+		drm_connector_to_sun4i_lvds(connector);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	return drm_panel_get_modes(tcon->panel);
+}
+
+static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = {
+	.get_modes	= sun4i_lvds_get_modes,
+};
+
+static void
+sun4i_lvds_connector_destroy(struct drm_connector *connector)
+{
+	struct sun4i_lvds *lvds = drm_connector_to_sun4i_lvds(connector);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	drm_panel_detach(tcon->panel);
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs sun4i_lvds_con_funcs = {
+	.fill_modes		= drm_helper_probe_single_connector_modes,
+	.destroy		= sun4i_lvds_connector_destroy,
+	.reset			= drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
+};
+
+static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder)
+{
+	struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	DRM_DEBUG_DRIVER("Enabling LVDS output\n");
+
+	if (!IS_ERR(tcon->panel)) {
+		drm_panel_prepare(tcon->panel);
+		drm_panel_enable(tcon->panel);
+	}
+}
+
+static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder)
+{
+	struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	DRM_DEBUG_DRIVER("Disabling LVDS output\n");
+
+	if (!IS_ERR(tcon->panel)) {
+		drm_panel_disable(tcon->panel);
+		drm_panel_unprepare(tcon->panel);
+	}
+}
+
+static const struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = {
+	.disable	= sun4i_lvds_encoder_disable,
+	.enable		= sun4i_lvds_encoder_enable,
+};
+
+static const struct drm_encoder_funcs sun4i_lvds_enc_funcs = {
+	.destroy	= drm_encoder_cleanup,
+};
+
+int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon)
+{
+	struct drm_encoder *encoder;
+	struct drm_bridge *bridge;
+	struct sun4i_lvds *lvds;
+	int ret;
+
+	lvds = devm_kzalloc(drm->dev, sizeof(*lvds), GFP_KERNEL);
+	if (!lvds)
+		return -ENOMEM;
+	lvds->tcon = tcon;
+	encoder = &lvds->encoder;
+
+	ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
+					  &tcon->panel, &bridge);
+	if (ret) {
+		dev_info(drm->dev, "No panel or bridge found... LVDS output disabled\n");
+		return 0;
+	}
+
+	drm_encoder_helper_add(&lvds->encoder,
+			       &sun4i_lvds_enc_helper_funcs);
+	ret = drm_encoder_init(drm,
+			       &lvds->encoder,
+			       &sun4i_lvds_enc_funcs,
+			       DRM_MODE_ENCODER_LVDS,
+			       NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialise the lvds encoder\n");
+		goto err_out;
+	}
+
+	/* The LVDS encoder can only work with the TCON channel 0 */
+	lvds->encoder.possible_crtcs = BIT(drm_crtc_index(&tcon->crtc->crtc));
+
+	if (tcon->panel) {
+		drm_connector_helper_add(&lvds->connector,
+					 &sun4i_lvds_con_helper_funcs);
+		ret = drm_connector_init(drm, &lvds->connector,
+					 &sun4i_lvds_con_funcs,
+					 DRM_MODE_CONNECTOR_LVDS);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't initialise the lvds connector\n");
+			goto err_cleanup_connector;
+		}
+
+		drm_mode_connector_attach_encoder(&lvds->connector,
+						  &lvds->encoder);
+
+		ret = drm_panel_attach(tcon->panel, &lvds->connector);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't attach our panel\n");
+			goto err_cleanup_connector;
+		}
+	}
+
+	if (bridge) {
+		ret = drm_bridge_attach(encoder, bridge, NULL);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't attach our bridge\n");
+			goto err_cleanup_connector;
+		}
+	}
+
+	return 0;
+
+err_cleanup_connector:
+	drm_encoder_cleanup(&lvds->encoder);
+err_out:
+	return ret;
+}
+EXPORT_SYMBOL(sun4i_lvds_init);
diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.h b/drivers/gpu/drm/sun4i/sun4i_lvds.h
new file mode 100644
index 000000000000..1b8fad4b82c3
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun4i_lvds.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 NextThing Co
+ * Copyright (C) 2015-2017 Free Electrons
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * 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 _SUN4I_LVDS_H_
+#define _SUN4I_LVDS_H_
+
+int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon);
+
+#endif /* _SUN4I_LVDS_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 3efa1ab045cd..6a20a467ee6d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -31,10 +31,52 @@
 #include "sun4i_crtc.h"
 #include "sun4i_dotclock.h"
 #include "sun4i_drv.h"
+#include "sun4i_lvds.h"
 #include "sun4i_rgb.h"
 #include "sun4i_tcon.h"
 #include "sunxi_engine.h"
 
+static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
+{
+	struct drm_connector *connector;
+	struct drm_connector_list_iter iter;
+
+	drm_connector_list_iter_begin(encoder->dev, &iter);
+	drm_for_each_connector_iter(connector, &iter)
+		if (connector->encoder == encoder) {
+			drm_connector_list_iter_end(&iter);
+			return connector;
+		}
+	drm_connector_list_iter_end(&iter);
+
+	return NULL;
+}
+
+static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder)
+{
+	struct drm_connector *connector;
+	struct drm_display_info *info;
+
+	connector = sun4i_tcon_get_connector(encoder);
+	if (!connector)
+		return -EINVAL;
+
+	info = &connector->display_info;
+	if (info->num_bus_formats != 1)
+		return -EINVAL;
+
+	switch (info->bus_formats[0]) {
+	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
+		return 18;
+
+	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
+	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
+		return 24;
+	}
+
+	return -EINVAL;
+}
+
 static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
 					  bool enabled)
 {
@@ -69,9 +111,13 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
 			   const struct drm_encoder *encoder,
 			   bool enabled)
 {
+	bool is_lvds = false;
 	int channel;
 
 	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_LVDS:
+		is_lvds = true;
+		/* Fallthrough */
 	case DRM_MODE_ENCODER_NONE:
 		channel = 0;
 		break;
@@ -84,10 +130,47 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
 		return;
 	}
 
+	if (is_lvds && !enabled)
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
+				   SUN4I_TCON0_LVDS_IF_EN, 0);
+
 	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
 			   SUN4I_TCON_GCTL_TCON_ENABLE,
 			   enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
 
+	if (is_lvds && enabled) {
+		u8 val;
+
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
+				   SUN4I_TCON0_LVDS_IF_EN,
+				   SUN4I_TCON0_LVDS_IF_EN);
+
+		regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+			     SUN4I_TCON0_LVDS_ANA0_C(2) |
+			     SUN4I_TCON0_LVDS_ANA0_V(3) |
+			     SUN4I_TCON0_LVDS_ANA0_PD(2) |
+			     SUN4I_TCON0_LVDS_ANA0_EN_LDO);
+		udelay(2);
+
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+				   SUN4I_TCON0_LVDS_ANA0_EN_MB,
+				   SUN4I_TCON0_LVDS_ANA0_EN_MB);
+		udelay(2);
+
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+				   SUN4I_TCON0_LVDS_ANA0_EN_DRVC,
+				   SUN4I_TCON0_LVDS_ANA0_EN_DRVC);
+
+		if (sun4i_tcon_get_pixel_depth(encoder) == 18)
+			val = 7;
+		else
+			val = 0xf;
+
+		regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+				  SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
+				  SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val));
+	}
+
 	sun4i_tcon_channel_set_status(tcon, channel, enabled);
 }
 
@@ -170,6 +253,78 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
 		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
 }
 
+static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
+				      const struct drm_encoder *encoder,
+				      const struct drm_display_mode *mode)
+{
+	unsigned int bp;
+	u8 clk_delay;
+	u32 reg, val = 0;
+
+	tcon->dclk_min_div = 7;
+	tcon->dclk_max_div = 7;
+	sun4i_tcon0_mode_set_common(tcon, mode);
+
+	/* Adjust clock delay */
+	clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
+	regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
+			   SUN4I_TCON0_CTL_CLK_DELAY_MASK,
+			   SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
+
+	/*
+	 * This is called a backporch in the register documentation,
+	 * but it really is the back porch + hsync
+	 */
+	bp = mode->crtc_htotal - mode->crtc_hsync_start;
+	DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
+			 mode->crtc_htotal, bp);
+
+	/* Set horizontal display timings */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
+		     SUN4I_TCON0_BASIC1_H_TOTAL(0x554) |
+		     SUN4I_TCON0_BASIC1_H_BACKPORCH(0xa0));
+
+	/*
+	 * This is called a backporch in the register documentation,
+	 * but it really is the back porch + hsync
+	 */
+	bp = mode->crtc_vtotal - mode->crtc_vsync_start;
+	DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
+			 mode->crtc_vtotal, bp);
+
+	/* Set vertical display timings */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
+		     SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
+		     SUN4I_TCON0_BASIC2_V_BACKPORCH(0x17));
+
+	reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0 |
+		SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL |
+		SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL;
+	if (sun4i_tcon_get_pixel_depth(encoder) == 24)
+		reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS;
+	else
+		reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
+
+	regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
+
+	/* Setup the polarity of the various signals */
+	if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
+		val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
+
+	if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
+		val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
+
+	regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, 0);
+
+	/* Map output pins to channel 0 */
+	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
+			   SUN4I_TCON_GCTL_IOMAP_MASK,
+			   SUN4I_TCON_GCTL_IOMAP_TCON0);
+
+	/* Enable the output on the pins */
+	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
+}
+
 static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
 				     const struct drm_display_mode *mode)
 {
@@ -336,6 +491,9 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
 			 const struct drm_display_mode *mode)
 {
 	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_LVDS:
+		sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
+		break;
 	case DRM_MODE_ENCODER_NONE:
 		sun4i_tcon0_mode_set_rgb(tcon, mode);
 		sun4i_tcon_set_mux(tcon, 0, encoder);
@@ -667,7 +825,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 	struct drm_device *drm = data;
 	struct sun4i_drv *drv = drm->dev_private;
 	struct sunxi_engine *engine;
+	struct device_node *remote;
 	struct sun4i_tcon *tcon;
+	bool has_lvds;
 	int ret;
 
 	engine = sun4i_tcon_find_engine(drv, dev->of_node);
@@ -698,6 +858,26 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
+	/*
+	 * This can only be made optional since we've had DT nodes
+	 * without the LVDS reset properties.
+	 *
+	 * If the property is missing, just disable LVDS, and print a
+	 * warning.
+	 */
+	tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
+	if (IS_ERR(tcon->lvds_rst)) {
+		dev_err(dev, "Couldn't get our reset line\n");
+		return PTR_ERR(tcon->lvds_rst);
+	} else if (tcon->lvds_rst) {
+		has_lvds = true;
+		reset_control_reset(tcon->lvds_rst);
+	} else {
+		has_lvds = false;
+		dev_warn(dev,
+			 "Missing LVDS reset property, you should consider upgrading your DT\n");
+	}
+
 	ret = sun4i_tcon_init_clocks(dev, tcon);
 	if (ret) {
 		dev_err(dev, "Couldn't init our TCON clocks\n");
@@ -729,7 +909,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		goto err_free_clocks;
 	}
 
-	ret = sun4i_rgb_init(drm, tcon);
+	/*
+	 * If we have an LVDS panel connected to the TCON, we should
+	 * just probe the LVDS connector. Otherwise, just probe RGB as
+	 * we used to.
+	 */
+	remote = of_graph_get_remote_node(dev->of_node, 1, 0);
+	if (has_lvds && of_device_is_compatible(remote, "panel-lvds"))
+		ret = sun4i_lvds_init(drm, tcon);
+	else
+		ret = sun4i_rgb_init(drm, tcon);
+	of_node_put(remote);
+
 	if (ret < 0)
 		goto err_free_clocks;
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 4141fbd97ddf..382689e5396e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -70,7 +70,21 @@
 #define SUN4I_TCON0_TTL2_REG			0x78
 #define SUN4I_TCON0_TTL3_REG			0x7c
 #define SUN4I_TCON0_TTL4_REG			0x80
+
 #define SUN4I_TCON0_LVDS_IF_REG			0x84
+#define SUN4I_TCON0_LVDS_IF_EN				BIT(31)
+#define SUN4I_TCON0_LVDS_IF_BITWIDTH_MASK		BIT(26)
+#define SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS		(1 << 26)
+#define SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS		(0 << 26)
+#define SUN4I_TCON0_LVDS_IF_CLK_SEL_MASK		BIT(20)
+#define SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0		(1 << 20)
+#define SUN4I_TCON0_LVDS_IF_CLK_POL_MASK		BIT(4)
+#define SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL		(1 << 4)
+#define SUN4I_TCON0_LVDS_IF_CLK_POL_INV			(0 << 4)
+#define SUN4I_TCON0_LVDS_IF_DATA_POL_MASK		GENMASK(3, 0)
+#define SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL		(0xf)
+#define SUN4I_TCON0_LVDS_IF_DATA_POL_INV		(0)
+
 #define SUN4I_TCON0_IO_POL_REG			0x88
 #define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase)		((phase & 3) << 28)
 #define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE		BIT(25)
@@ -131,6 +145,16 @@
 #define SUN4I_TCON_CEU_RANGE_G_REG		0x144
 #define SUN4I_TCON_CEU_RANGE_B_REG		0x148
 #define SUN4I_TCON_MUX_CTRL_REG			0x200
+
+#define SUN4I_TCON0_LVDS_ANA0_REG		0x220
+#define SUN4I_TCON0_LVDS_ANA0_EN_MB			BIT(31)
+#define SUN4I_TCON0_LVDS_ANA0_EN_LDO			BIT(30)
+#define SUN4I_TCON0_LVDS_ANA0_EN_DRVC			BIT(24)
+#define SUN4I_TCON0_LVDS_ANA0_EN_DRVD(x)		(((x) & 0xf) << 20)
+#define SUN4I_TCON0_LVDS_ANA0_C(x)			(((x) & 3) << 17)
+#define SUN4I_TCON0_LVDS_ANA0_V(x)			(((x) & 3) << 8)
+#define SUN4I_TCON0_LVDS_ANA0_PD(x)			(((x) & 3) << 4)
+
 #define SUN4I_TCON1_FILL_CTL_REG		0x300
 #define SUN4I_TCON1_FILL_BEG0_REG		0x304
 #define SUN4I_TCON1_FILL_END0_REG		0x308
@@ -174,6 +198,7 @@ struct sun4i_tcon {
 
 	/* Reset control */
 	struct reset_control		*lcd_rst;
+	struct reset_control		*lvds_rst;
 
 	struct drm_panel		*panel;
 
-- 
git-series 0.9.1

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

* [PATCH 15/23] drm/sun4i: Add LVDS support
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The TCON supports the LVDS interface to output to a panel or a bridge.
Let's add support for it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/Makefile     |   1 +-
 drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 ++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_lvds.h |  18 +++-
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 193 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  25 ++++-
 5 files changed, 419 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index cfba2c07519c..6fee15d016ef 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -10,6 +10,7 @@ sun4i-drm-hdmi-y		+= sun4i_hdmi_tmds_clk.o
 
 sun4i-tcon-y			+= sun4i_tcon.o
 sun4i-tcon-y			+= sun4i_rgb.o
+sun4i-tcon-y			+= sun4i_lvds.o
 sun4i-tcon-y			+= sun4i_dotclock.o
 sun4i-tcon-y			+= sun4i_crtc.o
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
new file mode 100644
index 000000000000..635a3f505ecb
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2015 NextThing Co
+ * Copyright (C) 2015-2017 Free Electrons
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * 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 <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+
+#include "sun4i_crtc.h"
+#include "sun4i_tcon.h"
+#include "sun4i_lvds.h"
+
+struct sun4i_lvds {
+	struct drm_connector	connector;
+	struct drm_encoder	encoder;
+
+	struct sun4i_tcon	*tcon;
+};
+
+static inline struct sun4i_lvds *
+drm_connector_to_sun4i_lvds(struct drm_connector *connector)
+{
+	return container_of(connector, struct sun4i_lvds,
+			    connector);
+}
+
+static inline struct sun4i_lvds *
+drm_encoder_to_sun4i_lvds(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct sun4i_lvds,
+			    encoder);
+}
+
+static int sun4i_lvds_get_modes(struct drm_connector *connector)
+{
+	struct sun4i_lvds *lvds =
+		drm_connector_to_sun4i_lvds(connector);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	return drm_panel_get_modes(tcon->panel);
+}
+
+static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = {
+	.get_modes	= sun4i_lvds_get_modes,
+};
+
+static void
+sun4i_lvds_connector_destroy(struct drm_connector *connector)
+{
+	struct sun4i_lvds *lvds = drm_connector_to_sun4i_lvds(connector);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	drm_panel_detach(tcon->panel);
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs sun4i_lvds_con_funcs = {
+	.fill_modes		= drm_helper_probe_single_connector_modes,
+	.destroy		= sun4i_lvds_connector_destroy,
+	.reset			= drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
+};
+
+static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder)
+{
+	struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	DRM_DEBUG_DRIVER("Enabling LVDS output\n");
+
+	if (!IS_ERR(tcon->panel)) {
+		drm_panel_prepare(tcon->panel);
+		drm_panel_enable(tcon->panel);
+	}
+}
+
+static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder)
+{
+	struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	DRM_DEBUG_DRIVER("Disabling LVDS output\n");
+
+	if (!IS_ERR(tcon->panel)) {
+		drm_panel_disable(tcon->panel);
+		drm_panel_unprepare(tcon->panel);
+	}
+}
+
+static const struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = {
+	.disable	= sun4i_lvds_encoder_disable,
+	.enable		= sun4i_lvds_encoder_enable,
+};
+
+static const struct drm_encoder_funcs sun4i_lvds_enc_funcs = {
+	.destroy	= drm_encoder_cleanup,
+};
+
+int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon)
+{
+	struct drm_encoder *encoder;
+	struct drm_bridge *bridge;
+	struct sun4i_lvds *lvds;
+	int ret;
+
+	lvds = devm_kzalloc(drm->dev, sizeof(*lvds), GFP_KERNEL);
+	if (!lvds)
+		return -ENOMEM;
+	lvds->tcon = tcon;
+	encoder = &lvds->encoder;
+
+	ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
+					  &tcon->panel, &bridge);
+	if (ret) {
+		dev_info(drm->dev, "No panel or bridge found... LVDS output disabled\n");
+		return 0;
+	}
+
+	drm_encoder_helper_add(&lvds->encoder,
+			       &sun4i_lvds_enc_helper_funcs);
+	ret = drm_encoder_init(drm,
+			       &lvds->encoder,
+			       &sun4i_lvds_enc_funcs,
+			       DRM_MODE_ENCODER_LVDS,
+			       NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialise the lvds encoder\n");
+		goto err_out;
+	}
+
+	/* The LVDS encoder can only work with the TCON channel 0 */
+	lvds->encoder.possible_crtcs = BIT(drm_crtc_index(&tcon->crtc->crtc));
+
+	if (tcon->panel) {
+		drm_connector_helper_add(&lvds->connector,
+					 &sun4i_lvds_con_helper_funcs);
+		ret = drm_connector_init(drm, &lvds->connector,
+					 &sun4i_lvds_con_funcs,
+					 DRM_MODE_CONNECTOR_LVDS);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't initialise the lvds connector\n");
+			goto err_cleanup_connector;
+		}
+
+		drm_mode_connector_attach_encoder(&lvds->connector,
+						  &lvds->encoder);
+
+		ret = drm_panel_attach(tcon->panel, &lvds->connector);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't attach our panel\n");
+			goto err_cleanup_connector;
+		}
+	}
+
+	if (bridge) {
+		ret = drm_bridge_attach(encoder, bridge, NULL);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't attach our bridge\n");
+			goto err_cleanup_connector;
+		}
+	}
+
+	return 0;
+
+err_cleanup_connector:
+	drm_encoder_cleanup(&lvds->encoder);
+err_out:
+	return ret;
+}
+EXPORT_SYMBOL(sun4i_lvds_init);
diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.h b/drivers/gpu/drm/sun4i/sun4i_lvds.h
new file mode 100644
index 000000000000..1b8fad4b82c3
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun4i_lvds.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 NextThing Co
+ * Copyright (C) 2015-2017 Free Electrons
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * 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 _SUN4I_LVDS_H_
+#define _SUN4I_LVDS_H_
+
+int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon);
+
+#endif /* _SUN4I_LVDS_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 3efa1ab045cd..6a20a467ee6d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -31,10 +31,52 @@
 #include "sun4i_crtc.h"
 #include "sun4i_dotclock.h"
 #include "sun4i_drv.h"
+#include "sun4i_lvds.h"
 #include "sun4i_rgb.h"
 #include "sun4i_tcon.h"
 #include "sunxi_engine.h"
 
+static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
+{
+	struct drm_connector *connector;
+	struct drm_connector_list_iter iter;
+
+	drm_connector_list_iter_begin(encoder->dev, &iter);
+	drm_for_each_connector_iter(connector, &iter)
+		if (connector->encoder == encoder) {
+			drm_connector_list_iter_end(&iter);
+			return connector;
+		}
+	drm_connector_list_iter_end(&iter);
+
+	return NULL;
+}
+
+static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder)
+{
+	struct drm_connector *connector;
+	struct drm_display_info *info;
+
+	connector = sun4i_tcon_get_connector(encoder);
+	if (!connector)
+		return -EINVAL;
+
+	info = &connector->display_info;
+	if (info->num_bus_formats != 1)
+		return -EINVAL;
+
+	switch (info->bus_formats[0]) {
+	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
+		return 18;
+
+	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
+	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
+		return 24;
+	}
+
+	return -EINVAL;
+}
+
 static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
 					  bool enabled)
 {
@@ -69,9 +111,13 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
 			   const struct drm_encoder *encoder,
 			   bool enabled)
 {
+	bool is_lvds = false;
 	int channel;
 
 	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_LVDS:
+		is_lvds = true;
+		/* Fallthrough */
 	case DRM_MODE_ENCODER_NONE:
 		channel = 0;
 		break;
@@ -84,10 +130,47 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
 		return;
 	}
 
+	if (is_lvds && !enabled)
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
+				   SUN4I_TCON0_LVDS_IF_EN, 0);
+
 	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
 			   SUN4I_TCON_GCTL_TCON_ENABLE,
 			   enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
 
+	if (is_lvds && enabled) {
+		u8 val;
+
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
+				   SUN4I_TCON0_LVDS_IF_EN,
+				   SUN4I_TCON0_LVDS_IF_EN);
+
+		regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+			     SUN4I_TCON0_LVDS_ANA0_C(2) |
+			     SUN4I_TCON0_LVDS_ANA0_V(3) |
+			     SUN4I_TCON0_LVDS_ANA0_PD(2) |
+			     SUN4I_TCON0_LVDS_ANA0_EN_LDO);
+		udelay(2);
+
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+				   SUN4I_TCON0_LVDS_ANA0_EN_MB,
+				   SUN4I_TCON0_LVDS_ANA0_EN_MB);
+		udelay(2);
+
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+				   SUN4I_TCON0_LVDS_ANA0_EN_DRVC,
+				   SUN4I_TCON0_LVDS_ANA0_EN_DRVC);
+
+		if (sun4i_tcon_get_pixel_depth(encoder) == 18)
+			val = 7;
+		else
+			val = 0xf;
+
+		regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+				  SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
+				  SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val));
+	}
+
 	sun4i_tcon_channel_set_status(tcon, channel, enabled);
 }
 
@@ -170,6 +253,78 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
 		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
 }
 
+static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
+				      const struct drm_encoder *encoder,
+				      const struct drm_display_mode *mode)
+{
+	unsigned int bp;
+	u8 clk_delay;
+	u32 reg, val = 0;
+
+	tcon->dclk_min_div = 7;
+	tcon->dclk_max_div = 7;
+	sun4i_tcon0_mode_set_common(tcon, mode);
+
+	/* Adjust clock delay */
+	clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
+	regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
+			   SUN4I_TCON0_CTL_CLK_DELAY_MASK,
+			   SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
+
+	/*
+	 * This is called a backporch in the register documentation,
+	 * but it really is the back porch + hsync
+	 */
+	bp = mode->crtc_htotal - mode->crtc_hsync_start;
+	DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
+			 mode->crtc_htotal, bp);
+
+	/* Set horizontal display timings */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
+		     SUN4I_TCON0_BASIC1_H_TOTAL(0x554) |
+		     SUN4I_TCON0_BASIC1_H_BACKPORCH(0xa0));
+
+	/*
+	 * This is called a backporch in the register documentation,
+	 * but it really is the back porch + hsync
+	 */
+	bp = mode->crtc_vtotal - mode->crtc_vsync_start;
+	DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
+			 mode->crtc_vtotal, bp);
+
+	/* Set vertical display timings */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
+		     SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
+		     SUN4I_TCON0_BASIC2_V_BACKPORCH(0x17));
+
+	reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0 |
+		SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL |
+		SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL;
+	if (sun4i_tcon_get_pixel_depth(encoder) == 24)
+		reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS;
+	else
+		reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
+
+	regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
+
+	/* Setup the polarity of the various signals */
+	if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
+		val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
+
+	if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
+		val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
+
+	regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, 0);
+
+	/* Map output pins to channel 0 */
+	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
+			   SUN4I_TCON_GCTL_IOMAP_MASK,
+			   SUN4I_TCON_GCTL_IOMAP_TCON0);
+
+	/* Enable the output on the pins */
+	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
+}
+
 static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
 				     const struct drm_display_mode *mode)
 {
@@ -336,6 +491,9 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
 			 const struct drm_display_mode *mode)
 {
 	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_LVDS:
+		sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
+		break;
 	case DRM_MODE_ENCODER_NONE:
 		sun4i_tcon0_mode_set_rgb(tcon, mode);
 		sun4i_tcon_set_mux(tcon, 0, encoder);
@@ -667,7 +825,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 	struct drm_device *drm = data;
 	struct sun4i_drv *drv = drm->dev_private;
 	struct sunxi_engine *engine;
+	struct device_node *remote;
 	struct sun4i_tcon *tcon;
+	bool has_lvds;
 	int ret;
 
 	engine = sun4i_tcon_find_engine(drv, dev->of_node);
@@ -698,6 +858,26 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
+	/*
+	 * This can only be made optional since we've had DT nodes
+	 * without the LVDS reset properties.
+	 *
+	 * If the property is missing, just disable LVDS, and print a
+	 * warning.
+	 */
+	tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
+	if (IS_ERR(tcon->lvds_rst)) {
+		dev_err(dev, "Couldn't get our reset line\n");
+		return PTR_ERR(tcon->lvds_rst);
+	} else if (tcon->lvds_rst) {
+		has_lvds = true;
+		reset_control_reset(tcon->lvds_rst);
+	} else {
+		has_lvds = false;
+		dev_warn(dev,
+			 "Missing LVDS reset property, you should consider upgrading your DT\n");
+	}
+
 	ret = sun4i_tcon_init_clocks(dev, tcon);
 	if (ret) {
 		dev_err(dev, "Couldn't init our TCON clocks\n");
@@ -729,7 +909,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		goto err_free_clocks;
 	}
 
-	ret = sun4i_rgb_init(drm, tcon);
+	/*
+	 * If we have an LVDS panel connected to the TCON, we should
+	 * just probe the LVDS connector. Otherwise, just probe RGB as
+	 * we used to.
+	 */
+	remote = of_graph_get_remote_node(dev->of_node, 1, 0);
+	if (has_lvds && of_device_is_compatible(remote, "panel-lvds"))
+		ret = sun4i_lvds_init(drm, tcon);
+	else
+		ret = sun4i_rgb_init(drm, tcon);
+	of_node_put(remote);
+
 	if (ret < 0)
 		goto err_free_clocks;
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 4141fbd97ddf..382689e5396e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -70,7 +70,21 @@
 #define SUN4I_TCON0_TTL2_REG			0x78
 #define SUN4I_TCON0_TTL3_REG			0x7c
 #define SUN4I_TCON0_TTL4_REG			0x80
+
 #define SUN4I_TCON0_LVDS_IF_REG			0x84
+#define SUN4I_TCON0_LVDS_IF_EN				BIT(31)
+#define SUN4I_TCON0_LVDS_IF_BITWIDTH_MASK		BIT(26)
+#define SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS		(1 << 26)
+#define SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS		(0 << 26)
+#define SUN4I_TCON0_LVDS_IF_CLK_SEL_MASK		BIT(20)
+#define SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0		(1 << 20)
+#define SUN4I_TCON0_LVDS_IF_CLK_POL_MASK		BIT(4)
+#define SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL		(1 << 4)
+#define SUN4I_TCON0_LVDS_IF_CLK_POL_INV			(0 << 4)
+#define SUN4I_TCON0_LVDS_IF_DATA_POL_MASK		GENMASK(3, 0)
+#define SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL		(0xf)
+#define SUN4I_TCON0_LVDS_IF_DATA_POL_INV		(0)
+
 #define SUN4I_TCON0_IO_POL_REG			0x88
 #define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase)		((phase & 3) << 28)
 #define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE		BIT(25)
@@ -131,6 +145,16 @@
 #define SUN4I_TCON_CEU_RANGE_G_REG		0x144
 #define SUN4I_TCON_CEU_RANGE_B_REG		0x148
 #define SUN4I_TCON_MUX_CTRL_REG			0x200
+
+#define SUN4I_TCON0_LVDS_ANA0_REG		0x220
+#define SUN4I_TCON0_LVDS_ANA0_EN_MB			BIT(31)
+#define SUN4I_TCON0_LVDS_ANA0_EN_LDO			BIT(30)
+#define SUN4I_TCON0_LVDS_ANA0_EN_DRVC			BIT(24)
+#define SUN4I_TCON0_LVDS_ANA0_EN_DRVD(x)		(((x) & 0xf) << 20)
+#define SUN4I_TCON0_LVDS_ANA0_C(x)			(((x) & 3) << 17)
+#define SUN4I_TCON0_LVDS_ANA0_V(x)			(((x) & 3) << 8)
+#define SUN4I_TCON0_LVDS_ANA0_PD(x)			(((x) & 3) << 4)
+
 #define SUN4I_TCON1_FILL_CTL_REG		0x300
 #define SUN4I_TCON1_FILL_BEG0_REG		0x304
 #define SUN4I_TCON1_FILL_END0_REG		0x308
@@ -174,6 +198,7 @@ struct sun4i_tcon {
 
 	/* Reset control */
 	struct reset_control		*lcd_rst;
+	struct reset_control		*lvds_rst;
 
 	struct drm_panel		*panel;
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 16/23] drm/sun4i: Add A83T support
  2017-10-17  9:06 ` Maxime Ripard
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

Add support for the A83T display pipeline.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 3 +++
 drivers/gpu/drm/sun4i/sun4i_drv.c                             | 2 ++
 drivers/gpu/drm/sun4i/sun4i_tcon.c                            | 1 +
 drivers/gpu/drm/sun4i/sun8i_mixer.c                           | 4 ++++
 4 files changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 46df3b78ae9e..c0fa233ec1fc 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -90,6 +90,7 @@ Required properties:
    * allwinner,sun6i-a31-tcon
    * allwinner,sun6i-a31s-tcon
    * allwinner,sun8i-a33-tcon
+   * allwinner,sun8i-a83t-tcon
    * allwinner,sun8i-v3s-tcon
  - reg: base address and size of memory-mapped region
  - interrupts: interrupt associated to this IP
@@ -209,6 +210,7 @@ supported.
 
 Required properties:
   - compatible: value must be one of:
+    * allwinner,sun8i-a83t-de2-mixer
     * allwinner,sun8i-v3s-de2-mixer
   - reg: base address and size of the memory-mapped region.
   - clocks: phandles to the clocks feeding the mixer
@@ -236,6 +238,7 @@ Required properties:
     * allwinner,sun6i-a31-display-engine
     * allwinner,sun6i-a31s-display-engine
     * allwinner,sun8i-a33-display-engine
+    * allwinner,sun8i-a83t-display-engine
     * allwinner,sun8i-v3s-display-engine
 
   - allwinner,pipelines: list of phandle to the display engine
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index a27efad9bc76..439f116bb3b5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -189,6 +189,7 @@ static bool sun4i_drv_node_is_tcon(struct device_node *node)
 		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-a83t-tcon") ||
 		of_device_is_compatible(node, "allwinner,sun8i-v3s-tcon");
 }
 
@@ -347,6 +348,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-a83t-display-engine" },
 	{ .compatible = "allwinner,sun8i-v3s-display-engine" },
 	{ }
 };
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 6a20a467ee6d..eb3c8bad4977 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -1063,6 +1063,7 @@ static const struct of_device_id sun4i_tcon_of_table[] = {
 	{ .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-a83t-tcon", .data = &sun8i_v3s_quirks },
 	{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
 	{ }
 };
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 86c6c24b5105..c6030ce130d3 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -385,6 +385,10 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
 
 static const struct of_device_id sun8i_mixer_of_table[] = {
 	{
+		.compatible = "allwinner,sun8i-a83t-de2-mixer",
+		.data = &sun8i_v3s_mixer_cfg,
+	},
+	{
 		.compatible = "allwinner,sun8i-v3s-de2-mixer",
 		.data = &sun8i_v3s_mixer_cfg,
 	},
-- 
git-series 0.9.1

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

* [PATCH 16/23] drm/sun4i: Add A83T support
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

Add support for the A83T display pipeline.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 3 +++
 drivers/gpu/drm/sun4i/sun4i_drv.c                             | 2 ++
 drivers/gpu/drm/sun4i/sun4i_tcon.c                            | 1 +
 drivers/gpu/drm/sun4i/sun8i_mixer.c                           | 4 ++++
 4 files changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 46df3b78ae9e..c0fa233ec1fc 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -90,6 +90,7 @@ Required properties:
    * allwinner,sun6i-a31-tcon
    * allwinner,sun6i-a31s-tcon
    * allwinner,sun8i-a33-tcon
+   * allwinner,sun8i-a83t-tcon
    * allwinner,sun8i-v3s-tcon
  - reg: base address and size of memory-mapped region
  - interrupts: interrupt associated to this IP
@@ -209,6 +210,7 @@ supported.
 
 Required properties:
   - compatible: value must be one of:
+    * allwinner,sun8i-a83t-de2-mixer
     * allwinner,sun8i-v3s-de2-mixer
   - reg: base address and size of the memory-mapped region.
   - clocks: phandles to the clocks feeding the mixer
@@ -236,6 +238,7 @@ Required properties:
     * allwinner,sun6i-a31-display-engine
     * allwinner,sun6i-a31s-display-engine
     * allwinner,sun8i-a33-display-engine
+    * allwinner,sun8i-a83t-display-engine
     * allwinner,sun8i-v3s-display-engine
 
   - allwinner,pipelines: list of phandle to the display engine
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index a27efad9bc76..439f116bb3b5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -189,6 +189,7 @@ static bool sun4i_drv_node_is_tcon(struct device_node *node)
 		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-a83t-tcon") ||
 		of_device_is_compatible(node, "allwinner,sun8i-v3s-tcon");
 }
 
@@ -347,6 +348,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-a83t-display-engine" },
 	{ .compatible = "allwinner,sun8i-v3s-display-engine" },
 	{ }
 };
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 6a20a467ee6d..eb3c8bad4977 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -1063,6 +1063,7 @@ static const struct of_device_id sun4i_tcon_of_table[] = {
 	{ .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-a83t-tcon", .data = &sun8i_v3s_quirks },
 	{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
 	{ }
 };
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 86c6c24b5105..c6030ce130d3 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -385,6 +385,10 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
 
 static const struct of_device_id sun8i_mixer_of_table[] = {
 	{
+		.compatible = "allwinner,sun8i-a83t-de2-mixer",
+		.data = &sun8i_v3s_mixer_cfg,
+	},
+	{
 		.compatible = "allwinner,sun8i-v3s-de2-mixer",
 		.data = &sun8i_v3s_mixer_cfg,
 	},
-- 
git-series 0.9.1

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

* [PATCH 16/23] drm/sun4i: Add A83T support
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

Add support for the A83T display pipeline.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 3 +++
 drivers/gpu/drm/sun4i/sun4i_drv.c                             | 2 ++
 drivers/gpu/drm/sun4i/sun4i_tcon.c                            | 1 +
 drivers/gpu/drm/sun4i/sun8i_mixer.c                           | 4 ++++
 4 files changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 46df3b78ae9e..c0fa233ec1fc 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -90,6 +90,7 @@ Required properties:
    * allwinner,sun6i-a31-tcon
    * allwinner,sun6i-a31s-tcon
    * allwinner,sun8i-a33-tcon
+   * allwinner,sun8i-a83t-tcon
    * allwinner,sun8i-v3s-tcon
  - reg: base address and size of memory-mapped region
  - interrupts: interrupt associated to this IP
@@ -209,6 +210,7 @@ supported.
 
 Required properties:
   - compatible: value must be one of:
+    * allwinner,sun8i-a83t-de2-mixer
     * allwinner,sun8i-v3s-de2-mixer
   - reg: base address and size of the memory-mapped region.
   - clocks: phandles to the clocks feeding the mixer
@@ -236,6 +238,7 @@ Required properties:
     * allwinner,sun6i-a31-display-engine
     * allwinner,sun6i-a31s-display-engine
     * allwinner,sun8i-a33-display-engine
+    * allwinner,sun8i-a83t-display-engine
     * allwinner,sun8i-v3s-display-engine
 
   - allwinner,pipelines: list of phandle to the display engine
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index a27efad9bc76..439f116bb3b5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -189,6 +189,7 @@ static bool sun4i_drv_node_is_tcon(struct device_node *node)
 		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-a83t-tcon") ||
 		of_device_is_compatible(node, "allwinner,sun8i-v3s-tcon");
 }
 
@@ -347,6 +348,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-a83t-display-engine" },
 	{ .compatible = "allwinner,sun8i-v3s-display-engine" },
 	{ }
 };
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 6a20a467ee6d..eb3c8bad4977 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -1063,6 +1063,7 @@ static const struct of_device_id sun4i_tcon_of_table[] = {
 	{ .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-a83t-tcon", .data = &sun8i_v3s_quirks },
 	{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
 	{ }
 };
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 86c6c24b5105..c6030ce130d3 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -385,6 +385,10 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
 
 static const struct of_device_id sun8i_mixer_of_table[] = {
 	{
+		.compatible = "allwinner,sun8i-a83t-de2-mixer",
+		.data = &sun8i_v3s_mixer_cfg,
+	},
+	{
 		.compatible = "allwinner,sun8i-v3s-de2-mixer",
 		.data = &sun8i_v3s_mixer_cfg,
 	},
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 17/23] arm: dts: sun8i: a83t: Add display pipeline
  2017-10-17  9:06 ` Maxime Ripard
  (?)
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

The display pipeline on the A83T is mainly composed of the mixers and
TCONs, plus various encoders.

Let's add the mixers and TCONs to the DTSI.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi | 80 ++++++++++++++++++++++++++++++++-
 1 file changed, 80 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index ce6e887c8938..57feeb6fee8b 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -151,6 +151,12 @@
 		};
 	};
 
+	de: display-engine {
+		compatible = "allwinner,sun8i-a83t-display-engine";
+		allwinner,pipelines = <&mixer0>;
+		status = "disabled";
+	};
+
 	memory {
 		reg = <0x40000000 0x80000000>;
 		device_type = "memory";
@@ -162,6 +168,46 @@
 		#size-cells = <1>;
 		ranges;
 
+		display_clocks: clock@1000000 {
+			compatible = "allwinner,sun8i-a83t-de2-clk";
+			reg = <0x01000000 0x100000>;
+			clocks = <&ccu CLK_PLL_DE>,
+				 <&ccu CLK_BUS_DE>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&ccu RST_BUS_DE>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		mixer0: mixer@1100000 {
+			compatible = "allwinner,sun8i-a83t-de2-mixer";
+			reg = <0x01100000 0x100000>;
+			clocks = <&display_clocks 0>,
+				 <&display_clocks 6>;
+			clock-names = "bus",
+				      "mod";
+			resets = <&display_clocks 0>;
+			assigned-clocks = <&display_clocks 6>;
+			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>;
+					};
+				};
+			};
+		};
+
 		syscon: syscon@1c00000 {
 			compatible = "allwinner,sun8i-a83t-system-controller",
 				"syscon";
@@ -177,6 +223,40 @@
 			#dma-cells = <1>;
 		};
 
+		tcon0: lcd-controller@1c0c000 {
+			compatible = "allwinner,sun8i-a83t-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>, <&ccu RST_BUS_LVDS>;
+			reset-names = "lcd", "lvds";
+			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@1c0f000 {
 			compatible = "allwinner,sun8i-a83t-mmc",
 				     "allwinner,sun7i-a20-mmc";
-- 
git-series 0.9.1

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

* [PATCH 17/23] arm: dts: sun8i: a83t: Add display pipeline
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The display pipeline on the A83T is mainly composed of the mixers and
TCONs, plus various encoders.

Let's add the mixers and TCONs to the DTSI.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi | 80 ++++++++++++++++++++++++++++++++-
 1 file changed, 80 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index ce6e887c8938..57feeb6fee8b 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -151,6 +151,12 @@
 		};
 	};
 
+	de: display-engine {
+		compatible = "allwinner,sun8i-a83t-display-engine";
+		allwinner,pipelines = <&mixer0>;
+		status = "disabled";
+	};
+
 	memory {
 		reg = <0x40000000 0x80000000>;
 		device_type = "memory";
@@ -162,6 +168,46 @@
 		#size-cells = <1>;
 		ranges;
 
+		display_clocks: clock@1000000 {
+			compatible = "allwinner,sun8i-a83t-de2-clk";
+			reg = <0x01000000 0x100000>;
+			clocks = <&ccu CLK_PLL_DE>,
+				 <&ccu CLK_BUS_DE>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&ccu RST_BUS_DE>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		mixer0: mixer@1100000 {
+			compatible = "allwinner,sun8i-a83t-de2-mixer";
+			reg = <0x01100000 0x100000>;
+			clocks = <&display_clocks 0>,
+				 <&display_clocks 6>;
+			clock-names = "bus",
+				      "mod";
+			resets = <&display_clocks 0>;
+			assigned-clocks = <&display_clocks 6>;
+			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>;
+					};
+				};
+			};
+		};
+
 		syscon: syscon@1c00000 {
 			compatible = "allwinner,sun8i-a83t-system-controller",
 				"syscon";
@@ -177,6 +223,40 @@
 			#dma-cells = <1>;
 		};
 
+		tcon0: lcd-controller@1c0c000 {
+			compatible = "allwinner,sun8i-a83t-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>, <&ccu RST_BUS_LVDS>;
+			reset-names = "lcd", "lvds";
+			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@1c0f000 {
 			compatible = "allwinner,sun8i-a83t-mmc",
 				     "allwinner,sun7i-a20-mmc";
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 17/23] arm: dts: sun8i: a83t: Add display pipeline
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

The display pipeline on the A83T is mainly composed of the mixers and
TCONs, plus various encoders.

Let's add the mixers and TCONs to the DTSI.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi | 80 ++++++++++++++++++++++++++++++++-
 1 file changed, 80 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index ce6e887c8938..57feeb6fee8b 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -151,6 +151,12 @@
 		};
 	};
 
+	de: display-engine {
+		compatible = "allwinner,sun8i-a83t-display-engine";
+		allwinner,pipelines = <&mixer0>;
+		status = "disabled";
+	};
+
 	memory {
 		reg = <0x40000000 0x80000000>;
 		device_type = "memory";
@@ -162,6 +168,46 @@
 		#size-cells = <1>;
 		ranges;
 
+		display_clocks: clock at 1000000 {
+			compatible = "allwinner,sun8i-a83t-de2-clk";
+			reg = <0x01000000 0x100000>;
+			clocks = <&ccu CLK_PLL_DE>,
+				 <&ccu CLK_BUS_DE>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&ccu RST_BUS_DE>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		mixer0: mixer at 1100000 {
+			compatible = "allwinner,sun8i-a83t-de2-mixer";
+			reg = <0x01100000 0x100000>;
+			clocks = <&display_clocks 0>,
+				 <&display_clocks 6>;
+			clock-names = "bus",
+				      "mod";
+			resets = <&display_clocks 0>;
+			assigned-clocks = <&display_clocks 6>;
+			assigned-clock-rates = <150000000>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				mixer0_out: port at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					mixer0_out_tcon0: endpoint at 0 {
+						reg = <0>;
+						remote-endpoint = <&tcon0_in_mixer0>;
+					};
+				};
+			};
+		};
+
 		syscon: syscon at 1c00000 {
 			compatible = "allwinner,sun8i-a83t-system-controller",
 				"syscon";
@@ -177,6 +223,40 @@
 			#dma-cells = <1>;
 		};
 
+		tcon0: lcd-controller at 1c0c000 {
+			compatible = "allwinner,sun8i-a83t-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>, <&ccu RST_BUS_LVDS>;
+			reset-names = "lcd", "lvds";
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon0_in: port at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					tcon0_in_mixer0: endpoint at 0 {
+						reg = <0>;
+						remote-endpoint = <&mixer0_out_tcon0>;
+					};
+				};
+
+				tcon0_out: port at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+			};
+		};
+
 		mmc0: mmc at 1c0f000 {
 			compatible = "allwinner,sun8i-a83t-mmc",
 				     "allwinner,sun7i-a20-mmc";
-- 
git-series 0.9.1

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

* [PATCH 17/23] arm: dts: sun8i: a83t: Add display pipeline
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The display pipeline on the A83T is mainly composed of the mixers and
TCONs, plus various encoders.

Let's add the mixers and TCONs to the DTSI.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi | 80 ++++++++++++++++++++++++++++++++-
 1 file changed, 80 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index ce6e887c8938..57feeb6fee8b 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -151,6 +151,12 @@
 		};
 	};
 
+	de: display-engine {
+		compatible = "allwinner,sun8i-a83t-display-engine";
+		allwinner,pipelines = <&mixer0>;
+		status = "disabled";
+	};
+
 	memory {
 		reg = <0x40000000 0x80000000>;
 		device_type = "memory";
@@ -162,6 +168,46 @@
 		#size-cells = <1>;
 		ranges;
 
+		display_clocks: clock@1000000 {
+			compatible = "allwinner,sun8i-a83t-de2-clk";
+			reg = <0x01000000 0x100000>;
+			clocks = <&ccu CLK_PLL_DE>,
+				 <&ccu CLK_BUS_DE>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&ccu RST_BUS_DE>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		mixer0: mixer@1100000 {
+			compatible = "allwinner,sun8i-a83t-de2-mixer";
+			reg = <0x01100000 0x100000>;
+			clocks = <&display_clocks 0>,
+				 <&display_clocks 6>;
+			clock-names = "bus",
+				      "mod";
+			resets = <&display_clocks 0>;
+			assigned-clocks = <&display_clocks 6>;
+			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>;
+					};
+				};
+			};
+		};
+
 		syscon: syscon@1c00000 {
 			compatible = "allwinner,sun8i-a83t-system-controller",
 				"syscon";
@@ -177,6 +223,40 @@
 			#dma-cells = <1>;
 		};
 
+		tcon0: lcd-controller@1c0c000 {
+			compatible = "allwinner,sun8i-a83t-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>, <&ccu RST_BUS_LVDS>;
+			reset-names = "lcd", "lvds";
+			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@1c0f000 {
 			compatible = "allwinner,sun8i-a83t-mmc",
 				     "allwinner,sun7i-a20-mmc";
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 18/23] arm: dts: sun8i: a83t: Enable the PWM
  2017-10-17  9:06 ` Maxime Ripard
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

The A83T has the same PWM block than the H3. Add it to our DT.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi |  9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index 57feeb6fee8b..ef07a58859c7 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -496,6 +496,15 @@
 			status = "disabled";
 		};
 
+		pwm: pwm@1c21400 {
+			compatible = "allwinner,sun8i-a83t-pwm",
+				     "allwinner,sun8i-h3-pwm";
+			reg = <0x01c21400 0x400>;
+			clocks = <&osc24M>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
 		uart0: serial@1c28000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x01c28000 0x400>;
-- 
git-series 0.9.1

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

* [PATCH 18/23] arm: dts: sun8i: a83t: Enable the PWM
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

The A83T has the same PWM block than the H3. Add it to our DT.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi |  9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index 57feeb6fee8b..ef07a58859c7 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -496,6 +496,15 @@
 			status = "disabled";
 		};
 
+		pwm: pwm at 1c21400 {
+			compatible = "allwinner,sun8i-a83t-pwm",
+				     "allwinner,sun8i-h3-pwm";
+			reg = <0x01c21400 0x400>;
+			clocks = <&osc24M>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
 		uart0: serial at 1c28000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x01c28000 0x400>;
-- 
git-series 0.9.1

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

* [PATCH 18/23] arm: dts: sun8i: a83t: Enable the PWM
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The A83T has the same PWM block than the H3. Add it to our DT.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi |  9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index 57feeb6fee8b..ef07a58859c7 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -496,6 +496,15 @@
 			status = "disabled";
 		};
 
+		pwm: pwm@1c21400 {
+			compatible = "allwinner,sun8i-a83t-pwm",
+				     "allwinner,sun8i-h3-pwm";
+			reg = <0x01c21400 0x400>;
+			clocks = <&osc24M>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
 		uart0: serial@1c28000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x01c28000 0x400>;
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 19/23] arm: dts: sun8i: a83t: Add LVDS pins group
  2017-10-17  9:06 ` Maxime Ripard
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

The A83T has an LVDS bus that can be connected to a panel or a bridge. Add
the pinctrl group for it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index ef07a58859c7..6f1221556587 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -414,6 +414,12 @@
 			#interrupt-cells = <3>;
 			#gpio-cells = <3>;
 
+			lcd_lvds_pins: lcd-lvds-pins {
+				pins = "PD18", "PD19", "PD20", "PD21", "PD22",
+				       "PD23", "PD24", "PD25", "PD26", "PD27";
+				function = "lvds0";
+			};
+
 			mmc0_pins: mmc0-pins {
 				pins = "PF0", "PF1", "PF2",
 				       "PF3", "PF4", "PF5";
-- 
git-series 0.9.1

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

* [PATCH 19/23] arm: dts: sun8i: a83t: Add LVDS pins group
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

The A83T has an LVDS bus that can be connected to a panel or a bridge. Add
the pinctrl group for it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index ef07a58859c7..6f1221556587 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -414,6 +414,12 @@
 			#interrupt-cells = <3>;
 			#gpio-cells = <3>;
 
+			lcd_lvds_pins: lcd-lvds-pins {
+				pins = "PD18", "PD19", "PD20", "PD21", "PD22",
+				       "PD23", "PD24", "PD25", "PD26", "PD27";
+				function = "lvds0";
+			};
+
 			mmc0_pins: mmc0-pins {
 				pins = "PF0", "PF1", "PF2",
 				       "PF3", "PF4", "PF5";
-- 
git-series 0.9.1

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

* [PATCH 19/23] arm: dts: sun8i: a83t: Add LVDS pins group
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The A83T has an LVDS bus that can be connected to a panel or a bridge. Add
the pinctrl group for it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index ef07a58859c7..6f1221556587 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -414,6 +414,12 @@
 			#interrupt-cells = <3>;
 			#gpio-cells = <3>;
 
+			lcd_lvds_pins: lcd-lvds-pins {
+				pins = "PD18", "PD19", "PD20", "PD21", "PD22",
+				       "PD23", "PD24", "PD25", "PD26", "PD27";
+				function = "lvds0";
+			};
+
 			mmc0_pins: mmc0-pins {
 				pins = "PF0", "PF1", "PF2",
 				       "PF3", "PF4", "PF5";
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 20/23] arm: dts: sun8i: a83t: Add the PWM pin group
  2017-10-17  9:06 ` Maxime Ripard
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

The A83T has a PWM that can be output from the SoC. Let's add a pinctrl
group for it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index 6f1221556587..1986e8341e33 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -445,6 +445,11 @@
 				bias-pull-up;
 			};
 
+			pwm_pin: pwm-pin {
+				pins = "PD28";
+				function = "pwm";
+			};
+
 			spdif_tx_pin: spdif-tx-pin {
 				pins = "PE18";
 				function = "spdif";
-- 
git-series 0.9.1

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

* [PATCH 20/23] arm: dts: sun8i: a83t: Add the PWM pin group
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

The A83T has a PWM that can be output from the SoC. Let's add a pinctrl
group for it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index 6f1221556587..1986e8341e33 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -445,6 +445,11 @@
 				bias-pull-up;
 			};
 
+			pwm_pin: pwm-pin {
+				pins = "PD28";
+				function = "pwm";
+			};
+
 			spdif_tx_pin: spdif-tx-pin {
 				pins = "PE18";
 				function = "spdif";
-- 
git-series 0.9.1

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

* [PATCH 20/23] arm: dts: sun8i: a83t: Add the PWM pin group
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

The A83T has a PWM that can be output from the SoC. Let's add a pinctrl
group for it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index 6f1221556587..1986e8341e33 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -445,6 +445,11 @@
 				bias-pull-up;
 			};
 
+			pwm_pin: pwm-pin {
+				pins = "PD28";
+				function = "pwm";
+			};
+
 			spdif_tx_pin: spdif-tx-pin {
 				pins = "PE18";
 				function = "spdif";
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 21/23] arm: dts: sun8i: a711: Add regulator support
  2017-10-17  9:06 ` Maxime Ripard
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts | 163 +++++++++++++++++++++--
 1 file changed, 154 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
index 723641f56a74..98dc0c22160b 100644
--- a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
+++ b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
@@ -43,7 +43,8 @@
 
 /dts-v1/;
 #include "sun8i-a83t.dtsi"
-#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "TBS A711 Tablet";
@@ -105,7 +106,7 @@
 };
 
 &mmc0 {
-	vmmc-supply = <&reg_vcc3v3>;
+	vmmc-supply = <&reg_dcdc1>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc0_pins>;
 	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
@@ -117,8 +118,8 @@
 	bus-width = <4>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc1_pins>;
-	vmmc-supply = <&reg_vcc3v3>;
-	vqmmc-supply = <&reg_vcc3v3>;
+	vmmc-supply = <&reg_dldo1>;
+	vqmmc-supply = <&reg_dldo1>;
 	non-removable;
 	wakeup-source;
 	status = "okay";
@@ -135,8 +136,8 @@
 &mmc2 {
 	pinctrl-0 = <&mmc2_8bit_emmc_pins>;
 	pinctrl-names = "default";
-	vmmc-supply = <&reg_vcc3v3>;
-	vqmmc-supply = <&reg_vcc3v3>;
+	vmmc-supply = <&reg_dcdc1>;
+	vqmmc-supply = <&reg_dcdc1>;
 	bus-width = <8>;
 	non-removable;
 	cap-mmc-hw-reset;
@@ -147,10 +148,11 @@
 	status = "okay";
 
 	axp813: pmic@3a3 {
-		compatible = "x-powers,axp813";
 		reg = <0x3a3>;
 		interrupt-parent = <&r_intc>;
 		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		swin-supply = <&reg_dcdc1>;
+		x-powers,drive-vbus-en;
 	};
 
 	ac100: codec@e89 {
@@ -179,6 +181,149 @@
 
 };
 
+#include "axp813.dtsi"
+
+&reg_aldo1 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-1.8";
+};
+
+&reg_aldo2 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-always-on;
+	regulator-name = "vdd-drampll";
+};
+
+&reg_aldo3 {
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-always-on;
+	regulator-name = "avcc";
+};
+
+&reg_dcdc1 {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-always-on;
+	regulator-name = "vcc-io";
+};
+
+&reg_dcdc2 {
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-always-on;
+	regulator-name = "vdd-cpu-A";
+};
+
+&reg_dcdc3 {
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-always-on;
+	regulator-name = "vdd-cpu-B";
+};
+
+&reg_dcdc4 {
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-name = "vdd-gpu";
+};
+
+&reg_dcdc5 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1500000>;
+	regulator-always-on;
+	regulator-name = "vcc-dram";
+};
+
+&reg_dcdc6 {
+	regulator-min-microvolt = <900000>;
+	regulator-max-microvolt = <900000>;
+	regulator-always-on;
+	regulator-name = "vdd-sys";
+};
+
+&reg_dldo1 {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-name = "vcc-wifi-io";
+};
+
+&reg_dldo2 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <4200000>;
+	regulator-name = "vcc-mipi";
+};
+
+&reg_dldo3 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+	regulator-name = "vdd-csi";
+};
+
+&reg_dldo4 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+	regulator-name = "avdd-csi";
+};
+
+&reg_drivevbus {
+	regulator-name = "usb0-vbus";
+	status = "okay";
+};
+
+&reg_eldo1 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "dvdd-csi-r";
+};
+
+&reg_eldo2 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-dsi";
+};
+
+&reg_eldo3 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "dvdd-csi-f";
+};
+
+&reg_fldo1 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1200000>;
+	regulator-name = "vcc-hsic";
+};
+
+&reg_fldo2 {
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-always-on;
+	regulator-name = "vdd-cpus";
+};
+
+&reg_ldo_io0 {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-name = "vcc-ctp";
+	status = "okay";
+};
+
+&reg_ldo_io1 {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-name = "vcc-vb";
+	status = "okay";
+};
+
+&reg_sw {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-name = "vcc-lcd";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pb_pins>;
@@ -193,7 +338,7 @@
 };
 
 &usbphy {
-	usb1_vbus_supply = <&reg_vcc5v0>;
-	usb2_vbus_supply = <&reg_vcc5v0>;
+	usb1_vbus_supply = <&reg_vmain>;
+	usb2_vbus_supply = <&reg_vmain>;
 	status = "okay";
 };
-- 
git-series 0.9.1

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

* [PATCH 21/23] arm: dts: sun8i: a711: Add regulator support
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts | 163 +++++++++++++++++++++--
 1 file changed, 154 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
index 723641f56a74..98dc0c22160b 100644
--- a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
+++ b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
@@ -43,7 +43,8 @@
 
 /dts-v1/;
 #include "sun8i-a83t.dtsi"
-#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "TBS A711 Tablet";
@@ -105,7 +106,7 @@
 };
 
 &mmc0 {
-	vmmc-supply = <&reg_vcc3v3>;
+	vmmc-supply = <&reg_dcdc1>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc0_pins>;
 	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
@@ -117,8 +118,8 @@
 	bus-width = <4>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc1_pins>;
-	vmmc-supply = <&reg_vcc3v3>;
-	vqmmc-supply = <&reg_vcc3v3>;
+	vmmc-supply = <&reg_dldo1>;
+	vqmmc-supply = <&reg_dldo1>;
 	non-removable;
 	wakeup-source;
 	status = "okay";
@@ -135,8 +136,8 @@
 &mmc2 {
 	pinctrl-0 = <&mmc2_8bit_emmc_pins>;
 	pinctrl-names = "default";
-	vmmc-supply = <&reg_vcc3v3>;
-	vqmmc-supply = <&reg_vcc3v3>;
+	vmmc-supply = <&reg_dcdc1>;
+	vqmmc-supply = <&reg_dcdc1>;
 	bus-width = <8>;
 	non-removable;
 	cap-mmc-hw-reset;
@@ -147,10 +148,11 @@
 	status = "okay";
 
 	axp813: pmic at 3a3 {
-		compatible = "x-powers,axp813";
 		reg = <0x3a3>;
 		interrupt-parent = <&r_intc>;
 		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		swin-supply = <&reg_dcdc1>;
+		x-powers,drive-vbus-en;
 	};
 
 	ac100: codec at e89 {
@@ -179,6 +181,149 @@
 
 };
 
+#include "axp813.dtsi"
+
+&reg_aldo1 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-1.8";
+};
+
+&reg_aldo2 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-always-on;
+	regulator-name = "vdd-drampll";
+};
+
+&reg_aldo3 {
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-always-on;
+	regulator-name = "avcc";
+};
+
+&reg_dcdc1 {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-always-on;
+	regulator-name = "vcc-io";
+};
+
+&reg_dcdc2 {
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-always-on;
+	regulator-name = "vdd-cpu-A";
+};
+
+&reg_dcdc3 {
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-always-on;
+	regulator-name = "vdd-cpu-B";
+};
+
+&reg_dcdc4 {
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-name = "vdd-gpu";
+};
+
+&reg_dcdc5 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1500000>;
+	regulator-always-on;
+	regulator-name = "vcc-dram";
+};
+
+&reg_dcdc6 {
+	regulator-min-microvolt = <900000>;
+	regulator-max-microvolt = <900000>;
+	regulator-always-on;
+	regulator-name = "vdd-sys";
+};
+
+&reg_dldo1 {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-name = "vcc-wifi-io";
+};
+
+&reg_dldo2 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <4200000>;
+	regulator-name = "vcc-mipi";
+};
+
+&reg_dldo3 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+	regulator-name = "vdd-csi";
+};
+
+&reg_dldo4 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+	regulator-name = "avdd-csi";
+};
+
+&reg_drivevbus {
+	regulator-name = "usb0-vbus";
+	status = "okay";
+};
+
+&reg_eldo1 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "dvdd-csi-r";
+};
+
+&reg_eldo2 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-dsi";
+};
+
+&reg_eldo3 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "dvdd-csi-f";
+};
+
+&reg_fldo1 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1200000>;
+	regulator-name = "vcc-hsic";
+};
+
+&reg_fldo2 {
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-always-on;
+	regulator-name = "vdd-cpus";
+};
+
+&reg_ldo_io0 {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-name = "vcc-ctp";
+	status = "okay";
+};
+
+&reg_ldo_io1 {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-name = "vcc-vb";
+	status = "okay";
+};
+
+&reg_sw {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-name = "vcc-lcd";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pb_pins>;
@@ -193,7 +338,7 @@
 };
 
 &usbphy {
-	usb1_vbus_supply = <&reg_vcc5v0>;
-	usb2_vbus_supply = <&reg_vcc5v0>;
+	usb1_vbus_supply = <&reg_vmain>;
+	usb2_vbus_supply = <&reg_vmain>;
 	status = "okay";
 };
-- 
git-series 0.9.1

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

* [PATCH 21/23] arm: dts: sun8i: a711: Add regulator support
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts | 163 +++++++++++++++++++++--
 1 file changed, 154 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
index 723641f56a74..98dc0c22160b 100644
--- a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
+++ b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
@@ -43,7 +43,8 @@
 
 /dts-v1/;
 #include "sun8i-a83t.dtsi"
-#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "TBS A711 Tablet";
@@ -105,7 +106,7 @@
 };
 
 &mmc0 {
-	vmmc-supply = <&reg_vcc3v3>;
+	vmmc-supply = <&reg_dcdc1>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc0_pins>;
 	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
@@ -117,8 +118,8 @@
 	bus-width = <4>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc1_pins>;
-	vmmc-supply = <&reg_vcc3v3>;
-	vqmmc-supply = <&reg_vcc3v3>;
+	vmmc-supply = <&reg_dldo1>;
+	vqmmc-supply = <&reg_dldo1>;
 	non-removable;
 	wakeup-source;
 	status = "okay";
@@ -135,8 +136,8 @@
 &mmc2 {
 	pinctrl-0 = <&mmc2_8bit_emmc_pins>;
 	pinctrl-names = "default";
-	vmmc-supply = <&reg_vcc3v3>;
-	vqmmc-supply = <&reg_vcc3v3>;
+	vmmc-supply = <&reg_dcdc1>;
+	vqmmc-supply = <&reg_dcdc1>;
 	bus-width = <8>;
 	non-removable;
 	cap-mmc-hw-reset;
@@ -147,10 +148,11 @@
 	status = "okay";
 
 	axp813: pmic@3a3 {
-		compatible = "x-powers,axp813";
 		reg = <0x3a3>;
 		interrupt-parent = <&r_intc>;
 		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		swin-supply = <&reg_dcdc1>;
+		x-powers,drive-vbus-en;
 	};
 
 	ac100: codec@e89 {
@@ -179,6 +181,149 @@
 
 };
 
+#include "axp813.dtsi"
+
+&reg_aldo1 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-1.8";
+};
+
+&reg_aldo2 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-always-on;
+	regulator-name = "vdd-drampll";
+};
+
+&reg_aldo3 {
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-always-on;
+	regulator-name = "avcc";
+};
+
+&reg_dcdc1 {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-always-on;
+	regulator-name = "vcc-io";
+};
+
+&reg_dcdc2 {
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-always-on;
+	regulator-name = "vdd-cpu-A";
+};
+
+&reg_dcdc3 {
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-always-on;
+	regulator-name = "vdd-cpu-B";
+};
+
+&reg_dcdc4 {
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-name = "vdd-gpu";
+};
+
+&reg_dcdc5 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1500000>;
+	regulator-always-on;
+	regulator-name = "vcc-dram";
+};
+
+&reg_dcdc6 {
+	regulator-min-microvolt = <900000>;
+	regulator-max-microvolt = <900000>;
+	regulator-always-on;
+	regulator-name = "vdd-sys";
+};
+
+&reg_dldo1 {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-name = "vcc-wifi-io";
+};
+
+&reg_dldo2 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <4200000>;
+	regulator-name = "vcc-mipi";
+};
+
+&reg_dldo3 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+	regulator-name = "vdd-csi";
+};
+
+&reg_dldo4 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+	regulator-name = "avdd-csi";
+};
+
+&reg_drivevbus {
+	regulator-name = "usb0-vbus";
+	status = "okay";
+};
+
+&reg_eldo1 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "dvdd-csi-r";
+};
+
+&reg_eldo2 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-dsi";
+};
+
+&reg_eldo3 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "dvdd-csi-f";
+};
+
+&reg_fldo1 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1200000>;
+	regulator-name = "vcc-hsic";
+};
+
+&reg_fldo2 {
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-always-on;
+	regulator-name = "vdd-cpus";
+};
+
+&reg_ldo_io0 {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-name = "vcc-ctp";
+	status = "okay";
+};
+
+&reg_ldo_io1 {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-name = "vcc-vb";
+	status = "okay";
+};
+
+&reg_sw {
+	regulator-min-microvolt = <3100000>;
+	regulator-max-microvolt = <3100000>;
+	regulator-name = "vcc-lcd";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pb_pins>;
@@ -193,7 +338,7 @@
 };
 
 &usbphy {
-	usb1_vbus_supply = <&reg_vcc5v0>;
-	usb2_vbus_supply = <&reg_vcc5v0>;
+	usb1_vbus_supply = <&reg_vmain>;
+	usb2_vbus_supply = <&reg_vmain>;
 	status = "okay";
 };
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 22/23] arm: dts: sun8i: a711: Enable USB OTG
  2017-10-17  9:06 ` Maxime Ripard
  (?)
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
index 98dc0c22160b..e4d08bff3158 100644
--- a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
+++ b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
@@ -337,7 +337,14 @@
 	status = "okay";
 };
 
+&usb_otg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
 &usbphy {
+	usb0_id_det-gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */
+	usb0_vbus-supply = <&reg_drivevbus>;
 	usb1_vbus_supply = <&reg_vmain>;
 	usb2_vbus_supply = <&reg_vmain>;
 	status = "okay";
-- 
git-series 0.9.1

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

* [PATCH 22/23] arm: dts: sun8i: a711: Enable USB OTG
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
index 98dc0c22160b..e4d08bff3158 100644
--- a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
+++ b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
@@ -337,7 +337,14 @@
 	status = "okay";
 };
 
+&usb_otg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
 &usbphy {
+	usb0_id_det-gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */
+	usb0_vbus-supply = <&reg_drivevbus>;
 	usb1_vbus_supply = <&reg_vmain>;
 	usb2_vbus_supply = <&reg_vmain>;
 	status = "okay";
-- 
git-series 0.9.1

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

* [PATCH 22/23] arm: dts: sun8i: a711: Enable USB OTG
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, plaes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
index 98dc0c22160b..e4d08bff3158 100644
--- a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
+++ b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
@@ -337,7 +337,14 @@
 	status = "okay";
 };
 
+&usb_otg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
 &usbphy {
+	usb0_id_det-gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */
+	usb0_vbus-supply = <&reg_drivevbus>;
 	usb1_vbus_supply = <&reg_vmain>;
 	usb2_vbus_supply = <&reg_vmain>;
 	status = "okay";
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 23/23] arm: dts: sun8i: a711: Enable the LCD
  2017-10-17  9:06 ` Maxime Ripard
@ 2017-10-17  9:06   ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, linux-clk, plaes, icenowy, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

The A711 has 1024x600 LVDS panel, with a PWM-based backlight. Add it to our
DT.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts | 62 ++++++++++++++++++++++++-
 1 file changed, 62 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
index e4d08bff3158..5abcb3c9f4b3 100644
--- a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
+++ b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
@@ -45,6 +45,7 @@
 #include "sun8i-a83t.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pwm/pwm.h>
 
 / {
 	model = "TBS A711 Tablet";
@@ -59,6 +60,44 @@
 		stdout-path = "serial0:115200n8";
 	};
 
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>;
+		enable-gpios = <&pio 3 29 GPIO_ACTIVE_HIGH>;
+
+		brightness-levels = <0 1 2 4 8 16 32 64 128 255>;
+		default-brightness-level = <9>;
+	};
+
+	panel {
+		compatible = "tbs,a711-panel", "panel-lvds";
+		backlight = <&backlight>;
+		power-supply = <&reg_sw>;
+
+		width-mm = <153>;
+		height-mm = <90>;
+		data-mapping = "vesa-24";
+
+		panel-timing {
+			/* 1024x600 @60Hz */
+			clock-frequency = <52000000>;
+			hactive = <1024>;
+			vactive = <600>;
+			hsync-len = <20>;
+			hfront-porch = <180>;
+			hback-porch = <160>;
+			vfront-porch = <12>;
+			vback-porch = <23>;
+			vsync-len = <5>;
+		};
+
+		port {
+			panel_input: endpoint {
+				remote-endpoint = <&tcon0_out_lcd>;
+			};
+		};
+	};
+
 	reg_vbat: reg-vbat {
 		compatible = "regulator-fixed";
 		regulator-name = "vbat";
@@ -89,6 +128,10 @@
 	};
 };
 
+&de {
+	status = "okay";
+};
+
 /*
  * An USB-2 hub is connected here, which also means we don't need to
  * enable the OHCI controller.
@@ -144,6 +187,12 @@
 	status = "okay";
 };
 
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm_pin>;
+	status = "okay";
+};
+
 &r_rsb {
 	status = "okay";
 
@@ -324,6 +373,19 @@
 	regulator-name = "vcc-lcd";
 };
 
+&tcon0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd_lvds_pins>;
+	status = "okay";
+};
+
+&tcon0_out {
+	tcon0_out_lcd: endpoint@0 {
+		reg = <0>;
+		remote-endpoint = <&panel_input>;
+	};
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pb_pins>;
-- 
git-series 0.9.1

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

* [PATCH 23/23] arm: dts: sun8i: a711: Enable the LCD
@ 2017-10-17  9:06   ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

The A711 has 1024x600 LVDS panel, with a PWM-based backlight. Add it to our
DT.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts | 62 ++++++++++++++++++++++++-
 1 file changed, 62 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
index e4d08bff3158..5abcb3c9f4b3 100644
--- a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
+++ b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
@@ -45,6 +45,7 @@
 #include "sun8i-a83t.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pwm/pwm.h>
 
 / {
 	model = "TBS A711 Tablet";
@@ -59,6 +60,44 @@
 		stdout-path = "serial0:115200n8";
 	};
 
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>;
+		enable-gpios = <&pio 3 29 GPIO_ACTIVE_HIGH>;
+
+		brightness-levels = <0 1 2 4 8 16 32 64 128 255>;
+		default-brightness-level = <9>;
+	};
+
+	panel {
+		compatible = "tbs,a711-panel", "panel-lvds";
+		backlight = <&backlight>;
+		power-supply = <&reg_sw>;
+
+		width-mm = <153>;
+		height-mm = <90>;
+		data-mapping = "vesa-24";
+
+		panel-timing {
+			/* 1024x600 @60Hz */
+			clock-frequency = <52000000>;
+			hactive = <1024>;
+			vactive = <600>;
+			hsync-len = <20>;
+			hfront-porch = <180>;
+			hback-porch = <160>;
+			vfront-porch = <12>;
+			vback-porch = <23>;
+			vsync-len = <5>;
+		};
+
+		port {
+			panel_input: endpoint {
+				remote-endpoint = <&tcon0_out_lcd>;
+			};
+		};
+	};
+
 	reg_vbat: reg-vbat {
 		compatible = "regulator-fixed";
 		regulator-name = "vbat";
@@ -89,6 +128,10 @@
 	};
 };
 
+&de {
+	status = "okay";
+};
+
 /*
  * An USB-2 hub is connected here, which also means we don't need to
  * enable the OHCI controller.
@@ -144,6 +187,12 @@
 	status = "okay";
 };
 
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm_pin>;
+	status = "okay";
+};
+
 &r_rsb {
 	status = "okay";
 
@@ -324,6 +373,19 @@
 	regulator-name = "vcc-lcd";
 };
 
+&tcon0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd_lvds_pins>;
+	status = "okay";
+};
+
+&tcon0_out {
+	tcon0_out_lcd: endpoint at 0 {
+		reg = <0>;
+		remote-endpoint = <&panel_input>;
+	};
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pb_pins>;
-- 
git-series 0.9.1

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

* Re: [PATCH 02/23] drm/sun4i: Realign Makefile padding and reorder it
  2017-10-17  9:06   ` Maxime Ripard
  (?)
@ 2017-10-17  9:14     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:14 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Some options were not padded as they should, and the order in the Makefile
> was chaotic. Fix that.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/Makefile | 28 ++++++++++++++--------------
>  1 file changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index 43c753cafc88..af18b70ba5ed 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -1,24 +1,24 @@
> -sun4i-drm-y += sun4i_drv.o
> -sun4i-drm-y += sun4i_framebuffer.o
> +sun4i-backend-y                        += sun4i_backend.o sun4i_layer.o
>
> -sun4i-drm-hdmi-y += sun4i_hdmi_enc.o
> -sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o
> -sun4i-drm-hdmi-y += sun4i_hdmi_ddc_clk.o
> -sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o
> +sun4i-drm-y                    += sun4i_drv.o
> +sun4i-drm-y                    += sun4i_framebuffer.o
>
> -sun4i-tcon-y += sun4i_tcon.o
> -sun4i-tcon-y += sun4i_rgb.o
> -sun4i-tcon-y += sun4i_dotclock.o
> -sun4i-tcon-y += sun4i_crtc.o
> +sun4i-drm-hdmi-y               += sun4i_hdmi_enc.o
> +sun4i-drm-hdmi-y               += sun4i_hdmi_i2c.o
> +sun4i-drm-hdmi-y               += sun4i_hdmi_ddc_clk.o
> +sun4i-drm-hdmi-y               += sun4i_hdmi_tmds_clk.o
>
> -sun4i-backend-y += sun4i_backend.o sun4i_layer.o
> +sun4i-tcon-y                   += sun4i_tcon.o
> +sun4i-tcon-y                   += sun4i_rgb.o
> +sun4i-tcon-y                   += sun4i_dotclock.o
> +sun4i-tcon-y                   += sun4i_crtc.o

I don't know if you wanted to sort the file names as well.
This would be a good time to do it.

Otherwise,

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

>
> -sun8i-mixer-y += sun8i_mixer.o sun8i_layer.o
> +sun8i-mixer-y                  += sun8i_mixer.o sun8i_layer.o
>
>  obj-$(CONFIG_DRM_SUN4I)                += sun4i-drm.o sun4i-tcon.o
>  obj-$(CONFIG_DRM_SUN4I)                += sun6i_drc.o
>  obj-$(CONFIG_DRM_SUN4I)                += sun4i_tv.o
>
> -obj-$(CONFIG_DRM_SUN4I_BACKEND)                += sun4i-backend.o
> +obj-$(CONFIG_DRM_SUN4I_BACKEND)        += sun4i-backend.o
>  obj-$(CONFIG_DRM_SUN4I_HDMI)   += sun4i-drm-hdmi.o
> -obj-$(CONFIG_DRM_SUN8I_MIXER)          += sun8i-mixer.o
> +obj-$(CONFIG_DRM_SUN8I_MIXER)  += sun8i-mixer.o
> --
> git-series 0.9.1

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

* [PATCH 02/23] drm/sun4i: Realign Makefile padding and reorder it
@ 2017-10-17  9:14     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Some options were not padded as they should, and the order in the Makefile
> was chaotic. Fix that.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/Makefile | 28 ++++++++++++++--------------
>  1 file changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index 43c753cafc88..af18b70ba5ed 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -1,24 +1,24 @@
> -sun4i-drm-y += sun4i_drv.o
> -sun4i-drm-y += sun4i_framebuffer.o
> +sun4i-backend-y                        += sun4i_backend.o sun4i_layer.o
>
> -sun4i-drm-hdmi-y += sun4i_hdmi_enc.o
> -sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o
> -sun4i-drm-hdmi-y += sun4i_hdmi_ddc_clk.o
> -sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o
> +sun4i-drm-y                    += sun4i_drv.o
> +sun4i-drm-y                    += sun4i_framebuffer.o
>
> -sun4i-tcon-y += sun4i_tcon.o
> -sun4i-tcon-y += sun4i_rgb.o
> -sun4i-tcon-y += sun4i_dotclock.o
> -sun4i-tcon-y += sun4i_crtc.o
> +sun4i-drm-hdmi-y               += sun4i_hdmi_enc.o
> +sun4i-drm-hdmi-y               += sun4i_hdmi_i2c.o
> +sun4i-drm-hdmi-y               += sun4i_hdmi_ddc_clk.o
> +sun4i-drm-hdmi-y               += sun4i_hdmi_tmds_clk.o
>
> -sun4i-backend-y += sun4i_backend.o sun4i_layer.o
> +sun4i-tcon-y                   += sun4i_tcon.o
> +sun4i-tcon-y                   += sun4i_rgb.o
> +sun4i-tcon-y                   += sun4i_dotclock.o
> +sun4i-tcon-y                   += sun4i_crtc.o

I don't know if you wanted to sort the file names as well.
This would be a good time to do it.

Otherwise,

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

>
> -sun8i-mixer-y += sun8i_mixer.o sun8i_layer.o
> +sun8i-mixer-y                  += sun8i_mixer.o sun8i_layer.o
>
>  obj-$(CONFIG_DRM_SUN4I)                += sun4i-drm.o sun4i-tcon.o
>  obj-$(CONFIG_DRM_SUN4I)                += sun6i_drc.o
>  obj-$(CONFIG_DRM_SUN4I)                += sun4i_tv.o
>
> -obj-$(CONFIG_DRM_SUN4I_BACKEND)                += sun4i-backend.o
> +obj-$(CONFIG_DRM_SUN4I_BACKEND)        += sun4i-backend.o
>  obj-$(CONFIG_DRM_SUN4I_HDMI)   += sun4i-drm-hdmi.o
> -obj-$(CONFIG_DRM_SUN8I_MIXER)          += sun8i-mixer.o
> +obj-$(CONFIG_DRM_SUN8I_MIXER)  += sun8i-mixer.o
> --
> git-series 0.9.1

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

* Re: [PATCH 02/23] drm/sun4i: Realign Makefile padding and reorder it
@ 2017-10-17  9:14     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:14 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, Priit Laes, linux-kernel,
	dri-devel, Quentin Schulz, Chen-Yu Tsai, Rob Herring,
	Daniel Vetter, Mylene Josserand, linux-clk, linux-arm-kernel,
	Icenowy Zheng

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Some options were not padded as they should, and the order in the Makefile
> was chaotic. Fix that.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/Makefile | 28 ++++++++++++++--------------
>  1 file changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index 43c753cafc88..af18b70ba5ed 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -1,24 +1,24 @@
> -sun4i-drm-y += sun4i_drv.o
> -sun4i-drm-y += sun4i_framebuffer.o
> +sun4i-backend-y                        += sun4i_backend.o sun4i_layer.o
>
> -sun4i-drm-hdmi-y += sun4i_hdmi_enc.o
> -sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o
> -sun4i-drm-hdmi-y += sun4i_hdmi_ddc_clk.o
> -sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o
> +sun4i-drm-y                    += sun4i_drv.o
> +sun4i-drm-y                    += sun4i_framebuffer.o
>
> -sun4i-tcon-y += sun4i_tcon.o
> -sun4i-tcon-y += sun4i_rgb.o
> -sun4i-tcon-y += sun4i_dotclock.o
> -sun4i-tcon-y += sun4i_crtc.o
> +sun4i-drm-hdmi-y               += sun4i_hdmi_enc.o
> +sun4i-drm-hdmi-y               += sun4i_hdmi_i2c.o
> +sun4i-drm-hdmi-y               += sun4i_hdmi_ddc_clk.o
> +sun4i-drm-hdmi-y               += sun4i_hdmi_tmds_clk.o
>
> -sun4i-backend-y += sun4i_backend.o sun4i_layer.o
> +sun4i-tcon-y                   += sun4i_tcon.o
> +sun4i-tcon-y                   += sun4i_rgb.o
> +sun4i-tcon-y                   += sun4i_dotclock.o
> +sun4i-tcon-y                   += sun4i_crtc.o

I don't know if you wanted to sort the file names as well.
This would be a good time to do it.

Otherwise,

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

>
> -sun8i-mixer-y += sun8i_mixer.o sun8i_layer.o
> +sun8i-mixer-y                  += sun8i_mixer.o sun8i_layer.o
>
>  obj-$(CONFIG_DRM_SUN4I)                += sun4i-drm.o sun4i-tcon.o
>  obj-$(CONFIG_DRM_SUN4I)                += sun6i_drc.o
>  obj-$(CONFIG_DRM_SUN4I)                += sun4i_tv.o
>
> -obj-$(CONFIG_DRM_SUN4I_BACKEND)                += sun4i-backend.o
> +obj-$(CONFIG_DRM_SUN4I_BACKEND)        += sun4i-backend.o
>  obj-$(CONFIG_DRM_SUN4I_HDMI)   += sun4i-drm-hdmi.o
> -obj-$(CONFIG_DRM_SUN8I_MIXER)          += sun8i-mixer.o
> +obj-$(CONFIG_DRM_SUN8I_MIXER)  += sun8i-mixer.o
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 01/23] drm/sun4i: Implement endpoint parsing using kfifo
  2017-10-17  9:06   ` Maxime Ripard
  (?)
@ 2017-10-17  9:19     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:19 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The commit da82b8785eeb ("drm/sun4i: add components in breadth first
> traversal order") implemented a breadth first traversal of our device tree
> nodes graph. However, it was relying on the kernel linked lists, and those
> are not really safe for addition.
>
> Indeed, in a single pipeline stage, your first stage (ie, the mixer or
> fronted) will be queued, and it will be the final iteration of that list as
> far as list_for_each_entry_safe is concerned. Then, during that final
> iteration, we'll queue another element (the TCON or the backend) that
> list_for_each_entry_safe will not account for, and we will leave the loop
> without having iterated over all the elements. And since we won't have
> built our components list properly, the DRM driver will be left
> non-functional.
>
> We can instead use a kfifo to queue and enqueue components in-order, as was
> the original intention. This also has the benefit of removing any dynamic
> allocation, making the error handling path simpler too. The only thing
> we're losing is the ability to tell whether an element has already been
> queued, but that was only needed to remove spurious logs, and therefore
> purely cosmetic.
>
> This means that this commit effectively reverses e8afb7b67fba ("drm/sun4i:
> don't add components that are already in the queue").
>
> Fixes: da82b8785eeb ("drm/sun4i: add components in breadth first traversal order")
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/sun4i_drv.c | 71 +++++---------------------------
>  1 file changed, 13 insertions(+), 58 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
> index b5879d4620d8..a27efad9bc76 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_drv.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
> @@ -11,6 +11,7 @@
>   */
>
>  #include <linux/component.h>
> +#include <linux/kfifo.h>
>  #include <linux/of_graph.h>
>  #include <linux/of_reserved_mem.h>
>
> @@ -222,29 +223,15 @@ static int compare_of(struct device *dev, void *data)
>   * matching system handles this for us.
>   */
>  struct endpoint_list {
> -       struct device_node *node;
> -       struct list_head list;
> +       DECLARE_KFIFO(fifo, struct device_node *, 16);
>  };

Is there any reason to keep using struct endpoint_list, other than
to avoid using kfifo in function parameter lists?

Otherwise the rest of the code looks sound.

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* [PATCH 01/23] drm/sun4i: Implement endpoint parsing using kfifo
@ 2017-10-17  9:19     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The commit da82b8785eeb ("drm/sun4i: add components in breadth first
> traversal order") implemented a breadth first traversal of our device tree
> nodes graph. However, it was relying on the kernel linked lists, and those
> are not really safe for addition.
>
> Indeed, in a single pipeline stage, your first stage (ie, the mixer or
> fronted) will be queued, and it will be the final iteration of that list as
> far as list_for_each_entry_safe is concerned. Then, during that final
> iteration, we'll queue another element (the TCON or the backend) that
> list_for_each_entry_safe will not account for, and we will leave the loop
> without having iterated over all the elements. And since we won't have
> built our components list properly, the DRM driver will be left
> non-functional.
>
> We can instead use a kfifo to queue and enqueue components in-order, as was
> the original intention. This also has the benefit of removing any dynamic
> allocation, making the error handling path simpler too. The only thing
> we're losing is the ability to tell whether an element has already been
> queued, but that was only needed to remove spurious logs, and therefore
> purely cosmetic.
>
> This means that this commit effectively reverses e8afb7b67fba ("drm/sun4i:
> don't add components that are already in the queue").
>
> Fixes: da82b8785eeb ("drm/sun4i: add components in breadth first traversal order")
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/sun4i_drv.c | 71 +++++---------------------------
>  1 file changed, 13 insertions(+), 58 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
> index b5879d4620d8..a27efad9bc76 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_drv.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
> @@ -11,6 +11,7 @@
>   */
>
>  #include <linux/component.h>
> +#include <linux/kfifo.h>
>  #include <linux/of_graph.h>
>  #include <linux/of_reserved_mem.h>
>
> @@ -222,29 +223,15 @@ static int compare_of(struct device *dev, void *data)
>   * matching system handles this for us.
>   */
>  struct endpoint_list {
> -       struct device_node *node;
> -       struct list_head list;
> +       DECLARE_KFIFO(fifo, struct device_node *, 16);
>  };

Is there any reason to keep using struct endpoint_list, other than
to avoid using kfifo in function parameter lists?

Otherwise the rest of the code looks sound.

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* Re: [PATCH 01/23] drm/sun4i: Implement endpoint parsing using kfifo
@ 2017-10-17  9:19     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:19 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, Priit Laes, linux-kernel,
	dri-devel, Quentin Schulz, Chen-Yu Tsai, Rob Herring,
	Daniel Vetter, Mylene Josserand, linux-clk, linux-arm-kernel,
	Icenowy Zheng

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The commit da82b8785eeb ("drm/sun4i: add components in breadth first
> traversal order") implemented a breadth first traversal of our device tree
> nodes graph. However, it was relying on the kernel linked lists, and those
> are not really safe for addition.
>
> Indeed, in a single pipeline stage, your first stage (ie, the mixer or
> fronted) will be queued, and it will be the final iteration of that list as
> far as list_for_each_entry_safe is concerned. Then, during that final
> iteration, we'll queue another element (the TCON or the backend) that
> list_for_each_entry_safe will not account for, and we will leave the loop
> without having iterated over all the elements. And since we won't have
> built our components list properly, the DRM driver will be left
> non-functional.
>
> We can instead use a kfifo to queue and enqueue components in-order, as was
> the original intention. This also has the benefit of removing any dynamic
> allocation, making the error handling path simpler too. The only thing
> we're losing is the ability to tell whether an element has already been
> queued, but that was only needed to remove spurious logs, and therefore
> purely cosmetic.
>
> This means that this commit effectively reverses e8afb7b67fba ("drm/sun4i:
> don't add components that are already in the queue").
>
> Fixes: da82b8785eeb ("drm/sun4i: add components in breadth first traversal order")
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/sun4i_drv.c | 71 +++++---------------------------
>  1 file changed, 13 insertions(+), 58 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
> index b5879d4620d8..a27efad9bc76 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_drv.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
> @@ -11,6 +11,7 @@
>   */
>
>  #include <linux/component.h>
> +#include <linux/kfifo.h>
>  #include <linux/of_graph.h>
>  #include <linux/of_reserved_mem.h>
>
> @@ -222,29 +223,15 @@ static int compare_of(struct device *dev, void *data)
>   * matching system handles this for us.
>   */
>  struct endpoint_list {
> -       struct device_node *node;
> -       struct list_head list;
> +       DECLARE_KFIFO(fifo, struct device_node *, 16);
>  };

Is there any reason to keep using struct endpoint_list, other than
to avoid using kfifo in function parameter lists?

Otherwise the rest of the code looks sound.

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 03/23] drm/sun4i: tcon: Make tcon_set_mux mode argument const
  2017-10-17  9:06   ` Maxime Ripard
  (?)
@ 2017-10-17  9:21     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:21 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The drm_display_mode pointer can be mark const, so let's do it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* [PATCH 03/23] drm/sun4i: tcon: Make tcon_set_mux mode argument const
@ 2017-10-17  9:21     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The drm_display_mode pointer can be mark const, so let's do it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* Re: [PATCH 03/23] drm/sun4i: tcon: Make tcon_set_mux mode argument const
@ 2017-10-17  9:21     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:21 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, Priit Laes, linux-kernel,
	dri-devel, Quentin Schulz, Chen-Yu Tsai, Rob Herring,
	Daniel Vetter, Mylene Josserand, linux-clk, linux-arm-kernel,
	Icenowy Zheng

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The drm_display_mode pointer can be mark const, so let's do it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 04/23] drm/sun4i: tcon: Make tcon_get_clk_delay mode argument const
  2017-10-17  9:06   ` Maxime Ripard
  (?)
@ 2017-10-17  9:22     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:22 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The drm_display_mode pointer can be mark const, so let's do it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* [PATCH 04/23] drm/sun4i: tcon: Make tcon_get_clk_delay mode argument const
@ 2017-10-17  9:22     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The drm_display_mode pointer can be mark const, so let's do it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* Re: [PATCH 04/23] drm/sun4i: tcon: Make tcon_get_clk_delay mode argument const
@ 2017-10-17  9:22     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:22 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, Priit Laes, linux-kernel,
	dri-devel, Quentin Schulz, Chen-Yu Tsai, Rob Herring,
	Daniel Vetter, Mylene Josserand, linux-clk, linux-arm-kernel,
	Icenowy Zheng

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The drm_display_mode pointer can be mark const, so let's do it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 05/23] drm/sun4i: tcon: Don't rely on encoders to enable the TCON
  2017-10-17  9:06   ` Maxime Ripard
  (?)
@ 2017-10-17  9:28     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:28 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> So far, we've required all the TCON-connected encoders to call the TCON
> enable and disable functions.
>
> This was made this way because in the RGB/LVDS case, the TCON is the CRTC
> and the encoder. However, in all the other cases (HDMI, TV, DSI, etc.), we
> have another encoder down the road that needs to be programmed.
>
> We also needed to know which channel the encoder is connected to, which is
> encoder-specific.
>
> The CRTC's enable and disable callbacks can work just fine for our use
> case, and we can get the channel to use just by looking at the type of
> encoder, since that is fixed. Implement those callbacks, which will
> remove some of the encoder boilerplate.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* [PATCH 05/23] drm/sun4i: tcon: Don't rely on encoders to enable the TCON
@ 2017-10-17  9:28     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> So far, we've required all the TCON-connected encoders to call the TCON
> enable and disable functions.
>
> This was made this way because in the RGB/LVDS case, the TCON is the CRTC
> and the encoder. However, in all the other cases (HDMI, TV, DSI, etc.), we
> have another encoder down the road that needs to be programmed.
>
> We also needed to know which channel the encoder is connected to, which is
> encoder-specific.
>
> The CRTC's enable and disable callbacks can work just fine for our use
> case, and we can get the channel to use just by looking at the type of
> encoder, since that is fixed. Implement those callbacks, which will
> remove some of the encoder boilerplate.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* Re: [PATCH 05/23] drm/sun4i: tcon: Don't rely on encoders to enable the TCON
@ 2017-10-17  9:28     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:28 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, Priit Laes, linux-kernel,
	dri-devel, Quentin Schulz, Chen-Yu Tsai, Rob Herring,
	Daniel Vetter, Mylene Josserand, linux-clk, linux-arm-kernel,
	Icenowy Zheng

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> So far, we've required all the TCON-connected encoders to call the TCON
> enable and disable functions.
>
> This was made this way because in the RGB/LVDS case, the TCON is the CRTC
> and the encoder. However, in all the other cases (HDMI, TV, DSI, etc.), we
> have another encoder down the road that needs to be programmed.
>
> We also needed to know which channel the encoder is connected to, which is
> encoder-specific.
>
> The CRTC's enable and disable callbacks can work just fine for our use
> case, and we can get the channel to use just by looking at the type of
> encoder, since that is fixed. Implement those callbacks, which will
> remove some of the encoder boilerplate.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 06/23] drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
  2017-10-17  9:06   ` Maxime Ripard
  (?)
@ 2017-10-17  9:56     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:56 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Just like we did for the TCON enable and disable, for historical reasons we
> used to rely on the encoders calling the TCON mode_set function, while the
> CRTC has a callback for that.
>
> Let's implement it in order to reduce the boilerplate code.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/sun4i_crtc.c          | 10 +++++++-
>  drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c  |  1 +-
>  drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c      |  7 +-----
>  drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c |  1 +-
>  drivers/gpu/drm/sun4i/sun4i_rgb.c           | 15 +-----------
>  drivers/gpu/drm/sun4i/sun4i_tcon.c          | 31 +++++++++++++++++-----
>  drivers/gpu/drm/sun4i/sun4i_tcon.h          | 11 ++------
>  drivers/gpu/drm/sun4i/sun4i_tv.c            |  6 +----
>  8 files changed, 37 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> index e86baa3746af..5decae0069d0 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> @@ -115,11 +115,21 @@ static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
>         sun4i_tcon_set_status(scrtc->tcon, encoder, true);
>  }
>
> +static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
> +       struct drm_display_mode *mode = &crtc->state->adjusted_mode;
> +       struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
> +       struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
> +
> +       sun4i_tcon_mode_set(scrtc->tcon, encoder, mode);
> +}
> +
>  static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
>         .atomic_begin   = sun4i_crtc_atomic_begin,
>         .atomic_flush   = sun4i_crtc_atomic_flush,
>         .atomic_enable  = sun4i_crtc_atomic_enable,
>         .atomic_disable = sun4i_crtc_atomic_disable,
> +       .mode_set_nofb  = sun4i_crtc_mode_set_nofb,
>  };
>
>  static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc)
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> index 04f85b1cf922..e826da34e919 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> @@ -13,7 +13,6 @@
>  #include <linux/clk-provider.h>
>  #include <linux/regmap.h>
>
> -#include "sun4i_tcon.h"
>  #include "sun4i_hdmi.h"
>
>  struct sun4i_ddc {
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> index 482bf03d55c1..d2eb0a60e568 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> @@ -30,7 +30,6 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_drv.h"
>  #include "sun4i_hdmi.h"
> -#include "sun4i_tcon.h"
>
>  static inline struct sun4i_hdmi *
>  drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
> @@ -120,15 +119,9 @@ static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
>                                 struct drm_display_mode *adjusted_mode)
>  {
>         struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> -       struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
> -       struct sun4i_tcon *tcon = crtc->tcon;
>         unsigned int x, y;
>         u32 val;
>
> -       sun4i_tcon1_mode_set(tcon, mode);
> -       sun4i_tcon_set_mux(tcon, 1, encoder);
> -
> -       clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
>         clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
>         clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> index 1b6b37aefc38..dc332ea56f6c 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> @@ -12,7 +12,6 @@
>
>  #include <linux/clk-provider.h>
>
> -#include "sun4i_tcon.h"
>  #include "sun4i_hdmi.h"
>
>  struct sun4i_tmds {
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index a7f297ed40c1..832f8f9bc47f 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -153,22 +153,7 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
>         }
>  }
>
> -static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
> -                                      struct drm_display_mode *mode,
> -                                      struct drm_display_mode *adjusted_mode)
> -{
> -       struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
> -       struct sun4i_tcon *tcon = rgb->tcon;
> -
> -       sun4i_tcon0_mode_set(tcon, mode);
> -       sun4i_tcon_set_mux(tcon, 0, encoder);
> -
> -       /* FIXME: This seems to be board specific */
> -       clk_set_phase(tcon->dclk, 120);
> -}
> -
>  static struct drm_encoder_helper_funcs sun4i_rgb_enc_helper_funcs = {
> -       .mode_set       = sun4i_rgb_encoder_mode_set,
>         .disable        = sun4i_rgb_encoder_disable,
>         .enable         = sun4i_rgb_encoder_enable,
>  };
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 964cf22a1ced..7ecd4f7c8411 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -139,7 +139,6 @@ void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
>         DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
>                          encoder->name, encoder->crtc->name, ret);
>  }
> -EXPORT_SYMBOL(sun4i_tcon_set_mux);
>
>  static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
>                                     int channel)
> @@ -159,8 +158,8 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
>         return delay;
>  }
>
> -void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> -                         struct drm_display_mode *mode)
> +static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> +                                struct drm_display_mode *mode)

This doesn't have const...

>  {
>         unsigned int bp, hsync, vsync;
>         u8 clk_delay;
> @@ -233,10 +232,9 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
>         /* Enable the output on the pins */
>         regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
>  }
> -EXPORT_SYMBOL(sun4i_tcon0_mode_set);
>
> -void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> -                         struct drm_display_mode *mode)
> +static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> +                                const struct drm_display_mode *mode)
>  {
>         unsigned int bp, hsync, vsync, vtotal;
>         u8 clk_delay;
> @@ -324,7 +322,26 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
>                            SUN4I_TCON_GCTL_IOMAP_MASK,
>                            SUN4I_TCON_GCTL_IOMAP_TCON1);
>  }
> -EXPORT_SYMBOL(sun4i_tcon1_mode_set);
> +
> +void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
> +                        const struct drm_encoder *encoder,
> +                        const struct drm_display_mode *mode)

But this does...

> +{
> +       switch (encoder->encoder_type) {
> +       case DRM_MODE_ENCODER_NONE:
> +               sun4i_tcon0_mode_set(tcon, mode);

So you're likely to get some warning about dropping const here.

Otherwise,

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* [PATCH 06/23] drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
@ 2017-10-17  9:56     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Just like we did for the TCON enable and disable, for historical reasons we
> used to rely on the encoders calling the TCON mode_set function, while the
> CRTC has a callback for that.
>
> Let's implement it in order to reduce the boilerplate code.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/sun4i_crtc.c          | 10 +++++++-
>  drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c  |  1 +-
>  drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c      |  7 +-----
>  drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c |  1 +-
>  drivers/gpu/drm/sun4i/sun4i_rgb.c           | 15 +-----------
>  drivers/gpu/drm/sun4i/sun4i_tcon.c          | 31 +++++++++++++++++-----
>  drivers/gpu/drm/sun4i/sun4i_tcon.h          | 11 ++------
>  drivers/gpu/drm/sun4i/sun4i_tv.c            |  6 +----
>  8 files changed, 37 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> index e86baa3746af..5decae0069d0 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> @@ -115,11 +115,21 @@ static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
>         sun4i_tcon_set_status(scrtc->tcon, encoder, true);
>  }
>
> +static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
> +       struct drm_display_mode *mode = &crtc->state->adjusted_mode;
> +       struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
> +       struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
> +
> +       sun4i_tcon_mode_set(scrtc->tcon, encoder, mode);
> +}
> +
>  static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
>         .atomic_begin   = sun4i_crtc_atomic_begin,
>         .atomic_flush   = sun4i_crtc_atomic_flush,
>         .atomic_enable  = sun4i_crtc_atomic_enable,
>         .atomic_disable = sun4i_crtc_atomic_disable,
> +       .mode_set_nofb  = sun4i_crtc_mode_set_nofb,
>  };
>
>  static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc)
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> index 04f85b1cf922..e826da34e919 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> @@ -13,7 +13,6 @@
>  #include <linux/clk-provider.h>
>  #include <linux/regmap.h>
>
> -#include "sun4i_tcon.h"
>  #include "sun4i_hdmi.h"
>
>  struct sun4i_ddc {
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> index 482bf03d55c1..d2eb0a60e568 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> @@ -30,7 +30,6 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_drv.h"
>  #include "sun4i_hdmi.h"
> -#include "sun4i_tcon.h"
>
>  static inline struct sun4i_hdmi *
>  drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
> @@ -120,15 +119,9 @@ static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
>                                 struct drm_display_mode *adjusted_mode)
>  {
>         struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> -       struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
> -       struct sun4i_tcon *tcon = crtc->tcon;
>         unsigned int x, y;
>         u32 val;
>
> -       sun4i_tcon1_mode_set(tcon, mode);
> -       sun4i_tcon_set_mux(tcon, 1, encoder);
> -
> -       clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
>         clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
>         clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> index 1b6b37aefc38..dc332ea56f6c 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> @@ -12,7 +12,6 @@
>
>  #include <linux/clk-provider.h>
>
> -#include "sun4i_tcon.h"
>  #include "sun4i_hdmi.h"
>
>  struct sun4i_tmds {
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index a7f297ed40c1..832f8f9bc47f 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -153,22 +153,7 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
>         }
>  }
>
> -static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
> -                                      struct drm_display_mode *mode,
> -                                      struct drm_display_mode *adjusted_mode)
> -{
> -       struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
> -       struct sun4i_tcon *tcon = rgb->tcon;
> -
> -       sun4i_tcon0_mode_set(tcon, mode);
> -       sun4i_tcon_set_mux(tcon, 0, encoder);
> -
> -       /* FIXME: This seems to be board specific */
> -       clk_set_phase(tcon->dclk, 120);
> -}
> -
>  static struct drm_encoder_helper_funcs sun4i_rgb_enc_helper_funcs = {
> -       .mode_set       = sun4i_rgb_encoder_mode_set,
>         .disable        = sun4i_rgb_encoder_disable,
>         .enable         = sun4i_rgb_encoder_enable,
>  };
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 964cf22a1ced..7ecd4f7c8411 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -139,7 +139,6 @@ void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
>         DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
>                          encoder->name, encoder->crtc->name, ret);
>  }
> -EXPORT_SYMBOL(sun4i_tcon_set_mux);
>
>  static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
>                                     int channel)
> @@ -159,8 +158,8 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
>         return delay;
>  }
>
> -void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> -                         struct drm_display_mode *mode)
> +static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> +                                struct drm_display_mode *mode)

This doesn't have const...

>  {
>         unsigned int bp, hsync, vsync;
>         u8 clk_delay;
> @@ -233,10 +232,9 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
>         /* Enable the output on the pins */
>         regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
>  }
> -EXPORT_SYMBOL(sun4i_tcon0_mode_set);
>
> -void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> -                         struct drm_display_mode *mode)
> +static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> +                                const struct drm_display_mode *mode)
>  {
>         unsigned int bp, hsync, vsync, vtotal;
>         u8 clk_delay;
> @@ -324,7 +322,26 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
>                            SUN4I_TCON_GCTL_IOMAP_MASK,
>                            SUN4I_TCON_GCTL_IOMAP_TCON1);
>  }
> -EXPORT_SYMBOL(sun4i_tcon1_mode_set);
> +
> +void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
> +                        const struct drm_encoder *encoder,
> +                        const struct drm_display_mode *mode)

But this does...

> +{
> +       switch (encoder->encoder_type) {
> +       case DRM_MODE_ENCODER_NONE:
> +               sun4i_tcon0_mode_set(tcon, mode);

So you're likely to get some warning about dropping const here.

Otherwise,

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* Re: [PATCH 06/23] drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
@ 2017-10-17  9:56     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17  9:56 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, Priit Laes, linux-kernel,
	dri-devel, Quentin Schulz, Chen-Yu Tsai, Rob Herring,
	Daniel Vetter, Mylene Josserand, linux-clk, linux-arm-kernel,
	Icenowy Zheng

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Just like we did for the TCON enable and disable, for historical reasons we
> used to rely on the encoders calling the TCON mode_set function, while the
> CRTC has a callback for that.
>
> Let's implement it in order to reduce the boilerplate code.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/sun4i_crtc.c          | 10 +++++++-
>  drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c  |  1 +-
>  drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c      |  7 +-----
>  drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c |  1 +-
>  drivers/gpu/drm/sun4i/sun4i_rgb.c           | 15 +-----------
>  drivers/gpu/drm/sun4i/sun4i_tcon.c          | 31 +++++++++++++++++-----
>  drivers/gpu/drm/sun4i/sun4i_tcon.h          | 11 ++------
>  drivers/gpu/drm/sun4i/sun4i_tv.c            |  6 +----
>  8 files changed, 37 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> index e86baa3746af..5decae0069d0 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> @@ -115,11 +115,21 @@ static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
>         sun4i_tcon_set_status(scrtc->tcon, encoder, true);
>  }
>
> +static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
> +       struct drm_display_mode *mode = &crtc->state->adjusted_mode;
> +       struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
> +       struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
> +
> +       sun4i_tcon_mode_set(scrtc->tcon, encoder, mode);
> +}
> +
>  static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
>         .atomic_begin   = sun4i_crtc_atomic_begin,
>         .atomic_flush   = sun4i_crtc_atomic_flush,
>         .atomic_enable  = sun4i_crtc_atomic_enable,
>         .atomic_disable = sun4i_crtc_atomic_disable,
> +       .mode_set_nofb  = sun4i_crtc_mode_set_nofb,
>  };
>
>  static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc)
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> index 04f85b1cf922..e826da34e919 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> @@ -13,7 +13,6 @@
>  #include <linux/clk-provider.h>
>  #include <linux/regmap.h>
>
> -#include "sun4i_tcon.h"
>  #include "sun4i_hdmi.h"
>
>  struct sun4i_ddc {
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> index 482bf03d55c1..d2eb0a60e568 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> @@ -30,7 +30,6 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_drv.h"
>  #include "sun4i_hdmi.h"
> -#include "sun4i_tcon.h"
>
>  static inline struct sun4i_hdmi *
>  drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
> @@ -120,15 +119,9 @@ static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
>                                 struct drm_display_mode *adjusted_mode)
>  {
>         struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> -       struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
> -       struct sun4i_tcon *tcon = crtc->tcon;
>         unsigned int x, y;
>         u32 val;
>
> -       sun4i_tcon1_mode_set(tcon, mode);
> -       sun4i_tcon_set_mux(tcon, 1, encoder);
> -
> -       clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
>         clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
>         clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> index 1b6b37aefc38..dc332ea56f6c 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> @@ -12,7 +12,6 @@
>
>  #include <linux/clk-provider.h>
>
> -#include "sun4i_tcon.h"
>  #include "sun4i_hdmi.h"
>
>  struct sun4i_tmds {
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index a7f297ed40c1..832f8f9bc47f 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -153,22 +153,7 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
>         }
>  }
>
> -static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
> -                                      struct drm_display_mode *mode,
> -                                      struct drm_display_mode *adjusted_mode)
> -{
> -       struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
> -       struct sun4i_tcon *tcon = rgb->tcon;
> -
> -       sun4i_tcon0_mode_set(tcon, mode);
> -       sun4i_tcon_set_mux(tcon, 0, encoder);
> -
> -       /* FIXME: This seems to be board specific */
> -       clk_set_phase(tcon->dclk, 120);
> -}
> -
>  static struct drm_encoder_helper_funcs sun4i_rgb_enc_helper_funcs = {
> -       .mode_set       = sun4i_rgb_encoder_mode_set,
>         .disable        = sun4i_rgb_encoder_disable,
>         .enable         = sun4i_rgb_encoder_enable,
>  };
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 964cf22a1ced..7ecd4f7c8411 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -139,7 +139,6 @@ void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
>         DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
>                          encoder->name, encoder->crtc->name, ret);
>  }
> -EXPORT_SYMBOL(sun4i_tcon_set_mux);
>
>  static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
>                                     int channel)
> @@ -159,8 +158,8 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
>         return delay;
>  }
>
> -void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> -                         struct drm_display_mode *mode)
> +static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> +                                struct drm_display_mode *mode)

This doesn't have const...

>  {
>         unsigned int bp, hsync, vsync;
>         u8 clk_delay;
> @@ -233,10 +232,9 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
>         /* Enable the output on the pins */
>         regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
>  }
> -EXPORT_SYMBOL(sun4i_tcon0_mode_set);
>
> -void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> -                         struct drm_display_mode *mode)
> +static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> +                                const struct drm_display_mode *mode)
>  {
>         unsigned int bp, hsync, vsync, vtotal;
>         u8 clk_delay;
> @@ -324,7 +322,26 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
>                            SUN4I_TCON_GCTL_IOMAP_MASK,
>                            SUN4I_TCON_GCTL_IOMAP_TCON1);
>  }
> -EXPORT_SYMBOL(sun4i_tcon1_mode_set);
> +
> +void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
> +                        const struct drm_encoder *encoder,
> +                        const struct drm_display_mode *mode)

But this does...

> +{
> +       switch (encoder->encoder_type) {
> +       case DRM_MODE_ENCODER_NONE:
> +               sun4i_tcon0_mode_set(tcon, mode);

So you're likely to get some warning about dropping const here.

Otherwise,

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 07/23] drm/sun4i: tcon: Move out the tcon0 common setup
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-17 10:00     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:00 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Some channel0 setup has to be done, no matter what the output interface is
> (RGB, CPU, LVDS). Move that code into a common function in order to avoid
> duplication.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* [PATCH 07/23] drm/sun4i: tcon: Move out the tcon0 common setup
@ 2017-10-17 10:00     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Some channel0 setup has to be done, no matter what the output interface is
> (RGB, CPU, LVDS). Move that code into a common function in order to avoid
> duplication.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* Re: [PATCH 08/23] dt-bindings: panel: lvds: Document power-supply property
  2017-10-17  9:06   ` Maxime Ripard
  (?)
@ 2017-10-17 10:01     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:01 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The power-supply property is used be a vast majority of panels, including
                                    ^^^ typo

ChenYu

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

* [PATCH 08/23] dt-bindings: panel: lvds: Document power-supply property
@ 2017-10-17 10:01     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The power-supply property is used be a vast majority of panels, including
                                    ^^^ typo

ChenYu

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

* Re: [PATCH 08/23] dt-bindings: panel: lvds: Document power-supply property
@ 2017-10-17 10:01     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:01 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, Priit Laes, linux-kernel,
	dri-devel, Quentin Schulz, Chen-Yu Tsai, Rob Herring,
	Daniel Vetter, Mylene Josserand, linux-clk, linux-arm-kernel,
	Icenowy Zheng

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The power-supply property is used be a vast majority of panels, including
                                    ^^^ typo

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

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

* Re: [PATCH 09/23] drm/panel: lvds: Add support for the power-supply property
  2017-10-17  9:06   ` Maxime Ripard
  (?)
@ 2017-10-17 10:02     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:02 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> A significant number of panels need to power up a regulator in order to
> operate properly. Add support for the power-supply property to enable and
> disable such a regulator whenever needed.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* [PATCH 09/23] drm/panel: lvds: Add support for the power-supply property
@ 2017-10-17 10:02     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> A significant number of panels need to power up a regulator in order to
> operate properly. Add support for the power-supply property to enable and
> disable such a regulator whenever needed.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* Re: [PATCH 09/23] drm/panel: lvds: Add support for the power-supply property
@ 2017-10-17 10:02     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:02 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, Priit Laes, linux-kernel,
	dri-devel, Quentin Schulz, Chen-Yu Tsai, Rob Herring,
	Daniel Vetter, Mylene Josserand, linux-clk, linux-arm-kernel,
	Icenowy Zheng

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> A significant number of panels need to power up a regulator in order to
> operate properly. Add support for the power-supply property to enable and
> disable such a regulator whenever needed.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 10/23] clk: sunxi-ng: Add A83T display clocks
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-17 10:04     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:04 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Unfortunately, the A83t display clocks are not children of the de clock,
> since that clocks doesn't exist at all on the A83t.
>
> For now, they are orphans, so let's move them to their true, existing,
> parent.
>
> Fixes: 763c5bd045b1 ("clk: sunxi-ng: add support for DE2 CCU")
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* [PATCH 10/23] clk: sunxi-ng: Add A83T display clocks
@ 2017-10-17 10:04     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Unfortunately, the A83t display clocks are not children of the de clock,
> since that clocks doesn't exist at all on the A83t.
>
> For now, they are orphans, so let's move them to their true, existing,
> parent.
>
> Fixes: 763c5bd045b1 ("clk: sunxi-ng: add support for DE2 CCU")
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* Re: [PATCH 11/23] drm/sun4i: Rename layers to UI planes
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-17 10:09     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:09 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The currently supported planes for DE2 are actually only UI planes, and the
> VI planes will differ both in terms of code and features.
>
> It will make sense to support them in a separate file, so let's make sure
> we don't create a confusing file name.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/Makefile      |   2 +-
>  drivers/gpu/drm/sun4i/sun8i_layer.c | 134 +-----------------------------
>  drivers/gpu/drm/sun4i/sun8i_layer.h |  36 +--------
>  drivers/gpu/drm/sun4i/sun8i_mixer.c |   4 +-
>  drivers/gpu/drm/sun4i/sun8i_ui.c    | 134 +++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun8i_ui.h    |  36 ++++++++-
>  6 files changed, 173 insertions(+), 173 deletions(-)
>  delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
>  delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.h
>

[...]

> diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.c b/drivers/gpu/drm/sun4i/sun8i_ui.c
> new file mode 100644
> index 000000000000..077099ef565a
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_ui.c
> @@ -0,0 +1,134 @@

[...]

> +static const struct sun8i_plane_desc sun8i_mixer_planes[] = {

You might want to update this name as well to be consistent.

Otherwise,

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* [PATCH 11/23] drm/sun4i: Rename layers to UI planes
@ 2017-10-17 10:09     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The currently supported planes for DE2 are actually only UI planes, and the
> VI planes will differ both in terms of code and features.
>
> It will make sense to support them in a separate file, so let's make sure
> we don't create a confusing file name.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/Makefile      |   2 +-
>  drivers/gpu/drm/sun4i/sun8i_layer.c | 134 +-----------------------------
>  drivers/gpu/drm/sun4i/sun8i_layer.h |  36 +--------
>  drivers/gpu/drm/sun4i/sun8i_mixer.c |   4 +-
>  drivers/gpu/drm/sun4i/sun8i_ui.c    | 134 +++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun8i_ui.h    |  36 ++++++++-
>  6 files changed, 173 insertions(+), 173 deletions(-)
>  delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
>  delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui.h
>

[...]

> diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.c b/drivers/gpu/drm/sun4i/sun8i_ui.c
> new file mode 100644
> index 000000000000..077099ef565a
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_ui.c
> @@ -0,0 +1,134 @@

[...]

> +static const struct sun8i_plane_desc sun8i_mixer_planes[] = {

You might want to update this name as well to be consistent.

Otherwise,

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* Re: [PATCH 14/23] drm/sun4i: Create minimal multipliers and dividers
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-17 10:15     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:15 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The various outputs the TCON can provide have different constraints on the
> dotclock divider. Let's make them configurable by the various mode_set
> functions.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* [PATCH 14/23] drm/sun4i: Create minimal multipliers and dividers
@ 2017-10-17 10:15     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The various outputs the TCON can provide have different constraints on the
> dotclock divider. Let's make them configurable by the various mode_set
> functions.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* Re: [PATCH 16/23] drm/sun4i: Add A83T support
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-17 10:34     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:34 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Add support for the A83T display pipeline.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* [PATCH 16/23] drm/sun4i: Add A83T support
@ 2017-10-17 10:34     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Add support for the A83T display pipeline.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* Re: [PATCH 17/23] arm: dts: sun8i: a83t: Add display pipeline
  2017-10-17  9:06   ` Maxime Ripard
  (?)
@ 2017-10-17 10:48     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:48 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The display pipeline on the A83T is mainly composed of the mixers and
> TCONs, plus various encoders.
>
> Let's add the mixers and TCONs to the DTSI.

You are only adding half of them, i.e. only the first pipeline.
Please mention why.

>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  arch/arm/boot/dts/sun8i-a83t.dtsi | 80 ++++++++++++++++++++++++++++++++-
>  1 file changed, 80 insertions(+)
>
> diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
> index ce6e887c8938..57feeb6fee8b 100644
> --- a/arch/arm/boot/dts/sun8i-a83t.dtsi
> +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
> @@ -151,6 +151,12 @@
>                 };
>         };
>
> +       de: display-engine {
> +               compatible = "allwinner,sun8i-a83t-display-engine";
> +               allwinner,pipelines = <&mixer0>;
> +               status = "disabled";
> +       };
> +
>         memory {
>                 reg = <0x40000000 0x80000000>;
>                 device_type = "memory";
> @@ -162,6 +168,46 @@
>                 #size-cells = <1>;
>                 ranges;
>
> +               display_clocks: clock@1000000 {
> +                       compatible = "allwinner,sun8i-a83t-de2-clk";
> +                       reg = <0x01000000 0x100000>;
> +                       clocks = <&ccu CLK_PLL_DE>,
> +                                <&ccu CLK_BUS_DE>;
> +                       clock-names = "mod",
> +                                     "bus";
> +                       resets = <&ccu RST_BUS_DE>;
> +                       #clock-cells = <1>;
> +                       #reset-cells = <1>;
> +               };
> +
> +               mixer0: mixer@1100000 {
> +                       compatible = "allwinner,sun8i-a83t-de2-mixer";
> +                       reg = <0x01100000 0x100000>;
> +                       clocks = <&display_clocks 0>,
> +                                <&display_clocks 6>;
> +                       clock-names = "bus",
> +                                     "mod";
> +                       resets = <&display_clocks 0>;
> +                       assigned-clocks = <&display_clocks 6>;

You can use the header file macros now.

> +                       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>;
> +                                       };
> +                               };
> +                       };
> +               };
> +
>                 syscon: syscon@1c00000 {
>                         compatible = "allwinner,sun8i-a83t-system-controller",
>                                 "syscon";
> @@ -177,6 +223,40 @@
>                         #dma-cells = <1>;
>                 };
>
> +               tcon0: lcd-controller@1c0c000 {
> +                       compatible = "allwinner,sun8i-a83t-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";

So I spotted that LVDS can use either TCON0 or MIPI-PLL as its clock parent.
See register TCON0_LVDS_IF_REG @ 0x084. Any chance this makes it into the
binding and device trees?

> +                       clock-output-names = "tcon-pixel-clock";
> +                       resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>;
> +                       reset-names = "lcd", "lvds";
> +                       status = "disabled";

Any reason not to have this enabled by default?

ChenYu

> +
> +                       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@1c0f000 {
>                         compatible = "allwinner,sun8i-a83t-mmc",
>                                      "allwinner,sun7i-a20-mmc";
> --
> git-series 0.9.1

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

* [PATCH 17/23] arm: dts: sun8i: a83t: Add display pipeline
@ 2017-10-17 10:48     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The display pipeline on the A83T is mainly composed of the mixers and
> TCONs, plus various encoders.
>
> Let's add the mixers and TCONs to the DTSI.

You are only adding half of them, i.e. only the first pipeline.
Please mention why.

>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  arch/arm/boot/dts/sun8i-a83t.dtsi | 80 ++++++++++++++++++++++++++++++++-
>  1 file changed, 80 insertions(+)
>
> diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
> index ce6e887c8938..57feeb6fee8b 100644
> --- a/arch/arm/boot/dts/sun8i-a83t.dtsi
> +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
> @@ -151,6 +151,12 @@
>                 };
>         };
>
> +       de: display-engine {
> +               compatible = "allwinner,sun8i-a83t-display-engine";
> +               allwinner,pipelines = <&mixer0>;
> +               status = "disabled";
> +       };
> +
>         memory {
>                 reg = <0x40000000 0x80000000>;
>                 device_type = "memory";
> @@ -162,6 +168,46 @@
>                 #size-cells = <1>;
>                 ranges;
>
> +               display_clocks: clock at 1000000 {
> +                       compatible = "allwinner,sun8i-a83t-de2-clk";
> +                       reg = <0x01000000 0x100000>;
> +                       clocks = <&ccu CLK_PLL_DE>,
> +                                <&ccu CLK_BUS_DE>;
> +                       clock-names = "mod",
> +                                     "bus";
> +                       resets = <&ccu RST_BUS_DE>;
> +                       #clock-cells = <1>;
> +                       #reset-cells = <1>;
> +               };
> +
> +               mixer0: mixer at 1100000 {
> +                       compatible = "allwinner,sun8i-a83t-de2-mixer";
> +                       reg = <0x01100000 0x100000>;
> +                       clocks = <&display_clocks 0>,
> +                                <&display_clocks 6>;
> +                       clock-names = "bus",
> +                                     "mod";
> +                       resets = <&display_clocks 0>;
> +                       assigned-clocks = <&display_clocks 6>;

You can use the header file macros now.

> +                       assigned-clock-rates = <150000000>;
> +
> +                       ports {
> +                               #address-cells = <1>;
> +                               #size-cells = <0>;
> +
> +                               mixer0_out: port at 1 {
> +                                       #address-cells = <1>;
> +                                       #size-cells = <0>;
> +                                       reg = <1>;
> +
> +                                       mixer0_out_tcon0: endpoint at 0 {
> +                                               reg = <0>;
> +                                               remote-endpoint = <&tcon0_in_mixer0>;
> +                                       };
> +                               };
> +                       };
> +               };
> +
>                 syscon: syscon at 1c00000 {
>                         compatible = "allwinner,sun8i-a83t-system-controller",
>                                 "syscon";
> @@ -177,6 +223,40 @@
>                         #dma-cells = <1>;
>                 };
>
> +               tcon0: lcd-controller at 1c0c000 {
> +                       compatible = "allwinner,sun8i-a83t-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";

So I spotted that LVDS can use either TCON0 or MIPI-PLL as its clock parent.
See register TCON0_LVDS_IF_REG @ 0x084. Any chance this makes it into the
binding and device trees?

> +                       clock-output-names = "tcon-pixel-clock";
> +                       resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>;
> +                       reset-names = "lcd", "lvds";
> +                       status = "disabled";

Any reason not to have this enabled by default?

ChenYu

> +
> +                       ports {
> +                               #address-cells = <1>;
> +                               #size-cells = <0>;
> +
> +                               tcon0_in: port at 0 {
> +                                       #address-cells = <1>;
> +                                       #size-cells = <0>;
> +                                       reg = <0>;
> +
> +                                       tcon0_in_mixer0: endpoint at 0 {
> +                                               reg = <0>;
> +                                               remote-endpoint = <&mixer0_out_tcon0>;
> +                                       };
> +                               };
> +
> +                               tcon0_out: port at 1 {
> +                                       #address-cells = <1>;
> +                                       #size-cells = <0>;
> +                                       reg = <1>;
> +                               };
> +                       };
> +               };
> +
>                 mmc0: mmc at 1c0f000 {
>                         compatible = "allwinner,sun8i-a83t-mmc",
>                                      "allwinner,sun7i-a20-mmc";
> --
> git-series 0.9.1

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

* Re: [PATCH 17/23] arm: dts: sun8i: a83t: Add display pipeline
@ 2017-10-17 10:48     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:48 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, Priit Laes, linux-kernel,
	dri-devel, Quentin Schulz, Chen-Yu Tsai, Rob Herring,
	Daniel Vetter, Mylene Josserand, linux-clk, linux-arm-kernel,
	Icenowy Zheng

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The display pipeline on the A83T is mainly composed of the mixers and
> TCONs, plus various encoders.
>
> Let's add the mixers and TCONs to the DTSI.

You are only adding half of them, i.e. only the first pipeline.
Please mention why.

>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  arch/arm/boot/dts/sun8i-a83t.dtsi | 80 ++++++++++++++++++++++++++++++++-
>  1 file changed, 80 insertions(+)
>
> diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
> index ce6e887c8938..57feeb6fee8b 100644
> --- a/arch/arm/boot/dts/sun8i-a83t.dtsi
> +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
> @@ -151,6 +151,12 @@
>                 };
>         };
>
> +       de: display-engine {
> +               compatible = "allwinner,sun8i-a83t-display-engine";
> +               allwinner,pipelines = <&mixer0>;
> +               status = "disabled";
> +       };
> +
>         memory {
>                 reg = <0x40000000 0x80000000>;
>                 device_type = "memory";
> @@ -162,6 +168,46 @@
>                 #size-cells = <1>;
>                 ranges;
>
> +               display_clocks: clock@1000000 {
> +                       compatible = "allwinner,sun8i-a83t-de2-clk";
> +                       reg = <0x01000000 0x100000>;
> +                       clocks = <&ccu CLK_PLL_DE>,
> +                                <&ccu CLK_BUS_DE>;
> +                       clock-names = "mod",
> +                                     "bus";
> +                       resets = <&ccu RST_BUS_DE>;
> +                       #clock-cells = <1>;
> +                       #reset-cells = <1>;
> +               };
> +
> +               mixer0: mixer@1100000 {
> +                       compatible = "allwinner,sun8i-a83t-de2-mixer";
> +                       reg = <0x01100000 0x100000>;
> +                       clocks = <&display_clocks 0>,
> +                                <&display_clocks 6>;
> +                       clock-names = "bus",
> +                                     "mod";
> +                       resets = <&display_clocks 0>;
> +                       assigned-clocks = <&display_clocks 6>;

You can use the header file macros now.

> +                       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>;
> +                                       };
> +                               };
> +                       };
> +               };
> +
>                 syscon: syscon@1c00000 {
>                         compatible = "allwinner,sun8i-a83t-system-controller",
>                                 "syscon";
> @@ -177,6 +223,40 @@
>                         #dma-cells = <1>;
>                 };
>
> +               tcon0: lcd-controller@1c0c000 {
> +                       compatible = "allwinner,sun8i-a83t-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";

So I spotted that LVDS can use either TCON0 or MIPI-PLL as its clock parent.
See register TCON0_LVDS_IF_REG @ 0x084. Any chance this makes it into the
binding and device trees?

> +                       clock-output-names = "tcon-pixel-clock";
> +                       resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>;
> +                       reset-names = "lcd", "lvds";
> +                       status = "disabled";

Any reason not to have this enabled by default?

ChenYu

> +
> +                       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@1c0f000 {
>                         compatible = "allwinner,sun8i-a83t-mmc",
>                                      "allwinner,sun7i-a20-mmc";
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 19/23] arm: dts: sun8i: a83t: Add LVDS pins group
  2017-10-17  9:06   ` Maxime Ripard
  (?)
@ 2017-10-17 10:50     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:50 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The A83T has an LVDS bus that can be connected to a panel or a bridge. Add
> the pinctrl group for it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* [PATCH 19/23] arm: dts: sun8i: a83t: Add LVDS pins group
@ 2017-10-17 10:50     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The A83T has an LVDS bus that can be connected to a panel or a bridge. Add
> the pinctrl group for it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* Re: [PATCH 19/23] arm: dts: sun8i: a83t: Add LVDS pins group
@ 2017-10-17 10:50     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:50 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, Priit Laes, linux-kernel,
	dri-devel, Quentin Schulz, Chen-Yu Tsai, Rob Herring,
	Daniel Vetter, Mylene Josserand, linux-clk, linux-arm-kernel,
	Icenowy Zheng

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The A83T has an LVDS bus that can be connected to a panel or a bridge. Add
> the pinctrl group for it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 20/23] arm: dts: sun8i: a83t: Add the PWM pin group
  2017-10-17  9:06   ` Maxime Ripard
  (?)
@ 2017-10-17 10:51     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:51 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The A83T has a PWM that can be output from the SoC. Let's add a pinctrl
> group for it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* [PATCH 20/23] arm: dts: sun8i: a83t: Add the PWM pin group
@ 2017-10-17 10:51     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The A83T has a PWM that can be output from the SoC. Let's add a pinctrl
> group for it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* Re: [PATCH 20/23] arm: dts: sun8i: a83t: Add the PWM pin group
@ 2017-10-17 10:51     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:51 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, Priit Laes, linux-kernel,
	dri-devel, Quentin Schulz, Chen-Yu Tsai, Rob Herring,
	Daniel Vetter, Mylene Josserand, linux-clk, linux-arm-kernel,
	Icenowy Zheng

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The A83T has a PWM that can be output from the SoC. Let's add a pinctrl
> group for it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 22/23] arm: dts: sun8i: a711: Enable USB OTG
  2017-10-17  9:06   ` Maxime Ripard
  (?)
@ 2017-10-17 10:53     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:53 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:

No description?

> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Changes look good, though unrelated to the rest of the series.

ChenYu

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

* [PATCH 22/23] arm: dts: sun8i: a711: Enable USB OTG
@ 2017-10-17 10:53     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:

No description?

> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Changes look good, though unrelated to the rest of the series.

ChenYu

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

* Re: [PATCH 22/23] arm: dts: sun8i: a711: Enable USB OTG
@ 2017-10-17 10:53     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 10:53 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, Priit Laes, linux-kernel,
	dri-devel, Quentin Schulz, Chen-Yu Tsai, Rob Herring,
	Daniel Vetter, Mylene Josserand, linux-clk, linux-arm-kernel,
	Icenowy Zheng

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:

No description?

> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Changes look good, though unrelated to the rest of the series.

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

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

* Re: [PATCH 15/23] drm/sun4i: Add LVDS support
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-17 11:51     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 11:51 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The TCON supports the LVDS interface to output to a panel or a bridge.
> Let's add support for it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/Makefile     |   1 +-
>  drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 ++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_lvds.h |  18 +++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 193 +++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.h |  25 ++++-
>  5 files changed, 419 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h
>
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index cfba2c07519c..6fee15d016ef 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -10,6 +10,7 @@ sun4i-drm-hdmi-y              += sun4i_hdmi_tmds_clk.o
>
>  sun4i-tcon-y                   += sun4i_tcon.o
>  sun4i-tcon-y                   += sun4i_rgb.o
> +sun4i-tcon-y                   += sun4i_lvds.o
>  sun4i-tcon-y                   += sun4i_dotclock.o
>  sun4i-tcon-y                   += sun4i_crtc.o
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
> new file mode 100644
> index 000000000000..635a3f505ecb
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
> @@ -0,0 +1,183 @@
> +/*
> + * Copyright (C) 2015 NextThing Co
> + * Copyright (C) 2015-2017 Free Electrons
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * 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 <linux/clk.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_of.h>
> +#include <drm/drm_panel.h>
> +
> +#include "sun4i_crtc.h"
> +#include "sun4i_tcon.h"
> +#include "sun4i_lvds.h"
> +
> +struct sun4i_lvds {
> +       struct drm_connector    connector;
> +       struct drm_encoder      encoder;
> +
> +       struct sun4i_tcon       *tcon;
> +};
> +
> +static inline struct sun4i_lvds *
> +drm_connector_to_sun4i_lvds(struct drm_connector *connector)
> +{
> +       return container_of(connector, struct sun4i_lvds,
> +                           connector);
> +}
> +
> +static inline struct sun4i_lvds *
> +drm_encoder_to_sun4i_lvds(struct drm_encoder *encoder)
> +{
> +       return container_of(encoder, struct sun4i_lvds,
> +                           encoder);
> +}
> +
> +static int sun4i_lvds_get_modes(struct drm_connector *connector)
> +{
> +       struct sun4i_lvds *lvds =
> +               drm_connector_to_sun4i_lvds(connector);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       return drm_panel_get_modes(tcon->panel);
> +}
> +
> +static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = {
> +       .get_modes      = sun4i_lvds_get_modes,
> +};
> +
> +static void
> +sun4i_lvds_connector_destroy(struct drm_connector *connector)
> +{
> +       struct sun4i_lvds *lvds = drm_connector_to_sun4i_lvds(connector);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       drm_panel_detach(tcon->panel);
> +       drm_connector_cleanup(connector);
> +}
> +
> +static const struct drm_connector_funcs sun4i_lvds_con_funcs = {
> +       .fill_modes             = drm_helper_probe_single_connector_modes,
> +       .destroy                = sun4i_lvds_connector_destroy,
> +       .reset                  = drm_atomic_helper_connector_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +       .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder)
> +{
> +       struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       DRM_DEBUG_DRIVER("Enabling LVDS output\n");
> +
> +       if (!IS_ERR(tcon->panel)) {
> +               drm_panel_prepare(tcon->panel);
> +               drm_panel_enable(tcon->panel);
> +       }
> +}
> +
> +static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder)
> +{
> +       struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       DRM_DEBUG_DRIVER("Disabling LVDS output\n");
> +
> +       if (!IS_ERR(tcon->panel)) {
> +               drm_panel_disable(tcon->panel);
> +               drm_panel_unprepare(tcon->panel);
> +       }
> +}
> +
> +static const struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = {
> +       .disable        = sun4i_lvds_encoder_disable,
> +       .enable         = sun4i_lvds_encoder_enable,
> +};
> +
> +static const struct drm_encoder_funcs sun4i_lvds_enc_funcs = {
> +       .destroy        = drm_encoder_cleanup,
> +};
> +
> +int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon)
> +{
> +       struct drm_encoder *encoder;
> +       struct drm_bridge *bridge;
> +       struct sun4i_lvds *lvds;
> +       int ret;
> +
> +       lvds = devm_kzalloc(drm->dev, sizeof(*lvds), GFP_KERNEL);
> +       if (!lvds)
> +               return -ENOMEM;
> +       lvds->tcon = tcon;
> +       encoder = &lvds->encoder;
> +
> +       ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
> +                                         &tcon->panel, &bridge);
> +       if (ret) {
> +               dev_info(drm->dev, "No panel or bridge found... LVDS output disabled\n");
> +               return 0;
> +       }
> +
> +       drm_encoder_helper_add(&lvds->encoder,
> +                              &sun4i_lvds_enc_helper_funcs);
> +       ret = drm_encoder_init(drm,
> +                              &lvds->encoder,
> +                              &sun4i_lvds_enc_funcs,
> +                              DRM_MODE_ENCODER_LVDS,
> +                              NULL);
> +       if (ret) {
> +               dev_err(drm->dev, "Couldn't initialise the lvds encoder\n");
> +               goto err_out;
> +       }
> +
> +       /* The LVDS encoder can only work with the TCON channel 0 */
> +       lvds->encoder.possible_crtcs = BIT(drm_crtc_index(&tcon->crtc->crtc));
> +
> +       if (tcon->panel) {
> +               drm_connector_helper_add(&lvds->connector,
> +                                        &sun4i_lvds_con_helper_funcs);
> +               ret = drm_connector_init(drm, &lvds->connector,
> +                                        &sun4i_lvds_con_funcs,
> +                                        DRM_MODE_CONNECTOR_LVDS);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't initialise the lvds connector\n");
> +                       goto err_cleanup_connector;
> +               }
> +
> +               drm_mode_connector_attach_encoder(&lvds->connector,
> +                                                 &lvds->encoder);
> +
> +               ret = drm_panel_attach(tcon->panel, &lvds->connector);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't attach our panel\n");
> +                       goto err_cleanup_connector;
> +               }
> +       }
> +
> +       if (bridge) {
> +               ret = drm_bridge_attach(encoder, bridge, NULL);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't attach our bridge\n");
> +                       goto err_cleanup_connector;
> +               }
> +       }
> +
> +       return 0;
> +
> +err_cleanup_connector:
> +       drm_encoder_cleanup(&lvds->encoder);
> +err_out:
> +       return ret;
> +}
> +EXPORT_SYMBOL(sun4i_lvds_init);
> diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.h b/drivers/gpu/drm/sun4i/sun4i_lvds.h
> new file mode 100644
> index 000000000000..1b8fad4b82c3
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.h
> @@ -0,0 +1,18 @@
> +/*
> + * Copyright (C) 2015 NextThing Co
> + * Copyright (C) 2015-2017 Free Electrons
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * 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 _SUN4I_LVDS_H_
> +#define _SUN4I_LVDS_H_
> +
> +int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon);
> +
> +#endif /* _SUN4I_LVDS_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 3efa1ab045cd..6a20a467ee6d 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -31,10 +31,52 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_dotclock.h"
>  #include "sun4i_drv.h"
> +#include "sun4i_lvds.h"
>  #include "sun4i_rgb.h"
>  #include "sun4i_tcon.h"
>  #include "sunxi_engine.h"
>
> +static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
> +{
> +       struct drm_connector *connector;
> +       struct drm_connector_list_iter iter;
> +
> +       drm_connector_list_iter_begin(encoder->dev, &iter);
> +       drm_for_each_connector_iter(connector, &iter)
> +               if (connector->encoder == encoder) {
> +                       drm_connector_list_iter_end(&iter);
> +                       return connector;
> +               }
> +       drm_connector_list_iter_end(&iter);
> +
> +       return NULL;
> +}
> +
> +static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder)
> +{
> +       struct drm_connector *connector;
> +       struct drm_display_info *info;
> +
> +       connector = sun4i_tcon_get_connector(encoder);
> +       if (!connector)
> +               return -EINVAL;
> +
> +       info = &connector->display_info;
> +       if (info->num_bus_formats != 1)
> +               return -EINVAL;
> +
> +       switch (info->bus_formats[0]) {
> +       case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
> +               return 18;
> +
> +       case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
> +       case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
> +               return 24;
> +       }
> +
> +       return -EINVAL;
> +}
> +
>  static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
>                                           bool enabled)
>  {
> @@ -69,9 +111,13 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
>                            const struct drm_encoder *encoder,
>                            bool enabled)
>  {
> +       bool is_lvds = false;
>         int channel;
>
>         switch (encoder->encoder_type) {
> +       case DRM_MODE_ENCODER_LVDS:
> +               is_lvds = true;
> +               /* Fallthrough */
>         case DRM_MODE_ENCODER_NONE:
>                 channel = 0;
>                 break;
> @@ -84,10 +130,47 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
>                 return;
>         }
>
> +       if (is_lvds && !enabled)
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> +                                  SUN4I_TCON0_LVDS_IF_EN, 0);
> +
>         regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
>                            SUN4I_TCON_GCTL_TCON_ENABLE,
>                            enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
>
> +       if (is_lvds && enabled) {
> +               u8 val;
> +
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> +                                  SUN4I_TCON0_LVDS_IF_EN,
> +                                  SUN4I_TCON0_LVDS_IF_EN);
> +
> +               regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                            SUN4I_TCON0_LVDS_ANA0_C(2) |
> +                            SUN4I_TCON0_LVDS_ANA0_V(3) |
> +                            SUN4I_TCON0_LVDS_ANA0_PD(2) |
> +                            SUN4I_TCON0_LVDS_ANA0_EN_LDO);
> +               udelay(2);
> +
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_MB,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_MB);
> +               udelay(2);
> +
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_DRVC,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_DRVC);
> +
> +               if (sun4i_tcon_get_pixel_depth(encoder) == 18)
> +                       val = 7;
> +               else
> +                       val = 0xf;
> +
> +               regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                                 SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
> +                                 SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val));
> +       }
> +

I suggest moving the LVDS bits into a separate helper (or two) to be
called from sun4i_tcon_set_status().

>         sun4i_tcon_channel_set_status(tcon, channel, enabled);
>  }
>
> @@ -170,6 +253,78 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
>                      SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
>  }
>
> +static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
> +                                     const struct drm_encoder *encoder,
> +                                     const struct drm_display_mode *mode)
> +{
> +       unsigned int bp;
> +       u8 clk_delay;
> +       u32 reg, val = 0;
> +
> +       tcon->dclk_min_div = 7;
> +       tcon->dclk_max_div = 7;
> +       sun4i_tcon0_mode_set_common(tcon, mode);
> +
> +       /* Adjust clock delay */
> +       clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
> +       regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
> +                          SUN4I_TCON0_CTL_CLK_DELAY_MASK,
> +                          SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
> +
> +       /*
> +        * This is called a backporch in the register documentation,
> +        * but it really is the back porch + hsync
> +        */
> +       bp = mode->crtc_htotal - mode->crtc_hsync_start;
> +       DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
> +                        mode->crtc_htotal, bp);
> +
> +       /* Set horizontal display timings */
> +       regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
> +                    SUN4I_TCON0_BASIC1_H_TOTAL(0x554) |
> +                    SUN4I_TCON0_BASIC1_H_BACKPORCH(0xa0));

Fixed, magic numbers?

> +
> +       /*
> +        * This is called a backporch in the register documentation,
> +        * but it really is the back porch + hsync
> +        */
> +       bp = mode->crtc_vtotal - mode->crtc_vsync_start;
> +       DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
> +                        mode->crtc_vtotal, bp);
> +
> +       /* Set vertical display timings */
> +       regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
> +                    SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
> +                    SUN4I_TCON0_BASIC2_V_BACKPORCH(0x17));

Same here. Are these left over from testing?

And the h/v sync stuff looks the same as for RGB. Can we move this
to the common function? Or does MIPI use something different?

> +
> +       reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0 |
> +               SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL |
> +               SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL;
> +       if (sun4i_tcon_get_pixel_depth(encoder) == 24)
> +               reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS;
> +       else
> +               reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
> +
> +       regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
> +
> +       /* Setup the polarity of the various signals */
> +       if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
> +               val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
> +
> +       if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
> +               val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
> +
> +       regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, 0);
> +
> +       /* Map output pins to channel 0 */
> +       regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
> +                          SUN4I_TCON_GCTL_IOMAP_MASK,
> +                          SUN4I_TCON_GCTL_IOMAP_TCON0);
> +
> +       /* Enable the output on the pins */
> +       regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);

Output pin settings look the same as well. Same question as above.

> +}
> +
>  static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
>                                      const struct drm_display_mode *mode)
>  {
> @@ -336,6 +491,9 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
>                          const struct drm_display_mode *mode)
>  {
>         switch (encoder->encoder_type) {
> +       case DRM_MODE_ENCODER_LVDS:
> +               sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
> +               break;
>         case DRM_MODE_ENCODER_NONE:
>                 sun4i_tcon0_mode_set_rgb(tcon, mode);
>                 sun4i_tcon_set_mux(tcon, 0, encoder);
> @@ -667,7 +825,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>         struct drm_device *drm = data;
>         struct sun4i_drv *drv = drm->dev_private;
>         struct sunxi_engine *engine;
> +       struct device_node *remote;
>         struct sun4i_tcon *tcon;
> +       bool has_lvds;
>         int ret;
>
>         engine = sun4i_tcon_find_engine(drv, dev->of_node);
> @@ -698,6 +858,26 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>                 return ret;
>         }
>
> +       /*
> +        * This can only be made optional since we've had DT nodes
> +        * without the LVDS reset properties.
> +        *
> +        * If the property is missing, just disable LVDS, and print a
> +        * warning.
> +        */
> +       tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
> +       if (IS_ERR(tcon->lvds_rst)) {
> +               dev_err(dev, "Couldn't get our reset line\n");
> +               return PTR_ERR(tcon->lvds_rst);
> +       } else if (tcon->lvds_rst) {
> +               has_lvds = true;
> +               reset_control_reset(tcon->lvds_rst);
> +       } else {
> +               has_lvds = false;
> +               dev_warn(dev,
> +                        "Missing LVDS reset property, you should consider upgrading your DT\n");
> +       }
> +
>         ret = sun4i_tcon_init_clocks(dev, tcon);
>         if (ret) {
>                 dev_err(dev, "Couldn't init our TCON clocks\n");
> @@ -729,7 +909,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>                 goto err_free_clocks;
>         }
>
> -       ret = sun4i_rgb_init(drm, tcon);
> +       /*
> +        * If we have an LVDS panel connected to the TCON, we should
> +        * just probe the LVDS connector. Otherwise, just probe RGB as
> +        * we used to.
> +        */
> +       remote = of_graph_get_remote_node(dev->of_node, 1, 0);
> +       if (has_lvds && of_device_is_compatible(remote, "panel-lvds"))

Is the compatible guaranteed? What about bridges?

Thanks
ChenYu

> +               ret = sun4i_lvds_init(drm, tcon);
> +       else
> +               ret = sun4i_rgb_init(drm, tcon);
> +       of_node_put(remote);
> +
>         if (ret < 0)
>                 goto err_free_clocks;
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> index 4141fbd97ddf..382689e5396e 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> @@ -70,7 +70,21 @@
>  #define SUN4I_TCON0_TTL2_REG                   0x78
>  #define SUN4I_TCON0_TTL3_REG                   0x7c
>  #define SUN4I_TCON0_TTL4_REG                   0x80
> +
>  #define SUN4I_TCON0_LVDS_IF_REG                        0x84
> +#define SUN4I_TCON0_LVDS_IF_EN                         BIT(31)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_MASK              BIT(26)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS            (1 << 26)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS            (0 << 26)
> +#define SUN4I_TCON0_LVDS_IF_CLK_SEL_MASK               BIT(20)
> +#define SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0              (1 << 20)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_MASK               BIT(4)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL             (1 << 4)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_INV                        (0 << 4)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_MASK              GENMASK(3, 0)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL            (0xf)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_INV               (0)
> +
>  #define SUN4I_TCON0_IO_POL_REG                 0x88
>  #define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase)           ((phase & 3) << 28)
>  #define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE              BIT(25)
> @@ -131,6 +145,16 @@
>  #define SUN4I_TCON_CEU_RANGE_G_REG             0x144
>  #define SUN4I_TCON_CEU_RANGE_B_REG             0x148
>  #define SUN4I_TCON_MUX_CTRL_REG                        0x200
> +
> +#define SUN4I_TCON0_LVDS_ANA0_REG              0x220
> +#define SUN4I_TCON0_LVDS_ANA0_EN_MB                    BIT(31)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_LDO                   BIT(30)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_DRVC                  BIT(24)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_DRVD(x)               (((x) & 0xf) << 20)
> +#define SUN4I_TCON0_LVDS_ANA0_C(x)                     (((x) & 3) << 17)
> +#define SUN4I_TCON0_LVDS_ANA0_V(x)                     (((x) & 3) << 8)
> +#define SUN4I_TCON0_LVDS_ANA0_PD(x)                    (((x) & 3) << 4)
> +
>  #define SUN4I_TCON1_FILL_CTL_REG               0x300
>  #define SUN4I_TCON1_FILL_BEG0_REG              0x304
>  #define SUN4I_TCON1_FILL_END0_REG              0x308
> @@ -174,6 +198,7 @@ struct sun4i_tcon {
>
>         /* Reset control */
>         struct reset_control            *lcd_rst;
> +       struct reset_control            *lvds_rst;
>
>         struct drm_panel                *panel;
>
> --
> git-series 0.9.1

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

* [PATCH 15/23] drm/sun4i: Add LVDS support
@ 2017-10-17 11:51     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 11:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The TCON supports the LVDS interface to output to a panel or a bridge.
> Let's add support for it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/Makefile     |   1 +-
>  drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 ++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_lvds.h |  18 +++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 193 +++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.h |  25 ++++-
>  5 files changed, 419 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h
>
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index cfba2c07519c..6fee15d016ef 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -10,6 +10,7 @@ sun4i-drm-hdmi-y              += sun4i_hdmi_tmds_clk.o
>
>  sun4i-tcon-y                   += sun4i_tcon.o
>  sun4i-tcon-y                   += sun4i_rgb.o
> +sun4i-tcon-y                   += sun4i_lvds.o
>  sun4i-tcon-y                   += sun4i_dotclock.o
>  sun4i-tcon-y                   += sun4i_crtc.o
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
> new file mode 100644
> index 000000000000..635a3f505ecb
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
> @@ -0,0 +1,183 @@
> +/*
> + * Copyright (C) 2015 NextThing Co
> + * Copyright (C) 2015-2017 Free Electrons
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * 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 <linux/clk.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_of.h>
> +#include <drm/drm_panel.h>
> +
> +#include "sun4i_crtc.h"
> +#include "sun4i_tcon.h"
> +#include "sun4i_lvds.h"
> +
> +struct sun4i_lvds {
> +       struct drm_connector    connector;
> +       struct drm_encoder      encoder;
> +
> +       struct sun4i_tcon       *tcon;
> +};
> +
> +static inline struct sun4i_lvds *
> +drm_connector_to_sun4i_lvds(struct drm_connector *connector)
> +{
> +       return container_of(connector, struct sun4i_lvds,
> +                           connector);
> +}
> +
> +static inline struct sun4i_lvds *
> +drm_encoder_to_sun4i_lvds(struct drm_encoder *encoder)
> +{
> +       return container_of(encoder, struct sun4i_lvds,
> +                           encoder);
> +}
> +
> +static int sun4i_lvds_get_modes(struct drm_connector *connector)
> +{
> +       struct sun4i_lvds *lvds =
> +               drm_connector_to_sun4i_lvds(connector);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       return drm_panel_get_modes(tcon->panel);
> +}
> +
> +static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = {
> +       .get_modes      = sun4i_lvds_get_modes,
> +};
> +
> +static void
> +sun4i_lvds_connector_destroy(struct drm_connector *connector)
> +{
> +       struct sun4i_lvds *lvds = drm_connector_to_sun4i_lvds(connector);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       drm_panel_detach(tcon->panel);
> +       drm_connector_cleanup(connector);
> +}
> +
> +static const struct drm_connector_funcs sun4i_lvds_con_funcs = {
> +       .fill_modes             = drm_helper_probe_single_connector_modes,
> +       .destroy                = sun4i_lvds_connector_destroy,
> +       .reset                  = drm_atomic_helper_connector_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +       .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder)
> +{
> +       struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       DRM_DEBUG_DRIVER("Enabling LVDS output\n");
> +
> +       if (!IS_ERR(tcon->panel)) {
> +               drm_panel_prepare(tcon->panel);
> +               drm_panel_enable(tcon->panel);
> +       }
> +}
> +
> +static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder)
> +{
> +       struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       DRM_DEBUG_DRIVER("Disabling LVDS output\n");
> +
> +       if (!IS_ERR(tcon->panel)) {
> +               drm_panel_disable(tcon->panel);
> +               drm_panel_unprepare(tcon->panel);
> +       }
> +}
> +
> +static const struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = {
> +       .disable        = sun4i_lvds_encoder_disable,
> +       .enable         = sun4i_lvds_encoder_enable,
> +};
> +
> +static const struct drm_encoder_funcs sun4i_lvds_enc_funcs = {
> +       .destroy        = drm_encoder_cleanup,
> +};
> +
> +int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon)
> +{
> +       struct drm_encoder *encoder;
> +       struct drm_bridge *bridge;
> +       struct sun4i_lvds *lvds;
> +       int ret;
> +
> +       lvds = devm_kzalloc(drm->dev, sizeof(*lvds), GFP_KERNEL);
> +       if (!lvds)
> +               return -ENOMEM;
> +       lvds->tcon = tcon;
> +       encoder = &lvds->encoder;
> +
> +       ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
> +                                         &tcon->panel, &bridge);
> +       if (ret) {
> +               dev_info(drm->dev, "No panel or bridge found... LVDS output disabled\n");
> +               return 0;
> +       }
> +
> +       drm_encoder_helper_add(&lvds->encoder,
> +                              &sun4i_lvds_enc_helper_funcs);
> +       ret = drm_encoder_init(drm,
> +                              &lvds->encoder,
> +                              &sun4i_lvds_enc_funcs,
> +                              DRM_MODE_ENCODER_LVDS,
> +                              NULL);
> +       if (ret) {
> +               dev_err(drm->dev, "Couldn't initialise the lvds encoder\n");
> +               goto err_out;
> +       }
> +
> +       /* The LVDS encoder can only work with the TCON channel 0 */
> +       lvds->encoder.possible_crtcs = BIT(drm_crtc_index(&tcon->crtc->crtc));
> +
> +       if (tcon->panel) {
> +               drm_connector_helper_add(&lvds->connector,
> +                                        &sun4i_lvds_con_helper_funcs);
> +               ret = drm_connector_init(drm, &lvds->connector,
> +                                        &sun4i_lvds_con_funcs,
> +                                        DRM_MODE_CONNECTOR_LVDS);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't initialise the lvds connector\n");
> +                       goto err_cleanup_connector;
> +               }
> +
> +               drm_mode_connector_attach_encoder(&lvds->connector,
> +                                                 &lvds->encoder);
> +
> +               ret = drm_panel_attach(tcon->panel, &lvds->connector);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't attach our panel\n");
> +                       goto err_cleanup_connector;
> +               }
> +       }
> +
> +       if (bridge) {
> +               ret = drm_bridge_attach(encoder, bridge, NULL);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't attach our bridge\n");
> +                       goto err_cleanup_connector;
> +               }
> +       }
> +
> +       return 0;
> +
> +err_cleanup_connector:
> +       drm_encoder_cleanup(&lvds->encoder);
> +err_out:
> +       return ret;
> +}
> +EXPORT_SYMBOL(sun4i_lvds_init);
> diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.h b/drivers/gpu/drm/sun4i/sun4i_lvds.h
> new file mode 100644
> index 000000000000..1b8fad4b82c3
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.h
> @@ -0,0 +1,18 @@
> +/*
> + * Copyright (C) 2015 NextThing Co
> + * Copyright (C) 2015-2017 Free Electrons
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * 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 _SUN4I_LVDS_H_
> +#define _SUN4I_LVDS_H_
> +
> +int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon);
> +
> +#endif /* _SUN4I_LVDS_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 3efa1ab045cd..6a20a467ee6d 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -31,10 +31,52 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_dotclock.h"
>  #include "sun4i_drv.h"
> +#include "sun4i_lvds.h"
>  #include "sun4i_rgb.h"
>  #include "sun4i_tcon.h"
>  #include "sunxi_engine.h"
>
> +static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
> +{
> +       struct drm_connector *connector;
> +       struct drm_connector_list_iter iter;
> +
> +       drm_connector_list_iter_begin(encoder->dev, &iter);
> +       drm_for_each_connector_iter(connector, &iter)
> +               if (connector->encoder == encoder) {
> +                       drm_connector_list_iter_end(&iter);
> +                       return connector;
> +               }
> +       drm_connector_list_iter_end(&iter);
> +
> +       return NULL;
> +}
> +
> +static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder)
> +{
> +       struct drm_connector *connector;
> +       struct drm_display_info *info;
> +
> +       connector = sun4i_tcon_get_connector(encoder);
> +       if (!connector)
> +               return -EINVAL;
> +
> +       info = &connector->display_info;
> +       if (info->num_bus_formats != 1)
> +               return -EINVAL;
> +
> +       switch (info->bus_formats[0]) {
> +       case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
> +               return 18;
> +
> +       case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
> +       case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
> +               return 24;
> +       }
> +
> +       return -EINVAL;
> +}
> +
>  static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
>                                           bool enabled)
>  {
> @@ -69,9 +111,13 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
>                            const struct drm_encoder *encoder,
>                            bool enabled)
>  {
> +       bool is_lvds = false;
>         int channel;
>
>         switch (encoder->encoder_type) {
> +       case DRM_MODE_ENCODER_LVDS:
> +               is_lvds = true;
> +               /* Fallthrough */
>         case DRM_MODE_ENCODER_NONE:
>                 channel = 0;
>                 break;
> @@ -84,10 +130,47 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
>                 return;
>         }
>
> +       if (is_lvds && !enabled)
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> +                                  SUN4I_TCON0_LVDS_IF_EN, 0);
> +
>         regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
>                            SUN4I_TCON_GCTL_TCON_ENABLE,
>                            enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
>
> +       if (is_lvds && enabled) {
> +               u8 val;
> +
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> +                                  SUN4I_TCON0_LVDS_IF_EN,
> +                                  SUN4I_TCON0_LVDS_IF_EN);
> +
> +               regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                            SUN4I_TCON0_LVDS_ANA0_C(2) |
> +                            SUN4I_TCON0_LVDS_ANA0_V(3) |
> +                            SUN4I_TCON0_LVDS_ANA0_PD(2) |
> +                            SUN4I_TCON0_LVDS_ANA0_EN_LDO);
> +               udelay(2);
> +
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_MB,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_MB);
> +               udelay(2);
> +
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_DRVC,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_DRVC);
> +
> +               if (sun4i_tcon_get_pixel_depth(encoder) == 18)
> +                       val = 7;
> +               else
> +                       val = 0xf;
> +
> +               regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                                 SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
> +                                 SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val));
> +       }
> +

I suggest moving the LVDS bits into a separate helper (or two) to be
called from sun4i_tcon_set_status().

>         sun4i_tcon_channel_set_status(tcon, channel, enabled);
>  }
>
> @@ -170,6 +253,78 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
>                      SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
>  }
>
> +static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
> +                                     const struct drm_encoder *encoder,
> +                                     const struct drm_display_mode *mode)
> +{
> +       unsigned int bp;
> +       u8 clk_delay;
> +       u32 reg, val = 0;
> +
> +       tcon->dclk_min_div = 7;
> +       tcon->dclk_max_div = 7;
> +       sun4i_tcon0_mode_set_common(tcon, mode);
> +
> +       /* Adjust clock delay */
> +       clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
> +       regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
> +                          SUN4I_TCON0_CTL_CLK_DELAY_MASK,
> +                          SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
> +
> +       /*
> +        * This is called a backporch in the register documentation,
> +        * but it really is the back porch + hsync
> +        */
> +       bp = mode->crtc_htotal - mode->crtc_hsync_start;
> +       DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
> +                        mode->crtc_htotal, bp);
> +
> +       /* Set horizontal display timings */
> +       regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
> +                    SUN4I_TCON0_BASIC1_H_TOTAL(0x554) |
> +                    SUN4I_TCON0_BASIC1_H_BACKPORCH(0xa0));

Fixed, magic numbers?

> +
> +       /*
> +        * This is called a backporch in the register documentation,
> +        * but it really is the back porch + hsync
> +        */
> +       bp = mode->crtc_vtotal - mode->crtc_vsync_start;
> +       DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
> +                        mode->crtc_vtotal, bp);
> +
> +       /* Set vertical display timings */
> +       regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
> +                    SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
> +                    SUN4I_TCON0_BASIC2_V_BACKPORCH(0x17));

Same here. Are these left over from testing?

And the h/v sync stuff looks the same as for RGB. Can we move this
to the common function? Or does MIPI use something different?

> +
> +       reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0 |
> +               SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL |
> +               SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL;
> +       if (sun4i_tcon_get_pixel_depth(encoder) == 24)
> +               reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS;
> +       else
> +               reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
> +
> +       regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
> +
> +       /* Setup the polarity of the various signals */
> +       if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
> +               val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
> +
> +       if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
> +               val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
> +
> +       regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, 0);
> +
> +       /* Map output pins to channel 0 */
> +       regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
> +                          SUN4I_TCON_GCTL_IOMAP_MASK,
> +                          SUN4I_TCON_GCTL_IOMAP_TCON0);
> +
> +       /* Enable the output on the pins */
> +       regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);

Output pin settings look the same as well. Same question as above.

> +}
> +
>  static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
>                                      const struct drm_display_mode *mode)
>  {
> @@ -336,6 +491,9 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
>                          const struct drm_display_mode *mode)
>  {
>         switch (encoder->encoder_type) {
> +       case DRM_MODE_ENCODER_LVDS:
> +               sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
> +               break;
>         case DRM_MODE_ENCODER_NONE:
>                 sun4i_tcon0_mode_set_rgb(tcon, mode);
>                 sun4i_tcon_set_mux(tcon, 0, encoder);
> @@ -667,7 +825,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>         struct drm_device *drm = data;
>         struct sun4i_drv *drv = drm->dev_private;
>         struct sunxi_engine *engine;
> +       struct device_node *remote;
>         struct sun4i_tcon *tcon;
> +       bool has_lvds;
>         int ret;
>
>         engine = sun4i_tcon_find_engine(drv, dev->of_node);
> @@ -698,6 +858,26 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>                 return ret;
>         }
>
> +       /*
> +        * This can only be made optional since we've had DT nodes
> +        * without the LVDS reset properties.
> +        *
> +        * If the property is missing, just disable LVDS, and print a
> +        * warning.
> +        */
> +       tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
> +       if (IS_ERR(tcon->lvds_rst)) {
> +               dev_err(dev, "Couldn't get our reset line\n");
> +               return PTR_ERR(tcon->lvds_rst);
> +       } else if (tcon->lvds_rst) {
> +               has_lvds = true;
> +               reset_control_reset(tcon->lvds_rst);
> +       } else {
> +               has_lvds = false;
> +               dev_warn(dev,
> +                        "Missing LVDS reset property, you should consider upgrading your DT\n");
> +       }
> +
>         ret = sun4i_tcon_init_clocks(dev, tcon);
>         if (ret) {
>                 dev_err(dev, "Couldn't init our TCON clocks\n");
> @@ -729,7 +909,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>                 goto err_free_clocks;
>         }
>
> -       ret = sun4i_rgb_init(drm, tcon);
> +       /*
> +        * If we have an LVDS panel connected to the TCON, we should
> +        * just probe the LVDS connector. Otherwise, just probe RGB as
> +        * we used to.
> +        */
> +       remote = of_graph_get_remote_node(dev->of_node, 1, 0);
> +       if (has_lvds && of_device_is_compatible(remote, "panel-lvds"))

Is the compatible guaranteed? What about bridges?

Thanks
ChenYu

> +               ret = sun4i_lvds_init(drm, tcon);
> +       else
> +               ret = sun4i_rgb_init(drm, tcon);
> +       of_node_put(remote);
> +
>         if (ret < 0)
>                 goto err_free_clocks;
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> index 4141fbd97ddf..382689e5396e 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> @@ -70,7 +70,21 @@
>  #define SUN4I_TCON0_TTL2_REG                   0x78
>  #define SUN4I_TCON0_TTL3_REG                   0x7c
>  #define SUN4I_TCON0_TTL4_REG                   0x80
> +
>  #define SUN4I_TCON0_LVDS_IF_REG                        0x84
> +#define SUN4I_TCON0_LVDS_IF_EN                         BIT(31)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_MASK              BIT(26)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS            (1 << 26)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS            (0 << 26)
> +#define SUN4I_TCON0_LVDS_IF_CLK_SEL_MASK               BIT(20)
> +#define SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0              (1 << 20)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_MASK               BIT(4)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL             (1 << 4)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_INV                        (0 << 4)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_MASK              GENMASK(3, 0)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL            (0xf)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_INV               (0)
> +
>  #define SUN4I_TCON0_IO_POL_REG                 0x88
>  #define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase)           ((phase & 3) << 28)
>  #define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE              BIT(25)
> @@ -131,6 +145,16 @@
>  #define SUN4I_TCON_CEU_RANGE_G_REG             0x144
>  #define SUN4I_TCON_CEU_RANGE_B_REG             0x148
>  #define SUN4I_TCON_MUX_CTRL_REG                        0x200
> +
> +#define SUN4I_TCON0_LVDS_ANA0_REG              0x220
> +#define SUN4I_TCON0_LVDS_ANA0_EN_MB                    BIT(31)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_LDO                   BIT(30)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_DRVC                  BIT(24)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_DRVD(x)               (((x) & 0xf) << 20)
> +#define SUN4I_TCON0_LVDS_ANA0_C(x)                     (((x) & 3) << 17)
> +#define SUN4I_TCON0_LVDS_ANA0_V(x)                     (((x) & 3) << 8)
> +#define SUN4I_TCON0_LVDS_ANA0_PD(x)                    (((x) & 3) << 4)
> +
>  #define SUN4I_TCON1_FILL_CTL_REG               0x300
>  #define SUN4I_TCON1_FILL_BEG0_REG              0x304
>  #define SUN4I_TCON1_FILL_END0_REG              0x308
> @@ -174,6 +198,7 @@ struct sun4i_tcon {
>
>         /* Reset control */
>         struct reset_control            *lcd_rst;
> +       struct reset_control            *lvds_rst;
>
>         struct drm_panel                *panel;
>
> --
> git-series 0.9.1

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

* Re: [PATCH 18/23] arm: dts: sun8i: a83t: Enable the PWM
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-17 11:57     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 11:57 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The A83T has the same PWM block than the H3. Add it to our DT.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* [PATCH 18/23] arm: dts: sun8i: a83t: Enable the PWM
@ 2017-10-17 11:57     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 11:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The A83T has the same PWM block than the H3. Add it to our DT.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

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

* Re: [PATCH 21/23] arm: dts: sun8i: a711: Add regulator support
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-17 12:08     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 12:08 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:

No description?

> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts | 163 +++++++++++++++++++++--
>  1 file changed, 154 insertions(+), 9 deletions(-)
>
> diff --git a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
> index 723641f56a74..98dc0c22160b 100644
> --- a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
> +++ b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts

[...]

> +&reg_dldo2 {
> +       regulator-min-microvolt = <2800000>;
> +       regulator-max-microvolt = <4200000>;
> +       regulator-name = "vcc-mipi";

Is this connected to anything? The wide voltage range
is kind of fishy.

[...]

> @@ -193,7 +338,7 @@
>  };
>
>  &usbphy {
> -       usb1_vbus_supply = <&reg_vcc5v0>;
> -       usb2_vbus_supply = <&reg_vcc5v0>;
> +       usb1_vbus_supply = <&reg_vmain>;
> +       usb2_vbus_supply = <&reg_vmain>;

I wonder why this wasn't done earlier.


Regards
ChenYu

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

* [PATCH 21/23] arm: dts: sun8i: a711: Add regulator support
@ 2017-10-17 12:08     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 12:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:

No description?

> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts | 163 +++++++++++++++++++++--
>  1 file changed, 154 insertions(+), 9 deletions(-)
>
> diff --git a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
> index 723641f56a74..98dc0c22160b 100644
> --- a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
> +++ b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts

[...]

> +&reg_dldo2 {
> +       regulator-min-microvolt = <2800000>;
> +       regulator-max-microvolt = <4200000>;
> +       regulator-name = "vcc-mipi";

Is this connected to anything? The wide voltage range
is kind of fishy.

[...]

> @@ -193,7 +338,7 @@
>  };
>
>  &usbphy {
> -       usb1_vbus_supply = <&reg_vcc5v0>;
> -       usb2_vbus_supply = <&reg_vcc5v0>;
> +       usb1_vbus_supply = <&reg_vmain>;
> +       usb2_vbus_supply = <&reg_vmain>;

I wonder why this wasn't done earlier.


Regards
ChenYu

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

* Re: [PATCH 23/23] arm: dts: sun8i: a711: Enable the LCD
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-17 12:16     ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 12:16 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The A711 has 1024x600 LVDS panel, with a PWM-based backlight. Add it to our
> DT.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Though I think tcon0 could be enabled by default all the time.

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

* [PATCH 23/23] arm: dts: sun8i: a711: Enable the LCD
@ 2017-10-17 12:16     ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 12:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The A711 has 1024x600 LVDS panel, with a PWM-based backlight. Add it to our
> DT.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Though I think tcon0 could be enabled by default all the time.

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

* Re: [PATCH 00/23] drm/sun4i: Add A83t LVDS support
  2017-10-17  9:06 ` Maxime Ripard
@ 2017-10-17 12:16   ` Chen-Yu Tsai
  -1 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 12:16 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, Priit Laes, Icenowy Zheng, Thomas Petazzoni,
	Quentin Schulz, Mylene Josserand

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> Here is an attempt at supporting the LVDS output in our DRM driver. This
> has been tested on the A83T (with DE2), but since everything is basically
> in the TCON, it should also be usable on the older SoCs with minor
> modifications.
>
> This was the occasion to refactor a bunch of things. The most notable ones
> would be the documentation, and split of the UI layers in the mixer code,
> and the switch to kfifo for our endpoint parsing code in the driver that
> fixes an issue introduced by the switch to BFS.
>
> Let me know what you think,
> Maxime
>
> Maxime Ripard (23):
>   drm/sun4i: Implement endpoint parsing using kfifo
>   drm/sun4i: Realign Makefile padding and reorder it
>   drm/sun4i: tcon: Make tcon_set_mux mode argument const
>   drm/sun4i: tcon: Make tcon_get_clk_delay mode argument const
>   drm/sun4i: tcon: Don't rely on encoders to enable the TCON
>   drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
>   drm/sun4i: tcon: Move out the tcon0 common setup
>   dt-bindings: panel: lvds: Document power-supply property
>   drm/panel: lvds: Add support for the power-supply property
>   clk: sunxi-ng: Add A83T display clocks
>   drm/sun4i: Rename layers to UI planes
>   drm/sun4i: sun8i: properly support UI channels
>   drm/sun4i: Reorder and document DE2 mixer registers
>   drm/sun4i: Create minimal multipliers and dividers
>   drm/sun4i: Add LVDS support
>   drm/sun4i: Add A83T support
>   arm: dts: sun8i: a83t: Add display pipeline
>   arm: dts: sun8i: a83t: Enable the PWM
>   arm: dts: sun8i: a83t: Add LVDS pins group
>   arm: dts: sun8i: a83t: Add the PWM pin group
>   arm: dts: sun8i: a711: Add regulator support
>   arm: dts: sun8i: a711: Enable USB OTG
>   arm: dts: sun8i: a711: Enable the LCD

AFAIK ARM should be uppercase for armv7, and lowercase for arm64.

ChenYu

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

* [PATCH 00/23] drm/sun4i: Add A83t LVDS support
@ 2017-10-17 12:16   ` Chen-Yu Tsai
  0 siblings, 0 replies; 161+ messages in thread
From: Chen-Yu Tsai @ 2017-10-17 12:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> Here is an attempt at supporting the LVDS output in our DRM driver. This
> has been tested on the A83T (with DE2), but since everything is basically
> in the TCON, it should also be usable on the older SoCs with minor
> modifications.
>
> This was the occasion to refactor a bunch of things. The most notable ones
> would be the documentation, and split of the UI layers in the mixer code,
> and the switch to kfifo for our endpoint parsing code in the driver that
> fixes an issue introduced by the switch to BFS.
>
> Let me know what you think,
> Maxime
>
> Maxime Ripard (23):
>   drm/sun4i: Implement endpoint parsing using kfifo
>   drm/sun4i: Realign Makefile padding and reorder it
>   drm/sun4i: tcon: Make tcon_set_mux mode argument const
>   drm/sun4i: tcon: Make tcon_get_clk_delay mode argument const
>   drm/sun4i: tcon: Don't rely on encoders to enable the TCON
>   drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
>   drm/sun4i: tcon: Move out the tcon0 common setup
>   dt-bindings: panel: lvds: Document power-supply property
>   drm/panel: lvds: Add support for the power-supply property
>   clk: sunxi-ng: Add A83T display clocks
>   drm/sun4i: Rename layers to UI planes
>   drm/sun4i: sun8i: properly support UI channels
>   drm/sun4i: Reorder and document DE2 mixer registers
>   drm/sun4i: Create minimal multipliers and dividers
>   drm/sun4i: Add LVDS support
>   drm/sun4i: Add A83T support
>   arm: dts: sun8i: a83t: Add display pipeline
>   arm: dts: sun8i: a83t: Enable the PWM
>   arm: dts: sun8i: a83t: Add LVDS pins group
>   arm: dts: sun8i: a83t: Add the PWM pin group
>   arm: dts: sun8i: a711: Add regulator support
>   arm: dts: sun8i: a711: Enable USB OTG
>   arm: dts: sun8i: a711: Enable the LCD

AFAIK ARM should be uppercase for armv7, and lowercase for arm64.

ChenYu

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

* Re: [PATCH 12/23] drm/sun4i: sun8i: properly support UI channels
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-17 12:17     ` icenowy at aosc.io
  -1 siblings, 0 replies; 161+ messages in thread
From: icenowy @ 2017-10-17 12:17 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, Mark Rutland,
	Thomas Petazzoni, plaes, linux-kernel, dri-devel, Quentin Schulz,
	Rob Herring, Mylene Josserand, linux-clk, linux-arm-kernel

在 2017-10-17 17:06,Maxime Ripard 写道:
> The current code has the wrong macro to get the registers offsets of 
> the
> UI-registers, with an off-by-0x1000 error.
> 
> It works so far by accident, since the UI channel used everywhere else 
> is
> the number of VI planes, which has always been 1 so far, and the offset
> between two UI channels is 0x1000.

No, I number the VI channels and UI channels in the same sequence, as 
it's
also what Allwinner does -- VI channels and UI channels all have the 
size
0x1000.

On H3/A64/A83T, the sequence is: 0 - VI, 1 - UI0(, 2 - UI1, 3 - UI2);
on V3s, the sequence is: 0 - VI0, 1 - VI1, 2 - UI.

This patch assumes that there's only one VI channel, which breaks V3s
support.

> 
> Let's correct that behaviour by setting the UI chan number in the 
> sun8i_ui
> structure, and remove the hardcoded values pretty much everywhere. Once 
> we
> have sane values, we can convert the macros to their actual definition.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/sun8i_mixer.c | 50 
> ++++++++++++------------------
>  drivers/gpu/drm/sun4i/sun8i_mixer.h | 32 ++++++++++---------
>  drivers/gpu/drm/sun4i/sun8i_ui.c    | 12 ++++---
>  drivers/gpu/drm/sun4i/sun8i_ui.h    |  1 +-
>  4 files changed, 46 insertions(+), 49 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> index 1955b2a36ac5..5afe8ef709a5 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> @@ -37,14 +37,12 @@ static void sun8i_mixer_commit(struct sunxi_engine 
> *engine)
>  		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
>  }
> 
> -void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
> -				int layer, bool enable)
> +void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct 
> sun8i_ui *ui,
> +			      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);
> +	DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", ui->id, 
> ui->chan);
> 
>  	if (enable)
>  		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
> @@ -52,16 +50,16 @@ void sun8i_mixer_layer_enable(struct sun8i_mixer 
> *mixer,
>  		val = 0;
> 
>  	regmap_update_bits(mixer->engine.regs,
> -			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
>  			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
> 
>  	/* Set the alpha configuration */
>  	regmap_update_bits(mixer->engine.regs,
> -			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
>  			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
>  			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
>  	regmap_update_bits(mixer->engine.regs,
> -			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
>  			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
>  			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
>  }
> @@ -90,14 +88,13 @@ static int sun8i_mixer_drm_format_to_layer(struct
> drm_plane *plane,
>  }
> 
>  int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
> -				     int layer, struct drm_plane *plane)
> +				   struct sun8i_ui *ui)
>  {
> +	struct drm_plane *plane = &ui->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;
> 
> -	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
> +	DRM_DEBUG_DRIVER("Updating layer %d\n", ui->id);
> 
>  	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
>  		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: 
> %u\n",
> @@ -115,7 +112,7 @@ int sun8i_mixer_update_layer_coord(struct
> sun8i_mixer *mixer,
>  					      state->crtc_h));
>  		DRM_DEBUG_DRIVER("Updating channel size\n");
>  		regmap_write(mixer->engine.regs,
> -			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
> +			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(ui->chan),
>  			     SUN8I_MIXER_SIZE(state->crtc_w,
>  					      state->crtc_h));
>  	}
> @@ -123,35 +120,34 @@ int sun8i_mixer_update_layer_coord(struct
> sun8i_mixer *mixer,
>  	/* Set the line width */
>  	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
>  	regmap_write(mixer->engine.regs,
> -		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
> +		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ui->chan, ui->id),
>  		     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->engine.regs,
> -		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
> +		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ui->chan, ui->id),
>  		     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->engine.regs,
> -		     SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
> +		     SUN8I_MIXER_CHAN_UI_LAYER_COORD(ui->chan, ui->id),
>  		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
> 
>  	return 0;
>  }
> 
>  int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
> -				       int layer, struct drm_plane *plane)
> +				     struct sun8i_ui *ui)
>  {
> +	struct drm_plane *plane = &ui->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)
> @@ -174,21 +170,20 @@ int sun8i_mixer_update_layer_formats(struct
> sun8i_mixer *mixer,
>  	}
> 
>  	regmap_update_bits(mixer->engine.regs,
> -			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
>  			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
> 
>  	return 0;
>  }
> 
>  int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
> -				      int layer, struct drm_plane *plane)
> +				    struct sun8i_ui *ui)
>  {
> +	struct drm_plane *plane = &ui->plane;
>  	struct drm_plane_state *state = plane->state;
>  	struct drm_framebuffer *fb = state->fb;
>  	struct drm_gem_cma_object *gem;
>  	dma_addr_t paddr;
> -	/* Currently the first UI channel is used */
> -	int chan = mixer->cfg->vi_num;
>  	int bpp;
> 
>  	/* Get the physical address of the buffer in memory */
> @@ -220,7 +215,7 @@ int sun8i_mixer_update_layer_buffer(struct
> sun8i_mixer *mixer,
>  	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
> 
>  	regmap_write(mixer->engine.regs,
> -		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
> +		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ui->chan, ui->id),
>  		     lower_32_bits(paddr));
> 
>  	return 0;
> @@ -342,11 +337,8 @@ static int sun8i_mixer_bind(struct device *dev,
> struct device *master,
>  		     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->engine.regs, SUN8I_MIXER_BLEND_ROUTE,
> -		     mixer->cfg->vi_num);
> -
> +	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n", 1);
> +	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE, 1);
>  	return 0;
> 
>  err_disable_bus_clk:
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h
> b/drivers/gpu/drm/sun4i/sun8i_mixer.h
> index 4785ac090b8c..20d2ee1c4187 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
> @@ -61,22 +61,22 @@
>   */
> 
>  #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
> -			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
> +			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
>  #define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
> -			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
> +			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
>  #define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
> -			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
> +			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
>  #define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
> -			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
> +			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
>  #define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
> -			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
> +			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
>  #define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
> -			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
> +			(0x3000 + 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)
> +			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
> +#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 
> 0x80)
> +#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 
> 0x84)
> +#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x3000 + 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)
> @@ -104,6 +104,8 @@
>  #define SUN8I_MIXER_FCC_EN			0xaa000
>  #define SUN8I_MIXER_DCSC_EN			0xb0000
> 
> +struct sun8i_ui;
> +
>  struct sun8i_mixer_cfg {
>  	int		vi_num;
>  	int		ui_num;
> @@ -126,12 +128,12 @@ engine_to_sun8i_mixer(struct sunxi_engine 
> *engine)
>  	return container_of(engine, struct sun8i_mixer, engine);
>  }
> 
> -void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
> -				int layer, bool enable);
> +void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct 
> sun8i_ui *ui,
> +			      bool enable);
>  int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
> -				     int layer, struct drm_plane *plane);
> +				   struct sun8i_ui *ui);
>  int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
> -				       int layer, struct drm_plane *plane);
> +				     struct sun8i_ui *ui);
>  int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
> -				      int layer, struct drm_plane *plane);
> +				    struct sun8i_ui *ui);
>  #endif /* _SUN8I_MIXER_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.c 
> b/drivers/gpu/drm/sun4i/sun8i_ui.c
> index 077099ef565a..a056bb0c63c7 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_ui.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_ui.c
> @@ -32,7 +32,7 @@ static void sun8i_mixer_ui_atomic_disable(struct
> drm_plane *plane,
>  	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
>  	struct sun8i_mixer *mixer = ui->mixer;
> 
> -	sun8i_mixer_layer_enable(mixer, ui->id, false);
> +	sun8i_mixer_layer_enable(mixer, ui, false);
>  }
> 
>  static void sun8i_mixer_ui_atomic_update(struct drm_plane *plane,
> @@ -41,10 +41,10 @@ static void sun8i_mixer_ui_atomic_update(struct
> drm_plane *plane,
>  	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
>  	struct sun8i_mixer *mixer = ui->mixer;
> 
> -	sun8i_mixer_update_layer_coord(mixer, ui->id, plane);
> -	sun8i_mixer_update_layer_formats(mixer, ui->id, plane);
> -	sun8i_mixer_update_layer_buffer(mixer, ui->id, plane);
> -	sun8i_mixer_layer_enable(mixer, ui->id, true);
> +	sun8i_mixer_update_layer_coord(mixer, ui);
> +	sun8i_mixer_update_layer_formats(mixer, ui);
> +	sun8i_mixer_update_layer_buffer(mixer, ui);
> +	sun8i_mixer_layer_enable(mixer, ui, true);
>  }
> 
>  static struct drm_plane_helper_funcs sun8i_mixer_ui_helper_funcs = {
> @@ -126,6 +126,8 @@ struct drm_plane **sun8i_ui_init(struct drm_device 
> *drm,
>  			return ERR_CAST(ui);
>  		};
> 
> +		/* TODO: Support several UI channels */
> +		ui->chan = 0;
>  		ui->id = i;
>  		planes[i] = &ui->plane;
>  	};
> diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.h 
> b/drivers/gpu/drm/sun4i/sun8i_ui.h
> index 17dfc92ccc9f..3c3185878ad1 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_ui.h
> +++ b/drivers/gpu/drm/sun4i/sun8i_ui.h
> @@ -22,6 +22,7 @@ struct sun8i_ui {
>  	struct drm_plane	plane;
>  	struct sun4i_drv	*drv;
>  	struct sun8i_mixer	*mixer;
> +	u8			chan;
>  	int			id;
>  };

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

* [PATCH 12/23] drm/sun4i: sun8i: properly support UI channels
@ 2017-10-17 12:17     ` icenowy at aosc.io
  0 siblings, 0 replies; 161+ messages in thread
From: icenowy at aosc.io @ 2017-10-17 12:17 UTC (permalink / raw)
  To: linux-arm-kernel

? 2017-10-17 17:06?Maxime Ripard ???
> The current code has the wrong macro to get the registers offsets of 
> the
> UI-registers, with an off-by-0x1000 error.
> 
> It works so far by accident, since the UI channel used everywhere else 
> is
> the number of VI planes, which has always been 1 so far, and the offset
> between two UI channels is 0x1000.

No, I number the VI channels and UI channels in the same sequence, as 
it's
also what Allwinner does -- VI channels and UI channels all have the 
size
0x1000.

On H3/A64/A83T, the sequence is: 0 - VI, 1 - UI0(, 2 - UI1, 3 - UI2);
on V3s, the sequence is: 0 - VI0, 1 - VI1, 2 - UI.

This patch assumes that there's only one VI channel, which breaks V3s
support.

> 
> Let's correct that behaviour by setting the UI chan number in the 
> sun8i_ui
> structure, and remove the hardcoded values pretty much everywhere. Once 
> we
> have sane values, we can convert the macros to their actual definition.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/sun8i_mixer.c | 50 
> ++++++++++++------------------
>  drivers/gpu/drm/sun4i/sun8i_mixer.h | 32 ++++++++++---------
>  drivers/gpu/drm/sun4i/sun8i_ui.c    | 12 ++++---
>  drivers/gpu/drm/sun4i/sun8i_ui.h    |  1 +-
>  4 files changed, 46 insertions(+), 49 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> index 1955b2a36ac5..5afe8ef709a5 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> @@ -37,14 +37,12 @@ static void sun8i_mixer_commit(struct sunxi_engine 
> *engine)
>  		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
>  }
> 
> -void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
> -				int layer, bool enable)
> +void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct 
> sun8i_ui *ui,
> +			      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);
> +	DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", ui->id, 
> ui->chan);
> 
>  	if (enable)
>  		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
> @@ -52,16 +50,16 @@ void sun8i_mixer_layer_enable(struct sun8i_mixer 
> *mixer,
>  		val = 0;
> 
>  	regmap_update_bits(mixer->engine.regs,
> -			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
>  			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
> 
>  	/* Set the alpha configuration */
>  	regmap_update_bits(mixer->engine.regs,
> -			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
>  			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
>  			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
>  	regmap_update_bits(mixer->engine.regs,
> -			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
>  			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
>  			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
>  }
> @@ -90,14 +88,13 @@ static int sun8i_mixer_drm_format_to_layer(struct
> drm_plane *plane,
>  }
> 
>  int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
> -				     int layer, struct drm_plane *plane)
> +				   struct sun8i_ui *ui)
>  {
> +	struct drm_plane *plane = &ui->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;
> 
> -	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
> +	DRM_DEBUG_DRIVER("Updating layer %d\n", ui->id);
> 
>  	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
>  		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: 
> %u\n",
> @@ -115,7 +112,7 @@ int sun8i_mixer_update_layer_coord(struct
> sun8i_mixer *mixer,
>  					      state->crtc_h));
>  		DRM_DEBUG_DRIVER("Updating channel size\n");
>  		regmap_write(mixer->engine.regs,
> -			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
> +			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(ui->chan),
>  			     SUN8I_MIXER_SIZE(state->crtc_w,
>  					      state->crtc_h));
>  	}
> @@ -123,35 +120,34 @@ int sun8i_mixer_update_layer_coord(struct
> sun8i_mixer *mixer,
>  	/* Set the line width */
>  	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
>  	regmap_write(mixer->engine.regs,
> -		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
> +		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ui->chan, ui->id),
>  		     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->engine.regs,
> -		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
> +		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ui->chan, ui->id),
>  		     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->engine.regs,
> -		     SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
> +		     SUN8I_MIXER_CHAN_UI_LAYER_COORD(ui->chan, ui->id),
>  		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
> 
>  	return 0;
>  }
> 
>  int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
> -				       int layer, struct drm_plane *plane)
> +				     struct sun8i_ui *ui)
>  {
> +	struct drm_plane *plane = &ui->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)
> @@ -174,21 +170,20 @@ int sun8i_mixer_update_layer_formats(struct
> sun8i_mixer *mixer,
>  	}
> 
>  	regmap_update_bits(mixer->engine.regs,
> -			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ui->chan, ui->id),
>  			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
> 
>  	return 0;
>  }
> 
>  int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
> -				      int layer, struct drm_plane *plane)
> +				    struct sun8i_ui *ui)
>  {
> +	struct drm_plane *plane = &ui->plane;
>  	struct drm_plane_state *state = plane->state;
>  	struct drm_framebuffer *fb = state->fb;
>  	struct drm_gem_cma_object *gem;
>  	dma_addr_t paddr;
> -	/* Currently the first UI channel is used */
> -	int chan = mixer->cfg->vi_num;
>  	int bpp;
> 
>  	/* Get the physical address of the buffer in memory */
> @@ -220,7 +215,7 @@ int sun8i_mixer_update_layer_buffer(struct
> sun8i_mixer *mixer,
>  	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
> 
>  	regmap_write(mixer->engine.regs,
> -		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
> +		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ui->chan, ui->id),
>  		     lower_32_bits(paddr));
> 
>  	return 0;
> @@ -342,11 +337,8 @@ static int sun8i_mixer_bind(struct device *dev,
> struct device *master,
>  		     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->engine.regs, SUN8I_MIXER_BLEND_ROUTE,
> -		     mixer->cfg->vi_num);
> -
> +	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n", 1);
> +	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE, 1);
>  	return 0;
> 
>  err_disable_bus_clk:
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h
> b/drivers/gpu/drm/sun4i/sun8i_mixer.h
> index 4785ac090b8c..20d2ee1c4187 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
> @@ -61,22 +61,22 @@
>   */
> 
>  #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
> -			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
> +			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
>  #define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
> -			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
> +			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
>  #define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
> -			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
> +			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
>  #define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
> -			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
> +			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
>  #define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
> -			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
> +			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
>  #define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
> -			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
> +			(0x3000 + 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)
> +			(0x3000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
> +#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 
> 0x80)
> +#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x3000 + 0x1000 * (ch) + 
> 0x84)
> +#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x3000 + 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)
> @@ -104,6 +104,8 @@
>  #define SUN8I_MIXER_FCC_EN			0xaa000
>  #define SUN8I_MIXER_DCSC_EN			0xb0000
> 
> +struct sun8i_ui;
> +
>  struct sun8i_mixer_cfg {
>  	int		vi_num;
>  	int		ui_num;
> @@ -126,12 +128,12 @@ engine_to_sun8i_mixer(struct sunxi_engine 
> *engine)
>  	return container_of(engine, struct sun8i_mixer, engine);
>  }
> 
> -void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
> -				int layer, bool enable);
> +void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, struct 
> sun8i_ui *ui,
> +			      bool enable);
>  int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
> -				     int layer, struct drm_plane *plane);
> +				   struct sun8i_ui *ui);
>  int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
> -				       int layer, struct drm_plane *plane);
> +				     struct sun8i_ui *ui);
>  int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
> -				      int layer, struct drm_plane *plane);
> +				    struct sun8i_ui *ui);
>  #endif /* _SUN8I_MIXER_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.c 
> b/drivers/gpu/drm/sun4i/sun8i_ui.c
> index 077099ef565a..a056bb0c63c7 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_ui.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_ui.c
> @@ -32,7 +32,7 @@ static void sun8i_mixer_ui_atomic_disable(struct
> drm_plane *plane,
>  	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
>  	struct sun8i_mixer *mixer = ui->mixer;
> 
> -	sun8i_mixer_layer_enable(mixer, ui->id, false);
> +	sun8i_mixer_layer_enable(mixer, ui, false);
>  }
> 
>  static void sun8i_mixer_ui_atomic_update(struct drm_plane *plane,
> @@ -41,10 +41,10 @@ static void sun8i_mixer_ui_atomic_update(struct
> drm_plane *plane,
>  	struct sun8i_ui *ui = plane_to_sun8i_ui(plane);
>  	struct sun8i_mixer *mixer = ui->mixer;
> 
> -	sun8i_mixer_update_layer_coord(mixer, ui->id, plane);
> -	sun8i_mixer_update_layer_formats(mixer, ui->id, plane);
> -	sun8i_mixer_update_layer_buffer(mixer, ui->id, plane);
> -	sun8i_mixer_layer_enable(mixer, ui->id, true);
> +	sun8i_mixer_update_layer_coord(mixer, ui);
> +	sun8i_mixer_update_layer_formats(mixer, ui);
> +	sun8i_mixer_update_layer_buffer(mixer, ui);
> +	sun8i_mixer_layer_enable(mixer, ui, true);
>  }
> 
>  static struct drm_plane_helper_funcs sun8i_mixer_ui_helper_funcs = {
> @@ -126,6 +126,8 @@ struct drm_plane **sun8i_ui_init(struct drm_device 
> *drm,
>  			return ERR_CAST(ui);
>  		};
> 
> +		/* TODO: Support several UI channels */
> +		ui->chan = 0;
>  		ui->id = i;
>  		planes[i] = &ui->plane;
>  	};
> diff --git a/drivers/gpu/drm/sun4i/sun8i_ui.h 
> b/drivers/gpu/drm/sun4i/sun8i_ui.h
> index 17dfc92ccc9f..3c3185878ad1 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_ui.h
> +++ b/drivers/gpu/drm/sun4i/sun8i_ui.h
> @@ -22,6 +22,7 @@ struct sun8i_ui {
>  	struct drm_plane	plane;
>  	struct sun4i_drv	*drv;
>  	struct sun8i_mixer	*mixer;
> +	u8			chan;
>  	int			id;
>  };

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

* Re: [PATCH 16/23] drm/sun4i: Add A83T support
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-17 12:28     ` icenowy at aosc.io
  -1 siblings, 0 replies; 161+ messages in thread
From: icenowy @ 2017-10-17 12:28 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, Mark Rutland,
	Thomas Petazzoni, plaes, linux-kernel, dri-devel, Quentin Schulz,
	Rob Herring, Mylene Josserand, linux-clk, linux-arm-kernel

在 2017-10-17 17:06,Maxime Ripard 写道:
> Add support for the A83T display pipeline.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 3 +++
>  drivers/gpu/drm/sun4i/sun4i_drv.c                             | 2 ++
>  drivers/gpu/drm/sun4i/sun4i_tcon.c                            | 1 +
>  drivers/gpu/drm/sun4i/sun8i_mixer.c                           | 4 ++++
>  4 files changed, 10 insertions(+)
> 
> diff --git
> a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> index 46df3b78ae9e..c0fa233ec1fc 100644
> --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> @@ -90,6 +90,7 @@ Required properties:
>     * allwinner,sun6i-a31-tcon
>     * allwinner,sun6i-a31s-tcon
>     * allwinner,sun8i-a33-tcon
> +   * allwinner,sun8i-a83t-tcon

Should be tcon0 -- tcon0 on A83T has only channel 0 and tcon1 has only
channel 1.

>     * allwinner,sun8i-v3s-tcon
>   - reg: base address and size of memory-mapped region
>   - interrupts: interrupt associated to this IP
> @@ -209,6 +210,7 @@ supported.
> 
>  Required properties:
>    - compatible: value must be one of:
> +    * allwinner,sun8i-a83t-de2-mixer

Since the capability of mixer0 and mixer1 are different (smart
backlight, write-back, VEP of the VI channel and extra UI
channels), I suggest to use ID-specific compatibles here.

>      * allwinner,sun8i-v3s-de2-mixer
>    - reg: base address and size of the memory-mapped region.
>    - clocks: phandles to the clocks feeding the mixer
> @@ -236,6 +238,7 @@ Required properties:
>      * allwinner,sun6i-a31-display-engine
>      * allwinner,sun6i-a31s-display-engine
>      * allwinner,sun8i-a33-display-engine
> +    * allwinner,sun8i-a83t-display-engine
>      * allwinner,sun8i-v3s-display-engine
> 
>    - allwinner,pipelines: list of phandle to the display engine
> diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c
> b/drivers/gpu/drm/sun4i/sun4i_drv.c
> index a27efad9bc76..439f116bb3b5 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_drv.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
> @@ -189,6 +189,7 @@ static bool sun4i_drv_node_is_tcon(struct 
> device_node *node)
>  		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-a83t-tcon") ||
>  		of_device_is_compatible(node, "allwinner,sun8i-v3s-tcon");
>  }
> 
> @@ -347,6 +348,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-a83t-display-engine" },
>  	{ .compatible = "allwinner,sun8i-v3s-display-engine" },
>  	{ }
>  };
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 6a20a467ee6d..eb3c8bad4977 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -1063,6 +1063,7 @@ static const struct of_device_id 
> sun4i_tcon_of_table[] = {
>  	{ .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-a83t-tcon", .data = 
> &sun8i_v3s_quirks },
>  	{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks 
> },
>  	{ }
>  };
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> index 86c6c24b5105..c6030ce130d3 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> @@ -385,6 +385,10 @@ static const struct sun8i_mixer_cfg 
> sun8i_v3s_mixer_cfg = {
> 
>  static const struct of_device_id sun8i_mixer_of_table[] = {
>  	{
> +		.compatible = "allwinner,sun8i-a83t-de2-mixer",
> +		.data = &sun8i_v3s_mixer_cfg,

As I said, V3s has 2 VI channels, so it totally shouldn't share
config with A83T.

> +	},
> +	{
>  		.compatible = "allwinner,sun8i-v3s-de2-mixer",
>  		.data = &sun8i_v3s_mixer_cfg,
>  	},

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

* [PATCH 16/23] drm/sun4i: Add A83T support
@ 2017-10-17 12:28     ` icenowy at aosc.io
  0 siblings, 0 replies; 161+ messages in thread
From: icenowy at aosc.io @ 2017-10-17 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

? 2017-10-17 17:06?Maxime Ripard ???
> Add support for the A83T display pipeline.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 3 +++
>  drivers/gpu/drm/sun4i/sun4i_drv.c                             | 2 ++
>  drivers/gpu/drm/sun4i/sun4i_tcon.c                            | 1 +
>  drivers/gpu/drm/sun4i/sun8i_mixer.c                           | 4 ++++
>  4 files changed, 10 insertions(+)
> 
> diff --git
> a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> index 46df3b78ae9e..c0fa233ec1fc 100644
> --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> @@ -90,6 +90,7 @@ Required properties:
>     * allwinner,sun6i-a31-tcon
>     * allwinner,sun6i-a31s-tcon
>     * allwinner,sun8i-a33-tcon
> +   * allwinner,sun8i-a83t-tcon

Should be tcon0 -- tcon0 on A83T has only channel 0 and tcon1 has only
channel 1.

>     * allwinner,sun8i-v3s-tcon
>   - reg: base address and size of memory-mapped region
>   - interrupts: interrupt associated to this IP
> @@ -209,6 +210,7 @@ supported.
> 
>  Required properties:
>    - compatible: value must be one of:
> +    * allwinner,sun8i-a83t-de2-mixer

Since the capability of mixer0 and mixer1 are different (smart
backlight, write-back, VEP of the VI channel and extra UI
channels), I suggest to use ID-specific compatibles here.

>      * allwinner,sun8i-v3s-de2-mixer
>    - reg: base address and size of the memory-mapped region.
>    - clocks: phandles to the clocks feeding the mixer
> @@ -236,6 +238,7 @@ Required properties:
>      * allwinner,sun6i-a31-display-engine
>      * allwinner,sun6i-a31s-display-engine
>      * allwinner,sun8i-a33-display-engine
> +    * allwinner,sun8i-a83t-display-engine
>      * allwinner,sun8i-v3s-display-engine
> 
>    - allwinner,pipelines: list of phandle to the display engine
> diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c
> b/drivers/gpu/drm/sun4i/sun4i_drv.c
> index a27efad9bc76..439f116bb3b5 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_drv.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
> @@ -189,6 +189,7 @@ static bool sun4i_drv_node_is_tcon(struct 
> device_node *node)
>  		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-a83t-tcon") ||
>  		of_device_is_compatible(node, "allwinner,sun8i-v3s-tcon");
>  }
> 
> @@ -347,6 +348,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-a83t-display-engine" },
>  	{ .compatible = "allwinner,sun8i-v3s-display-engine" },
>  	{ }
>  };
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 6a20a467ee6d..eb3c8bad4977 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -1063,6 +1063,7 @@ static const struct of_device_id 
> sun4i_tcon_of_table[] = {
>  	{ .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-a83t-tcon", .data = 
> &sun8i_v3s_quirks },
>  	{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks 
> },
>  	{ }
>  };
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> index 86c6c24b5105..c6030ce130d3 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> @@ -385,6 +385,10 @@ static const struct sun8i_mixer_cfg 
> sun8i_v3s_mixer_cfg = {
> 
>  static const struct of_device_id sun8i_mixer_of_table[] = {
>  	{
> +		.compatible = "allwinner,sun8i-a83t-de2-mixer",
> +		.data = &sun8i_v3s_mixer_cfg,

As I said, V3s has 2 VI channels, so it totally shouldn't share
config with A83T.

> +	},
> +	{
>  		.compatible = "allwinner,sun8i-v3s-de2-mixer",
>  		.data = &sun8i_v3s_mixer_cfg,
>  	},

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

* Re: [PATCH 01/23] drm/sun4i: Implement endpoint parsing using kfifo
  2017-10-17  9:19     ` Chen-Yu Tsai
@ 2017-10-17 14:29       ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17 14:29 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Daniel Vetter, David Airlie, dri-devel, linux-kernel,
	Mark Rutland, Rob Herring, linux-arm-kernel, linux-clk,
	Priit Laes, Icenowy Zheng, Thomas Petazzoni, Quentin Schulz,
	Mylene Josserand

[-- Attachment #1: Type: text/plain, Size: 3150 bytes --]

On Tue, Oct 17, 2017 at 05:19:04PM +0800, Chen-Yu Tsai wrote:
> On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > The commit da82b8785eeb ("drm/sun4i: add components in breadth first
> > traversal order") implemented a breadth first traversal of our device tree
> > nodes graph. However, it was relying on the kernel linked lists, and those
> > are not really safe for addition.
> >
> > Indeed, in a single pipeline stage, your first stage (ie, the mixer or
> > fronted) will be queued, and it will be the final iteration of that list as
> > far as list_for_each_entry_safe is concerned. Then, during that final
> > iteration, we'll queue another element (the TCON or the backend) that
> > list_for_each_entry_safe will not account for, and we will leave the loop
> > without having iterated over all the elements. And since we won't have
> > built our components list properly, the DRM driver will be left
> > non-functional.
> >
> > We can instead use a kfifo to queue and enqueue components in-order, as was
> > the original intention. This also has the benefit of removing any dynamic
> > allocation, making the error handling path simpler too. The only thing
> > we're losing is the ability to tell whether an element has already been
> > queued, but that was only needed to remove spurious logs, and therefore
> > purely cosmetic.
> >
> > This means that this commit effectively reverses e8afb7b67fba ("drm/sun4i:
> > don't add components that are already in the queue").
> >
> > Fixes: da82b8785eeb ("drm/sun4i: add components in breadth first traversal order")
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  drivers/gpu/drm/sun4i/sun4i_drv.c | 71 +++++---------------------------
> >  1 file changed, 13 insertions(+), 58 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
> > index b5879d4620d8..a27efad9bc76 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_drv.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
> > @@ -11,6 +11,7 @@
> >   */
> >
> >  #include <linux/component.h>
> > +#include <linux/kfifo.h>
> >  #include <linux/of_graph.h>
> >  #include <linux/of_reserved_mem.h>
> >
> > @@ -222,29 +223,15 @@ static int compare_of(struct device *dev, void *data)
> >   * matching system handles this for us.
> >   */
> >  struct endpoint_list {
> > -       struct device_node *node;
> > -       struct list_head list;
> > +       DECLARE_KFIFO(fifo, struct device_node *, 16);
> >  };
> 
> Is there any reason to keep using struct endpoint_list, other than
> to avoid using kfifo in function parameter lists?

It appears that you can't just pass a kifo pointer as a function
argument, so the only two remaining solutions were to have a global
pointer or embed it in a structure. It just seems like the best
solution.

> 
> Otherwise the rest of the code looks sound.
> 
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Applied, thanks!
Maxime

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

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

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

* [PATCH 01/23] drm/sun4i: Implement endpoint parsing using kfifo
@ 2017-10-17 14:29       ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17 14:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 05:19:04PM +0800, Chen-Yu Tsai wrote:
> On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > The commit da82b8785eeb ("drm/sun4i: add components in breadth first
> > traversal order") implemented a breadth first traversal of our device tree
> > nodes graph. However, it was relying on the kernel linked lists, and those
> > are not really safe for addition.
> >
> > Indeed, in a single pipeline stage, your first stage (ie, the mixer or
> > fronted) will be queued, and it will be the final iteration of that list as
> > far as list_for_each_entry_safe is concerned. Then, during that final
> > iteration, we'll queue another element (the TCON or the backend) that
> > list_for_each_entry_safe will not account for, and we will leave the loop
> > without having iterated over all the elements. And since we won't have
> > built our components list properly, the DRM driver will be left
> > non-functional.
> >
> > We can instead use a kfifo to queue and enqueue components in-order, as was
> > the original intention. This also has the benefit of removing any dynamic
> > allocation, making the error handling path simpler too. The only thing
> > we're losing is the ability to tell whether an element has already been
> > queued, but that was only needed to remove spurious logs, and therefore
> > purely cosmetic.
> >
> > This means that this commit effectively reverses e8afb7b67fba ("drm/sun4i:
> > don't add components that are already in the queue").
> >
> > Fixes: da82b8785eeb ("drm/sun4i: add components in breadth first traversal order")
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  drivers/gpu/drm/sun4i/sun4i_drv.c | 71 +++++---------------------------
> >  1 file changed, 13 insertions(+), 58 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
> > index b5879d4620d8..a27efad9bc76 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_drv.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
> > @@ -11,6 +11,7 @@
> >   */
> >
> >  #include <linux/component.h>
> > +#include <linux/kfifo.h>
> >  #include <linux/of_graph.h>
> >  #include <linux/of_reserved_mem.h>
> >
> > @@ -222,29 +223,15 @@ static int compare_of(struct device *dev, void *data)
> >   * matching system handles this for us.
> >   */
> >  struct endpoint_list {
> > -       struct device_node *node;
> > -       struct list_head list;
> > +       DECLARE_KFIFO(fifo, struct device_node *, 16);
> >  };
> 
> Is there any reason to keep using struct endpoint_list, other than
> to avoid using kfifo in function parameter lists?

It appears that you can't just pass a kifo pointer as a function
argument, so the only two remaining solutions were to have a global
pointer or embed it in a structure. It just seems like the best
solution.

> 
> Otherwise the rest of the code looks sound.
> 
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Applied, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171017/1013eea8/attachment-0001.sig>

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

* Re: [PATCH 02/23] drm/sun4i: Realign Makefile padding and reorder it
  2017-10-17  9:14     ` Chen-Yu Tsai
@ 2017-10-17 14:34       ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17 14:34 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Daniel Vetter, David Airlie, dri-devel, linux-kernel,
	Mark Rutland, Rob Herring, linux-arm-kernel, linux-clk,
	Priit Laes, Icenowy Zheng, Thomas Petazzoni, Quentin Schulz,
	Mylene Josserand

[-- Attachment #1: Type: text/plain, Size: 2075 bytes --]

On Tue, Oct 17, 2017 at 05:14:47PM +0800, Chen-Yu Tsai wrote:
> On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > Some options were not padded as they should, and the order in the Makefile
> > was chaotic. Fix that.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  drivers/gpu/drm/sun4i/Makefile | 28 ++++++++++++++--------------
> >  1 file changed, 14 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> > index 43c753cafc88..af18b70ba5ed 100644
> > --- a/drivers/gpu/drm/sun4i/Makefile
> > +++ b/drivers/gpu/drm/sun4i/Makefile
> > @@ -1,24 +1,24 @@
> > -sun4i-drm-y += sun4i_drv.o
> > -sun4i-drm-y += sun4i_framebuffer.o
> > +sun4i-backend-y                        += sun4i_backend.o sun4i_layer.o
> >
> > -sun4i-drm-hdmi-y += sun4i_hdmi_enc.o
> > -sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o
> > -sun4i-drm-hdmi-y += sun4i_hdmi_ddc_clk.o
> > -sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o
> > +sun4i-drm-y                    += sun4i_drv.o
> > +sun4i-drm-y                    += sun4i_framebuffer.o
> >
> > -sun4i-tcon-y += sun4i_tcon.o
> > -sun4i-tcon-y += sun4i_rgb.o
> > -sun4i-tcon-y += sun4i_dotclock.o
> > -sun4i-tcon-y += sun4i_crtc.o
> > +sun4i-drm-hdmi-y               += sun4i_hdmi_enc.o
> > +sun4i-drm-hdmi-y               += sun4i_hdmi_i2c.o
> > +sun4i-drm-hdmi-y               += sun4i_hdmi_ddc_clk.o
> > +sun4i-drm-hdmi-y               += sun4i_hdmi_tmds_clk.o
> >
> > -sun4i-backend-y += sun4i_backend.o sun4i_layer.o
> > +sun4i-tcon-y                   += sun4i_tcon.o
> > +sun4i-tcon-y                   += sun4i_rgb.o
> > +sun4i-tcon-y                   += sun4i_dotclock.o
> > +sun4i-tcon-y                   += sun4i_crtc.o
> 
> I don't know if you wanted to sort the file names as well.
> This would be a good time to do it.

Fixed while applying, thanks!
Maxime

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

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

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

* [PATCH 02/23] drm/sun4i: Realign Makefile padding and reorder it
@ 2017-10-17 14:34       ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17 14:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 05:14:47PM +0800, Chen-Yu Tsai wrote:
> On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > Some options were not padded as they should, and the order in the Makefile
> > was chaotic. Fix that.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  drivers/gpu/drm/sun4i/Makefile | 28 ++++++++++++++--------------
> >  1 file changed, 14 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> > index 43c753cafc88..af18b70ba5ed 100644
> > --- a/drivers/gpu/drm/sun4i/Makefile
> > +++ b/drivers/gpu/drm/sun4i/Makefile
> > @@ -1,24 +1,24 @@
> > -sun4i-drm-y += sun4i_drv.o
> > -sun4i-drm-y += sun4i_framebuffer.o
> > +sun4i-backend-y                        += sun4i_backend.o sun4i_layer.o
> >
> > -sun4i-drm-hdmi-y += sun4i_hdmi_enc.o
> > -sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o
> > -sun4i-drm-hdmi-y += sun4i_hdmi_ddc_clk.o
> > -sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o
> > +sun4i-drm-y                    += sun4i_drv.o
> > +sun4i-drm-y                    += sun4i_framebuffer.o
> >
> > -sun4i-tcon-y += sun4i_tcon.o
> > -sun4i-tcon-y += sun4i_rgb.o
> > -sun4i-tcon-y += sun4i_dotclock.o
> > -sun4i-tcon-y += sun4i_crtc.o
> > +sun4i-drm-hdmi-y               += sun4i_hdmi_enc.o
> > +sun4i-drm-hdmi-y               += sun4i_hdmi_i2c.o
> > +sun4i-drm-hdmi-y               += sun4i_hdmi_ddc_clk.o
> > +sun4i-drm-hdmi-y               += sun4i_hdmi_tmds_clk.o
> >
> > -sun4i-backend-y += sun4i_backend.o sun4i_layer.o
> > +sun4i-tcon-y                   += sun4i_tcon.o
> > +sun4i-tcon-y                   += sun4i_rgb.o
> > +sun4i-tcon-y                   += sun4i_dotclock.o
> > +sun4i-tcon-y                   += sun4i_crtc.o
> 
> I don't know if you wanted to sort the file names as well.
> This would be a good time to do it.

Fixed while applying, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171017/16f3dfc8/attachment.sig>

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

* Re: [PATCH 03/23] drm/sun4i: tcon: Make tcon_set_mux mode argument const
  2017-10-17  9:21     ` Chen-Yu Tsai
@ 2017-10-17 14:35       ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17 14:35 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Daniel Vetter, David Airlie, dri-devel, linux-kernel,
	Mark Rutland, Rob Herring, linux-arm-kernel, linux-clk,
	Priit Laes, Icenowy Zheng, Thomas Petazzoni, Quentin Schulz,
	Mylene Josserand

[-- Attachment #1: Type: text/plain, Size: 482 bytes --]

On Tue, Oct 17, 2017 at 05:21:09PM +0800, Chen-Yu Tsai wrote:
> On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > The drm_display_mode pointer can be mark const, so let's do it.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> 
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Applied, thanks!
Maxime

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

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

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

* [PATCH 03/23] drm/sun4i: tcon: Make tcon_set_mux mode argument const
@ 2017-10-17 14:35       ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17 14:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 05:21:09PM +0800, Chen-Yu Tsai wrote:
> On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > The drm_display_mode pointer can be mark const, so let's do it.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> 
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Applied, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171017/b6f8728e/attachment.sig>

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

* Re: [PATCH 04/23] drm/sun4i: tcon: Make tcon_get_clk_delay mode argument const
  2017-10-17  9:22     ` Chen-Yu Tsai
@ 2017-10-17 14:37       ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17 14:37 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Daniel Vetter, David Airlie, dri-devel, linux-kernel,
	Mark Rutland, Rob Herring, linux-arm-kernel, linux-clk,
	Priit Laes, Icenowy Zheng, Thomas Petazzoni, Quentin Schulz,
	Mylene Josserand

[-- Attachment #1: Type: text/plain, Size: 482 bytes --]

On Tue, Oct 17, 2017 at 05:22:03PM +0800, Chen-Yu Tsai wrote:
> On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > The drm_display_mode pointer can be mark const, so let's do it.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> 
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Applied, thanks!
Maxime

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

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

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

* [PATCH 04/23] drm/sun4i: tcon: Make tcon_get_clk_delay mode argument const
@ 2017-10-17 14:37       ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17 14:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 05:22:03PM +0800, Chen-Yu Tsai wrote:
> On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > The drm_display_mode pointer can be mark const, so let's do it.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> 
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Applied, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171017/73e38f65/attachment.sig>

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

* Re: [PATCH 05/23] drm/sun4i: tcon: Don't rely on encoders to enable the TCON
  2017-10-17  9:28     ` Chen-Yu Tsai
  (?)
@ 2017-10-17 14:38       ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17 14:38 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Daniel Vetter, David Airlie, dri-devel, linux-kernel,
	Mark Rutland, Rob Herring, linux-arm-kernel, linux-clk,
	Priit Laes, Icenowy Zheng, Thomas Petazzoni, Quentin Schulz,
	Mylene Josserand

[-- Attachment #1: Type: text/plain, Size: 1141 bytes --]

On Tue, Oct 17, 2017 at 05:28:42PM +0800, Chen-Yu Tsai wrote:
> On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > So far, we've required all the TCON-connected encoders to call the TCON
> > enable and disable functions.
> >
> > This was made this way because in the RGB/LVDS case, the TCON is the CRTC
> > and the encoder. However, in all the other cases (HDMI, TV, DSI, etc.), we
> > have another encoder down the road that needs to be programmed.
> >
> > We also needed to know which channel the encoder is connected to, which is
> > encoder-specific.
> >
> > The CRTC's enable and disable callbacks can work just fine for our use
> > case, and we can get the channel to use just by looking at the type of
> > encoder, since that is fixed. Implement those callbacks, which will
> > remove some of the encoder boilerplate.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> 
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Applied, thanks!
Maxime

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

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

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

* [PATCH 05/23] drm/sun4i: tcon: Don't rely on encoders to enable the TCON
@ 2017-10-17 14:38       ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17 14:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 05:28:42PM +0800, Chen-Yu Tsai wrote:
> On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > So far, we've required all the TCON-connected encoders to call the TCON
> > enable and disable functions.
> >
> > This was made this way because in the RGB/LVDS case, the TCON is the CRTC
> > and the encoder. However, in all the other cases (HDMI, TV, DSI, etc.), we
> > have another encoder down the road that needs to be programmed.
> >
> > We also needed to know which channel the encoder is connected to, which is
> > encoder-specific.
> >
> > The CRTC's enable and disable callbacks can work just fine for our use
> > case, and we can get the channel to use just by looking at the type of
> > encoder, since that is fixed. Implement those callbacks, which will
> > remove some of the encoder boilerplate.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> 
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Applied, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171017/56d9f846/attachment.sig>

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

* Re: [PATCH 05/23] drm/sun4i: tcon: Don't rely on encoders to enable the TCON
@ 2017-10-17 14:38       ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17 14:38 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Mark Rutland, Thomas Petazzoni, Priit Laes, linux-kernel,
	dri-devel, Quentin Schulz, Rob Herring, Daniel Vetter,
	Mylene Josserand, linux-clk, linux-arm-kernel, Icenowy Zheng


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

On Tue, Oct 17, 2017 at 05:28:42PM +0800, Chen-Yu Tsai wrote:
> On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > So far, we've required all the TCON-connected encoders to call the TCON
> > enable and disable functions.
> >
> > This was made this way because in the RGB/LVDS case, the TCON is the CRTC
> > and the encoder. However, in all the other cases (HDMI, TV, DSI, etc.), we
> > have another encoder down the road that needs to be programmed.
> >
> > We also needed to know which channel the encoder is connected to, which is
> > encoder-specific.
> >
> > The CRTC's enable and disable callbacks can work just fine for our use
> > case, and we can get the channel to use just by looking at the type of
> > encoder, since that is fixed. Implement those callbacks, which will
> > remove some of the encoder boilerplate.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> 
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Applied, thanks!
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] 161+ messages in thread

* Re: [PATCH 06/23] drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
  2017-10-17  9:56     ` Chen-Yu Tsai
  (?)
@ 2017-10-17 14:39       ` Maxime Ripard
  -1 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17 14:39 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Daniel Vetter, David Airlie, dri-devel, linux-kernel,
	Mark Rutland, Rob Herring, linux-arm-kernel, linux-clk,
	Priit Laes, Icenowy Zheng, Thomas Petazzoni, Quentin Schulz,
	Mylene Josserand

[-- Attachment #1: Type: text/plain, Size: 8276 bytes --]

On Tue, Oct 17, 2017 at 05:56:47PM +0800, Chen-Yu Tsai wrote:
> On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > Just like we did for the TCON enable and disable, for historical reasons we
> > used to rely on the encoders calling the TCON mode_set function, while the
> > CRTC has a callback for that.
> >
> > Let's implement it in order to reduce the boilerplate code.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  drivers/gpu/drm/sun4i/sun4i_crtc.c          | 10 +++++++-
> >  drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c  |  1 +-
> >  drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c      |  7 +-----
> >  drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c |  1 +-
> >  drivers/gpu/drm/sun4i/sun4i_rgb.c           | 15 +-----------
> >  drivers/gpu/drm/sun4i/sun4i_tcon.c          | 31 +++++++++++++++++-----
> >  drivers/gpu/drm/sun4i/sun4i_tcon.h          | 11 ++------
> >  drivers/gpu/drm/sun4i/sun4i_tv.c            |  6 +----
> >  8 files changed, 37 insertions(+), 45 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> > index e86baa3746af..5decae0069d0 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> > @@ -115,11 +115,21 @@ static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
> >         sun4i_tcon_set_status(scrtc->tcon, encoder, true);
> >  }
> >
> > +static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc)
> > +{
> > +       struct drm_display_mode *mode = &crtc->state->adjusted_mode;
> > +       struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
> > +       struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
> > +
> > +       sun4i_tcon_mode_set(scrtc->tcon, encoder, mode);
> > +}
> > +
> >  static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
> >         .atomic_begin   = sun4i_crtc_atomic_begin,
> >         .atomic_flush   = sun4i_crtc_atomic_flush,
> >         .atomic_enable  = sun4i_crtc_atomic_enable,
> >         .atomic_disable = sun4i_crtc_atomic_disable,
> > +       .mode_set_nofb  = sun4i_crtc_mode_set_nofb,
> >  };
> >
> >  static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc)
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> > index 04f85b1cf922..e826da34e919 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> > @@ -13,7 +13,6 @@
> >  #include <linux/clk-provider.h>
> >  #include <linux/regmap.h>
> >
> > -#include "sun4i_tcon.h"
> >  #include "sun4i_hdmi.h"
> >
> >  struct sun4i_ddc {
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> > index 482bf03d55c1..d2eb0a60e568 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> > @@ -30,7 +30,6 @@
> >  #include "sun4i_crtc.h"
> >  #include "sun4i_drv.h"
> >  #include "sun4i_hdmi.h"
> > -#include "sun4i_tcon.h"
> >
> >  static inline struct sun4i_hdmi *
> >  drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
> > @@ -120,15 +119,9 @@ static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
> >                                 struct drm_display_mode *adjusted_mode)
> >  {
> >         struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> > -       struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
> > -       struct sun4i_tcon *tcon = crtc->tcon;
> >         unsigned int x, y;
> >         u32 val;
> >
> > -       sun4i_tcon1_mode_set(tcon, mode);
> > -       sun4i_tcon_set_mux(tcon, 1, encoder);
> > -
> > -       clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
> >         clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
> >         clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> > index 1b6b37aefc38..dc332ea56f6c 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> > @@ -12,7 +12,6 @@
> >
> >  #include <linux/clk-provider.h>
> >
> > -#include "sun4i_tcon.h"
> >  #include "sun4i_hdmi.h"
> >
> >  struct sun4i_tmds {
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > index a7f297ed40c1..832f8f9bc47f 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > @@ -153,22 +153,7 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
> >         }
> >  }
> >
> > -static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
> > -                                      struct drm_display_mode *mode,
> > -                                      struct drm_display_mode *adjusted_mode)
> > -{
> > -       struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
> > -       struct sun4i_tcon *tcon = rgb->tcon;
> > -
> > -       sun4i_tcon0_mode_set(tcon, mode);
> > -       sun4i_tcon_set_mux(tcon, 0, encoder);
> > -
> > -       /* FIXME: This seems to be board specific */
> > -       clk_set_phase(tcon->dclk, 120);
> > -}
> > -
> >  static struct drm_encoder_helper_funcs sun4i_rgb_enc_helper_funcs = {
> > -       .mode_set       = sun4i_rgb_encoder_mode_set,
> >         .disable        = sun4i_rgb_encoder_disable,
> >         .enable         = sun4i_rgb_encoder_enable,
> >  };
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > index 964cf22a1ced..7ecd4f7c8411 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > @@ -139,7 +139,6 @@ void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
> >         DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
> >                          encoder->name, encoder->crtc->name, ret);
> >  }
> > -EXPORT_SYMBOL(sun4i_tcon_set_mux);
> >
> >  static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
> >                                     int channel)
> > @@ -159,8 +158,8 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
> >         return delay;
> >  }
> >
> > -void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> > -                         struct drm_display_mode *mode)
> > +static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> > +                                struct drm_display_mode *mode)
> 
> This doesn't have const...
> 
> >  {
> >         unsigned int bp, hsync, vsync;
> >         u8 clk_delay;
> > @@ -233,10 +232,9 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> >         /* Enable the output on the pins */
> >         regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
> >  }
> > -EXPORT_SYMBOL(sun4i_tcon0_mode_set);
> >
> > -void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> > -                         struct drm_display_mode *mode)
> > +static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> > +                                const struct drm_display_mode *mode)
> >  {
> >         unsigned int bp, hsync, vsync, vtotal;
> >         u8 clk_delay;
> > @@ -324,7 +322,26 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> >                            SUN4I_TCON_GCTL_IOMAP_MASK,
> >                            SUN4I_TCON_GCTL_IOMAP_TCON1);
> >  }
> > -EXPORT_SYMBOL(sun4i_tcon1_mode_set);
> > +
> > +void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
> > +                        const struct drm_encoder *encoder,
> > +                        const struct drm_display_mode *mode)
> 
> But this does...
> 
> > +{
> > +       switch (encoder->encoder_type) {
> > +       case DRM_MODE_ENCODER_NONE:
> > +               sun4i_tcon0_mode_set(tcon, mode);
> 
> So you're likely to get some warning about dropping const here.
> 
> Otherwise,
> 
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Strangely enough, it doesn't. I've fixed it and applied.

Thanks!
Maxime

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

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

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

* [PATCH 06/23] drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
@ 2017-10-17 14:39       ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17 14:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 05:56:47PM +0800, Chen-Yu Tsai wrote:
> On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > Just like we did for the TCON enable and disable, for historical reasons we
> > used to rely on the encoders calling the TCON mode_set function, while the
> > CRTC has a callback for that.
> >
> > Let's implement it in order to reduce the boilerplate code.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  drivers/gpu/drm/sun4i/sun4i_crtc.c          | 10 +++++++-
> >  drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c  |  1 +-
> >  drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c      |  7 +-----
> >  drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c |  1 +-
> >  drivers/gpu/drm/sun4i/sun4i_rgb.c           | 15 +-----------
> >  drivers/gpu/drm/sun4i/sun4i_tcon.c          | 31 +++++++++++++++++-----
> >  drivers/gpu/drm/sun4i/sun4i_tcon.h          | 11 ++------
> >  drivers/gpu/drm/sun4i/sun4i_tv.c            |  6 +----
> >  8 files changed, 37 insertions(+), 45 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> > index e86baa3746af..5decae0069d0 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> > @@ -115,11 +115,21 @@ static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
> >         sun4i_tcon_set_status(scrtc->tcon, encoder, true);
> >  }
> >
> > +static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc)
> > +{
> > +       struct drm_display_mode *mode = &crtc->state->adjusted_mode;
> > +       struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
> > +       struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
> > +
> > +       sun4i_tcon_mode_set(scrtc->tcon, encoder, mode);
> > +}
> > +
> >  static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
> >         .atomic_begin   = sun4i_crtc_atomic_begin,
> >         .atomic_flush   = sun4i_crtc_atomic_flush,
> >         .atomic_enable  = sun4i_crtc_atomic_enable,
> >         .atomic_disable = sun4i_crtc_atomic_disable,
> > +       .mode_set_nofb  = sun4i_crtc_mode_set_nofb,
> >  };
> >
> >  static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc)
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> > index 04f85b1cf922..e826da34e919 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> > @@ -13,7 +13,6 @@
> >  #include <linux/clk-provider.h>
> >  #include <linux/regmap.h>
> >
> > -#include "sun4i_tcon.h"
> >  #include "sun4i_hdmi.h"
> >
> >  struct sun4i_ddc {
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> > index 482bf03d55c1..d2eb0a60e568 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> > @@ -30,7 +30,6 @@
> >  #include "sun4i_crtc.h"
> >  #include "sun4i_drv.h"
> >  #include "sun4i_hdmi.h"
> > -#include "sun4i_tcon.h"
> >
> >  static inline struct sun4i_hdmi *
> >  drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
> > @@ -120,15 +119,9 @@ static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
> >                                 struct drm_display_mode *adjusted_mode)
> >  {
> >         struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> > -       struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
> > -       struct sun4i_tcon *tcon = crtc->tcon;
> >         unsigned int x, y;
> >         u32 val;
> >
> > -       sun4i_tcon1_mode_set(tcon, mode);
> > -       sun4i_tcon_set_mux(tcon, 1, encoder);
> > -
> > -       clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
> >         clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
> >         clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> > index 1b6b37aefc38..dc332ea56f6c 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> > @@ -12,7 +12,6 @@
> >
> >  #include <linux/clk-provider.h>
> >
> > -#include "sun4i_tcon.h"
> >  #include "sun4i_hdmi.h"
> >
> >  struct sun4i_tmds {
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > index a7f297ed40c1..832f8f9bc47f 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > @@ -153,22 +153,7 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
> >         }
> >  }
> >
> > -static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
> > -                                      struct drm_display_mode *mode,
> > -                                      struct drm_display_mode *adjusted_mode)
> > -{
> > -       struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
> > -       struct sun4i_tcon *tcon = rgb->tcon;
> > -
> > -       sun4i_tcon0_mode_set(tcon, mode);
> > -       sun4i_tcon_set_mux(tcon, 0, encoder);
> > -
> > -       /* FIXME: This seems to be board specific */
> > -       clk_set_phase(tcon->dclk, 120);
> > -}
> > -
> >  static struct drm_encoder_helper_funcs sun4i_rgb_enc_helper_funcs = {
> > -       .mode_set       = sun4i_rgb_encoder_mode_set,
> >         .disable        = sun4i_rgb_encoder_disable,
> >         .enable         = sun4i_rgb_encoder_enable,
> >  };
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > index 964cf22a1ced..7ecd4f7c8411 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > @@ -139,7 +139,6 @@ void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
> >         DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
> >                          encoder->name, encoder->crtc->name, ret);
> >  }
> > -EXPORT_SYMBOL(sun4i_tcon_set_mux);
> >
> >  static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
> >                                     int channel)
> > @@ -159,8 +158,8 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
> >         return delay;
> >  }
> >
> > -void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> > -                         struct drm_display_mode *mode)
> > +static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> > +                                struct drm_display_mode *mode)
> 
> This doesn't have const...
> 
> >  {
> >         unsigned int bp, hsync, vsync;
> >         u8 clk_delay;
> > @@ -233,10 +232,9 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> >         /* Enable the output on the pins */
> >         regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
> >  }
> > -EXPORT_SYMBOL(sun4i_tcon0_mode_set);
> >
> > -void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> > -                         struct drm_display_mode *mode)
> > +static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> > +                                const struct drm_display_mode *mode)
> >  {
> >         unsigned int bp, hsync, vsync, vtotal;
> >         u8 clk_delay;
> > @@ -324,7 +322,26 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> >                            SUN4I_TCON_GCTL_IOMAP_MASK,
> >                            SUN4I_TCON_GCTL_IOMAP_TCON1);
> >  }
> > -EXPORT_SYMBOL(sun4i_tcon1_mode_set);
> > +
> > +void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
> > +                        const struct drm_encoder *encoder,
> > +                        const struct drm_display_mode *mode)
> 
> But this does...
> 
> > +{
> > +       switch (encoder->encoder_type) {
> > +       case DRM_MODE_ENCODER_NONE:
> > +               sun4i_tcon0_mode_set(tcon, mode);
> 
> So you're likely to get some warning about dropping const here.
> 
> Otherwise,
> 
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Strangely enough, it doesn't. I've fixed it and applied.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171017/61dd8aaa/attachment.sig>

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

* Re: [PATCH 06/23] drm/sun4i: tcon: Don't rely on encoders to set the TCON mode
@ 2017-10-17 14:39       ` Maxime Ripard
  0 siblings, 0 replies; 161+ messages in thread
From: Maxime Ripard @ 2017-10-17 14:39 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Mark Rutland, Thomas Petazzoni, Priit Laes, linux-kernel,
	dri-devel, Quentin Schulz, Rob Herring, Daniel Vetter,
	Mylene Josserand, linux-clk, linux-arm-kernel, Icenowy Zheng


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

On Tue, Oct 17, 2017 at 05:56:47PM +0800, Chen-Yu Tsai wrote:
> On Tue, Oct 17, 2017 at 5:06 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > Just like we did for the TCON enable and disable, for historical reasons we
> > used to rely on the encoders calling the TCON mode_set function, while the
> > CRTC has a callback for that.
> >
> > Let's implement it in order to reduce the boilerplate code.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  drivers/gpu/drm/sun4i/sun4i_crtc.c          | 10 +++++++-
> >  drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c  |  1 +-
> >  drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c      |  7 +-----
> >  drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c |  1 +-
> >  drivers/gpu/drm/sun4i/sun4i_rgb.c           | 15 +-----------
> >  drivers/gpu/drm/sun4i/sun4i_tcon.c          | 31 +++++++++++++++++-----
> >  drivers/gpu/drm/sun4i/sun4i_tcon.h          | 11 ++------
> >  drivers/gpu/drm/sun4i/sun4i_tv.c            |  6 +----
> >  8 files changed, 37 insertions(+), 45 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> > index e86baa3746af..5decae0069d0 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> > @@ -115,11 +115,21 @@ static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
> >         sun4i_tcon_set_status(scrtc->tcon, encoder, true);
> >  }
> >
> > +static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc)
> > +{
> > +       struct drm_display_mode *mode = &crtc->state->adjusted_mode;
> > +       struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
> > +       struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
> > +
> > +       sun4i_tcon_mode_set(scrtc->tcon, encoder, mode);
> > +}
> > +
> >  static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
> >         .atomic_begin   = sun4i_crtc_atomic_begin,
> >         .atomic_flush   = sun4i_crtc_atomic_flush,
> >         .atomic_enable  = sun4i_crtc_atomic_enable,
> >         .atomic_disable = sun4i_crtc_atomic_disable,
> > +       .mode_set_nofb  = sun4i_crtc_mode_set_nofb,
> >  };
> >
> >  static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc)
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> > index 04f85b1cf922..e826da34e919 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> > @@ -13,7 +13,6 @@
> >  #include <linux/clk-provider.h>
> >  #include <linux/regmap.h>
> >
> > -#include "sun4i_tcon.h"
> >  #include "sun4i_hdmi.h"
> >
> >  struct sun4i_ddc {
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> > index 482bf03d55c1..d2eb0a60e568 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> > @@ -30,7 +30,6 @@
> >  #include "sun4i_crtc.h"
> >  #include "sun4i_drv.h"
> >  #include "sun4i_hdmi.h"
> > -#include "sun4i_tcon.h"
> >
> >  static inline struct sun4i_hdmi *
> >  drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
> > @@ -120,15 +119,9 @@ static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
> >                                 struct drm_display_mode *adjusted_mode)
> >  {
> >         struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> > -       struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
> > -       struct sun4i_tcon *tcon = crtc->tcon;
> >         unsigned int x, y;
> >         u32 val;
> >
> > -       sun4i_tcon1_mode_set(tcon, mode);
> > -       sun4i_tcon_set_mux(tcon, 1, encoder);
> > -
> > -       clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
> >         clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
> >         clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> > index 1b6b37aefc38..dc332ea56f6c 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> > @@ -12,7 +12,6 @@
> >
> >  #include <linux/clk-provider.h>
> >
> > -#include "sun4i_tcon.h"
> >  #include "sun4i_hdmi.h"
> >
> >  struct sun4i_tmds {
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > index a7f297ed40c1..832f8f9bc47f 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > @@ -153,22 +153,7 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
> >         }
> >  }
> >
> > -static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
> > -                                      struct drm_display_mode *mode,
> > -                                      struct drm_display_mode *adjusted_mode)
> > -{
> > -       struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
> > -       struct sun4i_tcon *tcon = rgb->tcon;
> > -
> > -       sun4i_tcon0_mode_set(tcon, mode);
> > -       sun4i_tcon_set_mux(tcon, 0, encoder);
> > -
> > -       /* FIXME: This seems to be board specific */
> > -       clk_set_phase(tcon->dclk, 120);
> > -}
> > -
> >  static struct drm_encoder_helper_funcs sun4i_rgb_enc_helper_funcs = {
> > -       .mode_set       = sun4i_rgb_encoder_mode_set,
> >         .disable        = sun4i_rgb_encoder_disable,
> >         .enable         = sun4i_rgb_encoder_enable,
> >  };
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > index 964cf22a1ced..7ecd4f7c8411 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > @@ -139,7 +139,6 @@ void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
> >         DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
> >                          encoder->name, encoder->crtc->name, ret);
> >  }
> > -EXPORT_SYMBOL(sun4i_tcon_set_mux);
> >
> >  static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
> >                                     int channel)
> > @@ -159,8 +158,8 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
> >         return delay;
> >  }
> >
> > -void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> > -                         struct drm_display_mode *mode)
> > +static void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> > +                                struct drm_display_mode *mode)
> 
> This doesn't have const...
> 
> >  {
> >         unsigned int bp, hsync, vsync;
> >         u8 clk_delay;
> > @@ -233,10 +232,9 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
> >         /* Enable the output on the pins */
> >         regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
> >  }
> > -EXPORT_SYMBOL(sun4i_tcon0_mode_set);
> >
> > -void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> > -                         struct drm_display_mode *mode)
> > +static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> > +                                const struct drm_display_mode *mode)
> >  {
> >         unsigned int bp, hsync, vsync, vtotal;
> >         u8 clk_delay;
> > @@ -324,7 +322,26 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
> >                            SUN4I_TCON_GCTL_IOMAP_MASK,
> >                            SUN4I_TCON_GCTL_IOMAP_TCON1);
> >  }
> > -EXPORT_SYMBOL(sun4i_tcon1_mode_set);
> > +
> > +void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
> > +                        const struct drm_encoder *encoder,
> > +                        const struct drm_display_mode *mode)
> 
> But this does...
> 
> > +{
> > +       switch (encoder->encoder_type) {
> > +       case DRM_MODE_ENCODER_NONE:
> > +               sun4i_tcon0_mode_set(tcon, mode);
> 
> So you're likely to get some warning about dropping const here.
> 
> Otherwise,
> 
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Strangely enough, it doesn't. I've fixed it and applied.

Thanks!
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] 161+ messages in thread

* Re: [PATCH 15/23] drm/sun4i: Add LVDS support
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-22 18:52     ` Priit Laes
  -1 siblings, 0 replies; 161+ messages in thread
From: Priit Laes @ 2017-10-22 18:52 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, icenowy, Thomas Petazzoni, Quentin Schulz,
	Mylene Josserand

On Tue, Oct 17, 2017 at 11:06:22AM +0200, Maxime Ripard wrote:
> The TCON supports the LVDS interface to output to a panel or a bridge.
> Let's add support for it.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/Makefile     |   1 +-
>  drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 ++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_lvds.h |  18 +++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 193 +++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.h |  25 ++++-
>  5 files changed, 419 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h
> 

[...]

> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 3efa1ab045cd..6a20a467ee6d 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c

[...]
> @@ -698,6 +858,26 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>  		return ret;
>  	}
>  
> +	/*
> +	 * This can only be made optional since we've had DT nodes
> +	 * without the LVDS reset properties.
> +	 *
> +	 * If the property is missing, just disable LVDS, and print a
> +	 * warning.
> +	 */
> +	tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
> +	if (IS_ERR(tcon->lvds_rst)) {
> +		dev_err(dev, "Couldn't get our reset line\n");
> +		return PTR_ERR(tcon->lvds_rst);
> +	} else if (tcon->lvds_rst) {
> +		has_lvds = true;
> +		reset_control_reset(tcon->lvds_rst);
> +	} else {
> +		has_lvds = false;
> +		dev_warn(dev,
> +			 "Missing LVDS reset property, you should consider upgrading your DT\n");

This will generate annoying warning for tcon1 on A10/A20.

> +	}
> +
>  	ret = sun4i_tcon_init_clocks(dev, tcon);
>  	if (ret) {
>  		dev_err(dev, "Couldn't init our TCON clocks\n");
> @@ -729,7 +909,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>  		goto err_free_clocks;
>  	}
>  
> -	ret = sun4i_rgb_init(drm, tcon);
> +	/*
> +	 * If we have an LVDS panel connected to the TCON, we should
> +	 * just probe the LVDS connector. Otherwise, just probe RGB as
> +	 * we used to.
> +	 */

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

* [PATCH 15/23] drm/sun4i: Add LVDS support
@ 2017-10-22 18:52     ` Priit Laes
  0 siblings, 0 replies; 161+ messages in thread
From: Priit Laes @ 2017-10-22 18:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 11:06:22AM +0200, Maxime Ripard wrote:
> The TCON supports the LVDS interface to output to a panel or a bridge.
> Let's add support for it.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/Makefile     |   1 +-
>  drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 ++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_lvds.h |  18 +++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 193 +++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.h |  25 ++++-
>  5 files changed, 419 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h
> 

[...]

> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 3efa1ab045cd..6a20a467ee6d 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c

[...]
> @@ -698,6 +858,26 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>  		return ret;
>  	}
>  
> +	/*
> +	 * This can only be made optional since we've had DT nodes
> +	 * without the LVDS reset properties.
> +	 *
> +	 * If the property is missing, just disable LVDS, and print a
> +	 * warning.
> +	 */
> +	tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
> +	if (IS_ERR(tcon->lvds_rst)) {
> +		dev_err(dev, "Couldn't get our reset line\n");
> +		return PTR_ERR(tcon->lvds_rst);
> +	} else if (tcon->lvds_rst) {
> +		has_lvds = true;
> +		reset_control_reset(tcon->lvds_rst);
> +	} else {
> +		has_lvds = false;
> +		dev_warn(dev,
> +			 "Missing LVDS reset property, you should consider upgrading your DT\n");

This will generate annoying warning for tcon1 on A10/A20.

> +	}
> +
>  	ret = sun4i_tcon_init_clocks(dev, tcon);
>  	if (ret) {
>  		dev_err(dev, "Couldn't init our TCON clocks\n");
> @@ -729,7 +909,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>  		goto err_free_clocks;
>  	}
>  
> -	ret = sun4i_rgb_init(drm, tcon);
> +	/*
> +	 * If we have an LVDS panel connected to the TCON, we should
> +	 * just probe the LVDS connector. Otherwise, just probe RGB as
> +	 * we used to.
> +	 */

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

* Re: [15/23] drm/sun4i: Add LVDS support
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-23  2:23     ` Jonathan Liu
  -1 siblings, 0 replies; 161+ messages in thread
From: Jonathan Liu @ 2017-10-23  2:23 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, Mark Rutland,
	Thomas Petazzoni, Priit Laes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

Hi Maxime,

On 17 October 2017 at 20:06, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The TCON supports the LVDS interface to output to a panel or a bridge.
> Let's add support for it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/Makefile     |   1 +-
>  drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 ++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_lvds.h |  18 +++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 193 +++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.h |  25 ++++-
>  5 files changed, 419 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h
>
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index cfba2c07519c..6fee15d016ef 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -10,6 +10,7 @@ sun4i-drm-hdmi-y              += sun4i_hdmi_tmds_clk.o
>
>  sun4i-tcon-y                   += sun4i_tcon.o
>  sun4i-tcon-y                   += sun4i_rgb.o
> +sun4i-tcon-y                   += sun4i_lvds.o
>  sun4i-tcon-y                   += sun4i_dotclock.o
>  sun4i-tcon-y                   += sun4i_crtc.o
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
> new file mode 100644
> index 000000000000..635a3f505ecb
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
> @@ -0,0 +1,183 @@
> +/*
> + * Copyright (C) 2015 NextThing Co
> + * Copyright (C) 2015-2017 Free Electrons
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * 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 <linux/clk.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_of.h>
> +#include <drm/drm_panel.h>
> +
> +#include "sun4i_crtc.h"
> +#include "sun4i_tcon.h"
> +#include "sun4i_lvds.h"
> +
> +struct sun4i_lvds {
> +       struct drm_connector    connector;
> +       struct drm_encoder      encoder;
> +
> +       struct sun4i_tcon       *tcon;
> +};
> +
> +static inline struct sun4i_lvds *
> +drm_connector_to_sun4i_lvds(struct drm_connector *connector)
> +{
> +       return container_of(connector, struct sun4i_lvds,
> +                           connector);
> +}
> +
> +static inline struct sun4i_lvds *
> +drm_encoder_to_sun4i_lvds(struct drm_encoder *encoder)
> +{
> +       return container_of(encoder, struct sun4i_lvds,
> +                           encoder);
> +}
> +
> +static int sun4i_lvds_get_modes(struct drm_connector *connector)
> +{
> +       struct sun4i_lvds *lvds =
> +               drm_connector_to_sun4i_lvds(connector);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       return drm_panel_get_modes(tcon->panel);
> +}
> +
> +static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = {
> +       .get_modes      = sun4i_lvds_get_modes,
> +};
> +
> +static void
> +sun4i_lvds_connector_destroy(struct drm_connector *connector)
> +{
> +       struct sun4i_lvds *lvds = drm_connector_to_sun4i_lvds(connector);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       drm_panel_detach(tcon->panel);
> +       drm_connector_cleanup(connector);
> +}
> +
> +static const struct drm_connector_funcs sun4i_lvds_con_funcs = {
> +       .fill_modes             = drm_helper_probe_single_connector_modes,
> +       .destroy                = sun4i_lvds_connector_destroy,
> +       .reset                  = drm_atomic_helper_connector_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +       .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder)
> +{
> +       struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       DRM_DEBUG_DRIVER("Enabling LVDS output\n");
> +
> +       if (!IS_ERR(tcon->panel)) {
> +               drm_panel_prepare(tcon->panel);
> +               drm_panel_enable(tcon->panel);
> +       }
> +}
> +
> +static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder)
> +{
> +       struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       DRM_DEBUG_DRIVER("Disabling LVDS output\n");
> +
> +       if (!IS_ERR(tcon->panel)) {
> +               drm_panel_disable(tcon->panel);
> +               drm_panel_unprepare(tcon->panel);
> +       }
> +}
> +
> +static const struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = {
> +       .disable        = sun4i_lvds_encoder_disable,
> +       .enable         = sun4i_lvds_encoder_enable,
> +};
> +
> +static const struct drm_encoder_funcs sun4i_lvds_enc_funcs = {
> +       .destroy        = drm_encoder_cleanup,
> +};
> +
> +int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon)
> +{
> +       struct drm_encoder *encoder;
> +       struct drm_bridge *bridge;
> +       struct sun4i_lvds *lvds;
> +       int ret;
> +
> +       lvds = devm_kzalloc(drm->dev, sizeof(*lvds), GFP_KERNEL);
> +       if (!lvds)
> +               return -ENOMEM;
> +       lvds->tcon = tcon;
> +       encoder = &lvds->encoder;
> +
> +       ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
> +                                         &tcon->panel, &bridge);
> +       if (ret) {
> +               dev_info(drm->dev, "No panel or bridge found... LVDS output disabled\n");
> +               return 0;
> +       }
> +
> +       drm_encoder_helper_add(&lvds->encoder,
> +                              &sun4i_lvds_enc_helper_funcs);
> +       ret = drm_encoder_init(drm,
> +                              &lvds->encoder,
> +                              &sun4i_lvds_enc_funcs,
> +                              DRM_MODE_ENCODER_LVDS,
> +                              NULL);
> +       if (ret) {
> +               dev_err(drm->dev, "Couldn't initialise the lvds encoder\n");
> +               goto err_out;
> +       }
> +
> +       /* The LVDS encoder can only work with the TCON channel 0 */
> +       lvds->encoder.possible_crtcs = BIT(drm_crtc_index(&tcon->crtc->crtc));
> +
> +       if (tcon->panel) {
> +               drm_connector_helper_add(&lvds->connector,
> +                                        &sun4i_lvds_con_helper_funcs);
> +               ret = drm_connector_init(drm, &lvds->connector,
> +                                        &sun4i_lvds_con_funcs,
> +                                        DRM_MODE_CONNECTOR_LVDS);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't initialise the lvds connector\n");
> +                       goto err_cleanup_connector;
> +               }
> +
> +               drm_mode_connector_attach_encoder(&lvds->connector,
> +                                                 &lvds->encoder);
> +
> +               ret = drm_panel_attach(tcon->panel, &lvds->connector);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't attach our panel\n");
> +                       goto err_cleanup_connector;
> +               }
> +       }
> +
> +       if (bridge) {
> +               ret = drm_bridge_attach(encoder, bridge, NULL);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't attach our bridge\n");
> +                       goto err_cleanup_connector;
> +               }
> +       }
> +
> +       return 0;
> +
> +err_cleanup_connector:
> +       drm_encoder_cleanup(&lvds->encoder);
> +err_out:
> +       return ret;
> +}
> +EXPORT_SYMBOL(sun4i_lvds_init);
> diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.h b/drivers/gpu/drm/sun4i/sun4i_lvds.h
> new file mode 100644
> index 000000000000..1b8fad4b82c3
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.h
> @@ -0,0 +1,18 @@
> +/*
> + * Copyright (C) 2015 NextThing Co
> + * Copyright (C) 2015-2017 Free Electrons
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * 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 _SUN4I_LVDS_H_
> +#define _SUN4I_LVDS_H_
> +
> +int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon);
> +
> +#endif /* _SUN4I_LVDS_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 3efa1ab045cd..6a20a467ee6d 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -31,10 +31,52 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_dotclock.h"
>  #include "sun4i_drv.h"
> +#include "sun4i_lvds.h"
>  #include "sun4i_rgb.h"
>  #include "sun4i_tcon.h"
>  #include "sunxi_engine.h"
>
> +static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
> +{
> +       struct drm_connector *connector;
> +       struct drm_connector_list_iter iter;
> +
> +       drm_connector_list_iter_begin(encoder->dev, &iter);
> +       drm_for_each_connector_iter(connector, &iter)
> +               if (connector->encoder == encoder) {
> +                       drm_connector_list_iter_end(&iter);
> +                       return connector;
> +               }
> +       drm_connector_list_iter_end(&iter);
> +
> +       return NULL;
> +}
> +
> +static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder)
> +{
> +       struct drm_connector *connector;
> +       struct drm_display_info *info;
> +
> +       connector = sun4i_tcon_get_connector(encoder);
> +       if (!connector)
> +               return -EINVAL;
> +
> +       info = &connector->display_info;
> +       if (info->num_bus_formats != 1)
> +               return -EINVAL;
> +
> +       switch (info->bus_formats[0]) {
> +       case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
> +               return 18;
> +
> +       case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
> +       case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
> +               return 24;
> +       }
> +
> +       return -EINVAL;
> +}
> +
>  static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
>                                           bool enabled)
>  {
> @@ -69,9 +111,13 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
>                            const struct drm_encoder *encoder,
>                            bool enabled)
>  {
> +       bool is_lvds = false;
>         int channel;
>
>         switch (encoder->encoder_type) {
> +       case DRM_MODE_ENCODER_LVDS:
> +               is_lvds = true;
> +               /* Fallthrough */
>         case DRM_MODE_ENCODER_NONE:
>                 channel = 0;
>                 break;
> @@ -84,10 +130,47 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
>                 return;
>         }
>
> +       if (is_lvds && !enabled)
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> +                                  SUN4I_TCON0_LVDS_IF_EN, 0);
> +
>         regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
>                            SUN4I_TCON_GCTL_TCON_ENABLE,
>                            enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
>
> +       if (is_lvds && enabled) {
> +               u8 val;
> +
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> +                                  SUN4I_TCON0_LVDS_IF_EN,
> +                                  SUN4I_TCON0_LVDS_IF_EN);
> +
> +               regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                            SUN4I_TCON0_LVDS_ANA0_C(2) |
> +                            SUN4I_TCON0_LVDS_ANA0_V(3) |
> +                            SUN4I_TCON0_LVDS_ANA0_PD(2) |
> +                            SUN4I_TCON0_LVDS_ANA0_EN_LDO);
> +               udelay(2);
> +
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_MB,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_MB);
> +               udelay(2);
> +
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_DRVC,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_DRVC);
> +
> +               if (sun4i_tcon_get_pixel_depth(encoder) == 18)
> +                       val = 7;
> +               else
> +                       val = 0xf;
> +
> +               regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                                 SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
> +                                 SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val));
> +       }
> +
>         sun4i_tcon_channel_set_status(tcon, channel, enabled);
>  }
>
> @@ -170,6 +253,78 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
>                      SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
>  }
>
> +static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
> +                                     const struct drm_encoder *encoder,
> +                                     const struct drm_display_mode *mode)
> +{
> +       unsigned int bp;
> +       u8 clk_delay;
> +       u32 reg, val = 0;
> +
> +       tcon->dclk_min_div = 7;
> +       tcon->dclk_max_div = 7;
> +       sun4i_tcon0_mode_set_common(tcon, mode);
> +
> +       /* Adjust clock delay */
> +       clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
> +       regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
> +                          SUN4I_TCON0_CTL_CLK_DELAY_MASK,
> +                          SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
> +
> +       /*
> +        * This is called a backporch in the register documentation,
> +        * but it really is the back porch + hsync
> +        */
> +       bp = mode->crtc_htotal - mode->crtc_hsync_start;
> +       DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
> +                        mode->crtc_htotal, bp);
> +
> +       /* Set horizontal display timings */
> +       regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
> +                    SUN4I_TCON0_BASIC1_H_TOTAL(0x554) |
> +                    SUN4I_TCON0_BASIC1_H_BACKPORCH(0xa0));
> +
> +       /*
> +        * This is called a backporch in the register documentation,
> +        * but it really is the back porch + hsync
> +        */
> +       bp = mode->crtc_vtotal - mode->crtc_vsync_start;
> +       DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
> +                        mode->crtc_vtotal, bp);
> +
> +       /* Set vertical display timings */
> +       regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
> +                    SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
> +                    SUN4I_TCON0_BASIC2_V_BACKPORCH(0x17));
> +
> +       reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0 |
> +               SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL |
> +               SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL;
> +       if (sun4i_tcon_get_pixel_depth(encoder) == 24)
> +               reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS;
> +       else
> +               reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
> +
> +       regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
> +

> +       /* Setup the polarity of the various signals */
> +       if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
> +               val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
> +
> +       if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
> +               val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
> +
> +       regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, 0);

val is set but not written to the SUN4I_TCON0_IO_POL_REG register.

> +
> +       /* Map output pins to channel 0 */
> +       regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
> +                          SUN4I_TCON_GCTL_IOMAP_MASK,
> +                          SUN4I_TCON_GCTL_IOMAP_TCON0);
> +
> +       /* Enable the output on the pins */
> +       regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
> +}
> +
>  static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
>                                      const struct drm_display_mode *mode)
>  {
> @@ -336,6 +491,9 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
>                          const struct drm_display_mode *mode)
>  {
>         switch (encoder->encoder_type) {
> +       case DRM_MODE_ENCODER_LVDS:
> +               sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
> +               break;
>         case DRM_MODE_ENCODER_NONE:
>                 sun4i_tcon0_mode_set_rgb(tcon, mode);
>                 sun4i_tcon_set_mux(tcon, 0, encoder);
> @@ -667,7 +825,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>         struct drm_device *drm = data;
>         struct sun4i_drv *drv = drm->dev_private;
>         struct sunxi_engine *engine;
> +       struct device_node *remote;
>         struct sun4i_tcon *tcon;
> +       bool has_lvds;
>         int ret;
>
>         engine = sun4i_tcon_find_engine(drv, dev->of_node);
> @@ -698,6 +858,26 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>                 return ret;
>         }
>
> +       /*
> +        * This can only be made optional since we've had DT nodes
> +        * without the LVDS reset properties.
> +        *
> +        * If the property is missing, just disable LVDS, and print a
> +        * warning.
> +        */
> +       tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
> +       if (IS_ERR(tcon->lvds_rst)) {
> +               dev_err(dev, "Couldn't get our reset line\n");
> +               return PTR_ERR(tcon->lvds_rst);
> +       } else if (tcon->lvds_rst) {
> +               has_lvds = true;
> +               reset_control_reset(tcon->lvds_rst);
> +       } else {
> +               has_lvds = false;
> +               dev_warn(dev,
> +                        "Missing LVDS reset property, you should consider upgrading your DT\n");
> +       }
> +
>         ret = sun4i_tcon_init_clocks(dev, tcon);
>         if (ret) {
>                 dev_err(dev, "Couldn't init our TCON clocks\n");
> @@ -729,7 +909,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>                 goto err_free_clocks;
>         }
>
> -       ret = sun4i_rgb_init(drm, tcon);
> +       /*
> +        * If we have an LVDS panel connected to the TCON, we should
> +        * just probe the LVDS connector. Otherwise, just probe RGB as
> +        * we used to.
> +        */
> +       remote = of_graph_get_remote_node(dev->of_node, 1, 0);
> +       if (has_lvds && of_device_is_compatible(remote, "panel-lvds"))
> +               ret = sun4i_lvds_init(drm, tcon);
> +       else
> +               ret = sun4i_rgb_init(drm, tcon);
> +       of_node_put(remote);
> +
>         if (ret < 0)
>                 goto err_free_clocks;
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> index 4141fbd97ddf..382689e5396e 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> @@ -70,7 +70,21 @@
>  #define SUN4I_TCON0_TTL2_REG                   0x78
>  #define SUN4I_TCON0_TTL3_REG                   0x7c
>  #define SUN4I_TCON0_TTL4_REG                   0x80
> +
>  #define SUN4I_TCON0_LVDS_IF_REG                        0x84
> +#define SUN4I_TCON0_LVDS_IF_EN                         BIT(31)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_MASK              BIT(26)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS            (1 << 26)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS            (0 << 26)
> +#define SUN4I_TCON0_LVDS_IF_CLK_SEL_MASK               BIT(20)
> +#define SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0              (1 << 20)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_MASK               BIT(4)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL             (1 << 4)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_INV                        (0 << 4)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_MASK              GENMASK(3, 0)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL            (0xf)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_INV               (0)
> +
>  #define SUN4I_TCON0_IO_POL_REG                 0x88
>  #define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase)           ((phase & 3) << 28)
>  #define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE              BIT(25)
> @@ -131,6 +145,16 @@
>  #define SUN4I_TCON_CEU_RANGE_G_REG             0x144
>  #define SUN4I_TCON_CEU_RANGE_B_REG             0x148
>  #define SUN4I_TCON_MUX_CTRL_REG                        0x200
> +
> +#define SUN4I_TCON0_LVDS_ANA0_REG              0x220
> +#define SUN4I_TCON0_LVDS_ANA0_EN_MB                    BIT(31)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_LDO                   BIT(30)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_DRVC                  BIT(24)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_DRVD(x)               (((x) & 0xf) << 20)
> +#define SUN4I_TCON0_LVDS_ANA0_C(x)                     (((x) & 3) << 17)
> +#define SUN4I_TCON0_LVDS_ANA0_V(x)                     (((x) & 3) << 8)
> +#define SUN4I_TCON0_LVDS_ANA0_PD(x)                    (((x) & 3) << 4)
> +
>  #define SUN4I_TCON1_FILL_CTL_REG               0x300
>  #define SUN4I_TCON1_FILL_BEG0_REG              0x304
>  #define SUN4I_TCON1_FILL_END0_REG              0x308
> @@ -174,6 +198,7 @@ struct sun4i_tcon {
>
>         /* Reset control */
>         struct reset_control            *lcd_rst;
> +       struct reset_control            *lvds_rst;
>
>         struct drm_panel                *panel;
>

Regards,
Jonathan

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

* [15/23] drm/sun4i: Add LVDS support
@ 2017-10-23  2:23     ` Jonathan Liu
  0 siblings, 0 replies; 161+ messages in thread
From: Jonathan Liu @ 2017-10-23  2:23 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Maxime,

On 17 October 2017 at 20:06, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The TCON supports the LVDS interface to output to a panel or a bridge.
> Let's add support for it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/Makefile     |   1 +-
>  drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 ++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_lvds.h |  18 +++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 193 +++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.h |  25 ++++-
>  5 files changed, 419 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h
>
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index cfba2c07519c..6fee15d016ef 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -10,6 +10,7 @@ sun4i-drm-hdmi-y              += sun4i_hdmi_tmds_clk.o
>
>  sun4i-tcon-y                   += sun4i_tcon.o
>  sun4i-tcon-y                   += sun4i_rgb.o
> +sun4i-tcon-y                   += sun4i_lvds.o
>  sun4i-tcon-y                   += sun4i_dotclock.o
>  sun4i-tcon-y                   += sun4i_crtc.o
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
> new file mode 100644
> index 000000000000..635a3f505ecb
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
> @@ -0,0 +1,183 @@
> +/*
> + * Copyright (C) 2015 NextThing Co
> + * Copyright (C) 2015-2017 Free Electrons
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * 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 <linux/clk.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_of.h>
> +#include <drm/drm_panel.h>
> +
> +#include "sun4i_crtc.h"
> +#include "sun4i_tcon.h"
> +#include "sun4i_lvds.h"
> +
> +struct sun4i_lvds {
> +       struct drm_connector    connector;
> +       struct drm_encoder      encoder;
> +
> +       struct sun4i_tcon       *tcon;
> +};
> +
> +static inline struct sun4i_lvds *
> +drm_connector_to_sun4i_lvds(struct drm_connector *connector)
> +{
> +       return container_of(connector, struct sun4i_lvds,
> +                           connector);
> +}
> +
> +static inline struct sun4i_lvds *
> +drm_encoder_to_sun4i_lvds(struct drm_encoder *encoder)
> +{
> +       return container_of(encoder, struct sun4i_lvds,
> +                           encoder);
> +}
> +
> +static int sun4i_lvds_get_modes(struct drm_connector *connector)
> +{
> +       struct sun4i_lvds *lvds =
> +               drm_connector_to_sun4i_lvds(connector);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       return drm_panel_get_modes(tcon->panel);
> +}
> +
> +static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = {
> +       .get_modes      = sun4i_lvds_get_modes,
> +};
> +
> +static void
> +sun4i_lvds_connector_destroy(struct drm_connector *connector)
> +{
> +       struct sun4i_lvds *lvds = drm_connector_to_sun4i_lvds(connector);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       drm_panel_detach(tcon->panel);
> +       drm_connector_cleanup(connector);
> +}
> +
> +static const struct drm_connector_funcs sun4i_lvds_con_funcs = {
> +       .fill_modes             = drm_helper_probe_single_connector_modes,
> +       .destroy                = sun4i_lvds_connector_destroy,
> +       .reset                  = drm_atomic_helper_connector_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +       .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder)
> +{
> +       struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       DRM_DEBUG_DRIVER("Enabling LVDS output\n");
> +
> +       if (!IS_ERR(tcon->panel)) {
> +               drm_panel_prepare(tcon->panel);
> +               drm_panel_enable(tcon->panel);
> +       }
> +}
> +
> +static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder)
> +{
> +       struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
> +       struct sun4i_tcon *tcon = lvds->tcon;
> +
> +       DRM_DEBUG_DRIVER("Disabling LVDS output\n");
> +
> +       if (!IS_ERR(tcon->panel)) {
> +               drm_panel_disable(tcon->panel);
> +               drm_panel_unprepare(tcon->panel);
> +       }
> +}
> +
> +static const struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = {
> +       .disable        = sun4i_lvds_encoder_disable,
> +       .enable         = sun4i_lvds_encoder_enable,
> +};
> +
> +static const struct drm_encoder_funcs sun4i_lvds_enc_funcs = {
> +       .destroy        = drm_encoder_cleanup,
> +};
> +
> +int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon)
> +{
> +       struct drm_encoder *encoder;
> +       struct drm_bridge *bridge;
> +       struct sun4i_lvds *lvds;
> +       int ret;
> +
> +       lvds = devm_kzalloc(drm->dev, sizeof(*lvds), GFP_KERNEL);
> +       if (!lvds)
> +               return -ENOMEM;
> +       lvds->tcon = tcon;
> +       encoder = &lvds->encoder;
> +
> +       ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
> +                                         &tcon->panel, &bridge);
> +       if (ret) {
> +               dev_info(drm->dev, "No panel or bridge found... LVDS output disabled\n");
> +               return 0;
> +       }
> +
> +       drm_encoder_helper_add(&lvds->encoder,
> +                              &sun4i_lvds_enc_helper_funcs);
> +       ret = drm_encoder_init(drm,
> +                              &lvds->encoder,
> +                              &sun4i_lvds_enc_funcs,
> +                              DRM_MODE_ENCODER_LVDS,
> +                              NULL);
> +       if (ret) {
> +               dev_err(drm->dev, "Couldn't initialise the lvds encoder\n");
> +               goto err_out;
> +       }
> +
> +       /* The LVDS encoder can only work with the TCON channel 0 */
> +       lvds->encoder.possible_crtcs = BIT(drm_crtc_index(&tcon->crtc->crtc));
> +
> +       if (tcon->panel) {
> +               drm_connector_helper_add(&lvds->connector,
> +                                        &sun4i_lvds_con_helper_funcs);
> +               ret = drm_connector_init(drm, &lvds->connector,
> +                                        &sun4i_lvds_con_funcs,
> +                                        DRM_MODE_CONNECTOR_LVDS);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't initialise the lvds connector\n");
> +                       goto err_cleanup_connector;
> +               }
> +
> +               drm_mode_connector_attach_encoder(&lvds->connector,
> +                                                 &lvds->encoder);
> +
> +               ret = drm_panel_attach(tcon->panel, &lvds->connector);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't attach our panel\n");
> +                       goto err_cleanup_connector;
> +               }
> +       }
> +
> +       if (bridge) {
> +               ret = drm_bridge_attach(encoder, bridge, NULL);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't attach our bridge\n");
> +                       goto err_cleanup_connector;
> +               }
> +       }
> +
> +       return 0;
> +
> +err_cleanup_connector:
> +       drm_encoder_cleanup(&lvds->encoder);
> +err_out:
> +       return ret;
> +}
> +EXPORT_SYMBOL(sun4i_lvds_init);
> diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.h b/drivers/gpu/drm/sun4i/sun4i_lvds.h
> new file mode 100644
> index 000000000000..1b8fad4b82c3
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.h
> @@ -0,0 +1,18 @@
> +/*
> + * Copyright (C) 2015 NextThing Co
> + * Copyright (C) 2015-2017 Free Electrons
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * 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 _SUN4I_LVDS_H_
> +#define _SUN4I_LVDS_H_
> +
> +int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon);
> +
> +#endif /* _SUN4I_LVDS_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 3efa1ab045cd..6a20a467ee6d 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -31,10 +31,52 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_dotclock.h"
>  #include "sun4i_drv.h"
> +#include "sun4i_lvds.h"
>  #include "sun4i_rgb.h"
>  #include "sun4i_tcon.h"
>  #include "sunxi_engine.h"
>
> +static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
> +{
> +       struct drm_connector *connector;
> +       struct drm_connector_list_iter iter;
> +
> +       drm_connector_list_iter_begin(encoder->dev, &iter);
> +       drm_for_each_connector_iter(connector, &iter)
> +               if (connector->encoder == encoder) {
> +                       drm_connector_list_iter_end(&iter);
> +                       return connector;
> +               }
> +       drm_connector_list_iter_end(&iter);
> +
> +       return NULL;
> +}
> +
> +static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder)
> +{
> +       struct drm_connector *connector;
> +       struct drm_display_info *info;
> +
> +       connector = sun4i_tcon_get_connector(encoder);
> +       if (!connector)
> +               return -EINVAL;
> +
> +       info = &connector->display_info;
> +       if (info->num_bus_formats != 1)
> +               return -EINVAL;
> +
> +       switch (info->bus_formats[0]) {
> +       case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
> +               return 18;
> +
> +       case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
> +       case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
> +               return 24;
> +       }
> +
> +       return -EINVAL;
> +}
> +
>  static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
>                                           bool enabled)
>  {
> @@ -69,9 +111,13 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
>                            const struct drm_encoder *encoder,
>                            bool enabled)
>  {
> +       bool is_lvds = false;
>         int channel;
>
>         switch (encoder->encoder_type) {
> +       case DRM_MODE_ENCODER_LVDS:
> +               is_lvds = true;
> +               /* Fallthrough */
>         case DRM_MODE_ENCODER_NONE:
>                 channel = 0;
>                 break;
> @@ -84,10 +130,47 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
>                 return;
>         }
>
> +       if (is_lvds && !enabled)
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> +                                  SUN4I_TCON0_LVDS_IF_EN, 0);
> +
>         regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
>                            SUN4I_TCON_GCTL_TCON_ENABLE,
>                            enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
>
> +       if (is_lvds && enabled) {
> +               u8 val;
> +
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> +                                  SUN4I_TCON0_LVDS_IF_EN,
> +                                  SUN4I_TCON0_LVDS_IF_EN);
> +
> +               regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                            SUN4I_TCON0_LVDS_ANA0_C(2) |
> +                            SUN4I_TCON0_LVDS_ANA0_V(3) |
> +                            SUN4I_TCON0_LVDS_ANA0_PD(2) |
> +                            SUN4I_TCON0_LVDS_ANA0_EN_LDO);
> +               udelay(2);
> +
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_MB,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_MB);
> +               udelay(2);
> +
> +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_DRVC,
> +                                  SUN4I_TCON0_LVDS_ANA0_EN_DRVC);
> +
> +               if (sun4i_tcon_get_pixel_depth(encoder) == 18)
> +                       val = 7;
> +               else
> +                       val = 0xf;
> +
> +               regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +                                 SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
> +                                 SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val));
> +       }
> +
>         sun4i_tcon_channel_set_status(tcon, channel, enabled);
>  }
>
> @@ -170,6 +253,78 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
>                      SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
>  }
>
> +static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
> +                                     const struct drm_encoder *encoder,
> +                                     const struct drm_display_mode *mode)
> +{
> +       unsigned int bp;
> +       u8 clk_delay;
> +       u32 reg, val = 0;
> +
> +       tcon->dclk_min_div = 7;
> +       tcon->dclk_max_div = 7;
> +       sun4i_tcon0_mode_set_common(tcon, mode);
> +
> +       /* Adjust clock delay */
> +       clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
> +       regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
> +                          SUN4I_TCON0_CTL_CLK_DELAY_MASK,
> +                          SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
> +
> +       /*
> +        * This is called a backporch in the register documentation,
> +        * but it really is the back porch + hsync
> +        */
> +       bp = mode->crtc_htotal - mode->crtc_hsync_start;
> +       DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
> +                        mode->crtc_htotal, bp);
> +
> +       /* Set horizontal display timings */
> +       regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
> +                    SUN4I_TCON0_BASIC1_H_TOTAL(0x554) |
> +                    SUN4I_TCON0_BASIC1_H_BACKPORCH(0xa0));
> +
> +       /*
> +        * This is called a backporch in the register documentation,
> +        * but it really is the back porch + hsync
> +        */
> +       bp = mode->crtc_vtotal - mode->crtc_vsync_start;
> +       DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
> +                        mode->crtc_vtotal, bp);
> +
> +       /* Set vertical display timings */
> +       regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
> +                    SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
> +                    SUN4I_TCON0_BASIC2_V_BACKPORCH(0x17));
> +
> +       reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0 |
> +               SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL |
> +               SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL;
> +       if (sun4i_tcon_get_pixel_depth(encoder) == 24)
> +               reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS;
> +       else
> +               reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
> +
> +       regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
> +

> +       /* Setup the polarity of the various signals */
> +       if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
> +               val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
> +
> +       if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
> +               val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
> +
> +       regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, 0);

val is set but not written to the SUN4I_TCON0_IO_POL_REG register.

> +
> +       /* Map output pins to channel 0 */
> +       regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
> +                          SUN4I_TCON_GCTL_IOMAP_MASK,
> +                          SUN4I_TCON_GCTL_IOMAP_TCON0);
> +
> +       /* Enable the output on the pins */
> +       regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
> +}
> +
>  static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
>                                      const struct drm_display_mode *mode)
>  {
> @@ -336,6 +491,9 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
>                          const struct drm_display_mode *mode)
>  {
>         switch (encoder->encoder_type) {
> +       case DRM_MODE_ENCODER_LVDS:
> +               sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
> +               break;
>         case DRM_MODE_ENCODER_NONE:
>                 sun4i_tcon0_mode_set_rgb(tcon, mode);
>                 sun4i_tcon_set_mux(tcon, 0, encoder);
> @@ -667,7 +825,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>         struct drm_device *drm = data;
>         struct sun4i_drv *drv = drm->dev_private;
>         struct sunxi_engine *engine;
> +       struct device_node *remote;
>         struct sun4i_tcon *tcon;
> +       bool has_lvds;
>         int ret;
>
>         engine = sun4i_tcon_find_engine(drv, dev->of_node);
> @@ -698,6 +858,26 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>                 return ret;
>         }
>
> +       /*
> +        * This can only be made optional since we've had DT nodes
> +        * without the LVDS reset properties.
> +        *
> +        * If the property is missing, just disable LVDS, and print a
> +        * warning.
> +        */
> +       tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
> +       if (IS_ERR(tcon->lvds_rst)) {
> +               dev_err(dev, "Couldn't get our reset line\n");
> +               return PTR_ERR(tcon->lvds_rst);
> +       } else if (tcon->lvds_rst) {
> +               has_lvds = true;
> +               reset_control_reset(tcon->lvds_rst);
> +       } else {
> +               has_lvds = false;
> +               dev_warn(dev,
> +                        "Missing LVDS reset property, you should consider upgrading your DT\n");
> +       }
> +
>         ret = sun4i_tcon_init_clocks(dev, tcon);
>         if (ret) {
>                 dev_err(dev, "Couldn't init our TCON clocks\n");
> @@ -729,7 +909,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>                 goto err_free_clocks;
>         }
>
> -       ret = sun4i_rgb_init(drm, tcon);
> +       /*
> +        * If we have an LVDS panel connected to the TCON, we should
> +        * just probe the LVDS connector. Otherwise, just probe RGB as
> +        * we used to.
> +        */
> +       remote = of_graph_get_remote_node(dev->of_node, 1, 0);
> +       if (has_lvds && of_device_is_compatible(remote, "panel-lvds"))
> +               ret = sun4i_lvds_init(drm, tcon);
> +       else
> +               ret = sun4i_rgb_init(drm, tcon);
> +       of_node_put(remote);
> +
>         if (ret < 0)
>                 goto err_free_clocks;
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> index 4141fbd97ddf..382689e5396e 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> @@ -70,7 +70,21 @@
>  #define SUN4I_TCON0_TTL2_REG                   0x78
>  #define SUN4I_TCON0_TTL3_REG                   0x7c
>  #define SUN4I_TCON0_TTL4_REG                   0x80
> +
>  #define SUN4I_TCON0_LVDS_IF_REG                        0x84
> +#define SUN4I_TCON0_LVDS_IF_EN                         BIT(31)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_MASK              BIT(26)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS            (1 << 26)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS            (0 << 26)
> +#define SUN4I_TCON0_LVDS_IF_CLK_SEL_MASK               BIT(20)
> +#define SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0              (1 << 20)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_MASK               BIT(4)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL             (1 << 4)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_INV                        (0 << 4)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_MASK              GENMASK(3, 0)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL            (0xf)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_INV               (0)
> +
>  #define SUN4I_TCON0_IO_POL_REG                 0x88
>  #define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase)           ((phase & 3) << 28)
>  #define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE              BIT(25)
> @@ -131,6 +145,16 @@
>  #define SUN4I_TCON_CEU_RANGE_G_REG             0x144
>  #define SUN4I_TCON_CEU_RANGE_B_REG             0x148
>  #define SUN4I_TCON_MUX_CTRL_REG                        0x200
> +
> +#define SUN4I_TCON0_LVDS_ANA0_REG              0x220
> +#define SUN4I_TCON0_LVDS_ANA0_EN_MB                    BIT(31)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_LDO                   BIT(30)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_DRVC                  BIT(24)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_DRVD(x)               (((x) & 0xf) << 20)
> +#define SUN4I_TCON0_LVDS_ANA0_C(x)                     (((x) & 3) << 17)
> +#define SUN4I_TCON0_LVDS_ANA0_V(x)                     (((x) & 3) << 8)
> +#define SUN4I_TCON0_LVDS_ANA0_PD(x)                    (((x) & 3) << 4)
> +
>  #define SUN4I_TCON1_FILL_CTL_REG               0x300
>  #define SUN4I_TCON1_FILL_BEG0_REG              0x304
>  #define SUN4I_TCON1_FILL_END0_REG              0x308
> @@ -174,6 +198,7 @@ struct sun4i_tcon {
>
>         /* Reset control */
>         struct reset_control            *lcd_rst;
> +       struct reset_control            *lvds_rst;
>
>         struct drm_panel                *panel;
>

Regards,
Jonathan

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

* Re: [PATCH 15/23] drm/sun4i: Add LVDS support
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-23 20:17     ` Priit Laes
  -1 siblings, 0 replies; 161+ messages in thread
From: Priit Laes @ 2017-10-23 20:17 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, dri-devel,
	linux-kernel, Mark Rutland, Rob Herring, linux-arm-kernel,
	linux-clk, icenowy, Thomas Petazzoni, Quentin Schulz,
	Mylene Josserand

On Tue, Oct 17, 2017 at 11:06:22AM +0200, Maxime Ripard wrote:
> The TCON supports the LVDS interface to output to a panel or a bridge.
> Let's add support for it.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/Makefile     |   1 +-
>  drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 ++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_lvds.h |  18 +++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 193 +++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.h |  25 ++++-
>  5 files changed, 419 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h
> 
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index cfba2c07519c..6fee15d016ef 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -10,6 +10,7 @@ sun4i-drm-hdmi-y		+= sun4i_hdmi_tmds_clk.o
>  
>  sun4i-tcon-y			+= sun4i_tcon.o
>  sun4i-tcon-y			+= sun4i_rgb.o
> +sun4i-tcon-y			+= sun4i_lvds.o
>  sun4i-tcon-y			+= sun4i_dotclock.o
>  sun4i-tcon-y			+= sun4i_crtc.o

[...]

> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 3efa1ab045cd..6a20a467ee6d 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -31,10 +31,52 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_dotclock.h"
>  #include "sun4i_drv.h"
> +#include "sun4i_lvds.h"
>  #include "sun4i_rgb.h"
>  #include "sun4i_tcon.h"
>  #include "sunxi_engine.h"

[...]

>  static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
>  					  bool enabled)
>  {
> @@ -69,9 +111,13 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
>  			   const struct drm_encoder *encoder,
>  			   bool enabled)
>  {
> +	bool is_lvds = false;
>  	int channel;
>  
>  	switch (encoder->encoder_type) {
> +	case DRM_MODE_ENCODER_LVDS:
> +		is_lvds = true;
> +		/* Fallthrough */
>  	case DRM_MODE_ENCODER_NONE:
>  		channel = 0;
>  		break;
> @@ -84,10 +130,47 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
>  		return;
>  	}
>  
> +	if (is_lvds && !enabled)
> +		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> +				   SUN4I_TCON0_LVDS_IF_EN, 0);
> +
>  	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
>  			   SUN4I_TCON_GCTL_TCON_ENABLE,
>  			   enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
>  
> +	if (is_lvds && enabled) {
> +		u8 val;
> +
> +		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> +				   SUN4I_TCON0_LVDS_IF_EN,
> +				   SUN4I_TCON0_LVDS_IF_EN);
> +

OK, this part below seems to be quite A83T specific, as A10/A20
has different register bits.

For example ANA0 bits:

A10:
#define SUN4I_TCON0_LVDS_ANA0_EN_MB	BIT(22)

But here it is:
#define SUN4I_TCON0_LVDS_ANA0_EN_MB	BIT(31)


Also, the programming sequence for A10/A20 (from u-boot),
and my initial patchset. (I haven't yet had time to get output working
on top of your stuff).

1. Set ANA0 (0x220) 
2. Set ANA1 
3. Update ANA1

regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
             SUN4I_TCON0_LVDS_ANA0_CK_EN |
             SUN4I_TCON0_LVDS_ANA0_REG_V |
             SUN4I_TCON0_LVDS_ANA0_REG_C |
             SUN4I_TCON0_LVDS_ANA0_EN_MB |
             SUN4I_TCON0_LVDS_ANA0_PD |
             SUN4I_TCON0_LVDS_ANA0_DCHS);

udelay(2000);

regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA1_REG,
             SUN4I_TCON0_LVDS_ANA1_INIT);

udelay(1000);

regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA1_REG,
                   SUN4I_TCON0_LVDS_ANA1_UPDATE,
                   SUN4I_TCON0_LVDS_ANA1_UPDATE);


> +		regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +			     SUN4I_TCON0_LVDS_ANA0_C(2) |
> +			     SUN4I_TCON0_LVDS_ANA0_V(3) |
> +			     SUN4I_TCON0_LVDS_ANA0_PD(2) |
> +			     SUN4I_TCON0_LVDS_ANA0_EN_LDO);
> +		udelay(2);
> +
> +		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +				   SUN4I_TCON0_LVDS_ANA0_EN_MB,
> +				   SUN4I_TCON0_LVDS_ANA0_EN_MB);
> +		udelay(2);
> +
> +		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +				   SUN4I_TCON0_LVDS_ANA0_EN_DRVC,
> +				   SUN4I_TCON0_LVDS_ANA0_EN_DRVC);
> +
> +		if (sun4i_tcon_get_pixel_depth(encoder) == 18)
> +			val = 7;
> +		else
> +			val = 0xf;
> +
> +		regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +				  SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
> +				  SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val));
> +	}
> +
>  	sun4i_tcon_channel_set_status(tcon, channel, enabled);
>  }
>  
> @@ -170,6 +253,78 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
>  		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
>  }
>  
> +static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
> +				      const struct drm_encoder *encoder,
> +				      const struct drm_display_mode *mode)
> +{
> +	unsigned int bp;
> +	u8 clk_delay;
> +	u32 reg, val = 0;
> +
> +	tcon->dclk_min_div = 7;
> +	tcon->dclk_max_div = 7;
> +	sun4i_tcon0_mode_set_common(tcon, mode);
> +
> +	/* Adjust clock delay */
> +	clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
> +	regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
> +			   SUN4I_TCON0_CTL_CLK_DELAY_MASK,
> +			   SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
> +
> +	/*
> +	 * This is called a backporch in the register documentation,
> +	 * but it really is the back porch + hsync
> +	 */
> +	bp = mode->crtc_htotal - mode->crtc_hsync_start;
> +	DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
> +			 mode->crtc_htotal, bp);
> +
> +	/* Set horizontal display timings */
> +	regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
> +		     SUN4I_TCON0_BASIC1_H_TOTAL(0x554) |
> +		     SUN4I_TCON0_BASIC1_H_BACKPORCH(0xa0));
> +
> +	/*
> +	 * This is called a backporch in the register documentation,
> +	 * but it really is the back porch + hsync
> +	 */
> +	bp = mode->crtc_vtotal - mode->crtc_vsync_start;
> +	DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
> +			 mode->crtc_vtotal, bp);
> +
> +	/* Set vertical display timings */
> +	regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
> +		     SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
> +		     SUN4I_TCON0_BASIC2_V_BACKPORCH(0x17));
> +
> +	reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0 |
> +		SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL |
> +		SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL;
> +	if (sun4i_tcon_get_pixel_depth(encoder) == 24)
> +		reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS;
> +	else
> +		reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
> +
> +	regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
> +
> +	/* Setup the polarity of the various signals */
> +	if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
> +		val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
> +
> +	if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
> +		val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
> +
> +	regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, 0);
> +
> +	/* Map output pins to channel 0 */
> +	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
> +			   SUN4I_TCON_GCTL_IOMAP_MASK,
> +			   SUN4I_TCON_GCTL_IOMAP_TCON0);
> +
> +	/* Enable the output on the pins */
> +	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
> +}
> +
>  static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
>  				     const struct drm_display_mode *mode)
>  {
> @@ -336,6 +491,9 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
>  			 const struct drm_display_mode *mode)
>  {
>  	switch (encoder->encoder_type) {
> +	case DRM_MODE_ENCODER_LVDS:
> +		sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
> +		break;
>  	case DRM_MODE_ENCODER_NONE:
>  		sun4i_tcon0_mode_set_rgb(tcon, mode);
>  		sun4i_tcon_set_mux(tcon, 0, encoder);
> @@ -667,7 +825,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>  	struct drm_device *drm = data;
>  	struct sun4i_drv *drv = drm->dev_private;
>  	struct sunxi_engine *engine;
> +	struct device_node *remote;
>  	struct sun4i_tcon *tcon;
> +	bool has_lvds;
>  	int ret;
>  
>  	engine = sun4i_tcon_find_engine(drv, dev->of_node);
> @@ -698,6 +858,26 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>  		return ret;
>  	}
>  
> +	/*
> +	 * This can only be made optional since we've had DT nodes
> +	 * without the LVDS reset properties.
> +	 *
> +	 * If the property is missing, just disable LVDS, and print a
> +	 * warning.
> +	 */
> +	tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
> +	if (IS_ERR(tcon->lvds_rst)) {
> +		dev_err(dev, "Couldn't get our reset line\n");
> +		return PTR_ERR(tcon->lvds_rst);
> +	} else if (tcon->lvds_rst) {
> +		has_lvds = true;
> +		reset_control_reset(tcon->lvds_rst);
> +	} else {
> +		has_lvds = false;
> +		dev_warn(dev,
> +			 "Missing LVDS reset property, you should consider upgrading your DT\n");
> +	}
> +
>  	ret = sun4i_tcon_init_clocks(dev, tcon);
>  	if (ret) {
>  		dev_err(dev, "Couldn't init our TCON clocks\n");
> @@ -729,7 +909,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>  		goto err_free_clocks;
>  	}
>  
> -	ret = sun4i_rgb_init(drm, tcon);
> +	/*
> +	 * If we have an LVDS panel connected to the TCON, we should
> +	 * just probe the LVDS connector. Otherwise, just probe RGB as
> +	 * we used to.
> +	 */
> +	remote = of_graph_get_remote_node(dev->of_node, 1, 0);
> +	if (has_lvds && of_device_is_compatible(remote, "panel-lvds"))
> +		ret = sun4i_lvds_init(drm, tcon);
> +	else
> +		ret = sun4i_rgb_init(drm, tcon);
> +	of_node_put(remote);
> +
>  	if (ret < 0)
>  		goto err_free_clocks;
>  
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> index 4141fbd97ddf..382689e5396e 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> @@ -70,7 +70,21 @@
>  #define SUN4I_TCON0_TTL2_REG			0x78
>  #define SUN4I_TCON0_TTL3_REG			0x7c
>  #define SUN4I_TCON0_TTL4_REG			0x80
> +
>  #define SUN4I_TCON0_LVDS_IF_REG			0x84
> +#define SUN4I_TCON0_LVDS_IF_EN				BIT(31)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_MASK		BIT(26)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS		(1 << 26)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS		(0 << 26)
> +#define SUN4I_TCON0_LVDS_IF_CLK_SEL_MASK		BIT(20)
> +#define SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0		(1 << 20)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_MASK		BIT(4)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL		(1 << 4)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_INV			(0 << 4)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_MASK		GENMASK(3, 0)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL		(0xf)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_INV		(0)
> +
>  #define SUN4I_TCON0_IO_POL_REG			0x88
>  #define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase)		((phase & 3) << 28)
>  #define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE		BIT(25)
> @@ -131,6 +145,16 @@
>  #define SUN4I_TCON_CEU_RANGE_G_REG		0x144
>  #define SUN4I_TCON_CEU_RANGE_B_REG		0x148
>  #define SUN4I_TCON_MUX_CTRL_REG			0x200
> +
> +#define SUN4I_TCON0_LVDS_ANA0_REG		0x220

Although register address is same as A10/A20, its contents
seem to be different here...

> +#define SUN4I_TCON0_LVDS_ANA0_EN_MB			BIT(31)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_LDO			BIT(30)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_DRVC			BIT(24)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_DRVD(x)		(((x) & 0xf) << 20)
> +#define SUN4I_TCON0_LVDS_ANA0_C(x)			(((x) & 3) << 17)
> +#define SUN4I_TCON0_LVDS_ANA0_V(x)			(((x) & 3) << 8)
> +#define SUN4I_TCON0_LVDS_ANA0_PD(x)			(((x) & 3) << 4)
> +
>  #define SUN4I_TCON1_FILL_CTL_REG		0x300
>  #define SUN4I_TCON1_FILL_BEG0_REG		0x304
>  #define SUN4I_TCON1_FILL_END0_REG		0x308
> @@ -174,6 +198,7 @@ struct sun4i_tcon {
>  
>  	/* Reset control */
>  	struct reset_control		*lcd_rst;
> +	struct reset_control		*lvds_rst;
>  
>  	struct drm_panel		*panel;
>  
> -- 
> git-series 0.9.1

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

* [PATCH 15/23] drm/sun4i: Add LVDS support
@ 2017-10-23 20:17     ` Priit Laes
  0 siblings, 0 replies; 161+ messages in thread
From: Priit Laes @ 2017-10-23 20:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 11:06:22AM +0200, Maxime Ripard wrote:
> The TCON supports the LVDS interface to output to a panel or a bridge.
> Let's add support for it.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/Makefile     |   1 +-
>  drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 ++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_lvds.h |  18 +++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 193 +++++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_tcon.h |  25 ++++-
>  5 files changed, 419 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h
> 
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index cfba2c07519c..6fee15d016ef 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -10,6 +10,7 @@ sun4i-drm-hdmi-y		+= sun4i_hdmi_tmds_clk.o
>  
>  sun4i-tcon-y			+= sun4i_tcon.o
>  sun4i-tcon-y			+= sun4i_rgb.o
> +sun4i-tcon-y			+= sun4i_lvds.o
>  sun4i-tcon-y			+= sun4i_dotclock.o
>  sun4i-tcon-y			+= sun4i_crtc.o

[...]

> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 3efa1ab045cd..6a20a467ee6d 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -31,10 +31,52 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_dotclock.h"
>  #include "sun4i_drv.h"
> +#include "sun4i_lvds.h"
>  #include "sun4i_rgb.h"
>  #include "sun4i_tcon.h"
>  #include "sunxi_engine.h"

[...]

>  static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
>  					  bool enabled)
>  {
> @@ -69,9 +111,13 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
>  			   const struct drm_encoder *encoder,
>  			   bool enabled)
>  {
> +	bool is_lvds = false;
>  	int channel;
>  
>  	switch (encoder->encoder_type) {
> +	case DRM_MODE_ENCODER_LVDS:
> +		is_lvds = true;
> +		/* Fallthrough */
>  	case DRM_MODE_ENCODER_NONE:
>  		channel = 0;
>  		break;
> @@ -84,10 +130,47 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
>  		return;
>  	}
>  
> +	if (is_lvds && !enabled)
> +		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> +				   SUN4I_TCON0_LVDS_IF_EN, 0);
> +
>  	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
>  			   SUN4I_TCON_GCTL_TCON_ENABLE,
>  			   enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
>  
> +	if (is_lvds && enabled) {
> +		u8 val;
> +
> +		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> +				   SUN4I_TCON0_LVDS_IF_EN,
> +				   SUN4I_TCON0_LVDS_IF_EN);
> +

OK, this part below seems to be quite A83T specific, as A10/A20
has different register bits.

For example ANA0 bits:

A10:
#define SUN4I_TCON0_LVDS_ANA0_EN_MB	BIT(22)

But here it is:
#define SUN4I_TCON0_LVDS_ANA0_EN_MB	BIT(31)


Also, the programming sequence for A10/A20 (from u-boot),
and my initial patchset. (I haven't yet had time to get output working
on top of your stuff).

1. Set ANA0 (0x220) 
2. Set ANA1 
3. Update ANA1

regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
             SUN4I_TCON0_LVDS_ANA0_CK_EN |
             SUN4I_TCON0_LVDS_ANA0_REG_V |
             SUN4I_TCON0_LVDS_ANA0_REG_C |
             SUN4I_TCON0_LVDS_ANA0_EN_MB |
             SUN4I_TCON0_LVDS_ANA0_PD |
             SUN4I_TCON0_LVDS_ANA0_DCHS);

udelay(2000);

regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA1_REG,
             SUN4I_TCON0_LVDS_ANA1_INIT);

udelay(1000);

regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA1_REG,
                   SUN4I_TCON0_LVDS_ANA1_UPDATE,
                   SUN4I_TCON0_LVDS_ANA1_UPDATE);


> +		regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +			     SUN4I_TCON0_LVDS_ANA0_C(2) |
> +			     SUN4I_TCON0_LVDS_ANA0_V(3) |
> +			     SUN4I_TCON0_LVDS_ANA0_PD(2) |
> +			     SUN4I_TCON0_LVDS_ANA0_EN_LDO);
> +		udelay(2);
> +
> +		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +				   SUN4I_TCON0_LVDS_ANA0_EN_MB,
> +				   SUN4I_TCON0_LVDS_ANA0_EN_MB);
> +		udelay(2);
> +
> +		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +				   SUN4I_TCON0_LVDS_ANA0_EN_DRVC,
> +				   SUN4I_TCON0_LVDS_ANA0_EN_DRVC);
> +
> +		if (sun4i_tcon_get_pixel_depth(encoder) == 18)
> +			val = 7;
> +		else
> +			val = 0xf;
> +
> +		regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> +				  SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
> +				  SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val));
> +	}
> +
>  	sun4i_tcon_channel_set_status(tcon, channel, enabled);
>  }
>  
> @@ -170,6 +253,78 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
>  		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
>  }
>  
> +static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
> +				      const struct drm_encoder *encoder,
> +				      const struct drm_display_mode *mode)
> +{
> +	unsigned int bp;
> +	u8 clk_delay;
> +	u32 reg, val = 0;
> +
> +	tcon->dclk_min_div = 7;
> +	tcon->dclk_max_div = 7;
> +	sun4i_tcon0_mode_set_common(tcon, mode);
> +
> +	/* Adjust clock delay */
> +	clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
> +	regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
> +			   SUN4I_TCON0_CTL_CLK_DELAY_MASK,
> +			   SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
> +
> +	/*
> +	 * This is called a backporch in the register documentation,
> +	 * but it really is the back porch + hsync
> +	 */
> +	bp = mode->crtc_htotal - mode->crtc_hsync_start;
> +	DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
> +			 mode->crtc_htotal, bp);
> +
> +	/* Set horizontal display timings */
> +	regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
> +		     SUN4I_TCON0_BASIC1_H_TOTAL(0x554) |
> +		     SUN4I_TCON0_BASIC1_H_BACKPORCH(0xa0));
> +
> +	/*
> +	 * This is called a backporch in the register documentation,
> +	 * but it really is the back porch + hsync
> +	 */
> +	bp = mode->crtc_vtotal - mode->crtc_vsync_start;
> +	DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
> +			 mode->crtc_vtotal, bp);
> +
> +	/* Set vertical display timings */
> +	regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
> +		     SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
> +		     SUN4I_TCON0_BASIC2_V_BACKPORCH(0x17));
> +
> +	reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0 |
> +		SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL |
> +		SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL;
> +	if (sun4i_tcon_get_pixel_depth(encoder) == 24)
> +		reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS;
> +	else
> +		reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
> +
> +	regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
> +
> +	/* Setup the polarity of the various signals */
> +	if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
> +		val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
> +
> +	if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
> +		val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
> +
> +	regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, 0);
> +
> +	/* Map output pins to channel 0 */
> +	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
> +			   SUN4I_TCON_GCTL_IOMAP_MASK,
> +			   SUN4I_TCON_GCTL_IOMAP_TCON0);
> +
> +	/* Enable the output on the pins */
> +	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
> +}
> +
>  static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
>  				     const struct drm_display_mode *mode)
>  {
> @@ -336,6 +491,9 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
>  			 const struct drm_display_mode *mode)
>  {
>  	switch (encoder->encoder_type) {
> +	case DRM_MODE_ENCODER_LVDS:
> +		sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
> +		break;
>  	case DRM_MODE_ENCODER_NONE:
>  		sun4i_tcon0_mode_set_rgb(tcon, mode);
>  		sun4i_tcon_set_mux(tcon, 0, encoder);
> @@ -667,7 +825,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>  	struct drm_device *drm = data;
>  	struct sun4i_drv *drv = drm->dev_private;
>  	struct sunxi_engine *engine;
> +	struct device_node *remote;
>  	struct sun4i_tcon *tcon;
> +	bool has_lvds;
>  	int ret;
>  
>  	engine = sun4i_tcon_find_engine(drv, dev->of_node);
> @@ -698,6 +858,26 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>  		return ret;
>  	}
>  
> +	/*
> +	 * This can only be made optional since we've had DT nodes
> +	 * without the LVDS reset properties.
> +	 *
> +	 * If the property is missing, just disable LVDS, and print a
> +	 * warning.
> +	 */
> +	tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
> +	if (IS_ERR(tcon->lvds_rst)) {
> +		dev_err(dev, "Couldn't get our reset line\n");
> +		return PTR_ERR(tcon->lvds_rst);
> +	} else if (tcon->lvds_rst) {
> +		has_lvds = true;
> +		reset_control_reset(tcon->lvds_rst);
> +	} else {
> +		has_lvds = false;
> +		dev_warn(dev,
> +			 "Missing LVDS reset property, you should consider upgrading your DT\n");
> +	}
> +
>  	ret = sun4i_tcon_init_clocks(dev, tcon);
>  	if (ret) {
>  		dev_err(dev, "Couldn't init our TCON clocks\n");
> @@ -729,7 +909,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>  		goto err_free_clocks;
>  	}
>  
> -	ret = sun4i_rgb_init(drm, tcon);
> +	/*
> +	 * If we have an LVDS panel connected to the TCON, we should
> +	 * just probe the LVDS connector. Otherwise, just probe RGB as
> +	 * we used to.
> +	 */
> +	remote = of_graph_get_remote_node(dev->of_node, 1, 0);
> +	if (has_lvds && of_device_is_compatible(remote, "panel-lvds"))
> +		ret = sun4i_lvds_init(drm, tcon);
> +	else
> +		ret = sun4i_rgb_init(drm, tcon);
> +	of_node_put(remote);
> +
>  	if (ret < 0)
>  		goto err_free_clocks;
>  
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> index 4141fbd97ddf..382689e5396e 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> @@ -70,7 +70,21 @@
>  #define SUN4I_TCON0_TTL2_REG			0x78
>  #define SUN4I_TCON0_TTL3_REG			0x7c
>  #define SUN4I_TCON0_TTL4_REG			0x80
> +
>  #define SUN4I_TCON0_LVDS_IF_REG			0x84
> +#define SUN4I_TCON0_LVDS_IF_EN				BIT(31)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_MASK		BIT(26)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS		(1 << 26)
> +#define SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS		(0 << 26)
> +#define SUN4I_TCON0_LVDS_IF_CLK_SEL_MASK		BIT(20)
> +#define SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0		(1 << 20)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_MASK		BIT(4)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL		(1 << 4)
> +#define SUN4I_TCON0_LVDS_IF_CLK_POL_INV			(0 << 4)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_MASK		GENMASK(3, 0)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL		(0xf)
> +#define SUN4I_TCON0_LVDS_IF_DATA_POL_INV		(0)
> +
>  #define SUN4I_TCON0_IO_POL_REG			0x88
>  #define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase)		((phase & 3) << 28)
>  #define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE		BIT(25)
> @@ -131,6 +145,16 @@
>  #define SUN4I_TCON_CEU_RANGE_G_REG		0x144
>  #define SUN4I_TCON_CEU_RANGE_B_REG		0x148
>  #define SUN4I_TCON_MUX_CTRL_REG			0x200
> +
> +#define SUN4I_TCON0_LVDS_ANA0_REG		0x220

Although register address is same as A10/A20, its contents
seem to be different here...

> +#define SUN4I_TCON0_LVDS_ANA0_EN_MB			BIT(31)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_LDO			BIT(30)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_DRVC			BIT(24)
> +#define SUN4I_TCON0_LVDS_ANA0_EN_DRVD(x)		(((x) & 0xf) << 20)
> +#define SUN4I_TCON0_LVDS_ANA0_C(x)			(((x) & 3) << 17)
> +#define SUN4I_TCON0_LVDS_ANA0_V(x)			(((x) & 3) << 8)
> +#define SUN4I_TCON0_LVDS_ANA0_PD(x)			(((x) & 3) << 4)
> +
>  #define SUN4I_TCON1_FILL_CTL_REG		0x300
>  #define SUN4I_TCON1_FILL_BEG0_REG		0x304
>  #define SUN4I_TCON1_FILL_END0_REG		0x308
> @@ -174,6 +198,7 @@ struct sun4i_tcon {
>  
>  	/* Reset control */
>  	struct reset_control		*lcd_rst;
> +	struct reset_control		*lvds_rst;
>  
>  	struct drm_panel		*panel;
>  
> -- 
> git-series 0.9.1

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

* Re: [14/23] drm/sun4i: Create minimal multipliers and dividers
  2017-10-17  9:06   ` Maxime Ripard
@ 2017-10-24  2:12     ` Jonathan Liu
  -1 siblings, 0 replies; 161+ messages in thread
From: Jonathan Liu @ 2017-10-24  2:12 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Daniel Vetter, David Airlie, Chen-Yu Tsai, Mark Rutland,
	Thomas Petazzoni, Priit Laes, linux-kernel, dri-devel,
	Quentin Schulz, Rob Herring, Mylene Josserand, linux-clk,
	linux-arm-kernel, icenowy

Hi Maxime,

On 17 October 2017 at 20:06, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The various outputs the TCON can provide have different constraints on the
> dotclock divider. Let's make them configurable by the various mode_set
> functions.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> ---
>  drivers/gpu/drm/sun4i/sun4i_dotclock.c | 10 +++++++---
>  drivers/gpu/drm/sun4i/sun4i_tcon.c     |  2 ++
>  drivers/gpu/drm/sun4i/sun4i_tcon.h     |  2 ++
>  3 files changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
> index d401156490f3..023f39bda633 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
> @@ -17,8 +17,9 @@
>  #include "sun4i_dotclock.h"
>
>  struct sun4i_dclk {
> -       struct clk_hw   hw;
> -       struct regmap   *regmap;
> +       struct clk_hw           hw;
> +       struct regmap           *regmap;
> +       struct sun4i_tcon       *tcon;
>  };
>
>  static inline struct sun4i_dclk *hw_to_dclk(struct clk_hw *hw)
> @@ -73,11 +74,13 @@ static unsigned long sun4i_dclk_recalc_rate(struct clk_hw *hw,
>  static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
>                                   unsigned long *parent_rate)
>  {
> +       struct sun4i_dclk *dclk = hw_to_dclk(hw);
> +       struct sun4i_tcon *tcon = dclk->tcon;
>         unsigned long best_parent = 0;
>         u8 best_div = 1;
>         int i;
>
> -       for (i = 6; i <= 127; i++) {
> +       for (i = tcon->dclk_min_div; i <= tcon->dclk_max_div; i++) {
>                 unsigned long ideal = rate * i;
>                 unsigned long rounded;
>
> @@ -167,6 +170,7 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
>         dclk = devm_kzalloc(dev, sizeof(*dclk), GFP_KERNEL);
>         if (!dclk)
>                 return -ENOMEM;
> +       dclk->tcon = tcon;
>
>         init.name = clk_name;
>         init.ops = &sun4i_dclk_ops;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index f69bcdf11cb8..3efa1ab045cd 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -177,6 +177,8 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
>         u8 clk_delay;
>         u32 val = 0;
>
> +       tcon->dclk_min_div = 6;
> +       tcon->dclk_max_div = 127;
>         sun4i_tcon0_mode_set_common(tcon, mode);
>
>         /* Adjust clock delay */
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> index f61bf6d83b4a..4141fbd97ddf 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> @@ -169,6 +169,8 @@ struct sun4i_tcon {
>
>         /* Pixel clock */
>         struct clk                      *dclk;
> +       u8                              dclk_max_div;
> +       u8                              dclk_min_div;
>
>         /* Reset control */
>         struct reset_control            *lcd_rst;

I have 4.3" RGB LCD enabled on sun7i-a20-olinuxino-lime and hdmi
disabled. After applying this patch the LCD no longer turns on.
If I add some debug statements to sun4i_dclk_recalc_rate, it shows
tcon->dclk_min_div and tcon->dclk_max_div are both 0.

Regards,
Jonathan

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

* [14/23] drm/sun4i: Create minimal multipliers and dividers
@ 2017-10-24  2:12     ` Jonathan Liu
  0 siblings, 0 replies; 161+ messages in thread
From: Jonathan Liu @ 2017-10-24  2:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Maxime,

On 17 October 2017 at 20:06, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The various outputs the TCON can provide have different constraints on the
> dotclock divider. Let's make them configurable by the various mode_set
> functions.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> ---
>  drivers/gpu/drm/sun4i/sun4i_dotclock.c | 10 +++++++---
>  drivers/gpu/drm/sun4i/sun4i_tcon.c     |  2 ++
>  drivers/gpu/drm/sun4i/sun4i_tcon.h     |  2 ++
>  3 files changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
> index d401156490f3..023f39bda633 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
> @@ -17,8 +17,9 @@
>  #include "sun4i_dotclock.h"
>
>  struct sun4i_dclk {
> -       struct clk_hw   hw;
> -       struct regmap   *regmap;
> +       struct clk_hw           hw;
> +       struct regmap           *regmap;
> +       struct sun4i_tcon       *tcon;
>  };
>
>  static inline struct sun4i_dclk *hw_to_dclk(struct clk_hw *hw)
> @@ -73,11 +74,13 @@ static unsigned long sun4i_dclk_recalc_rate(struct clk_hw *hw,
>  static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
>                                   unsigned long *parent_rate)
>  {
> +       struct sun4i_dclk *dclk = hw_to_dclk(hw);
> +       struct sun4i_tcon *tcon = dclk->tcon;
>         unsigned long best_parent = 0;
>         u8 best_div = 1;
>         int i;
>
> -       for (i = 6; i <= 127; i++) {
> +       for (i = tcon->dclk_min_div; i <= tcon->dclk_max_div; i++) {
>                 unsigned long ideal = rate * i;
>                 unsigned long rounded;
>
> @@ -167,6 +170,7 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
>         dclk = devm_kzalloc(dev, sizeof(*dclk), GFP_KERNEL);
>         if (!dclk)
>                 return -ENOMEM;
> +       dclk->tcon = tcon;
>
>         init.name = clk_name;
>         init.ops = &sun4i_dclk_ops;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index f69bcdf11cb8..3efa1ab045cd 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -177,6 +177,8 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
>         u8 clk_delay;
>         u32 val = 0;
>
> +       tcon->dclk_min_div = 6;
> +       tcon->dclk_max_div = 127;
>         sun4i_tcon0_mode_set_common(tcon, mode);
>
>         /* Adjust clock delay */
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> index f61bf6d83b4a..4141fbd97ddf 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> @@ -169,6 +169,8 @@ struct sun4i_tcon {
>
>         /* Pixel clock */
>         struct clk                      *dclk;
> +       u8                              dclk_max_div;
> +       u8                              dclk_min_div;
>
>         /* Reset control */
>         struct reset_control            *lcd_rst;

I have 4.3" RGB LCD enabled on sun7i-a20-olinuxino-lime and hdmi
disabled. After applying this patch the LCD no longer turns on.
If I add some debug statements to sun4i_dclk_recalc_rate, it shows
tcon->dclk_min_div and tcon->dclk_max_div are both 0.

Regards,
Jonathan

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

end of thread, other threads:[~2017-10-24  2:12 UTC | newest]

Thread overview: 161+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-17  9:06 [PATCH 00/23] drm/sun4i: Add A83t LVDS support Maxime Ripard
2017-10-17  9:06 ` Maxime Ripard
2017-10-17  9:06 ` Maxime Ripard
2017-10-17  9:06 ` [PATCH 01/23] drm/sun4i: Implement endpoint parsing using kfifo Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:19   ` Chen-Yu Tsai
2017-10-17  9:19     ` Chen-Yu Tsai
2017-10-17  9:19     ` Chen-Yu Tsai
2017-10-17 14:29     ` Maxime Ripard
2017-10-17 14:29       ` Maxime Ripard
2017-10-17  9:06 ` [PATCH 02/23] drm/sun4i: Realign Makefile padding and reorder it Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:14   ` Chen-Yu Tsai
2017-10-17  9:14     ` Chen-Yu Tsai
2017-10-17  9:14     ` Chen-Yu Tsai
2017-10-17 14:34     ` Maxime Ripard
2017-10-17 14:34       ` Maxime Ripard
2017-10-17  9:06 ` [PATCH 03/23] drm/sun4i: tcon: Make tcon_set_mux mode argument const Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:21   ` Chen-Yu Tsai
2017-10-17  9:21     ` Chen-Yu Tsai
2017-10-17  9:21     ` Chen-Yu Tsai
2017-10-17 14:35     ` Maxime Ripard
2017-10-17 14:35       ` Maxime Ripard
2017-10-17  9:06 ` [PATCH 04/23] drm/sun4i: tcon: Make tcon_get_clk_delay " Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:22   ` Chen-Yu Tsai
2017-10-17  9:22     ` Chen-Yu Tsai
2017-10-17  9:22     ` Chen-Yu Tsai
2017-10-17 14:37     ` Maxime Ripard
2017-10-17 14:37       ` Maxime Ripard
2017-10-17  9:06 ` [PATCH 05/23] drm/sun4i: tcon: Don't rely on encoders to enable the TCON Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:28   ` Chen-Yu Tsai
2017-10-17  9:28     ` Chen-Yu Tsai
2017-10-17  9:28     ` Chen-Yu Tsai
2017-10-17 14:38     ` Maxime Ripard
2017-10-17 14:38       ` Maxime Ripard
2017-10-17 14:38       ` Maxime Ripard
2017-10-17  9:06 ` [PATCH 06/23] drm/sun4i: tcon: Don't rely on encoders to set the TCON mode Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:56   ` Chen-Yu Tsai
2017-10-17  9:56     ` Chen-Yu Tsai
2017-10-17  9:56     ` Chen-Yu Tsai
2017-10-17 14:39     ` Maxime Ripard
2017-10-17 14:39       ` Maxime Ripard
2017-10-17 14:39       ` Maxime Ripard
2017-10-17  9:06 ` [PATCH 07/23] drm/sun4i: tcon: Move out the tcon0 common setup Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 10:00   ` Chen-Yu Tsai
2017-10-17 10:00     ` Chen-Yu Tsai
2017-10-17  9:06 ` [PATCH 08/23] dt-bindings: panel: lvds: Document power-supply property Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 10:01   ` Chen-Yu Tsai
2017-10-17 10:01     ` Chen-Yu Tsai
2017-10-17 10:01     ` Chen-Yu Tsai
2017-10-17  9:06 ` [PATCH 09/23] drm/panel: lvds: Add support for the " Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 10:02   ` Chen-Yu Tsai
2017-10-17 10:02     ` Chen-Yu Tsai
2017-10-17 10:02     ` Chen-Yu Tsai
2017-10-17  9:06 ` [PATCH 10/23] clk: sunxi-ng: Add A83T display clocks Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 10:04   ` Chen-Yu Tsai
2017-10-17 10:04     ` Chen-Yu Tsai
2017-10-17  9:06 ` [PATCH 11/23] drm/sun4i: Rename layers to UI planes Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 10:09   ` Chen-Yu Tsai
2017-10-17 10:09     ` Chen-Yu Tsai
2017-10-17  9:06 ` [PATCH 12/23] drm/sun4i: sun8i: properly support UI channels Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 12:17   ` icenowy
2017-10-17 12:17     ` icenowy at aosc.io
2017-10-17  9:06 ` [PATCH 13/23] drm/sun4i: Reorder and document DE2 mixer registers Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06 ` [PATCH 14/23] drm/sun4i: Create minimal multipliers and dividers Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 10:15   ` Chen-Yu Tsai
2017-10-17 10:15     ` Chen-Yu Tsai
2017-10-24  2:12   ` [14/23] " Jonathan Liu
2017-10-24  2:12     ` Jonathan Liu
2017-10-17  9:06 ` [PATCH 15/23] drm/sun4i: Add LVDS support Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 11:51   ` Chen-Yu Tsai
2017-10-17 11:51     ` Chen-Yu Tsai
2017-10-22 18:52   ` Priit Laes
2017-10-22 18:52     ` Priit Laes
2017-10-23  2:23   ` [15/23] " Jonathan Liu
2017-10-23  2:23     ` Jonathan Liu
2017-10-23 20:17   ` [PATCH 15/23] " Priit Laes
2017-10-23 20:17     ` Priit Laes
2017-10-17  9:06 ` [PATCH 16/23] drm/sun4i: Add A83T support Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 10:34   ` Chen-Yu Tsai
2017-10-17 10:34     ` Chen-Yu Tsai
2017-10-17 12:28   ` icenowy
2017-10-17 12:28     ` icenowy at aosc.io
2017-10-17  9:06 ` [PATCH 17/23] arm: dts: sun8i: a83t: Add display pipeline Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 10:48   ` Chen-Yu Tsai
2017-10-17 10:48     ` Chen-Yu Tsai
2017-10-17 10:48     ` Chen-Yu Tsai
2017-10-17  9:06 ` [PATCH 18/23] arm: dts: sun8i: a83t: Enable the PWM Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 11:57   ` Chen-Yu Tsai
2017-10-17 11:57     ` Chen-Yu Tsai
2017-10-17  9:06 ` [PATCH 19/23] arm: dts: sun8i: a83t: Add LVDS pins group Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 10:50   ` Chen-Yu Tsai
2017-10-17 10:50     ` Chen-Yu Tsai
2017-10-17 10:50     ` Chen-Yu Tsai
2017-10-17  9:06 ` [PATCH 20/23] arm: dts: sun8i: a83t: Add the PWM pin group Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 10:51   ` Chen-Yu Tsai
2017-10-17 10:51     ` Chen-Yu Tsai
2017-10-17 10:51     ` Chen-Yu Tsai
2017-10-17  9:06 ` [PATCH 21/23] arm: dts: sun8i: a711: Add regulator support Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 12:08   ` Chen-Yu Tsai
2017-10-17 12:08     ` Chen-Yu Tsai
2017-10-17  9:06 ` [PATCH 22/23] arm: dts: sun8i: a711: Enable USB OTG Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 10:53   ` Chen-Yu Tsai
2017-10-17 10:53     ` Chen-Yu Tsai
2017-10-17 10:53     ` Chen-Yu Tsai
2017-10-17  9:06 ` [PATCH 23/23] arm: dts: sun8i: a711: Enable the LCD Maxime Ripard
2017-10-17  9:06   ` Maxime Ripard
2017-10-17 12:16   ` Chen-Yu Tsai
2017-10-17 12:16     ` Chen-Yu Tsai
2017-10-17 12:16 ` [PATCH 00/23] drm/sun4i: Add A83t LVDS support Chen-Yu Tsai
2017-10-17 12:16   ` Chen-Yu Tsai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.