dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230
@ 2025-07-22 14:41 Otto Pflüger
  2025-07-22 14:41 ` [PATCH v2 01/15] dt-bindings: display: sprd: adapt for UMS9230 support Otto Pflüger
                   ` (14 more replies)
  0 siblings, 15 replies; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

Fix some existing bugs that prevent the driver from working properly
and adapt the platform-specific code to support the UMS9230 SoC.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
Changes in v2:
- Fix device tree binding syntax
- Use more descriptive clock names
- Keep IOMMU handle in DPU node and make the driver handle this instead
  (otherwise the binding turns out to be incorrect for newer hardware)
- Remove all accesses to IOMMU registers from the DPU driver (after
  observing that sharkl3 can also use sprd_iommu, I concluded that they
  should not be needed at all)
- Fix container_of macros in sprd_dsi.h
- Link to v1: https://lore.kernel.org/r/20250719-ums9230-drm-v1-0-e4344a05eb3d@abscue.de

---
Otto Pflüger (15):
      dt-bindings: display: sprd: adapt for UMS9230 support
      dt-bindings: display: sprd: add memory-region property
      dt-bindings: display: sprd: allow attaching a DSI panel
      drm: of: try binding port parent node instead of the port itself
      drm: sprd: remove plane and crtc destroy callbacks
      drm: sprd: register a DSI bridge and move init code to pre_enable
      drm: sprd: add support for UMS9230 DSI PLL
      drm: sprd: fix DSI rate and PLL setup code
      drm: sprd: select REGMAP in Kconfig
      drm: sprd: add clock gating support
      drm: sprd: add support for newer DPU versions
      drm: sprd: always initialize DPU and DSI registers
      drm: sprd: do not access IOMMU registers
      drm: sprd: implement IOMMU-based buffer management
      drm: sprd: add fbdev support

 .../bindings/display/sprd/sprd,sharkl3-dpu.yaml    |  32 +-
 .../display/sprd/sprd,sharkl3-dsi-host.yaml        |  42 ++-
 drivers/gpu/drm/drm_of.c                           |   2 +-
 drivers/gpu/drm/sprd/Kconfig                       |   3 +
 drivers/gpu/drm/sprd/Makefile                      |   3 +-
 drivers/gpu/drm/sprd/megacores_pll.c               |  28 +-
 drivers/gpu/drm/sprd/sprd_dpu.c                    |  62 ++--
 drivers/gpu/drm/sprd/sprd_dpu.h                    |   1 +
 drivers/gpu/drm/sprd/sprd_drm.c                    |  57 +++-
 drivers/gpu/drm/sprd/sprd_drm.h                    |  10 +
 drivers/gpu/drm/sprd/sprd_dsi.c                    | 181 +++++++----
 drivers/gpu/drm/sprd/sprd_dsi.h                    |  19 +-
 drivers/gpu/drm/sprd/sprd_gem.c                    | 343 +++++++++++++++++++++
 drivers/gpu/drm/sprd/sprd_gem.h                    |  34 ++
 14 files changed, 697 insertions(+), 120 deletions(-)
---
base-commit: 05adbee3ad528100ab0285c15c91100e19e10138
change-id: 20250719-ums9230-drm-eb271289bfcd
prerequisite-message-id: <20250720123003.37662-3-krzysztof.kozlowski@linaro.org>
prerequisite-patch-id: da2f2d2034f4b3fd5ffea122a6d0df20cb68fb88
prerequisite-patch-id: 2ccbc6b30bb53f303470b2a8376df4356e8785a3

Best regards,
-- 
Otto Pflüger <otto.pflueger@abscue.de>

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

* [PATCH v2 01/15] dt-bindings: display: sprd: adapt for UMS9230 support
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  2025-07-23  7:50   ` Krzysztof Kozlowski
  2025-07-22 14:41 ` [PATCH v2 02/15] dt-bindings: display: sprd: add memory-region property Otto Pflüger
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

Add the compatible strings for the display controller found in the
UMS9230 SoC and introduce more descriptive names for the clocks.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 .../bindings/display/sprd/sprd,sharkl3-dpu.yaml    | 24 +++++++++++++++-------
 .../display/sprd/sprd,sharkl3-dsi-host.yaml        | 15 ++++++++++----
 2 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml b/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml
index 8c52fa0ea5f8ee2149ebf1d4b0d5b052832e3d97..7f34652080b22e7b7072a709fd390a72375110ef 100644
--- a/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml
+++ b/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml
@@ -16,7 +16,12 @@ description: |
 
 properties:
   compatible:
-    const: sprd,sharkl3-dpu
+    oneOf:
+      - items:
+          - enum:
+              - sprd,ums9230-dpu
+          - const: sprd,sharkl3-dpu
+      - const: sprd,sharkl3-dpu
 
   reg:
     maxItems: 1
@@ -28,9 +33,14 @@ properties:
     maxItems: 2
 
   clock-names:
-    items:
-      - const: clk_src_128m
-      - const: clk_src_384m
+    oneOf:
+      - deprecated: true
+        items:
+          - const: clk_src_128m
+          - const: clk_src_384m
+      - items:
+          - const: core
+          - const: dpi
 
   power-domains:
     maxItems: 1
@@ -64,10 +74,10 @@ examples:
         compatible = "sprd,sharkl3-dpu";
         reg = <0x63000000 0x1000>;
         interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
-        clock-names = "clk_src_128m", "clk_src_384m";
 
-        clocks = <&pll CLK_TWPLL_128M>,
-          <&pll CLK_TWPLL_384M>;
+        clocks = <&pll CLK_TWPLL_384M>,
+                 <&pll CLK_TWPLL_128M>;
+        clock-names = "core", "dpi";
 
         dpu_port: port {
             dpu_out: endpoint {
diff --git a/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml b/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml
index 300bf2252c3e8e589dc74927520e24aa4a59f81b..71abbc2de8dbb1b674f151a87490c865b187fdd0 100644
--- a/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml
+++ b/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml
@@ -11,7 +11,9 @@ maintainers:
 
 properties:
   compatible:
-    const: sprd,sharkl3-dsi-host
+    enum:
+      - sprd,sharkl3-dsi-host
+      - sprd,ums9230-dsi-host
 
   reg:
     maxItems: 1
@@ -23,8 +25,12 @@ properties:
     maxItems: 1
 
   clock-names:
-    items:
-      - const: clk_src_96m
+    oneOf:
+      - deprecated: true
+        items:
+          - const: clk_src_96m
+      - items:
+          - const: pclk
 
   power-domains:
     maxItems: 1
@@ -73,8 +79,9 @@ examples:
         reg = <0x63100000 0x1000>;
         interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
           <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
-        clock-names = "clk_src_96m";
         clocks = <&pll CLK_TWPLL_96M>;
+        clock-names = "pclk";
+
         ports {
             #address-cells = <1>;
             #size-cells = <0>;

-- 
2.50.0

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

* [PATCH v2 02/15] dt-bindings: display: sprd: add memory-region property
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
  2025-07-22 14:41 ` [PATCH v2 01/15] dt-bindings: display: sprd: adapt for UMS9230 support Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  2025-07-23  7:51   ` Krzysztof Kozlowski
  2025-07-22 14:41 ` [PATCH v2 03/15] dt-bindings: display: sprd: allow attaching a DSI panel Otto Pflüger
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

Explain that the DPU node supports a memory-region property that can be
used to describe an initial framebuffer set up by the bootloader,
usually in order to create a passthrough mapping for this framebuffer
when the IOMMU is used.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 .../devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml        | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml b/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml
index 7f34652080b22e7b7072a709fd390a72375110ef..fa9ad2600f150e1023606898322a1a7b4675bab3 100644
--- a/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml
+++ b/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml
@@ -48,6 +48,14 @@ properties:
   iommus:
     maxItems: 1
 
+  memory-region:
+    maxItems: 1
+    description:
+      A phandle to the framebuffer region configured by the bootloader. This
+      can be used together with an iommu-addresses property on the reserved
+      memory region to create an initial passthrough mapping for the boot
+      splash framebuffer.
+
   port:
     type: object
     description:

-- 
2.50.0

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

* [PATCH v2 03/15] dt-bindings: display: sprd: allow attaching a DSI panel
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
  2025-07-22 14:41 ` [PATCH v2 01/15] dt-bindings: display: sprd: adapt for UMS9230 support Otto Pflüger
  2025-07-22 14:41 ` [PATCH v2 02/15] dt-bindings: display: sprd: add memory-region property Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  2025-07-23  7:54   ` Krzysztof Kozlowski
  2025-07-22 14:41 ` [PATCH v2 04/15] drm: of: try binding port parent node instead of the port itself Otto Pflüger
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

Add a DSI output port and include common DSI controller bindings in the
bindings for the Unisoc DSI controller.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 .../display/sprd/sprd,sharkl3-dsi-host.yaml        | 27 ++++++++++++++++------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml b/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml
index 71abbc2de8dbb1b674f151a87490c865b187fdd0..7da68eb026b97932515b470764fa3948104db4e8 100644
--- a/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml
+++ b/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml
@@ -46,12 +46,22 @@ properties:
         const: 0
 
       port@0:
-        type: object
-        description:
-          A port node with endpoint definitions as defined in
-          Documentation/devicetree/bindings/media/video-interfaces.txt.
-          That port should be the input endpoint, usually coming from
-          the associated DPU.
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+            description: The input endpoint, usually connected to the DPU
+
+      port@1:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+            description: The output endpoint, usually connected to the panel
 
     required:
       - "#address-cells"
@@ -60,6 +70,9 @@ properties:
 
     additionalProperties: false
 
+allOf:
+  - $ref: /schemas/display/dsi-controller.yaml#
+
 required:
   - compatible
   - reg
@@ -68,7 +81,7 @@ required:
   - clock-names
   - ports
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |

-- 
2.50.0

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

* [PATCH v2 04/15] drm: of: try binding port parent node instead of the port itself
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
                   ` (2 preceding siblings ...)
  2025-07-22 14:41 ` [PATCH v2 03/15] dt-bindings: display: sprd: allow attaching a DSI panel Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  2025-07-23  7:02   ` Maxime Ripard
  2025-07-22 14:41 ` [PATCH v2 05/15] drm: sprd: remove plane and crtc destroy callbacks Otto Pflüger
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

The drm_of_component_probe function is intended to bind all devices in
an OF graph given a set of ports linked using the "ports" property on a
main device node. This means that it should also bind the components
providing these ports, not just the components of other ports connected
to them. In order to do this, it calls drm_of_component_match_add with
a pointer to each port node after checking that its parent node is a
device.

However, when given a pointer to the port node, the compare_of callback
does not match it with a device node and thus fails to detect that the
node belongs to a component. Fix this by passing a pointer to the parent
node here too.

Currently only the Unisoc platform driver relies on this feature, which
was previously broken and is fixed by this change. On other platforms,
the "ports" property points to ports that are not part of a component,
i.e. the components only have indirect connections to the main node.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/gpu/drm/drm_of.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index d0183dea770308e77f05da364ffe087d53f3be36..b972facc2ec3fe40a4e10b5d7178b5ac8c0158d5 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -132,7 +132,7 @@ int drm_of_component_probe(struct device *dev,
 
 		if (of_device_is_available(port->parent))
 			drm_of_component_match_add(dev, &match, compare_of,
-						   port);
+						   port->parent);
 
 		of_node_put(port);
 	}

-- 
2.50.0

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

* [PATCH v2 05/15] drm: sprd: remove plane and crtc destroy callbacks
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
                   ` (3 preceding siblings ...)
  2025-07-22 14:41 ` [PATCH v2 04/15] drm: of: try binding port parent node instead of the port itself Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  2025-07-22 14:41 ` [PATCH v2 06/15] drm: sprd: register a DSI bridge and move init code to pre_enable Otto Pflüger
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

These callbacks are now required to be NULL and trigger a runtime
warning if they are present.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/gpu/drm/sprd/sprd_dpu.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c
index a3447622a33cd612e34be038e833222567bdcd2c..0d9eb778794d92418b39f8535d94abde3566de43 100644
--- a/drivers/gpu/drm/sprd/sprd_dpu.c
+++ b/drivers/gpu/drm/sprd/sprd_dpu.c
@@ -577,7 +577,6 @@ static const struct drm_plane_helper_funcs sprd_plane_helper_funcs = {
 static const struct drm_plane_funcs sprd_plane_funcs = {
 	.update_plane = drm_atomic_helper_update_plane,
 	.disable_plane	= drm_atomic_helper_disable_plane,
-	.destroy = drm_plane_cleanup,
 	.reset = drm_atomic_helper_plane_reset,
 	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
@@ -704,7 +703,6 @@ static const struct drm_crtc_helper_funcs sprd_crtc_helper_funcs = {
 };
 
 static const struct drm_crtc_funcs sprd_crtc_funcs = {
-	.destroy	= drm_crtc_cleanup,
 	.set_config	= drm_atomic_helper_set_config,
 	.page_flip	= drm_atomic_helper_page_flip,
 	.reset		= drm_atomic_helper_crtc_reset,

-- 
2.50.0

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

* [PATCH v2 06/15] drm: sprd: register a DSI bridge and move init code to pre_enable
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
                   ` (4 preceding siblings ...)
  2025-07-22 14:41 ` [PATCH v2 05/15] drm: sprd: remove plane and crtc destroy callbacks Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  2025-07-22 14:41 ` [PATCH v2 07/15] drm: sprd: add support for UMS9230 DSI PLL Otto Pflüger
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

If a panel needs to send DSI commands during initialization, it sets the
prepare_prev_first flag, which allows the DSI host to initialize itself
before the panel's prepare function is called. To support this, the DSI
host must register a bridge and perform the necessary initialization
steps in its pre_enable function.

Implement this for the Unisoc DSI driver by moving the initialization
code from the encoder callbacks to a bridge and simplify the remaining
encoder-related code which no longer needs any callbacks.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/gpu/drm/sprd/Kconfig    |   2 +
 drivers/gpu/drm/sprd/sprd_dsi.c | 143 +++++++++++++++++++++++++---------------
 drivers/gpu/drm/sprd/sprd_dsi.h |   6 +-
 3 files changed, 97 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/sprd/Kconfig b/drivers/gpu/drm/sprd/Kconfig
index e22b780fe82248296a7153d02269faf8cd63294f..1afcdbf6f0ee3304f2297835241c9bb10d422154 100644
--- a/drivers/gpu/drm/sprd/Kconfig
+++ b/drivers/gpu/drm/sprd/Kconfig
@@ -2,6 +2,8 @@ config DRM_SPRD
 	tristate "DRM Support for Unisoc SoCs Platform"
 	depends on ARCH_SPRD || COMPILE_TEST
 	depends on DRM && OF
+	select DRM_BRIDGE_CONNECTOR
+	select DRM_DISPLAY_HELPER
 	select DRM_GEM_DMA_HELPER
 	select DRM_KMS_HELPER
 	select DRM_MIPI_DSI
diff --git a/drivers/gpu/drm/sprd/sprd_dsi.c b/drivers/gpu/drm/sprd/sprd_dsi.c
index 23b0e1dc547a5023ee6ad7d5e1c49e2cec986bf0..43fff12d73f12619da57606a3c4785924e2c1507 100644
--- a/drivers/gpu/drm/sprd/sprd_dsi.c
+++ b/drivers/gpu/drm/sprd/sprd_dsi.c
@@ -11,8 +11,10 @@
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_bridge.h>
+#include <drm/drm_bridge_connector.h>
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_simple_kms_helper.h>
 
 #include "sprd_drm.h"
 #include "sprd_dpu.h"
@@ -778,19 +780,53 @@ static void sprd_dphy_fini(struct dsi_context *ctx)
 	dsi_reg_up(ctx, PHY_INTERFACE_CTRL, RF_PHY_RESET_N, RF_PHY_RESET_N);
 }
 
-static void sprd_dsi_encoder_mode_set(struct drm_encoder *encoder,
-				      struct drm_display_mode *mode,
-				 struct drm_display_mode *adj_mode)
+static int sprd_dsi_encoder_init(struct sprd_dsi *dsi,
+				 struct device *dev)
+{
+	struct drm_encoder *encoder = &dsi->encoder;
+	u32 crtc_mask;
+	int ret;
+
+	crtc_mask = drm_of_find_possible_crtcs(dsi->drm, dev->of_node);
+	if (!crtc_mask) {
+		drm_err(dsi->drm, "failed to find crtc mask\n");
+		return -EINVAL;
+	}
+
+	drm_dbg(dsi->drm, "find possible crtcs: 0x%08x\n", crtc_mask);
+
+	encoder->possible_crtcs = crtc_mask;
+	ret = drm_simple_encoder_init(dsi->drm, encoder, DRM_MODE_ENCODER_DSI);
+	if (ret) {
+		drm_err(dsi->drm, "failed to init dsi encoder\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int sprd_dsi_bridge_attach(struct drm_bridge *bridge,
+				  struct drm_encoder *encoder,
+				  enum drm_bridge_attach_flags flags)
+{
+	struct sprd_dsi *dsi = bridge_to_dsi(bridge);
+
+	return drm_bridge_attach(&dsi->encoder, dsi->panel_bridge,
+				 bridge, flags);
+}
+
+static void sprd_dsi_bridge_mode_set(struct drm_bridge *bridge,
+				     const struct drm_display_mode *mode,
+				     const struct drm_display_mode *adj_mode)
 {
-	struct sprd_dsi *dsi = encoder_to_dsi(encoder);
+	struct sprd_dsi *dsi = bridge_to_dsi(bridge);
 
 	drm_display_mode_to_videomode(adj_mode, &dsi->ctx.vm);
 }
 
-static void sprd_dsi_encoder_enable(struct drm_encoder *encoder)
+static void sprd_dsi_bridge_pre_enable(struct drm_bridge *bridge)
 {
-	struct sprd_dsi *dsi = encoder_to_dsi(encoder);
-	struct sprd_dpu *dpu = to_sprd_crtc(encoder->crtc);
+	struct sprd_dsi *dsi = bridge_to_dsi(bridge);
 	struct dsi_context *ctx = &dsi->ctx;
 
 	if (ctx->enabled) {
@@ -819,15 +855,15 @@ static void sprd_dsi_encoder_enable(struct drm_encoder *encoder)
 		dphy_wait_pll_locked(ctx);
 	}
 
-	sprd_dpu_run(dpu);
+	/* DSI commands cannot be issued unless the DPU is running. */
+	sprd_dpu_run(to_sprd_crtc(dsi->encoder.crtc));
 
 	ctx->enabled = true;
 }
 
-static void sprd_dsi_encoder_disable(struct drm_encoder *encoder)
+static void sprd_dsi_bridge_post_disable(struct drm_bridge *bridge)
 {
-	struct sprd_dsi *dsi = encoder_to_dsi(encoder);
-	struct sprd_dpu *dpu = to_sprd_crtc(encoder->crtc);
+	struct sprd_dsi *dsi = bridge_to_dsi(bridge);
 	struct dsi_context *ctx = &dsi->ctx;
 
 	if (!ctx->enabled) {
@@ -835,51 +871,21 @@ static void sprd_dsi_encoder_disable(struct drm_encoder *encoder)
 		return;
 	}
 
-	sprd_dpu_stop(dpu);
+	sprd_dpu_stop(to_sprd_crtc(dsi->encoder.crtc));
+
 	sprd_dphy_fini(ctx);
 	sprd_dsi_fini(ctx);
 
 	ctx->enabled = false;
 }
 
-static const struct drm_encoder_helper_funcs sprd_encoder_helper_funcs = {
-	.mode_set	= sprd_dsi_encoder_mode_set,
-	.enable		= sprd_dsi_encoder_enable,
-	.disable	= sprd_dsi_encoder_disable
+static const struct drm_bridge_funcs sprd_dsi_bridge_funcs = {
+	.attach		= sprd_dsi_bridge_attach,
+	.mode_set	= sprd_dsi_bridge_mode_set,
+	.pre_enable	= sprd_dsi_bridge_pre_enable,
+	.post_disable	= sprd_dsi_bridge_post_disable,
 };
 
-static const struct drm_encoder_funcs sprd_encoder_funcs = {
-	.destroy = drm_encoder_cleanup,
-};
-
-static int sprd_dsi_encoder_init(struct sprd_dsi *dsi,
-				 struct device *dev)
-{
-	struct drm_encoder *encoder = &dsi->encoder;
-	u32 crtc_mask;
-	int ret;
-
-	crtc_mask = drm_of_find_possible_crtcs(dsi->drm, dev->of_node);
-	if (!crtc_mask) {
-		drm_err(dsi->drm, "failed to find crtc mask\n");
-		return -EINVAL;
-	}
-
-	drm_dbg(dsi->drm, "find possible crtcs: 0x%08x\n", crtc_mask);
-
-	encoder->possible_crtcs = crtc_mask;
-	ret = drm_encoder_init(dsi->drm, encoder, &sprd_encoder_funcs,
-			       DRM_MODE_ENCODER_DSI, NULL);
-	if (ret) {
-		drm_err(dsi->drm, "failed to init dsi encoder\n");
-		return ret;
-	}
-
-	drm_encoder_helper_add(encoder, &sprd_encoder_helper_funcs);
-
-	return 0;
-}
-
 static int sprd_dsi_bridge_init(struct sprd_dsi *dsi,
 				struct device *dev)
 {
@@ -889,11 +895,35 @@ static int sprd_dsi_bridge_init(struct sprd_dsi *dsi,
 	if (IS_ERR(dsi->panel_bridge))
 		return PTR_ERR(dsi->panel_bridge);
 
-	ret = drm_bridge_attach(&dsi->encoder, dsi->panel_bridge, NULL, 0);
+	dsi->bridge.funcs = &sprd_dsi_bridge_funcs;
+	dsi->bridge.of_node = dev->of_node;
+	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
+
+	drm_bridge_add(&dsi->bridge);
+
+	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
+				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
 	if (ret)
-		return ret;
+		goto err_cleanup;
+
+	dsi->connector = drm_bridge_connector_init(dsi->drm, &dsi->encoder);
+	if (IS_ERR(dsi->connector)) {
+		drm_err(dsi->drm, "Unable to create bridge connector\n");
+		ret = PTR_ERR(dsi->connector);
+		goto err_cleanup;
+	}
+
+	ret = drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
+	if (ret < 0)
+		goto err_cleanup;
 
 	return 0;
+
+err_cleanup:
+	drm_bridge_remove(&dsi->bridge);
+	drm_of_panel_bridge_remove(dev->of_node, 1, 0);
+
+	return ret;
 }
 
 static int sprd_dsi_context_init(struct sprd_dsi *dsi,
@@ -940,13 +970,21 @@ static int sprd_dsi_bind(struct device *dev, struct device *master, void *data)
 
 	ret = sprd_dsi_bridge_init(dsi, dev);
 	if (ret)
-		return ret;
+		goto err_cleanup_encoder;
 
 	ret = sprd_dsi_context_init(dsi, dev);
 	if (ret)
-		return ret;
+		goto err_cleanup_bridge;
 
 	return 0;
+
+err_cleanup_encoder:
+	drm_encoder_cleanup(&dsi->encoder);
+err_cleanup_bridge:
+	drm_bridge_remove(&dsi->bridge);
+	drm_of_panel_bridge_remove(dev->of_node, 1, 0);
+
+	return ret;
 }
 
 static void sprd_dsi_unbind(struct device *dev,
@@ -954,6 +992,7 @@ static void sprd_dsi_unbind(struct device *dev,
 {
 	struct sprd_dsi *dsi = dev_get_drvdata(dev);
 
+	drm_bridge_remove(&dsi->bridge);
 	drm_of_panel_bridge_remove(dev->of_node, 1, 0);
 
 	drm_encoder_cleanup(&dsi->encoder);
diff --git a/drivers/gpu/drm/sprd/sprd_dsi.h b/drivers/gpu/drm/sprd/sprd_dsi.h
index d858ebb111150546e99403a87bc7cea42cad0158..1956ead3237a17ada14804302ec3d7dadd8ddab0 100644
--- a/drivers/gpu/drm/sprd/sprd_dsi.h
+++ b/drivers/gpu/drm/sprd/sprd_dsi.h
@@ -18,8 +18,8 @@
 #include <drm/drm_print.h>
 #include <drm/drm_panel.h>
 
-#define encoder_to_dsi(encoder) \
-	container_of(encoder, struct sprd_dsi, encoder)
+#define bridge_to_dsi(x)	container_of(x, struct sprd_dsi, bridge)
+#define encoder_to_dsi(x)	container_of(x, struct sprd_dsi, encoder)
 
 enum dsi_work_mode {
 	DSI_MODE_CMD = 0,
@@ -116,7 +116,9 @@ struct sprd_dsi {
 	struct mipi_dsi_host host;
 	struct mipi_dsi_device *slave;
 	struct drm_encoder encoder;
+	struct drm_bridge bridge;
 	struct drm_bridge *panel_bridge;
+	struct drm_connector *connector;
 	struct dsi_context ctx;
 };
 

-- 
2.50.0

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

* [PATCH v2 07/15] drm: sprd: add support for UMS9230 DSI PLL
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
                   ` (5 preceding siblings ...)
  2025-07-22 14:41 ` [PATCH v2 06/15] drm: sprd: register a DSI bridge and move init code to pre_enable Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  2025-07-22 14:41 ` [PATCH v2 08/15] drm: sprd: fix DSI rate and PLL setup code Otto Pflüger
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

Move platform-specific PLL parameters to the device tree match data and
add the parameters for UMS9230.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/gpu/drm/sprd/megacores_pll.c | 21 ++++++++-------------
 drivers/gpu/drm/sprd/sprd_dsi.c      | 21 ++++++++++++++++++++-
 drivers/gpu/drm/sprd/sprd_dsi.h      |  9 ++++++++-
 3 files changed, 36 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/sprd/megacores_pll.c b/drivers/gpu/drm/sprd/megacores_pll.c
index 3091dfdc11e3b547a05a9edaa4047a1e367c1596..e5a18599678ab6e3771cd732dcca409ab2d59f72 100644
--- a/drivers/gpu/drm/sprd/megacores_pll.c
+++ b/drivers/gpu/drm/sprd/megacores_pll.c
@@ -21,12 +21,6 @@
 
 #define AVERAGE(a, b) (min(a, b) + abs((b) - (a)) / 2)
 
-/* sharkle */
-#define VCO_BAND_LOW	750
-#define VCO_BAND_MID	1100
-#define VCO_BAND_HIGH	1500
-#define PHY_REF_CLK	26000
-
 static int dphy_calc_pll_param(struct dphy_pll *pll)
 {
 	const u32 khz = 1000;
@@ -36,11 +30,10 @@ static int dphy_calc_pll_param(struct dphy_pll *pll)
 	int i;
 
 	pll->potential_fvco = pll->freq / khz;
-	pll->ref_clk = PHY_REF_CLK / khz;
 
 	for (i = 0; i < 4; ++i) {
-		if (pll->potential_fvco >= VCO_BAND_LOW &&
-		    pll->potential_fvco <= VCO_BAND_HIGH) {
+		if (pll->potential_fvco >= pll->platform->band_low &&
+		    pll->potential_fvco <= pll->platform->band_high) {
 			pll->fvco = pll->potential_fvco;
 			pll->out_sel = BIT(i);
 			break;
@@ -50,21 +43,23 @@ static int dphy_calc_pll_param(struct dphy_pll *pll)
 	if (pll->fvco == 0)
 		return -EINVAL;
 
-	if (pll->fvco >= VCO_BAND_LOW && pll->fvco <= VCO_BAND_MID) {
+	if (pll->fvco >= pll->platform->band_low &&
+	    pll->fvco <= pll->platform->band_mid) {
 		/* vco band control */
 		pll->vco_band = 0x0;
 		/* low pass filter control */
 		pll->lpf_sel = 1;
-	} else if (pll->fvco > VCO_BAND_MID && pll->fvco <= VCO_BAND_HIGH) {
+	} else if (pll->fvco > pll->platform->band_mid &&
+		   pll->fvco <= pll->platform->band_high) {
 		pll->vco_band = 0x1;
 		pll->lpf_sel = 0;
 	} else {
 		return -EINVAL;
 	}
 
-	pll->nint = pll->fvco / pll->ref_clk;
+	pll->nint = pll->fvco / pll->platform->ref_clk;
 	tmp = pll->fvco * factor * mhz;
-	do_div(tmp, pll->ref_clk);
+	do_div(tmp, pll->platform->ref_clk);
 	tmp = tmp - pll->nint * factor * mhz;
 	tmp *= BIT(20);
 	do_div(tmp, 100000000);
diff --git a/drivers/gpu/drm/sprd/sprd_dsi.c b/drivers/gpu/drm/sprd/sprd_dsi.c
index 43fff12d73f12619da57606a3c4785924e2c1507..db5f9bcbb2500096402b9d44b9cc4428070e69ba 100644
--- a/drivers/gpu/drm/sprd/sprd_dsi.c
+++ b/drivers/gpu/drm/sprd/sprd_dsi.c
@@ -1061,8 +1061,23 @@ static const struct mipi_dsi_host_ops sprd_dsi_host_ops = {
 	.transfer = sprd_dsi_host_transfer,
 };
 
+static const struct dphy_pll_platform dphy_pll_sharkl3 = {
+	.band_low = 750,
+	.band_mid = 1100,
+	.band_high = 1500,
+	.ref_clk = 26,
+};
+
+static const struct dphy_pll_platform dphy_pll_ums9230 = {
+	.band_low = 1250,
+	.band_mid = 1800,
+	.band_high = 2500,
+	.ref_clk = 26,
+};
+
 static const struct of_device_id dsi_match_table[] = {
-	{ .compatible = "sprd,sharkl3-dsi-host" },
+	{ .compatible = "sprd,sharkl3-dsi-host", .data = &dphy_pll_sharkl3 },
+	{ .compatible = "sprd,ums9230-dsi-host", .data = &dphy_pll_ums9230 },
 	{ /* sentinel */ },
 };
 
@@ -1080,6 +1095,10 @@ static int sprd_dsi_probe(struct platform_device *pdev)
 	dsi->host.ops = &sprd_dsi_host_ops;
 	dsi->host.dev = dev;
 
+	dsi->ctx.pll.platform = of_device_get_match_data(dev);
+	if (!dsi->ctx.pll.platform)
+		return -EINVAL;
+
 	return mipi_dsi_host_register(&dsi->host);
 }
 
diff --git a/drivers/gpu/drm/sprd/sprd_dsi.h b/drivers/gpu/drm/sprd/sprd_dsi.h
index 1956ead3237a17ada14804302ec3d7dadd8ddab0..e5a0bd42eb548a9b85a60d79a74412b39ffa5c7c 100644
--- a/drivers/gpu/drm/sprd/sprd_dsi.h
+++ b/drivers/gpu/drm/sprd/sprd_dsi.h
@@ -64,6 +64,13 @@ enum pll_timing {
 	TA_WAIT,
 };
 
+struct dphy_pll_platform {
+	u32 band_low;
+	u32 band_mid;
+	u32 band_high;
+	u32 ref_clk; /* dphy reference clock, unit: MHz */
+};
+
 struct dphy_pll {
 	u8 refin; /* Pre-divider control signal */
 	u8 cp_s; /* 00: SDM_EN=1, 10: SDM_EN=0 */
@@ -71,7 +78,6 @@ struct dphy_pll {
 	u8 sdm_en;
 	u8 div;
 	u8 int_n; /* integer N PLL */
-	u32 ref_clk; /* dphy reference clock, unit: MHz */
 	u32 freq; /* panel config, unit: KHz */
 	u32 fvco;
 	u32 potential_fvco;
@@ -81,6 +87,7 @@ struct dphy_pll {
 	u8 out_sel; /* post divider control */
 	u8 vco_band; /* vco range */
 	u8 det_delay;
+	const struct dphy_pll_platform *platform;
 };
 
 struct dsi_context {

-- 
2.50.0

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

* [PATCH v2 08/15] drm: sprd: fix DSI rate and PLL setup code
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
                   ` (6 preceding siblings ...)
  2025-07-22 14:41 ` [PATCH v2 07/15] drm: sprd: add support for UMS9230 DSI PLL Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  2025-07-22 14:41 ` [PATCH v2 09/15] drm: sprd: select REGMAP in Kconfig Otto Pflüger
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

Correct the initialization code to treat the hs_rate and lp_rate values
as hertz instead of kilohertz. While at it, fix a bit operation bug in
the PLL initialization code which caused a PLL register to be set to
zero instead of the desired value.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/gpu/drm/sprd/megacores_pll.c | 7 +++----
 drivers/gpu/drm/sprd/sprd_dsi.c      | 7 +++----
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/sprd/megacores_pll.c b/drivers/gpu/drm/sprd/megacores_pll.c
index e5a18599678ab6e3771cd732dcca409ab2d59f72..f214f906b58fb006c4305de9b8b86b4a934f2074 100644
--- a/drivers/gpu/drm/sprd/megacores_pll.c
+++ b/drivers/gpu/drm/sprd/megacores_pll.c
@@ -23,13 +23,12 @@
 
 static int dphy_calc_pll_param(struct dphy_pll *pll)
 {
-	const u32 khz = 1000;
 	const u32 mhz = 1000000;
 	const unsigned long long factor = 100;
 	unsigned long long tmp;
 	int i;
 
-	pll->potential_fvco = pll->freq / khz;
+	pll->potential_fvco = pll->freq / mhz;
 
 	for (i = 0; i < 4; ++i) {
 		if (pll->potential_fvco >= pll->platform->band_low &&
@@ -89,7 +88,7 @@ static void dphy_set_pll_reg(struct dphy_pll *pll, struct regmap *regmap)
 	reg_val[3] = pll->vco_band | (pll->sdm_en << 1) | (pll->refin << 2);
 	reg_val[4] = pll->kint >> 12;
 	reg_val[5] = pll->kint >> 4;
-	reg_val[6] = pll->out_sel | ((pll->kint << 4) & 0xf);
+	reg_val[6] = pll->out_sel | ((pll->kint & 0xf) << 4);
 	reg_val[7] = 1 << 4;
 	reg_val[8] = pll->det_delay;
 
@@ -218,7 +217,7 @@ void dphy_timing_config(struct dsi_context *ctx)
 	u32 tmp = 0;
 
 	/* t_ui: 1 ui, byteck: 8 ui, half byteck: 4 ui */
-	t_ui = 1000 * scale / (pll->freq / 1000);
+	t_ui = 1000 * scale / (pll->freq / 1000000);
 	t_byteck = t_ui << 3;
 	t_half_byteck = t_ui << 2;
 	constant = t_ui << 1;
diff --git a/drivers/gpu/drm/sprd/sprd_dsi.c b/drivers/gpu/drm/sprd/sprd_dsi.c
index db5f9bcbb2500096402b9d44b9cc4428070e69ba..e01d1d28fe579644ec2e0c83ec9170269932adfe 100644
--- a/drivers/gpu/drm/sprd/sprd_dsi.c
+++ b/drivers/gpu/drm/sprd/sprd_dsi.c
@@ -391,7 +391,7 @@ static u32 fmt_to_coding(u32 fmt)
 static void sprd_dsi_init(struct dsi_context *ctx)
 {
 	struct sprd_dsi *dsi = container_of(ctx, struct sprd_dsi, ctx);
-	u32 byte_clk = dsi->slave->hs_rate / 8;
+	u32 byte_clk = dsi->slave->hs_rate / 8000;
 	u16 data_hs2lp, data_lp2hs, clk_hs2lp, clk_lp2hs;
 	u16 max_rd_time;
 	int div;
@@ -408,7 +408,7 @@ static void sprd_dsi_init(struct dsi_context *ctx)
 	dsi_reg_up(ctx, VIRTUAL_CHANNEL_ID, VIDEO_PKT_VCID, 0);
 	dsi_reg_up(ctx, VIRTUAL_CHANNEL_ID, GEN_RX_VCID, 0);
 
-	div = DIV_ROUND_UP(byte_clk, dsi->slave->lp_rate);
+	div = DIV_ROUND_UP(byte_clk, dsi->slave->lp_rate / 1000);
 	writel(div, ctx->base + TX_ESC_CLK_CONFIG);
 
 	max_rd_time = ns_to_cycle(ctx->max_rd_time, byte_clk);
@@ -450,7 +450,6 @@ static int sprd_dsi_dpi_video(struct dsi_context *ctx)
 {
 	struct sprd_dsi *dsi = container_of(ctx, struct sprd_dsi, ctx);
 	struct videomode *vm = &ctx->vm;
-	u32 byte_clk = dsi->slave->hs_rate / 8;
 	u16 bpp_x100;
 	u16 video_size;
 	u32 ratio_x1000;
@@ -472,7 +471,7 @@ static int sprd_dsi_dpi_video(struct dsi_context *ctx)
 	video_size = round_video_size(coding, vm->hactive);
 	bpp_x100 = calc_bytes_per_pixel_x100(coding);
 	video_size_step = calc_video_size_step(coding);
-	ratio_x1000 = byte_clk * 1000 / (vm->pixelclock / 1000);
+	ratio_x1000 = dsi->slave->hs_rate / 8 / (vm->pixelclock / 1000);
 	hline = vm->hactive + vm->hsync_len + vm->hfront_porch +
 		vm->hback_porch;
 

-- 
2.50.0

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

* [PATCH v2 09/15] drm: sprd: select REGMAP in Kconfig
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
                   ` (7 preceding siblings ...)
  2025-07-22 14:41 ` [PATCH v2 08/15] drm: sprd: fix DSI rate and PLL setup code Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  2025-07-22 14:41 ` [PATCH v2 10/15] drm: sprd: add clock gating support Otto Pflüger
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

When compile-testing this driver with all other drivers disabled,
sprd_dsi.c fails to compile due to a missing definition of struct
regmap_bus. Ensure that this does not happen by declaring the
compile-time dependency on regmap in Kconfig.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/gpu/drm/sprd/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/sprd/Kconfig b/drivers/gpu/drm/sprd/Kconfig
index 1afcdbf6f0ee3304f2297835241c9bb10d422154..828384d42c5aac4bf194558f22d9a77f7c693572 100644
--- a/drivers/gpu/drm/sprd/Kconfig
+++ b/drivers/gpu/drm/sprd/Kconfig
@@ -7,6 +7,7 @@ config DRM_SPRD
 	select DRM_GEM_DMA_HELPER
 	select DRM_KMS_HELPER
 	select DRM_MIPI_DSI
+	select REGMAP
 	select VIDEOMODE_HELPERS
 	help
 	  Choose this option if you have a Unisoc chipset.

-- 
2.50.0

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

* [PATCH v2 10/15] drm: sprd: add clock gating support
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
                   ` (8 preceding siblings ...)
  2025-07-22 14:41 ` [PATCH v2 09/15] drm: sprd: select REGMAP in Kconfig Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  2025-07-23  7:00   ` Maxime Ripard
  2025-07-22 14:41 ` [PATCH v2 11/15] drm: sprd: add support for newer DPU versions Otto Pflüger
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

Enable the DPU and DSI clocks specified in the device tree.
Disable the DSI clock when it is not needed.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/gpu/drm/sprd/sprd_dpu.c | 7 +++++++
 drivers/gpu/drm/sprd/sprd_dpu.h | 1 +
 drivers/gpu/drm/sprd/sprd_dsi.c | 9 +++++++++
 drivers/gpu/drm/sprd/sprd_dsi.h | 4 +++-
 4 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c
index 0d9eb778794d92418b39f8535d94abde3566de43..9d274600e6a80bdfc435f6c6eff77c9dd71cb38c 100644
--- a/drivers/gpu/drm/sprd/sprd_dpu.c
+++ b/drivers/gpu/drm/sprd/sprd_dpu.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2020 Unisoc Inc.
  */
 
+#include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/delay.h>
 #include <linux/dma-buf.h>
@@ -794,6 +795,12 @@ static int sprd_dpu_context_init(struct sprd_dpu *dpu,
 	if (ctx->irq < 0)
 		return ctx->irq;
 
+	ctx->clk = devm_clk_get_optional_enabled(dev, "core");
+	if (IS_ERR(ctx->clk)) {
+		dev_err(dev, "failed to get DPU core clock\n");
+		return PTR_ERR(ctx->clk);
+	}
+
 	/* disable and clear interrupts before register dpu IRQ. */
 	writel(0x00, ctx->base + REG_DPU_INT_EN);
 	writel(0xff, ctx->base + REG_DPU_INT_CLR);
diff --git a/drivers/gpu/drm/sprd/sprd_dpu.h b/drivers/gpu/drm/sprd/sprd_dpu.h
index 157a78f24dc18b071602552ea9d005af66525263..d48b922de580a8a4bf07c4610c431d3321f7b810 100644
--- a/drivers/gpu/drm/sprd/sprd_dpu.h
+++ b/drivers/gpu/drm/sprd/sprd_dpu.h
@@ -44,6 +44,7 @@ enum {
  */
 struct dpu_context {
 	void __iomem *base;
+	struct clk *clk;
 	int irq;
 	u8 if_type;
 	struct videomode vm;
diff --git a/drivers/gpu/drm/sprd/sprd_dsi.c b/drivers/gpu/drm/sprd/sprd_dsi.c
index e01d1d28fe579644ec2e0c83ec9170269932adfe..2af4273a6c73185084290c9d14b8ac18914d514b 100644
--- a/drivers/gpu/drm/sprd/sprd_dsi.c
+++ b/drivers/gpu/drm/sprd/sprd_dsi.c
@@ -828,6 +828,8 @@ static void sprd_dsi_bridge_pre_enable(struct drm_bridge *bridge)
 	struct sprd_dsi *dsi = bridge_to_dsi(bridge);
 	struct dsi_context *ctx = &dsi->ctx;
 
+	clk_prepare_enable(ctx->clk);
+
 	if (ctx->enabled) {
 		drm_warn(dsi->drm, "dsi is initialized\n");
 		return;
@@ -875,6 +877,8 @@ static void sprd_dsi_bridge_post_disable(struct drm_bridge *bridge)
 	sprd_dphy_fini(ctx);
 	sprd_dsi_fini(ctx);
 
+	clk_disable_unprepare(ctx->clk);
+
 	ctx->enabled = false;
 }
 
@@ -1098,6 +1102,11 @@ static int sprd_dsi_probe(struct platform_device *pdev)
 	if (!dsi->ctx.pll.platform)
 		return -EINVAL;
 
+	dsi->ctx.clk = devm_clk_get_optional(dev, "pclk");
+	if (IS_ERR(dsi->ctx.clk))
+		return dev_err_probe(dev, PTR_ERR(dsi->ctx.clk),
+				     "failed to get pclk\n");
+
 	return mipi_dsi_host_register(&dsi->host);
 }
 
diff --git a/drivers/gpu/drm/sprd/sprd_dsi.h b/drivers/gpu/drm/sprd/sprd_dsi.h
index e5a0bd42eb548a9b85a60d79a74412b39ffa5c7c..f8bcef13ffd36aa7d98403ea22d50b8532043473 100644
--- a/drivers/gpu/drm/sprd/sprd_dsi.h
+++ b/drivers/gpu/drm/sprd/sprd_dsi.h
@@ -6,8 +6,9 @@
 #ifndef __SPRD_DSI_H__
 #define __SPRD_DSI_H__
 
-#include <linux/of.h>
+#include <linux/clk.h>
 #include <linux/device.h>
+#include <linux/of.h>
 #include <linux/regmap.h>
 #include <video/videomode.h>
 
@@ -93,6 +94,7 @@ struct dphy_pll {
 struct dsi_context {
 	void __iomem *base;
 	struct regmap *regmap;
+	struct clk *clk;
 	struct dphy_pll pll;
 	struct videomode vm;
 	bool enabled;

-- 
2.50.0

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

* [PATCH v2 11/15] drm: sprd: add support for newer DPU versions
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
                   ` (9 preceding siblings ...)
  2025-07-22 14:41 ` [PATCH v2 10/15] drm: sprd: add clock gating support Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  2025-07-22 14:41 ` [PATCH v2 12/15] drm: sprd: always initialize DPU and DSI registers Otto Pflüger
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

Newer DPU revisions with the same register layout, such as the one used
in UMS9230 (version 5), require different defaults for the display
interface configuration but otherwise remain compatible with the version
this driver was originally written for.

Check the DPU version register to account for these configuration
differences.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/gpu/drm/sprd/sprd_dpu.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c
index 9d274600e6a80bdfc435f6c6eff77c9dd71cb38c..978d4947e1bc5cd5b13b1f25719268fa08b77297 100644
--- a/drivers/gpu/drm/sprd/sprd_dpu.c
+++ b/drivers/gpu/drm/sprd/sprd_dpu.c
@@ -27,6 +27,7 @@
 #include "sprd_dsi.h"
 
 /* Global control registers */
+#define REG_DPU_VERSION	0x00
 #define REG_DPU_CTRL	0x04
 #define REG_DPU_CFG0	0x08
 #define REG_PANEL_SIZE	0x20
@@ -406,6 +407,7 @@ static void sprd_dpu_init(struct sprd_dpu *dpu)
 {
 	struct dpu_context *ctx = &dpu->ctx;
 	u32 int_mask = 0;
+	u32 dpu_version = readl(ctx->base + REG_DPU_VERSION);
 
 	writel(0x00, ctx->base + REG_BG_COLOR);
 	writel(0x00, ctx->base + REG_MMU_EN);
@@ -418,10 +420,16 @@ static void sprd_dpu_init(struct sprd_dpu *dpu)
 	if (ctx->if_type == SPRD_DPU_IF_DPI) {
 		/* use dpi as interface */
 		dpu_reg_clr(ctx, REG_DPU_CFG0, BIT_DPU_IF_EDPI);
-		/* disable Halt function for SPRD DSI */
-		dpu_reg_clr(ctx, REG_DPI_CTRL, BIT_DPU_DPI_HALT_EN);
-		/* select te from external pad */
-		dpu_reg_set(ctx, REG_DPI_CTRL, BIT_DPU_EDPI_FROM_EXTERNAL_PAD);
+
+		if (dpu_version < 0x300) {
+			/* disable Halt function for SPRD DSI */
+			dpu_reg_clr(ctx, REG_DPI_CTRL, BIT_DPU_DPI_HALT_EN);
+			/* select te from external pad */
+			dpu_reg_set(ctx, REG_DPI_CTRL, BIT_DPU_EDPI_FROM_EXTERNAL_PAD);
+		} else {
+			/* enable Halt function for SPRD DSI */
+			dpu_reg_set(ctx, REG_DPI_CTRL, BIT_DPU_DPI_HALT_EN);
+		}
 
 		/* enable dpu update done INT */
 		int_mask |= BIT_DPU_INT_UPDATE_DONE;

-- 
2.50.0

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

* [PATCH v2 12/15] drm: sprd: always initialize DPU and DSI registers
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
                   ` (10 preceding siblings ...)
  2025-07-22 14:41 ` [PATCH v2 11/15] drm: sprd: add support for newer DPU versions Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  2025-07-22 14:41 ` [PATCH v2 13/15] drm: sprd: do not access IOMMU registers Otto Pflüger
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

When the Unisoc DRM driver is initialized for the first time to display
an image on the screen, reinitialize the display properly instead of
relying on the bootloader.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/gpu/drm/sprd/sprd_dpu.c | 8 ++++++++
 drivers/gpu/drm/sprd/sprd_dsi.c | 1 -
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c
index 978d4947e1bc5cd5b13b1f25719268fa08b77297..b946d015133db44d2d3d0b18803ed887b2b7ae2e 100644
--- a/drivers/gpu/drm/sprd/sprd_dpu.c
+++ b/drivers/gpu/drm/sprd/sprd_dpu.c
@@ -456,6 +456,14 @@ static void sprd_dpu_init(struct sprd_dpu *dpu)
 	}
 
 	writel(int_mask, ctx->base + REG_DPU_INT_EN);
+
+	/*
+	 * The DPU is usually enabled by the bootloader to show
+	 * a splash screen. Stop it here when the kernel initializes
+	 * the display.
+	 */
+	if (!ctx->stopped)
+		sprd_dpu_stop(dpu);
 }
 
 static void sprd_dpu_fini(struct sprd_dpu *dpu)
diff --git a/drivers/gpu/drm/sprd/sprd_dsi.c b/drivers/gpu/drm/sprd/sprd_dsi.c
index 2af4273a6c73185084290c9d14b8ac18914d514b..7186d11bbdc753f52aba18995f4863b572f4fecb 100644
--- a/drivers/gpu/drm/sprd/sprd_dsi.c
+++ b/drivers/gpu/drm/sprd/sprd_dsi.c
@@ -954,7 +954,6 @@ static int sprd_dsi_context_init(struct sprd_dsi *dsi,
 	ctx->max_rd_time = 6000;
 	ctx->int0_mask = 0xffffffff;
 	ctx->int1_mask = 0xffffffff;
-	ctx->enabled = true;
 
 	return 0;
 }

-- 
2.50.0

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

* [PATCH v2 13/15] drm: sprd: do not access IOMMU registers
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
                   ` (11 preceding siblings ...)
  2025-07-22 14:41 ` [PATCH v2 12/15] drm: sprd: always initialize DPU and DSI registers Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  2025-07-22 14:41 ` [PATCH v2 14/15] drm: sprd: implement IOMMU-based buffer management Otto Pflüger
  2025-07-22 14:41 ` [PATCH v2 15/15] drm: sprd: add fbdev support Otto Pflüger
  14 siblings, 0 replies; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

Changing the IOMMU registers results in conflicts with the sprd_iommu
driver. Remove all references to IOMMU registers in the graphics driver.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/gpu/drm/sprd/sprd_dpu.c | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c
index b946d015133db44d2d3d0b18803ed887b2b7ae2e..acf28de3fd08edaad03f01104f3e6cc7c243123c 100644
--- a/drivers/gpu/drm/sprd/sprd_dpu.c
+++ b/drivers/gpu/drm/sprd/sprd_dpu.c
@@ -55,14 +55,6 @@
 #define REG_DPI_H_TIMING	0x1F4
 #define REG_DPI_V_TIMING	0x1F8
 
-/* MMU control registers */
-#define REG_MMU_EN			0x800
-#define REG_MMU_VPN_RANGE		0x80C
-#define REG_MMU_PPN1			0x83C
-#define REG_MMU_RANGE1			0x840
-#define REG_MMU_PPN2			0x844
-#define REG_MMU_RANGE2			0x848
-
 /* Global control bits */
 #define BIT_DPU_RUN			BIT(0)
 #define BIT_DPU_STOP			BIT(1)
@@ -410,12 +402,6 @@ static void sprd_dpu_init(struct sprd_dpu *dpu)
 	u32 dpu_version = readl(ctx->base + REG_DPU_VERSION);
 
 	writel(0x00, ctx->base + REG_BG_COLOR);
-	writel(0x00, ctx->base + REG_MMU_EN);
-	writel(0x00, ctx->base + REG_MMU_PPN1);
-	writel(0xffff, ctx->base + REG_MMU_RANGE1);
-	writel(0x00, ctx->base + REG_MMU_PPN2);
-	writel(0xffff, ctx->base + REG_MMU_RANGE2);
-	writel(0x1ffff, ctx->base + REG_MMU_VPN_RANGE);
 
 	if (ctx->if_type == SPRD_DPU_IF_DPI) {
 		/* use dpi as interface */

-- 
2.50.0

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

* [PATCH v2 14/15] drm: sprd: implement IOMMU-based buffer management
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
                   ` (12 preceding siblings ...)
  2025-07-22 14:41 ` [PATCH v2 13/15] drm: sprd: do not access IOMMU registers Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  2025-07-23 22:43   ` kernel test robot
  2025-07-22 14:41 ` [PATCH v2 15/15] drm: sprd: add fbdev support Otto Pflüger
  14 siblings, 1 reply; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

The default GEM DMA helpers use the DMA API to allocate and map buffers.
Since the DMA API integrates IOMMU support only in simple cases where the
main device has one IOMMU attached to it, this is not sufficient for
Unisoc SoCs in which multiple DPU instances with separate IOMMUs can
exist. Although this driver does not yet support such SoCs, the device
tree bindings specify that IOMMUs are connected to their respective DPU
nodes and not to the main "display-subsystem" node.

To utilize an IOMMU connected to the DPU node without ruling out future
use-cases as described in [1], implement buffer allocation and mapping
by using the IOMMU API directly, as done in other DRM drivers, e.g.
Rockchip and Tegra. Adding a second DPU should now automatically attach
its IOMMU to the same domain as the first IOMMU, causing the address
space to be shared between both DPUs.

[1]: https://lore.kernel.org/dri-devel/CAFPSGXZLXh__GuXT2NPqF0jpO2DnMAhz+NtE721EZfMCSKLBjQ@mail.gmail.com/

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/gpu/drm/sprd/Makefile   |   3 +-
 drivers/gpu/drm/sprd/sprd_dpu.c |  15 ++
 drivers/gpu/drm/sprd/sprd_drm.c |  51 +++++-
 drivers/gpu/drm/sprd/sprd_drm.h |  10 ++
 drivers/gpu/drm/sprd/sprd_gem.c | 343 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sprd/sprd_gem.h |  34 ++++
 6 files changed, 454 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sprd/Makefile b/drivers/gpu/drm/sprd/Makefile
index e82e6a6f89de2576b12af1975cc27045f3887570..80f6c66145b14372e0ce1f54ebdc09d1f4c2a569 100644
--- a/drivers/gpu/drm/sprd/Makefile
+++ b/drivers/gpu/drm/sprd/Makefile
@@ -3,6 +3,7 @@
 sprd-drm-y := sprd_drm.o \
 	sprd_dpu.o \
 	sprd_dsi.o \
+	sprd_gem.o \
 	megacores_pll.o
 
-obj-$(CONFIG_DRM_SPRD) += sprd-drm.o
\ No newline at end of file
+obj-$(CONFIG_DRM_SPRD) += sprd-drm.o
diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c
index acf28de3fd08edaad03f01104f3e6cc7c243123c..c18fabbf670208f744cd59c8352726dc8c098590 100644
--- a/drivers/gpu/drm/sprd/sprd_dpu.c
+++ b/drivers/gpu/drm/sprd/sprd_dpu.c
@@ -841,11 +841,26 @@ static int sprd_dpu_bind(struct device *dev, struct device *master, void *data)
 	if (ret)
 		return ret;
 
+	if (device_iommu_mapped(dev)) {
+		ret = sprd_drm_iommu_attach(drm, dev);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
+static void sprd_dpu_unbind(struct device *dev,
+			    struct device *master, void *data)
+{
+	struct drm_device *drm = data;
+
+	sprd_drm_iommu_detach(drm, dev);
+}
+
 static const struct component_ops dpu_component_ops = {
 	.bind = sprd_dpu_bind,
+	.unbind = sprd_dpu_unbind,
 };
 
 static const struct of_device_id dpu_match_table[] = {
diff --git a/drivers/gpu/drm/sprd/sprd_drm.c b/drivers/gpu/drm/sprd/sprd_drm.c
index ceacdcb7c566d00b98d83c27dbab80523bc6a7d5..4abc0b0b14f46ced91ea4478d861931db83dc87c 100644
--- a/drivers/gpu/drm/sprd/sprd_drm.c
+++ b/drivers/gpu/drm/sprd/sprd_drm.c
@@ -5,6 +5,7 @@
 
 #include <linux/component.h>
 #include <linux/dma-mapping.h>
+#include <linux/iommu.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -20,6 +21,7 @@
 #include <drm/drm_vblank.h>
 
 #include "sprd_drm.h"
+#include "sprd_gem.h"
 
 #define DRIVER_NAME	"sprd"
 #define DRIVER_DESC	"Spreadtrum SoCs' DRM Driver"
@@ -54,7 +56,8 @@ static struct drm_driver sprd_drm_drv = {
 	.fops			= &sprd_drm_fops,
 
 	/* GEM Operations */
-	DRM_GEM_DMA_DRIVER_OPS,
+	.dumb_create		= sprd_gem_dumb_create,
+	.gem_prime_import_sg_table = sprd_gem_prime_import_sg_table,
 
 	.name			= DRIVER_NAME,
 	.desc			= DRIVER_DESC,
@@ -62,6 +65,49 @@ static struct drm_driver sprd_drm_drv = {
 	.minor			= DRIVER_MINOR,
 };
 
+int sprd_drm_iommu_attach(struct drm_device *drm, struct device *dpu_dev)
+{
+	struct sprd_drm *sprd = to_sprd_drm(drm);
+	struct iommu_domain_geometry *geometry;
+	int ret;
+
+	if (!sprd->iommu_domain) {
+		sprd->iommu_domain = iommu_paging_domain_alloc(dpu_dev);
+		if (IS_ERR(sprd->iommu_domain)) {
+			ret = PTR_ERR(sprd->iommu_domain);
+			sprd->iommu_domain = NULL;
+			return ret;
+		}
+
+		geometry = &sprd->iommu_domain->geometry;
+
+		drm_mm_init(&sprd->mm, geometry->aperture_start,
+			    geometry->aperture_end -
+			    geometry->aperture_start + 1);
+		mutex_init(&sprd->mm_lock);
+	}
+
+	return iommu_attach_device(sprd->iommu_domain, dpu_dev);
+}
+
+void sprd_drm_iommu_detach(struct drm_device *drm, struct device *dpu_dev)
+{
+	struct sprd_drm *sprd = to_sprd_drm(drm);
+
+	if (sprd->iommu_domain)
+		iommu_detach_device(sprd->iommu_domain, dpu_dev);
+}
+
+static void sprd_drm_iommu_cleanup(struct sprd_drm *sprd)
+{
+	if (!sprd->iommu_domain)
+		return;
+
+	mutex_destroy(&sprd->mm_lock);
+	drm_mm_takedown(&sprd->mm);
+	iommu_domain_free(sprd->iommu_domain);
+}
+
 static int sprd_drm_bind(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -112,6 +158,7 @@ static int sprd_drm_bind(struct device *dev)
 	drm_kms_helper_poll_fini(drm);
 err_unbind_all:
 	component_unbind_all(drm->dev, drm);
+	sprd_drm_iommu_cleanup(sprd);
 	return ret;
 }
 
@@ -124,6 +171,8 @@ static void sprd_drm_unbind(struct device *dev)
 	drm_kms_helper_poll_fini(drm);
 
 	component_unbind_all(drm->dev, drm);
+
+	sprd_drm_iommu_cleanup(to_sprd_drm(drm));
 }
 
 static const struct component_master_ops drm_component_ops = {
diff --git a/drivers/gpu/drm/sprd/sprd_drm.h b/drivers/gpu/drm/sprd/sprd_drm.h
index 95d1b972f333c7056ac940d91255c6a812d264de..fa1f01ead6a55aa52ece483fd8f0bca2fad7a8a0 100644
--- a/drivers/gpu/drm/sprd/sprd_drm.h
+++ b/drivers/gpu/drm/sprd/sprd_drm.h
@@ -7,12 +7,22 @@
 #define _SPRD_DRM_H_
 
 #include <drm/drm_atomic.h>
+#include <drm/drm_mm.h>
 #include <drm/drm_print.h>
 
 struct sprd_drm {
 	struct drm_device drm;
+
+	struct iommu_domain *iommu_domain;
+	struct mutex mm_lock;
+	struct drm_mm mm;
 };
 
+#define to_sprd_drm(x)	container_of(x, struct sprd_drm, drm)
+
+int sprd_drm_iommu_attach(struct drm_device *drm, struct device *dpu_dev);
+void sprd_drm_iommu_detach(struct drm_device *drm, struct device *dpu_dev);
+
 extern struct platform_driver sprd_dpu_driver;
 extern struct platform_driver sprd_dsi_driver;
 
diff --git a/drivers/gpu/drm/sprd/sprd_gem.c b/drivers/gpu/drm/sprd/sprd_gem.c
new file mode 100644
index 0000000000000000000000000000000000000000..5fa56ac35e977eae5f01d3f5c37873fa631fb224
--- /dev/null
+++ b/drivers/gpu/drm/sprd/sprd_gem.c
@@ -0,0 +1,343 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Unisoc Inc.
+ * Copyright (C) 2025 Otto Pflüger
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/iommu.h>
+#include <linux/vmalloc.h>
+
+#include <drm/drm_gem_dma_helper.h>
+
+#include "sprd_drm.h"
+#include "sprd_gem.h"
+
+static int sprd_gem_get_pages(struct sprd_gem_obj *sprd_gem)
+{
+	struct drm_gem_object *obj = &sprd_gem->base;
+	struct scatterlist *s;
+	int i, ret;
+
+	sprd_gem->pages = drm_gem_get_pages(obj);
+	if (IS_ERR(sprd_gem->pages))
+		return PTR_ERR(sprd_gem->pages);
+
+	sprd_gem->sgt = drm_prime_pages_to_sg(obj->dev, sprd_gem->pages,
+					      obj->size >> PAGE_SHIFT);
+	if (IS_ERR(sprd_gem->sgt)) {
+		ret = PTR_ERR(sprd_gem->sgt);
+		goto err_put_pages;
+	}
+
+	/*
+	 * From drivers/gpu/drm/rockchip/rockchip_drm_gem.c:
+	 *
+	 * Fake up the SG table so that dma_sync_sg_for_device() can be used
+	 * to flush the pages associated with it.
+	 *
+	 * TODO: Replace this by drm_clflush_sg() once it can be implemented
+	 * without relying on symbols that are not exported.
+	 */
+	for_each_sgtable_sg(sprd_gem->sgt, s, i)
+		sg_dma_address(s) = sg_phys(s);
+
+	dma_sync_sgtable_for_device(obj->dev->dev, sprd_gem->sgt, DMA_TO_DEVICE);
+
+	return 0;
+
+err_put_pages:
+	drm_gem_put_pages(obj, sprd_gem->pages, false, false);
+	return ret;
+}
+
+static void sprd_gem_put_pages(struct sprd_gem_obj *sprd_gem)
+{
+	sg_free_table(sprd_gem->sgt);
+	kfree(sprd_gem->sgt);
+	drm_gem_put_pages(&sprd_gem->base, sprd_gem->pages, true, true);
+}
+
+static int sprd_gem_iommu_map(struct sprd_gem_obj *sprd_gem)
+{
+	struct drm_gem_object *obj = &sprd_gem->base;
+	struct sprd_drm *sprd = to_sprd_drm(obj->dev);
+	ssize_t ret;
+
+	mutex_lock(&sprd->mm_lock);
+	ret = drm_mm_insert_node_generic(&sprd->mm, &sprd_gem->mm,
+					 obj->size, PAGE_SIZE, 0, 0);
+	mutex_unlock(&sprd->mm_lock);
+
+	if (ret) {
+		drm_err(obj->dev, "out of I/O virtual memory\n");
+		return ret;
+	}
+
+	sprd_gem->dma_addr = sprd_gem->mm.start;
+
+	ret = iommu_map_sgtable(sprd->iommu_domain, sprd_gem->dma_addr,
+				sprd_gem->sgt, IOMMU_READ | IOMMU_WRITE);
+	if (ret < (ssize_t)obj->size) {
+		drm_err(obj->dev,
+			"failed to map buffer: requested=%zd, ret=%zd\n",
+			obj->size, ret);
+		ret = -ENOMEM;
+		goto err_remove_node;
+	}
+
+	sprd_gem->map_size = ret;
+
+	return 0;
+
+err_remove_node:
+	mutex_lock(&sprd->mm_lock);
+	drm_mm_remove_node(&sprd_gem->mm);
+	mutex_unlock(&sprd->mm_lock);
+	return ret;
+}
+
+static void sprd_gem_iommu_unmap(struct sprd_gem_obj *sprd_gem)
+{
+	struct drm_gem_object *obj = &sprd_gem->base;
+	struct sprd_drm *sprd = to_sprd_drm(obj->dev);
+
+	iommu_unmap(sprd->iommu_domain, sprd_gem->dma_addr, sprd_gem->map_size);
+
+	mutex_lock(&sprd->mm_lock);
+	drm_mm_remove_node(&sprd_gem->mm);
+	mutex_unlock(&sprd->mm_lock);
+}
+
+static void sprd_gem_free_object(struct drm_gem_object *obj)
+{
+	struct sprd_drm *sprd = to_sprd_drm(obj->dev);
+	struct sprd_gem_obj *sprd_gem = to_sprd_gem_obj(obj);
+
+	if (obj->import_attach) {
+		if (sprd->iommu_domain)
+			sprd_gem_iommu_unmap(sprd_gem);
+		drm_prime_gem_destroy(obj, sprd_gem->sgt);
+	} else {
+		if (sprd->iommu_domain) {
+			sprd_gem_iommu_unmap(sprd_gem);
+			sprd_gem_put_pages(sprd_gem);
+		} else {
+			dma_free_wc(obj->dev->dev, obj->size,
+				    sprd_gem->vaddr, sprd_gem->dma_addr);
+		}
+	}
+
+	drm_gem_object_release(obj);
+
+	kfree(sprd_gem);
+}
+
+static struct sg_table *sprd_gem_object_get_sg_table(struct drm_gem_object *obj)
+{
+	struct sprd_gem_obj *sprd_gem = to_sprd_gem_obj(obj);
+	struct sg_table *sgt;
+	int ret;
+
+	if (sprd_gem->pages)
+		return drm_prime_pages_to_sg(obj->dev, sprd_gem->pages,
+					     obj->size >> PAGE_SHIFT);
+
+	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
+	if (!sgt)
+		return ERR_PTR(-ENOMEM);
+
+	ret = dma_get_sgtable(obj->dev->dev, sgt, sprd_gem->vaddr,
+			      sprd_gem->dma_addr, obj->size);
+	if (ret < 0) {
+		kfree(sgt);
+		return ERR_PTR(ret);
+	}
+
+	return 0;
+}
+
+static int sprd_gem_object_vmap(struct drm_gem_object *obj,
+				struct iosys_map *map)
+{
+	struct sprd_gem_obj *sprd_gem = to_sprd_gem_obj(obj);
+	void *vaddr;
+
+	if (!sprd_gem->pages) {
+		iosys_map_set_vaddr(map, sprd_gem->vaddr);
+		return 0;
+	}
+
+	vaddr = vmap(sprd_gem->pages, sprd_gem->base.size >> PAGE_SHIFT,
+		     VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+	if (!vaddr)
+		return -ENOMEM;
+
+	iosys_map_set_vaddr(map, vaddr);
+
+	return 0;
+}
+
+static void sprd_gem_object_vunmap(struct drm_gem_object *obj,
+				   struct iosys_map *map)
+{
+	struct sprd_gem_obj *sprd_gem = to_sprd_gem_obj(obj);
+
+	if (sprd_gem->pages)
+		vunmap(map->vaddr);
+}
+
+static int sprd_gem_object_mmap(struct drm_gem_object *obj,
+				struct vm_area_struct *vma)
+{
+	struct sprd_gem_obj *sprd_gem = to_sprd_gem_obj(obj);
+	int ret;
+
+	/*
+	 * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
+	 * vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
+	 * the whole buffer.
+	 */
+	vm_flags_mod(vma, VM_DONTEXPAND, VM_PFNMAP);
+	vma->vm_pgoff = 0;
+
+	vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
+
+	if (sprd_gem->pages)
+		ret = vm_map_pages(vma, sprd_gem->pages,
+				   obj->size >> PAGE_SHIFT);
+	else
+		ret = dma_mmap_wc(obj->dev->dev, vma, sprd_gem->vaddr,
+				  sprd_gem->dma_addr, obj->size);
+
+	if (ret)
+		drm_gem_vm_close(vma);
+
+	return ret;
+}
+
+static const struct drm_gem_object_funcs sprd_gem_object_funcs = {
+	.free = sprd_gem_free_object,
+	.get_sg_table = sprd_gem_object_get_sg_table,
+	.vmap = sprd_gem_object_vmap,
+	.vunmap = sprd_gem_object_vunmap,
+	.mmap = sprd_gem_object_mmap,
+	.vm_ops = &drm_gem_dma_vm_ops,
+};
+
+static struct sprd_gem_obj *sprd_gem_obj_create(struct drm_device *drm,
+						unsigned long size)
+{
+	struct sprd_gem_obj *sprd_gem;
+	int ret;
+
+	sprd_gem = kzalloc(sizeof(*sprd_gem), GFP_KERNEL);
+	if (!sprd_gem)
+		return ERR_PTR(-ENOMEM);
+
+	sprd_gem->base.funcs = &sprd_gem_object_funcs;
+
+	ret = drm_gem_object_init(drm, &sprd_gem->base, size);
+	if (ret < 0) {
+		drm_err(drm, "failed to initialize gem object\n");
+		goto err_free;
+	}
+
+	return sprd_gem;
+
+err_free:
+	kfree(sprd_gem);
+	return ERR_PTR(ret);
+}
+
+int sprd_gem_dumb_create(struct drm_file *file_priv, struct drm_device *drm,
+			 struct drm_mode_create_dumb *args)
+{
+	struct sprd_drm *sprd = to_sprd_drm(drm);
+	struct sprd_gem_obj *sprd_gem;
+	int ret;
+
+	args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+	args->size = round_up(args->pitch * args->height, PAGE_SIZE);
+
+	sprd_gem = sprd_gem_obj_create(drm, args->size);
+	if (IS_ERR(sprd_gem))
+		return PTR_ERR(sprd_gem);
+
+	if (sprd->iommu_domain) {
+		ret = sprd_gem_get_pages(sprd_gem);
+		if (ret < 0)
+			goto err_free_object;
+
+		ret = sprd_gem_iommu_map(sprd_gem);
+		if (ret < 0) {
+			sprd_gem_put_pages(sprd_gem);
+			goto err_free_object;
+		}
+	} else {
+		sprd_gem->vaddr = dma_alloc_wc(drm->dev, args->size,
+					       &sprd_gem->dma_addr,
+					       GFP_KERNEL);
+		if (!sprd_gem->vaddr) {
+			drm_err(drm, "failed to allocate buffer of size %llu\n",
+				args->size);
+			ret = -ENOMEM;
+			goto err_free_object;
+		}
+	}
+
+	ret = drm_gem_handle_create(file_priv, &sprd_gem->base, &args->handle);
+	if (ret)
+		goto err_free_buf;
+
+	/* The handle holds its own reference, so we can drop ours now. */
+	drm_gem_object_put(&sprd_gem->base);
+
+	return 0;
+
+err_free_buf:
+	if (sprd->iommu_domain) {
+		sprd_gem_iommu_unmap(sprd_gem);
+		sprd_gem_put_pages(sprd_gem);
+	} else {
+		dma_free_wc(drm->dev, args->size, sprd_gem->vaddr,
+			    sprd_gem->dma_addr);
+	}
+err_free_object:
+	drm_gem_object_release(&sprd_gem->base);
+	kfree(sprd_gem);
+	return ret;
+}
+
+struct drm_gem_object *
+sprd_gem_prime_import_sg_table(struct drm_device *drm,
+			       struct dma_buf_attachment *attach,
+			       struct sg_table *sgt)
+{
+	struct sprd_drm *sprd = to_sprd_drm(drm);
+	struct sprd_gem_obj *sprd_gem;
+	int ret;
+
+	sprd_gem = sprd_gem_obj_create(drm, attach->dmabuf->size);
+	if (IS_ERR(sprd_gem))
+		return ERR_CAST(sprd_gem);
+
+	sprd_gem->sgt = sgt;
+
+	if (sprd->iommu_domain) {
+		ret = sprd_gem_iommu_map(sprd_gem);
+		if (ret < 0) {
+			drm_err(drm, "failed to import with IOMMU: %d\n", ret);
+			goto err_free_object;
+		}
+	} else {
+		sprd_gem->dma_addr = sg_dma_address(sgt->sgl);
+	}
+
+	return &sprd_gem->base;
+
+err_free_object:
+	drm_gem_object_release(&sprd_gem->base);
+	kfree(sprd_gem);
+	return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/sprd/sprd_gem.h b/drivers/gpu/drm/sprd/sprd_gem.h
new file mode 100644
index 0000000000000000000000000000000000000000..9531f37836c9f032aad28e4c8232651055f3b98c
--- /dev/null
+++ b/drivers/gpu/drm/sprd/sprd_gem.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 Unisoc Inc.
+ */
+
+#ifndef _SPRD_GEM_H_
+#define _SPRD_GEM_H_
+
+#include <drm/drm_gem.h>
+
+struct sprd_gem_obj {
+	struct drm_gem_object	base;
+	dma_addr_t		dma_addr;
+	struct sg_table		*sgt;
+	void			*vaddr;
+
+	/* Used when IOMMU is enabled */
+	struct drm_mm_node	mm;
+	struct page		**pages;
+	size_t			map_size;
+};
+
+#define to_sprd_gem_obj(x)	container_of(x, struct sprd_gem_obj, base)
+
+int sprd_gem_dumb_create(struct drm_file *file_priv,
+			 struct drm_device *dev,
+			 struct drm_mode_create_dumb *args);
+
+struct drm_gem_object *
+sprd_gem_prime_import_sg_table(struct drm_device *dev,
+			       struct dma_buf_attachment *attach,
+			       struct sg_table *sgtb);
+
+#endif

-- 
2.50.0

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

* [PATCH v2 15/15] drm: sprd: add fbdev support
  2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
                   ` (13 preceding siblings ...)
  2025-07-22 14:41 ` [PATCH v2 14/15] drm: sprd: implement IOMMU-based buffer management Otto Pflüger
@ 2025-07-22 14:41 ` Otto Pflüger
  14 siblings, 0 replies; 24+ messages in thread
From: Otto Pflüger @ 2025-07-22 14:41 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang
  Cc: dri-devel, devicetree, linux-kernel, Otto Pflüger

Set up the internal fbdev client in the Unisoc DRM driver. This is
needed to make the framebuffer console work.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/gpu/drm/sprd/sprd_drm.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/sprd/sprd_drm.c b/drivers/gpu/drm/sprd/sprd_drm.c
index 4abc0b0b14f46ced91ea4478d861931db83dc87c..6153c06573a355457f897c66c91ece409aba62bf 100644
--- a/drivers/gpu/drm/sprd/sprd_drm.c
+++ b/drivers/gpu/drm/sprd/sprd_drm.c
@@ -12,8 +12,10 @@
 #include <linux/of_graph.h>
 #include <linux/platform_device.h>
 
+#include <drm/clients/drm_client_setup.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_fbdev_dma.h>
 #include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_of.h>
@@ -59,6 +61,8 @@ static struct drm_driver sprd_drm_drv = {
 	.dumb_create		= sprd_gem_dumb_create,
 	.gem_prime_import_sg_table = sprd_gem_prime_import_sg_table,
 
+	DRM_FBDEV_DMA_DRIVER_OPS,
+
 	.name			= DRIVER_NAME,
 	.desc			= DRIVER_DESC,
 	.major			= DRIVER_MAJOR,
@@ -152,6 +156,8 @@ static int sprd_drm_bind(struct device *dev)
 	if (ret < 0)
 		goto err_kms_helper_poll_fini;
 
+	drm_client_setup(drm, NULL);
+
 	return 0;
 
 err_kms_helper_poll_fini:

-- 
2.50.0

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

* Re: [PATCH v2 10/15] drm: sprd: add clock gating support
  2025-07-22 14:41 ` [PATCH v2 10/15] drm: sprd: add clock gating support Otto Pflüger
@ 2025-07-23  7:00   ` Maxime Ripard
  2025-07-23  8:32     ` Otto Pflüger
  0 siblings, 1 reply; 24+ messages in thread
From: Maxime Ripard @ 2025-07-23  7:00 UTC (permalink / raw)
  To: Otto Pflüger
  Cc: David Airlie, Simona Vetter, Maarten Lankhorst, Thomas Zimmermann,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Orson Zhai,
	Baolin Wang, Chunyan Zhang, Kevin Tang, dri-devel, devicetree,
	linux-kernel

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

Hi,

On Tue, Jul 22, 2025 at 04:41:12PM +0200, Otto Pflüger wrote:
> Enable the DPU and DSI clocks specified in the device tree.
> Disable the DSI clock when it is not needed.
> 
> Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
> ---
>  drivers/gpu/drm/sprd/sprd_dpu.c | 7 +++++++
>  drivers/gpu/drm/sprd/sprd_dpu.h | 1 +
>  drivers/gpu/drm/sprd/sprd_dsi.c | 9 +++++++++
>  drivers/gpu/drm/sprd/sprd_dsi.h | 4 +++-
>  4 files changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c
> index 0d9eb778794d92418b39f8535d94abde3566de43..9d274600e6a80bdfc435f6c6eff77c9dd71cb38c 100644
> --- a/drivers/gpu/drm/sprd/sprd_dpu.c
> +++ b/drivers/gpu/drm/sprd/sprd_dpu.c
> @@ -3,6 +3,7 @@
>   * Copyright (C) 2020 Unisoc Inc.
>   */
>  
> +#include <linux/clk.h>
>  #include <linux/component.h>
>  #include <linux/delay.h>
>  #include <linux/dma-buf.h>
> @@ -794,6 +795,12 @@ static int sprd_dpu_context_init(struct sprd_dpu *dpu,
>  	if (ctx->irq < 0)
>  		return ctx->irq;
>  
> +	ctx->clk = devm_clk_get_optional_enabled(dev, "core");
> +	if (IS_ERR(ctx->clk)) {
> +		dev_err(dev, "failed to get DPU core clock\n");
> +		return PTR_ERR(ctx->clk);
> +	}
> +
>  	/* disable and clear interrupts before register dpu IRQ. */
>  	writel(0x00, ctx->base + REG_DPU_INT_EN);
>  	writel(0xff, ctx->base + REG_DPU_INT_CLR);
> diff --git a/drivers/gpu/drm/sprd/sprd_dpu.h b/drivers/gpu/drm/sprd/sprd_dpu.h
> index 157a78f24dc18b071602552ea9d005af66525263..d48b922de580a8a4bf07c4610c431d3321f7b810 100644
> --- a/drivers/gpu/drm/sprd/sprd_dpu.h
> +++ b/drivers/gpu/drm/sprd/sprd_dpu.h
> @@ -44,6 +44,7 @@ enum {
>   */
>  struct dpu_context {
>  	void __iomem *base;
> +	struct clk *clk;
>  	int irq;
>  	u8 if_type;
>  	struct videomode vm;
> diff --git a/drivers/gpu/drm/sprd/sprd_dsi.c b/drivers/gpu/drm/sprd/sprd_dsi.c
> index e01d1d28fe579644ec2e0c83ec9170269932adfe..2af4273a6c73185084290c9d14b8ac18914d514b 100644
> --- a/drivers/gpu/drm/sprd/sprd_dsi.c
> +++ b/drivers/gpu/drm/sprd/sprd_dsi.c
> @@ -828,6 +828,8 @@ static void sprd_dsi_bridge_pre_enable(struct drm_bridge *bridge)
>  	struct sprd_dsi *dsi = bridge_to_dsi(bridge);
>  	struct dsi_context *ctx = &dsi->ctx;
>  
> +	clk_prepare_enable(ctx->clk);
> +
>  	if (ctx->enabled) {
>  		drm_warn(dsi->drm, "dsi is initialized\n");
>  		return;
> @@ -875,6 +877,8 @@ static void sprd_dsi_bridge_post_disable(struct drm_bridge *bridge)
>  	sprd_dphy_fini(ctx);
>  	sprd_dsi_fini(ctx);
>  
> +	clk_disable_unprepare(ctx->clk);
> +
>  	ctx->enabled = false;
>  }

I'm a bit confused. Why do you need to enable / disable that clock in
pre_enable / post_disable, if you already enabled it at probe?

Maxime

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

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

* Re: [PATCH v2 04/15] drm: of: try binding port parent node instead of the port itself
  2025-07-22 14:41 ` [PATCH v2 04/15] drm: of: try binding port parent node instead of the port itself Otto Pflüger
@ 2025-07-23  7:02   ` Maxime Ripard
  0 siblings, 0 replies; 24+ messages in thread
From: Maxime Ripard @ 2025-07-23  7:02 UTC (permalink / raw)
  To: Otto Pflüger
  Cc: David Airlie, Simona Vetter, Maarten Lankhorst, Thomas Zimmermann,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Orson Zhai,
	Baolin Wang, Chunyan Zhang, Kevin Tang, dri-devel, devicetree,
	linux-kernel

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

On Tue, Jul 22, 2025 at 04:41:06PM +0200, Otto Pflüger wrote:
> The drm_of_component_probe function is intended to bind all devices in
> an OF graph given a set of ports linked using the "ports" property on a
> main device node. This means that it should also bind the components
> providing these ports, not just the components of other ports connected
> to them. In order to do this, it calls drm_of_component_match_add with
> a pointer to each port node after checking that its parent node is a
> device.
> 
> However, when given a pointer to the port node, the compare_of callback
> does not match it with a device node and thus fails to detect that the
> node belongs to a component. Fix this by passing a pointer to the parent
> node here too.
> 
> Currently only the Unisoc platform driver relies on this feature, which
> was previously broken and is fixed by this change. On other platforms,
> the "ports" property points to ports that are not part of a component,
> i.e. the components only have indirect connections to the main node.
> 
> Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>

Should this get a Fixes tag?

Maxime

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

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

* Re: [PATCH v2 01/15] dt-bindings: display: sprd: adapt for UMS9230 support
  2025-07-22 14:41 ` [PATCH v2 01/15] dt-bindings: display: sprd: adapt for UMS9230 support Otto Pflüger
@ 2025-07-23  7:50   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 24+ messages in thread
From: Krzysztof Kozlowski @ 2025-07-23  7:50 UTC (permalink / raw)
  To: Otto Pflüger
  Cc: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang, dri-devel,
	devicetree, linux-kernel

On Tue, Jul 22, 2025 at 04:41:03PM +0200, Otto Pflüger wrote:
> Add the compatible strings for the display controller found in the
> UMS9230 SoC and introduce more descriptive names for the clocks.
> 
> Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
> ---
>  .../bindings/display/sprd/sprd,sharkl3-dpu.yaml    | 24 +++++++++++++++-------
>  .../display/sprd/sprd,sharkl3-dsi-host.yaml        | 15 ++++++++++----
>  2 files changed, 28 insertions(+), 11 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml b/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml
> index 8c52fa0ea5f8ee2149ebf1d4b0d5b052832e3d97..7f34652080b22e7b7072a709fd390a72375110ef 100644
> --- a/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml
> +++ b/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml
> @@ -16,7 +16,12 @@ description: |
>  
>  properties:
>    compatible:
> -    const: sprd,sharkl3-dpu
> +    oneOf:
> +      - items:
> +          - enum:
> +              - sprd,ums9230-dpu
> +          - const: sprd,sharkl3-dpu
> +      - const: sprd,sharkl3-dpu
>  
>    reg:
>      maxItems: 1
> @@ -28,9 +33,14 @@ properties:
>      maxItems: 2
>  
>    clock-names:
> -    items:
> -      - const: clk_src_128m
> -      - const: clk_src_384m
> +    oneOf:
> +      - deprecated: true
> +        items:
> +          - const: clk_src_128m
> +          - const: clk_src_384m
> +      - items:
> +          - const: core
> +          - const: dpi

This should be rather a separate change with its own explanation. You
are affecting/changing existing binding and new device bringup should
usually not affect it. Same with second file.

Changes are fine, just split to clearly see the impact on existing
binding.

Best regards,
Krzysztof


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

* Re: [PATCH v2 02/15] dt-bindings: display: sprd: add memory-region property
  2025-07-22 14:41 ` [PATCH v2 02/15] dt-bindings: display: sprd: add memory-region property Otto Pflüger
@ 2025-07-23  7:51   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 24+ messages in thread
From: Krzysztof Kozlowski @ 2025-07-23  7:51 UTC (permalink / raw)
  To: Otto Pflüger
  Cc: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang, dri-devel,
	devicetree, linux-kernel

On Tue, Jul 22, 2025 at 04:41:04PM +0200, Otto Pflüger wrote:
> Explain that the DPU node supports a memory-region property that can be
> used to describe an initial framebuffer set up by the bootloader,
> usually in order to create a passthrough mapping for this framebuffer
> when the IOMMU is used.
> 
> Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
> ---
>  .../devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml        | 8 ++++++++
>  1 file changed, 8 insertions(+)

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

Best regards,
Krzysztof


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

* Re: [PATCH v2 03/15] dt-bindings: display: sprd: allow attaching a DSI panel
  2025-07-22 14:41 ` [PATCH v2 03/15] dt-bindings: display: sprd: allow attaching a DSI panel Otto Pflüger
@ 2025-07-23  7:54   ` Krzysztof Kozlowski
  2025-07-23  8:03     ` Krzysztof Kozlowski
  0 siblings, 1 reply; 24+ messages in thread
From: Krzysztof Kozlowski @ 2025-07-23  7:54 UTC (permalink / raw)
  To: Otto Pflüger
  Cc: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang, dri-devel,
	devicetree, linux-kernel

On Tue, Jul 22, 2025 at 04:41:05PM +0200, Otto Pflüger wrote:
> +      port@1:
> +        $ref: /schemas/graph.yaml#/$defs/port-base
> +        unevaluatedProperties: false
> +        properties:
> +          endpoint:
> +            $ref: /schemas/media/video-interfaces.yaml#
> +            unevaluatedProperties: false
> +            description: The output endpoint, usually connected to the panel

I never remember if the output should be a "port" here or a panel@ child
(as described by dsi-controller.yaml). Various users do it differently.

Syntax looks fine to me, so happy to get second opinion on above point.

Anyway:

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

Best regards,
Krzysztof


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

* Re: [PATCH v2 03/15] dt-bindings: display: sprd: allow attaching a DSI panel
  2025-07-23  7:54   ` Krzysztof Kozlowski
@ 2025-07-23  8:03     ` Krzysztof Kozlowski
  0 siblings, 0 replies; 24+ messages in thread
From: Krzysztof Kozlowski @ 2025-07-23  8:03 UTC (permalink / raw)
  To: Otto Pflüger
  Cc: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Kevin Tang, dri-devel,
	devicetree, linux-kernel

On Wed, Jul 23, 2025 at 09:54:57AM +0200, Krzysztof Kozlowski wrote:
> On Tue, Jul 22, 2025 at 04:41:05PM +0200, Otto Pflüger wrote:
> > +      port@1:
> > +        $ref: /schemas/graph.yaml#/$defs/port-base
> > +        unevaluatedProperties: false
> > +        properties:
> > +          endpoint:
> > +            $ref: /schemas/media/video-interfaces.yaml#
> > +            unevaluatedProperties: false
> > +            description: The output endpoint, usually connected to the panel
> 
> I never remember if the output should be a "port" here or a panel@ child
> (as described by dsi-controller.yaml). Various users do it differently.
> 
> Syntax looks fine to me, so happy to get second opinion on above point.

I got now explanation from Neil, so all is fine.

> 
> Anyway:
> 
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

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

* Re: [PATCH v2 10/15] drm: sprd: add clock gating support
  2025-07-23  7:00   ` Maxime Ripard
@ 2025-07-23  8:32     ` Otto Pflüger
  0 siblings, 0 replies; 24+ messages in thread
From: Otto Pflüger @ 2025-07-23  8:32 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: David Airlie, Simona Vetter, Maarten Lankhorst, Thomas Zimmermann,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Orson Zhai,
	Baolin Wang, Chunyan Zhang, Kevin Tang, dri-devel, devicetree,
	linux-kernel

Hi Maxime,

On Wed, Jul 23, 2025 at 09:00:28AM +0200, Maxime Ripard wrote:
> Hi,
> 
> On Tue, Jul 22, 2025 at 04:41:12PM +0200, Otto Pflüger wrote:
> > Enable the DPU and DSI clocks specified in the device tree.
> > Disable the DSI clock when it is not needed.
> > 
> > Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
> > ---
> >  drivers/gpu/drm/sprd/sprd_dpu.c | 7 +++++++
> >  drivers/gpu/drm/sprd/sprd_dpu.h | 1 +
> >  drivers/gpu/drm/sprd/sprd_dsi.c | 9 +++++++++
> >  drivers/gpu/drm/sprd/sprd_dsi.h | 4 +++-
> >  4 files changed, 20 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c
> > index 0d9eb778794d92418b39f8535d94abde3566de43..9d274600e6a80bdfc435f6c6eff77c9dd71cb38c 100644
> > --- a/drivers/gpu/drm/sprd/sprd_dpu.c
> > +++ b/drivers/gpu/drm/sprd/sprd_dpu.c
> > @@ -3,6 +3,7 @@
> >   * Copyright (C) 2020 Unisoc Inc.
> >   */
> >  
> > +#include <linux/clk.h>
> >  #include <linux/component.h>
> >  #include <linux/delay.h>
> >  #include <linux/dma-buf.h>
> > @@ -794,6 +795,12 @@ static int sprd_dpu_context_init(struct sprd_dpu *dpu,
> >  	if (ctx->irq < 0)
> >  		return ctx->irq;
> >  
> > +	ctx->clk = devm_clk_get_optional_enabled(dev, "core");
> > +	if (IS_ERR(ctx->clk)) {
> > +		dev_err(dev, "failed to get DPU core clock\n");
> > +		return PTR_ERR(ctx->clk);
> > +	}
> > +
> >  	/* disable and clear interrupts before register dpu IRQ. */
> >  	writel(0x00, ctx->base + REG_DPU_INT_EN);
> >  	writel(0xff, ctx->base + REG_DPU_INT_CLR);
> > diff --git a/drivers/gpu/drm/sprd/sprd_dpu.h b/drivers/gpu/drm/sprd/sprd_dpu.h
> > index 157a78f24dc18b071602552ea9d005af66525263..d48b922de580a8a4bf07c4610c431d3321f7b810 100644
> > --- a/drivers/gpu/drm/sprd/sprd_dpu.h
> > +++ b/drivers/gpu/drm/sprd/sprd_dpu.h
> > @@ -44,6 +44,7 @@ enum {
> >   */
> >  struct dpu_context {
> >  	void __iomem *base;
> > +	struct clk *clk;
> >  	int irq;
> >  	u8 if_type;
> >  	struct videomode vm;
> > diff --git a/drivers/gpu/drm/sprd/sprd_dsi.c b/drivers/gpu/drm/sprd/sprd_dsi.c
> > index e01d1d28fe579644ec2e0c83ec9170269932adfe..2af4273a6c73185084290c9d14b8ac18914d514b 100644
> > --- a/drivers/gpu/drm/sprd/sprd_dsi.c
> > +++ b/drivers/gpu/drm/sprd/sprd_dsi.c
> > @@ -828,6 +828,8 @@ static void sprd_dsi_bridge_pre_enable(struct drm_bridge *bridge)
> >  	struct sprd_dsi *dsi = bridge_to_dsi(bridge);
> >  	struct dsi_context *ctx = &dsi->ctx;
> >  
> > +	clk_prepare_enable(ctx->clk);
> > +
> >  	if (ctx->enabled) {
> >  		drm_warn(dsi->drm, "dsi is initialized\n");
> >  		return;
> > @@ -875,6 +877,8 @@ static void sprd_dsi_bridge_post_disable(struct drm_bridge *bridge)
> >  	sprd_dphy_fini(ctx);
> >  	sprd_dsi_fini(ctx);
> >  
> > +	clk_disable_unprepare(ctx->clk);
> > +
> >  	ctx->enabled = false;
> >  }
> 
> I'm a bit confused. Why do you need to enable / disable that clock in
> pre_enable / post_disable, if you already enabled it at probe?

These are two different clocks. DPU uses devm_clk_get_optional_enabled,
while DSI uses devm_clk_get_optional and enables/disables it when
needed. Ideally both clocks should be disabled when not needed, but this
will be implemented later.

Best regards,
Otto Pflüger

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

* Re: [PATCH v2 14/15] drm: sprd: implement IOMMU-based buffer management
  2025-07-22 14:41 ` [PATCH v2 14/15] drm: sprd: implement IOMMU-based buffer management Otto Pflüger
@ 2025-07-23 22:43   ` kernel test robot
  0 siblings, 0 replies; 24+ messages in thread
From: kernel test robot @ 2025-07-23 22:43 UTC (permalink / raw)
  To: Otto Pflüger, David Airlie, Simona Vetter, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Orson Zhai, Baolin Wang,
	Chunyan Zhang, Kevin Tang
  Cc: oe-kbuild-all, dri-devel, devicetree, linux-kernel,
	Otto Pflüger

Hi Otto,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 05adbee3ad528100ab0285c15c91100e19e10138]

url:    https://github.com/intel-lab-lkp/linux/commits/Otto-Pfl-ger/dt-bindings-display-sprd-adapt-for-UMS9230-support/20250722-224414
base:   05adbee3ad528100ab0285c15c91100e19e10138
patch link:    https://lore.kernel.org/r/20250722-ums9230-drm-v2-14-054276ec213d%40abscue.de
patch subject: [PATCH v2 14/15] drm: sprd: implement IOMMU-based buffer management
config: hexagon-randconfig-r132-20250724 (https://download.01.org/0day-ci/archive/20250724/202507240607.WFI08aBs-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 853c343b45b3e83cc5eeef5a52fc8cc9d8a09252)
reproduce: (https://download.01.org/0day-ci/archive/20250724/202507240607.WFI08aBs-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507240607.WFI08aBs-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/gpu/drm/sprd/sprd_gem.c:157:16: sparse: sparse: Using plain integer as NULL pointer

vim +157 drivers/gpu/drm/sprd/sprd_gem.c

   135	
   136	static struct sg_table *sprd_gem_object_get_sg_table(struct drm_gem_object *obj)
   137	{
   138		struct sprd_gem_obj *sprd_gem = to_sprd_gem_obj(obj);
   139		struct sg_table *sgt;
   140		int ret;
   141	
   142		if (sprd_gem->pages)
   143			return drm_prime_pages_to_sg(obj->dev, sprd_gem->pages,
   144						     obj->size >> PAGE_SHIFT);
   145	
   146		sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
   147		if (!sgt)
   148			return ERR_PTR(-ENOMEM);
   149	
   150		ret = dma_get_sgtable(obj->dev->dev, sgt, sprd_gem->vaddr,
   151				      sprd_gem->dma_addr, obj->size);
   152		if (ret < 0) {
   153			kfree(sgt);
   154			return ERR_PTR(ret);
   155		}
   156	
 > 157		return 0;
   158	}
   159	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

end of thread, other threads:[~2025-07-23 22:43 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-22 14:41 [PATCH v2 00/15] drm: sprd: Make the Unisoc DRM driver usable on UMS9230 Otto Pflüger
2025-07-22 14:41 ` [PATCH v2 01/15] dt-bindings: display: sprd: adapt for UMS9230 support Otto Pflüger
2025-07-23  7:50   ` Krzysztof Kozlowski
2025-07-22 14:41 ` [PATCH v2 02/15] dt-bindings: display: sprd: add memory-region property Otto Pflüger
2025-07-23  7:51   ` Krzysztof Kozlowski
2025-07-22 14:41 ` [PATCH v2 03/15] dt-bindings: display: sprd: allow attaching a DSI panel Otto Pflüger
2025-07-23  7:54   ` Krzysztof Kozlowski
2025-07-23  8:03     ` Krzysztof Kozlowski
2025-07-22 14:41 ` [PATCH v2 04/15] drm: of: try binding port parent node instead of the port itself Otto Pflüger
2025-07-23  7:02   ` Maxime Ripard
2025-07-22 14:41 ` [PATCH v2 05/15] drm: sprd: remove plane and crtc destroy callbacks Otto Pflüger
2025-07-22 14:41 ` [PATCH v2 06/15] drm: sprd: register a DSI bridge and move init code to pre_enable Otto Pflüger
2025-07-22 14:41 ` [PATCH v2 07/15] drm: sprd: add support for UMS9230 DSI PLL Otto Pflüger
2025-07-22 14:41 ` [PATCH v2 08/15] drm: sprd: fix DSI rate and PLL setup code Otto Pflüger
2025-07-22 14:41 ` [PATCH v2 09/15] drm: sprd: select REGMAP in Kconfig Otto Pflüger
2025-07-22 14:41 ` [PATCH v2 10/15] drm: sprd: add clock gating support Otto Pflüger
2025-07-23  7:00   ` Maxime Ripard
2025-07-23  8:32     ` Otto Pflüger
2025-07-22 14:41 ` [PATCH v2 11/15] drm: sprd: add support for newer DPU versions Otto Pflüger
2025-07-22 14:41 ` [PATCH v2 12/15] drm: sprd: always initialize DPU and DSI registers Otto Pflüger
2025-07-22 14:41 ` [PATCH v2 13/15] drm: sprd: do not access IOMMU registers Otto Pflüger
2025-07-22 14:41 ` [PATCH v2 14/15] drm: sprd: implement IOMMU-based buffer management Otto Pflüger
2025-07-23 22:43   ` kernel test robot
2025-07-22 14:41 ` [PATCH v2 15/15] drm: sprd: add fbdev support Otto Pflüger

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