summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2026-03-15 00:53:05 +0300
committerDave Airlie <airlied@redhat.com>2026-03-15 00:54:10 +0300
commitd9a4a2021d4a5ced93b7d9a6d1b13298c631dbdd (patch)
treea024ee0aa3a8c5f3da518c7a9e15c6be131dd4f5
parent58351f46de26bcc4403f9972f7aed430d15cbd03 (diff)
parentf08ceb71c5a5615577e7c841e1e00a89f495ab51 (diff)
downloadlinux-d9a4a2021d4a5ced93b7d9a6d1b13298c631dbdd.tar.xz
Merge tag 'drm-misc-next-2026-03-12' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next
drm-misc-next for v7.1: UAPI Changes: amdxdna: - Add sensors ioctls Cross-subsystem Changes: dma-buf: - clean pages with helpers Documenatation: - devicetree: Add lxd vendor prefix Core Changes: buddy: - improve aligned allocations gem-shmem: - Track page accessed/dirty status across mmap/vmap ttm: - fix fence signalling Driver Changes: amdxdna: - provide NPU power estimate - support sensor for column utilization bridge: - anx7625: Fix USB Type-C handling - cdns-mhdp8546-core: Handle HDCP state in bridge atomic_check ivpu: - fixes loongson: - replace custom code with drm_gem_ttm_dumb_map_offset() mxsfb: - lcdif: report probing errors with dev_err_probe() panel: - ilitek-ili9882t: Allow GPIO calls to sleep - jadard: Support TAIGUAN XTI05101-01A - lxd: Support LXD M9189A plus DT bindings - mantix: Fix pixel clock; Clean up - motorola: Support Motorola Atrix 4G and Droid X2 plus DT bindings - novatek: Support Novatek/Tianma NT37700F plus DT bindings - renesas: Clean up - simple: Support EDT ET057023UDBA plus DT bindings; Support Powertip PH800480T032-ZHC19 plus DT bindings; Support Waveshare 13.3" - clean up DT bindings of various drivers panthor: - fix fence handling vc4: - check return value of platform_get_irq_byname() Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patch.msgid.link/20260312075629.GA21234@linux.fritz.box
-rw-r--r--Documentation/devicetree/bindings/arm/qcom.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/panel/abt,y030xx067a.yaml5
-rw-r--r--Documentation/devicetree/bindings/display/panel/advantech,idk-1110wr.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/bananapi,s070wv20-ct16.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/himax,hx83112a.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/ilitek,ili9322.yaml3
-rw-r--r--Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/panel/innolux,ej030na.yaml5
-rw-r--r--Documentation/devicetree/bindings/display/panel/innolux,p097pfg.yaml26
-rw-r--r--Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/kingdisplay,kd035g6-54nt.yaml5
-rw-r--r--Documentation/devicetree/bindings/display/panel/lgphilips,lb035q02.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/lxd,m9189a.yaml64
-rw-r--r--Documentation/devicetree/bindings/display/panel/mitsubishi,aa104xd12.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/mitsubishi,aa121td01.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/motorola,mot-panel.yaml69
-rw-r--r--Documentation/devicetree/bindings/display/panel/nec,nl8048hl11.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/novatek,nt36523.yaml3
-rw-r--r--Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml3
-rw-r--r--Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/panel-simple.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/pda,91-00156-a0.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/raydium,rm68200.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/raydium,rm692e5.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,ld9040.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,s6d7aa0.yaml8
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,s6e3ha8.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,s6e63m0.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/sgd,gktw70sdae4se.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/panel/sony,acx565akm.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/startek,kd070fhfid015.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/tpo,td.yaml5
-rw-r--r--Documentation/devicetree/bindings/display/panel/visionox,r66451.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/visionox,vtdr6130.yaml4
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.yaml4
-rw-r--r--MAINTAINERS11
-rw-r--r--drivers/accel/amdxdna/aie2_pci.c53
-rw-r--r--drivers/accel/amdxdna/aie2_pci.h28
-rw-r--r--drivers/accel/amdxdna/amdxdna_pci_drv.c4
-rw-r--r--drivers/accel/ivpu/ivpu_gem.c12
-rw-r--r--drivers/accel/ivpu/ivpu_hw_40xx_reg.h6
-rw-r--r--drivers/accel/ivpu/ivpu_hw_ip.c1
-rw-r--r--drivers/dma-buf/heaps/cma_heap.c7
-rw-r--r--drivers/gpu/buddy.c272
-rw-r--r--drivers/gpu/drm/bridge/analogix/Kconfig3
-rw-r--r--drivers/gpu/drm/bridge/analogix/anx7625.c41
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c257
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h2
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c18
-rw-r--r--drivers/gpu/drm/drm_gem_shmem_helper.c79
-rw-r--r--drivers/gpu/drm/imagination/pvr_gem.c6
-rw-r--r--drivers/gpu/drm/loongson/lsdc_drv.c3
-rw-r--r--drivers/gpu/drm/loongson/lsdc_gem.c15
-rw-r--r--drivers/gpu/drm/loongson/lsdc_gem.h4
-rw-r--r--drivers/gpu/drm/mxsfb/lcdif_drv.c8
-rw-r--r--drivers/gpu/drm/panel/Kconfig32
-rw-r--r--drivers/gpu/drm/panel/Makefile3
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9882t.c14
-rw-r--r--drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c244
-rw-r--r--drivers/gpu/drm/panel/panel-lxd-m9189a.c243
-rw-r--r--drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c15
-rw-r--r--drivers/gpu/drm/panel/panel-motorola-mot.c244
-rw-r--r--drivers/gpu/drm/panel/panel-novatek-nt37700f.c299
-rw-r--r--drivers/gpu/drm/panel/panel-renesas-r61307.c40
-rw-r--r--drivers/gpu/drm/panel/panel-renesas-r69328.c38
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c92
-rw-r--r--drivers/gpu/drm/panthor/panthor_sched.c2
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c6
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c14
-rw-r--r--drivers/gpu/tests/gpu_buddy_test.c493
-rw-r--r--include/linux/gpu_buddy.h2
-rw-r--r--include/uapi/drm/amdxdna_accel.h3
84 files changed, 2396 insertions, 564 deletions
diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml
index d48c625d3fc4..1a955d1b14bf 100644
--- a/Documentation/devicetree/bindings/arm/qcom.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom.yaml
@@ -846,6 +846,12 @@ properties:
- items:
- enum:
+ - google,bonito-tianma
+ - const: google,bonito
+ - const: qcom,sdm670
+
+ - items:
+ - enum:
- qcom,sdx55-mtp
- qcom,sdx55-telit-fn980-tlb
- qcom,sdx55-t55
diff --git a/Documentation/devicetree/bindings/display/panel/abt,y030xx067a.yaml b/Documentation/devicetree/bindings/display/panel/abt,y030xx067a.yaml
index 0aa2d3fbadaa..72cbb9ee5eae 100644
--- a/Documentation/devicetree/bindings/display/panel/abt,y030xx067a.yaml
+++ b/Documentation/devicetree/bindings/display/panel/abt,y030xx067a.yaml
@@ -20,11 +20,6 @@ properties:
reg:
maxItems: 1
- backlight: true
- port: true
- power-supply: true
- reset-gpios: true
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/panel/advantech,idk-1110wr.yaml b/Documentation/devicetree/bindings/display/panel/advantech,idk-1110wr.yaml
index f6fea9085aab..76b48836ddf6 100644
--- a/Documentation/devicetree/bindings/display/panel/advantech,idk-1110wr.yaml
+++ b/Documentation/devicetree/bindings/display/panel/advantech,idk-1110wr.yaml
@@ -41,8 +41,6 @@ properties:
panel-timing: true
port: true
-additionalProperties: false
-
required:
- compatible
- data-mapping
@@ -51,6 +49,8 @@ required:
- panel-timing
- port
+additionalProperties: false
+
examples:
- |+
panel {
diff --git a/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml b/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
index 05ca3b2385f8..c9b066e69e2f 100644
--- a/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
+++ b/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
@@ -56,8 +56,6 @@ properties:
- port@0
- port@1
-additionalProperties: false
-
required:
- compatible
- width-mm
@@ -65,6 +63,8 @@ required:
- data-mapping
- panel-timing
+additionalProperties: false
+
examples:
- |+
panel-lvds {
diff --git a/Documentation/devicetree/bindings/display/panel/bananapi,s070wv20-ct16.yaml b/Documentation/devicetree/bindings/display/panel/bananapi,s070wv20-ct16.yaml
index bbf127fb28f7..46e7cff5b2fa 100644
--- a/Documentation/devicetree/bindings/display/panel/bananapi,s070wv20-ct16.yaml
+++ b/Documentation/devicetree/bindings/display/panel/bananapi,s070wv20-ct16.yaml
@@ -22,10 +22,10 @@ properties:
enable-gpios: true
port: true
-additionalProperties: false
-
required:
- compatible
- power-supply
+additionalProperties: false
+
...
diff --git a/Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.yaml b/Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.yaml
index 287e2feb6533..9a2c532dbc92 100644
--- a/Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.yaml
+++ b/Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.yaml
@@ -22,10 +22,10 @@ properties:
backlight: true
port: true
-additionalProperties: false
-
required:
- compatible
- power-supply
+additionalProperties: false
+
...
diff --git a/Documentation/devicetree/bindings/display/panel/himax,hx83112a.yaml b/Documentation/devicetree/bindings/display/panel/himax,hx83112a.yaml
index 56bcd152f43c..2c60d0cd704e 100644
--- a/Documentation/devicetree/bindings/display/panel/himax,hx83112a.yaml
+++ b/Documentation/devicetree/bindings/display/panel/himax,hx83112a.yaml
@@ -33,8 +33,6 @@ properties:
vsp-supply:
description: Negative source voltage rail
- port: true
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml b/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml
index 5725a587e35c..182a2b825e1c 100644
--- a/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml
+++ b/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml
@@ -54,8 +54,6 @@ required:
- vcc-supply
- iovcc-supply
-additionalProperties: false
-
allOf:
- $ref: panel-common.yaml#
- if:
@@ -68,6 +66,8 @@ allOf:
required:
- reset-gpios
+additionalProperties: false
+
examples:
- |
#include <dt-bindings/gpio/gpio.h>
diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml
index ef5a2240b684..cc80d0e90f1a 100644
--- a/Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml
+++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml
@@ -34,10 +34,6 @@ properties:
maxItems: 1
description: Display data/command selection (D/CX)
- backlight: true
- reset-gpios: true
- rotation: true
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili9322.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili9322.yaml
index 4bdc33d12306..c97bfd0f2ebc 100644
--- a/Documentation/devicetree/bindings/display/panel/ilitek,ili9322.yaml
+++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili9322.yaml
@@ -29,9 +29,6 @@ properties:
reg:
maxItems: 1
- reset-gpios: true
- port: true
-
vcc-supply:
description: Core voltage supply
diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
index 5f41758c96d5..aeb7cb26c058 100644
--- a/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
+++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
@@ -40,8 +40,6 @@ properties:
spi-max-frequency:
const: 10000000
- port: true
-
vci-supply:
description: Analog voltage supply (2.5 .. 3.3V)
@@ -51,8 +49,6 @@ properties:
vddi-led-supply:
description: Voltage supply for the LED driver (1.65 .. 3.3 V)
-unevaluatedProperties: false
-
required:
- compatible
- reg
@@ -68,6 +64,8 @@ then:
required:
- port
+unevaluatedProperties: false
+
examples:
- |+
#include <dt-bindings/gpio/gpio.h>
diff --git a/Documentation/devicetree/bindings/display/panel/innolux,ej030na.yaml b/Documentation/devicetree/bindings/display/panel/innolux,ej030na.yaml
index c7df9a7f6589..59cc7edb22bb 100644
--- a/Documentation/devicetree/bindings/display/panel/innolux,ej030na.yaml
+++ b/Documentation/devicetree/bindings/display/panel/innolux,ej030na.yaml
@@ -20,11 +20,6 @@ properties:
reg:
maxItems: 1
- backlight: true
- port: true
- power-supply: true
- reset-gpios: true
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/panel/innolux,p097pfg.yaml b/Documentation/devicetree/bindings/display/panel/innolux,p097pfg.yaml
index 4164e3f7061d..7c75e01797f6 100644
--- a/Documentation/devicetree/bindings/display/panel/innolux,p097pfg.yaml
+++ b/Documentation/devicetree/bindings/display/panel/innolux,p097pfg.yaml
@@ -10,7 +10,7 @@ maintainers:
- Lin Huang <hl@rock-chips.com>
allOf:
- - $ref: panel-common.yaml#
+ - $ref: panel-common-dual.yaml#
properties:
compatible:
@@ -28,6 +28,9 @@ properties:
avee-supply:
description: The regulator that provides negative voltage
+ port: true
+ ports: true
+
required:
- compatible
- reg
@@ -52,6 +55,27 @@ examples:
avee-supply = <&avee>;
backlight = <&backlight>;
enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ mipi_in_panel: endpoint {
+ remote-endpoint = <&mipi_out_panel>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ mipi1_in_panel: endpoint {
+ remote-endpoint = <&mipi1_out_panel>;
+ };
+ };
+ };
};
};
diff --git a/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml b/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml
index 5802fb3c9ffe..e39efb44ed42 100644
--- a/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml
+++ b/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml
@@ -23,6 +23,7 @@ properties:
- melfas,lmfbx101117480
- radxa,display-10hd-ad001
- radxa,display-8hd-ad002
+ - taiguanck,xti05101-01a
- const: jadard,jd9365da-h3
reg:
@@ -35,9 +36,8 @@ properties:
description: supply regulator for VCCIO, usually 1.8V
reset-gpios: true
-
backlight: true
-
+ rotation: true
port: true
required:
diff --git a/Documentation/devicetree/bindings/display/panel/kingdisplay,kd035g6-54nt.yaml b/Documentation/devicetree/bindings/display/panel/kingdisplay,kd035g6-54nt.yaml
index d86c916f7b55..fe7ad266e1b0 100644
--- a/Documentation/devicetree/bindings/display/panel/kingdisplay,kd035g6-54nt.yaml
+++ b/Documentation/devicetree/bindings/display/panel/kingdisplay,kd035g6-54nt.yaml
@@ -20,11 +20,6 @@ properties:
reg:
maxItems: 1
- backlight: true
- port: true
- power-supply: true
- reset-gpios: true
-
spi-3wire: true
required:
diff --git a/Documentation/devicetree/bindings/display/panel/lgphilips,lb035q02.yaml b/Documentation/devicetree/bindings/display/panel/lgphilips,lb035q02.yaml
index 3de17fd8513b..3c8c65c6a869 100644
--- a/Documentation/devicetree/bindings/display/panel/lgphilips,lb035q02.yaml
+++ b/Documentation/devicetree/bindings/display/panel/lgphilips,lb035q02.yaml
@@ -20,10 +20,6 @@ properties:
reg:
maxItems: 1
- label: true
- enable-gpios: true
- port: true
-
spi-cpha: true
spi-cpol: true
diff --git a/Documentation/devicetree/bindings/display/panel/lxd,m9189a.yaml b/Documentation/devicetree/bindings/display/panel/lxd,m9189a.yaml
new file mode 100644
index 000000000000..226974a4077f
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/lxd,m9189a.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/lxd,m9189a.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LXD M9189A DSI Display Panel
+
+maintainers:
+ - Michael Tretter <m.tretter@pengutronix.de>
+
+allOf:
+ - $ref: panel-common.yaml
+
+properties:
+ compatible:
+ const: lxd,m9189a
+
+ reg:
+ maxItems: 1
+
+ standby-gpios:
+ description: GPIO used for the standby pin
+ maxItems: 1
+
+ reset-gpios: true
+ power-supply: true
+ backlight: true
+ port: true
+
+required:
+ - compatible
+ - reg
+ - standby-gpios
+ - reset-gpios
+ - power-supply
+ - backlight
+ - port
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ dsi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "lxd,m9189a";
+ reg = <0>;
+ backlight = <&backlight>;
+ reset-gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
+ standby-gpios = <&gpio5 22 GPIO_ACTIVE_LOW>;
+ power-supply = <&reg_display_3v3>;
+
+ port {
+ mipi_panel_in: endpoint {
+ remote-endpoint = <&mipi_dsi_out>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/display/panel/mitsubishi,aa104xd12.yaml b/Documentation/devicetree/bindings/display/panel/mitsubishi,aa104xd12.yaml
index 96621b89ae9e..43e98bb07c38 100644
--- a/Documentation/devicetree/bindings/display/panel/mitsubishi,aa104xd12.yaml
+++ b/Documentation/devicetree/bindings/display/panel/mitsubishi,aa104xd12.yaml
@@ -47,8 +47,6 @@ properties:
panel-timing: true
port: true
-additionalProperties: false
-
required:
- compatible
- data-mapping
@@ -57,6 +55,8 @@ required:
- panel-timing
- port
+additionalProperties: false
+
examples:
- |+
diff --git a/Documentation/devicetree/bindings/display/panel/mitsubishi,aa121td01.yaml b/Documentation/devicetree/bindings/display/panel/mitsubishi,aa121td01.yaml
index 37f01d847aac..2af993d73619 100644
--- a/Documentation/devicetree/bindings/display/panel/mitsubishi,aa121td01.yaml
+++ b/Documentation/devicetree/bindings/display/panel/mitsubishi,aa121td01.yaml
@@ -44,8 +44,6 @@ properties:
panel-timing: true
port: true
-additionalProperties: false
-
required:
- compatible
- vcc-supply
@@ -55,6 +53,8 @@ required:
- panel-timing
- port
+additionalProperties: false
+
examples:
- |+
panel {
diff --git a/Documentation/devicetree/bindings/display/panel/motorola,mot-panel.yaml b/Documentation/devicetree/bindings/display/panel/motorola,mot-panel.yaml
new file mode 100644
index 000000000000..99fa1b3ed426
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/motorola,mot-panel.yaml
@@ -0,0 +1,69 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/motorola,mot-panel.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Atrix 4G and Droid X2 DSI Display Panel
+
+maintainers:
+ - Svyatoslav Ryhel <clamor95@gmail.com>
+
+description:
+ Atrix 4G and Droid X2 use the same 540x960 DSI video mode panel. Exact
+ panel vendor and model are unknown hence generic compatible based on the
+ board name "Mot" is used.
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: motorola,mot-panel
+
+ reg:
+ maxItems: 1
+
+ vdd-supply:
+ description: Regulator for main power supply.
+
+ vddio-supply:
+ description: Regulator for 1.8V IO power supply.
+
+ backlight: true
+ reset-gpios: true
+ port: true
+
+required:
+ - compatible
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ dsi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "motorola,mot-panel";
+ reg = <0>;
+
+ reset-gpios = <&gpio 35 GPIO_ACTIVE_LOW>;
+
+ vdd-supply = <&vdd_5v0_panel>;
+ vddio-supply = <&vdd_1v8_vio>;
+
+ backlight = <&backlight>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&dsi_out>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/panel/nec,nl8048hl11.yaml b/Documentation/devicetree/bindings/display/panel/nec,nl8048hl11.yaml
index 1cffe4d6d498..eb9eeba92359 100644
--- a/Documentation/devicetree/bindings/display/panel/nec,nl8048hl11.yaml
+++ b/Documentation/devicetree/bindings/display/panel/nec,nl8048hl11.yaml
@@ -24,10 +24,6 @@ properties:
reg:
maxItems: 1
- label: true
- port: true
- reset-gpios: true
-
spi-max-frequency:
maximum: 10000000
diff --git a/Documentation/devicetree/bindings/display/panel/novatek,nt36523.yaml b/Documentation/devicetree/bindings/display/panel/novatek,nt36523.yaml
index c4bae4f77085..b9300a1f2646 100644
--- a/Documentation/devicetree/bindings/display/panel/novatek,nt36523.yaml
+++ b/Documentation/devicetree/bindings/display/panel/novatek,nt36523.yaml
@@ -37,9 +37,6 @@ properties:
vddio-supply:
description: regulator that supplies the I/O voltage
- rotation: true
- backlight: true
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml b/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml
index 800a2f0a4dad..5d16d8511725 100644
--- a/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml
+++ b/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml
@@ -47,9 +47,6 @@ properties:
vddneg-supply:
description: phandle of the negative boost supply regulator
- port: true
- backlight: true
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.yaml b/Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.yaml
index 1e4f140f48b8..1f697dab832b 100644
--- a/Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.yaml
+++ b/Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.yaml
@@ -31,12 +31,12 @@ properties:
reset-gpios:
maxItems: 1
-additionalProperties: false
-
required:
- compatible
- reg
+additionalProperties: false
+
examples:
- |
dsi {
diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
index 2f90c887b7b8..cc8d795df732 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
@@ -49,6 +49,8 @@ properties:
- lg,lh500wx1-sd03
# Lincoln LCD197 5" 1080x1920 LCD panel
- lincolntech,lcd197
+ # Novatek NT37700F 1080x2160 AMOLED panel
+ - novatek,nt37700f
# One Stop Displays OSD101T2587-53TS 10.1" 1920x1200 panel
- osddisplays,osd101t2587-53ts
# Panasonic 10" WUXGA TFT LCD panel
diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
index 106ae91ff474..e98ca672ba49 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
@@ -103,6 +103,8 @@ properties:
- dlc,dlc1010gig
# Emerging Display Technology Corp. 3.5" QVGA TFT LCD panel
- edt,et035012dm6
+ # Emerging Display Technology Corp. 5.7" 24-bit VGA TFT LCD panel
+ - edt,et057023udba
# Emerging Display Technology Corp. 5.7" VGA TFT LCD panel
- edt,et057090dhu
- edt,et070080dh6
@@ -266,6 +268,8 @@ properties:
- powertip,ph128800t006-zhc01
# POWERTIP PH800480T013-IDF2 7.0" WVGA TFT LCD panel
- powertip,ph800480t013-idf02
+ # POWERTIP PH800480T032-ZHC19 7.0" WVGA TFT LCD panel
+ - powertip,ph800480t032-zhc19
# PrimeView PM070WL4 7.0" 800x480 TFT LCD panel
- primeview,pm070wl4
# QiaoDian XianShi Corporation 4"3 TFT LCD panel
diff --git a/Documentation/devicetree/bindings/display/panel/pda,91-00156-a0.yaml b/Documentation/devicetree/bindings/display/panel/pda,91-00156-a0.yaml
index ccd3623b4955..871e4c2d9824 100644
--- a/Documentation/devicetree/bindings/display/panel/pda,91-00156-a0.yaml
+++ b/Documentation/devicetree/bindings/display/panel/pda,91-00156-a0.yaml
@@ -21,11 +21,11 @@ properties:
backlight: true
port: true
-additionalProperties: false
-
required:
- compatible
- power-supply
- backlight
+additionalProperties: false
+
...
diff --git a/Documentation/devicetree/bindings/display/panel/raydium,rm68200.yaml b/Documentation/devicetree/bindings/display/panel/raydium,rm68200.yaml
index 46fe1014ebc4..8fb7c013dfb8 100644
--- a/Documentation/devicetree/bindings/display/panel/raydium,rm68200.yaml
+++ b/Documentation/devicetree/bindings/display/panel/raydium,rm68200.yaml
@@ -33,13 +33,13 @@ properties:
reset-gpios:
maxItems: 1
-additionalProperties: false
-
required:
- compatible
- power-supply
- reg
+additionalProperties: false
+
examples:
- |
dsi {
diff --git a/Documentation/devicetree/bindings/display/panel/raydium,rm692e5.yaml b/Documentation/devicetree/bindings/display/panel/raydium,rm692e5.yaml
index 7ad223f98253..616a5f3ec9fc 100644
--- a/Documentation/devicetree/bindings/display/panel/raydium,rm692e5.yaml
+++ b/Documentation/devicetree/bindings/display/panel/raydium,rm692e5.yaml
@@ -34,8 +34,6 @@ properties:
vddio-supply:
description: I/O voltage rail
- port: true
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml b/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml
index f1723e910252..1bbe0da3997c 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml
@@ -43,13 +43,13 @@ properties:
no-hpd: true
hpd-gpios: true
-additionalProperties: false
-
required:
- compatible
- enable-gpios
- power-supply
+additionalProperties: false
+
examples:
- |
#include <dt-bindings/clock/qcom,rpmh.h>
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,ld9040.yaml b/Documentation/devicetree/bindings/display/panel/samsung,ld9040.yaml
index bc92b16c95b9..2e64fba472cc 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,ld9040.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,ld9040.yaml
@@ -20,10 +20,6 @@ properties:
reg:
maxItems: 1
- display-timings: true
- port: true
- reset-gpios: true
-
vdd3-supply:
description: core voltage supply
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml b/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
index 74c2a617c2ff..828b7d7ba17f 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
@@ -31,8 +31,6 @@ properties:
configuration.
maxItems: 1
- reset-gpios: true
-
vci-supply:
description: regulator that supplies the VCI analog voltage
usually around 3.0 V
@@ -41,8 +39,6 @@ properties:
description: regulator that supplies the VCCIO voltage usually
around 1.8 V
- backlight: true
-
spi-cpha: true
spi-cpol: true
@@ -50,8 +46,6 @@ properties:
spi-max-frequency:
maximum: 1200000
- port: true
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml b/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
index 4cecf502a150..c04d47e59f24 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
@@ -23,8 +23,6 @@ properties:
reg:
maxItems: 1
- reset-gpios: true
-
vci-supply:
description: regulator that supplies the VCI analog voltage
usually around 3.0 V
@@ -33,8 +31,6 @@ properties:
description: regulator that supplies the VCCIO voltage usually
around 1.8 V
- backlight: true
-
spi-cpha: true
spi-cpol: true
@@ -44,8 +40,6 @@ properties:
maximum 300 ns minimum cycle which gives around 3 MHz max frequency
maximum: 3000000
- port: true
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml b/Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml
index d74904164719..0d57f97e8a76 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml
@@ -30,8 +30,6 @@ properties:
configuration.
maxItems: 1
- reset-gpios: true
-
vci-supply:
description: regulator that supplies the VCI analog voltage
usually around 3.0 V
@@ -40,8 +38,6 @@ properties:
description: regulator that supplies the VCCIO voltage usually
around 1.8 V
- backlight: true
-
spi-cpha: true
spi-cpol: true
@@ -49,8 +45,6 @@ properties:
spi-max-frequency:
maximum: 1200000
- port: true
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6d7aa0.yaml b/Documentation/devicetree/bindings/display/panel/samsung,s6d7aa0.yaml
index 939da65114bf..1f753b706911 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,s6d7aa0.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,s6d7aa0.yaml
@@ -44,6 +44,8 @@ properties:
vmipi-supply:
description: VMIPI supply, usually 1.8v.
+ port: true
+
required:
- compatible
- reg
@@ -65,6 +67,12 @@ examples:
power-supply = <&display_3v3_supply>;
reset-gpios = <&gpf0 4 GPIO_ACTIVE_LOW>;
backlight = <&backlight>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
};
};
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha8.yaml b/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha8.yaml
index 05a78429aaea..00ce5a4e1c6b 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha8.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha8.yaml
@@ -22,10 +22,6 @@ properties:
reg:
maxItems: 1
- reset-gpios: true
-
- port: true
-
vdd3-supply:
description: VDD regulator
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6e63m0.yaml b/Documentation/devicetree/bindings/display/panel/samsung,s6e63m0.yaml
index c47e2a1a30e5..b65f0688bdf0 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,s6e63m0.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,s6e63m0.yaml
@@ -21,8 +21,6 @@ properties:
reg:
maxItems: 1
- reset-gpios: true
- port: true
default-brightness: true
max-brightness: true
diff --git a/Documentation/devicetree/bindings/display/panel/sgd,gktw70sdae4se.yaml b/Documentation/devicetree/bindings/display/panel/sgd,gktw70sdae4se.yaml
index e32d9188a3e0..1beb4ba92248 100644
--- a/Documentation/devicetree/bindings/display/panel/sgd,gktw70sdae4se.yaml
+++ b/Documentation/devicetree/bindings/display/panel/sgd,gktw70sdae4se.yaml
@@ -41,8 +41,6 @@ properties:
panel-timing: true
port: true
-additionalProperties: false
-
required:
- compatible
- port
@@ -51,6 +49,8 @@ required:
- height-mm
- panel-timing
+additionalProperties: false
+
examples:
- |+
panel {
diff --git a/Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml b/Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml
index 1e434240ea3f..044b84d8638d 100644
--- a/Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml
+++ b/Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml
@@ -49,12 +49,6 @@ properties:
If not set, the controller is in 3-line SPI mode.
Disallowed for DSI.
- port: true
- reset-gpios: true
- rotation: true
-
- backlight: true
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml b/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
index c35d4f2ab9a4..e4fa05163d2d 100644
--- a/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
+++ b/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
@@ -24,12 +24,6 @@ properties:
reg:
maxItems: 1
- reset-gpios: true
- power-supply: true
- backlight: true
- port: true
- rotation: true
-
spi-cpha: true
spi-cpol: true
diff --git a/Documentation/devicetree/bindings/display/panel/sony,acx565akm.yaml b/Documentation/devicetree/bindings/display/panel/sony,acx565akm.yaml
index 5a8260224b74..12e5ad504001 100644
--- a/Documentation/devicetree/bindings/display/panel/sony,acx565akm.yaml
+++ b/Documentation/devicetree/bindings/display/panel/sony,acx565akm.yaml
@@ -20,10 +20,6 @@ properties:
reg:
maxItems: 1
- label: true
- reset-gpios: true
- port: true
-
required:
- compatible
- port
diff --git a/Documentation/devicetree/bindings/display/panel/startek,kd070fhfid015.yaml b/Documentation/devicetree/bindings/display/panel/startek,kd070fhfid015.yaml
index d817f998cddc..0819f38a9d2c 100644
--- a/Documentation/devicetree/bindings/display/panel/startek,kd070fhfid015.yaml
+++ b/Documentation/devicetree/bindings/display/panel/startek,kd070fhfid015.yaml
@@ -31,8 +31,6 @@ properties:
power-supply: true
-additionalProperties: false
-
required:
- compatible
- enable-gpios
@@ -42,6 +40,8 @@ required:
- port
- power-supply
+additionalProperties: false
+
examples:
- |
#include <dt-bindings/gpio/gpio.h>
diff --git a/Documentation/devicetree/bindings/display/panel/tpo,td.yaml b/Documentation/devicetree/bindings/display/panel/tpo,td.yaml
index 7edd29df4bbb..855911588d73 100644
--- a/Documentation/devicetree/bindings/display/panel/tpo,td.yaml
+++ b/Documentation/devicetree/bindings/display/panel/tpo,td.yaml
@@ -25,11 +25,6 @@ properties:
reg:
maxItems: 1
- label: true
- reset-gpios: true
- backlight: true
- port: true
-
spi-cpha: true
spi-cpol: true
diff --git a/Documentation/devicetree/bindings/display/panel/visionox,r66451.yaml b/Documentation/devicetree/bindings/display/panel/visionox,r66451.yaml
index 187840bb76c7..49ef45c03593 100644
--- a/Documentation/devicetree/bindings/display/panel/visionox,r66451.yaml
+++ b/Documentation/devicetree/bindings/display/panel/visionox,r66451.yaml
@@ -25,8 +25,6 @@ properties:
port: true
reset-gpios: true
-additionalProperties: false
-
required:
- compatible
- reg
@@ -35,6 +33,8 @@ required:
- reset-gpios
- port
+additionalProperties: false
+
examples:
- |
#include <dt-bindings/gpio/gpio.h>
diff --git a/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml b/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml
index f0a82f0ff790..f61a528c0413 100644
--- a/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml
+++ b/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml
@@ -36,8 +36,6 @@ properties:
port: true
reset-gpios: true
-additionalProperties: false
-
required:
- compatible
- reg
@@ -46,6 +44,8 @@ required:
- reset-gpios
- port
+additionalProperties: false
+
examples:
- |
dsi {
diff --git a/Documentation/devicetree/bindings/display/panel/visionox,vtdr6130.yaml b/Documentation/devicetree/bindings/display/panel/visionox,vtdr6130.yaml
index d5a8295106c1..c99f4146f1bb 100644
--- a/Documentation/devicetree/bindings/display/panel/visionox,vtdr6130.yaml
+++ b/Documentation/devicetree/bindings/display/panel/visionox,vtdr6130.yaml
@@ -26,8 +26,6 @@ properties:
port: true
reset-gpios: true
-additionalProperties: false
-
required:
- compatible
- reg
@@ -37,6 +35,8 @@ required:
- reset-gpios
- port
+additionalProperties: false
+
examples:
- |
#include <dt-bindings/gpio/gpio.h>
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 1ef679f88203..3ec0951c09c1 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -973,6 +973,8 @@ patternProperties:
description: Liebherr-Werk Nenzing GmbH
"^lxa,.*":
description: Linux Automation GmbH
+ "^lxd,.*":
+ description: LXD Research & Display, LLC
"^m5stack,.*":
description: M5Stack
"^macnica,.*":
@@ -1610,6 +1612,8 @@ patternProperties:
"^synopsys,.*":
description: Synopsys, Inc. (deprecated, use snps)
deprecated: true
+ "^taiguanck,.*":
+ description: Shenzhen Top Group Technology Co., Ltd.
"^taos,.*":
description: Texas Advanced Optoelectronic Solutions Inc.
"^tbs,.*":
diff --git a/MAINTAINERS b/MAINTAINERS
index afff2d0e7761..00b05e5328be 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8059,6 +8059,12 @@ F: Documentation/devicetree/bindings/display/lvds.yaml
F: Documentation/devicetree/bindings/display/panel/panel-lvds.yaml
F: drivers/gpu/drm/panel/panel-lvds.c
+DRM DRIVER FOR LXD M9189A PANELS
+M: Michael Tretter <m.tretter@pengutronix.de>
+S: Maintained
+F: Documentation/devicetree/bindings/display/panel/lxd,m9189a.yaml
+F: drivers/gpu/drm/panel/panel-lxd-m9189a.c
+
DRM DRIVER FOR MANTIX MLAF057WE51 PANELS
M: Guido Günther <agx@sigxcpu.org>
R: Purism Kernel Team <kernel@puri.sm>
@@ -8916,11 +8922,11 @@ R: Christian Koenig <christian.koenig@amd.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
-F: drivers/gpu/drm_buddy.c
F: drivers/gpu/buddy.c
+F: drivers/gpu/drm/drm_buddy.c
F: drivers/gpu/tests/gpu_buddy_test.c
-F: include/linux/gpu_buddy.h
F: include/drm/drm_buddy.h
+F: include/linux/gpu_buddy.h
DRM AUTOMATED TESTING
M: Helen Koike <helen.fornazier@gmail.com>
@@ -12985,7 +12991,6 @@ F: drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
INTEL KEEM BAY DRM DRIVER
M: Anitha Chrisanthus <anitha.chrisanthus@intel.com>
-M: Edmund Dea <edmund.j.dea@intel.com>
S: Maintained
F: Documentation/devicetree/bindings/display/intel,keembay-display.yaml
F: drivers/gpu/drm/kmb/
diff --git a/drivers/accel/amdxdna/aie2_pci.c b/drivers/accel/amdxdna/aie2_pci.c
index 4924a9da55b6..ddd3d82f3426 100644
--- a/drivers/accel/amdxdna/aie2_pci.c
+++ b/drivers/accel/amdxdna/aie2_pci.c
@@ -10,6 +10,7 @@
#include <drm/drm_managed.h>
#include <drm/drm_print.h>
#include <drm/gpu_scheduler.h>
+#include <linux/amd-pmf-io.h>
#include <linux/cleanup.h>
#include <linux/errno.h>
#include <linux/firmware.h>
@@ -791,6 +792,55 @@ static int aie2_get_clock_metadata(struct amdxdna_client *client,
return ret;
}
+static int aie2_get_sensors(struct amdxdna_client *client,
+ struct amdxdna_drm_get_info *args)
+{
+ struct amdxdna_dev_hdl *ndev = client->xdna->dev_handle;
+ struct amdxdna_drm_query_sensor sensor = {};
+ struct amd_pmf_npu_metrics npu_metrics;
+ u32 sensors_count = 0, i;
+ int ret;
+
+ ret = AIE2_GET_PMF_NPU_METRICS(&npu_metrics);
+ if (ret)
+ return ret;
+
+ sensor.type = AMDXDNA_SENSOR_TYPE_POWER;
+ sensor.input = npu_metrics.npu_power;
+ sensor.unitm = -3;
+ scnprintf(sensor.label, sizeof(sensor.label), "Total Power");
+ scnprintf(sensor.units, sizeof(sensor.units), "mW");
+
+ if (copy_to_user(u64_to_user_ptr(args->buffer), &sensor, sizeof(sensor)))
+ return -EFAULT;
+
+ sensors_count++;
+ if (args->buffer_size <= sensors_count * sizeof(sensor))
+ goto out;
+
+ for (i = 0; i < min_t(u32, ndev->total_col, 8); i++) {
+ memset(&sensor, 0, sizeof(sensor));
+ sensor.input = npu_metrics.npu_busy[i];
+ sensor.type = AMDXDNA_SENSOR_TYPE_COLUMN_UTILIZATION;
+ sensor.unitm = 0;
+ scnprintf(sensor.label, sizeof(sensor.label), "Column %d Utilization", i);
+ scnprintf(sensor.units, sizeof(sensor.units), "%%");
+
+ if (copy_to_user(u64_to_user_ptr(args->buffer) + sensors_count * sizeof(sensor),
+ &sensor, sizeof(sensor)))
+ return -EFAULT;
+
+ sensors_count++;
+ if (args->buffer_size <= sensors_count * sizeof(sensor))
+ goto out;
+ }
+
+out:
+ args->buffer_size = sensors_count * sizeof(sensor);
+
+ return 0;
+}
+
static int aie2_hwctx_status_cb(struct amdxdna_hwctx *hwctx, void *arg)
{
struct amdxdna_drm_hwctx_entry *tmp __free(kfree) = NULL;
@@ -994,6 +1044,9 @@ static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_i
case DRM_AMDXDNA_QUERY_CLOCK_METADATA:
ret = aie2_get_clock_metadata(client, args);
break;
+ case DRM_AMDXDNA_QUERY_SENSORS:
+ ret = aie2_get_sensors(client, args);
+ break;
case DRM_AMDXDNA_QUERY_HW_CONTEXTS:
ret = aie2_get_hwctx_status(client, args);
break;
diff --git a/drivers/accel/amdxdna/aie2_pci.h b/drivers/accel/amdxdna/aie2_pci.h
index e72311c77996..c0959e6937ba 100644
--- a/drivers/accel/amdxdna/aie2_pci.h
+++ b/drivers/accel/amdxdna/aie2_pci.h
@@ -7,6 +7,7 @@
#define _AIE2_PCI_H_
#include <drm/amdxdna_accel.h>
+#include <linux/limits.h>
#include <linux/semaphore.h>
#include "amdxdna_mailbox.h"
@@ -46,6 +47,33 @@
pci_resource_len(NDEV2PDEV(_ndev), (_ndev)->xdna->dev_info->mbox_bar); \
})
+#if IS_ENABLED(CONFIG_AMD_PMF)
+#define AIE2_GET_PMF_NPU_METRICS(metrics) amd_pmf_get_npu_data(metrics)
+#define AIE2_GET_PMF_NPU_DATA(field, val) \
+({ \
+ struct amd_pmf_npu_metrics _npu_metrics; \
+ int _ret; \
+ \
+ _ret = amd_pmf_get_npu_data(&_npu_metrics); \
+ val = _ret ? U32_MAX : _npu_metrics.field; \
+ (_ret); \
+})
+#else
+#define AIE2_GET_PMF_NPU_METRICS(metrics) \
+({ \
+ typeof(metrics) _m = metrics; \
+ memset(_m, 0xff, sizeof(*_m)); \
+ (-EOPNOTSUPP); \
+})
+
+#define SENSOR_DEFAULT_npu_power U32_MAX
+#define AIE2_GET_PMF_NPU_DATA(field, val) \
+({ \
+ val = SENSOR_DEFAULT_##field; \
+ (-EOPNOTSUPP); \
+})
+#endif
+
enum aie2_smu_reg_idx {
SMU_CMD_REG = 0,
SMU_ARG_REG,
diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.c b/drivers/accel/amdxdna/amdxdna_pci_drv.c
index a4384593bdcc..d6d12355bd2b 100644
--- a/drivers/accel/amdxdna/amdxdna_pci_drv.c
+++ b/drivers/accel/amdxdna/amdxdna_pci_drv.c
@@ -35,9 +35,10 @@ MODULE_FIRMWARE("amdnpu/17f0_11/npu_7.sbin");
* 0.4: Support getting resource information
* 0.5: Support getting telemetry data
* 0.6: Support preemption
+ * 0.7: Support getting power and utilization data
*/
#define AMDXDNA_DRIVER_MAJOR 0
-#define AMDXDNA_DRIVER_MINOR 6
+#define AMDXDNA_DRIVER_MINOR 7
/*
* Bind the driver base on (vendor_id, device_id) pair and later use the
@@ -358,5 +359,6 @@ static struct pci_driver amdxdna_pci_driver = {
module_pci_driver(amdxdna_pci_driver);
MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("AMD_PMF");
MODULE_AUTHOR("XRT Team <runtimeca39d@amd.com>");
MODULE_DESCRIPTION("amdxdna driver");
diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/ivpu_gem.c
index 98b9ce26962b..4f2005a8d496 100644
--- a/drivers/accel/ivpu/ivpu_gem.c
+++ b/drivers/accel/ivpu/ivpu_gem.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (C) 2020-2023 Intel Corporation
+ * Copyright (C) 2020-2026 Intel Corporation
*/
#include <linux/dma-buf.h>
@@ -31,7 +31,7 @@ static inline void ivpu_dbg_bo(struct ivpu_device *vdev, struct ivpu_bo *bo, con
"%6s: bo %8p size %9zu ctx %d vpu_addr %9llx pages %d sgt %d mmu_mapped %d wc %d imported %d\n",
action, bo, ivpu_bo_size(bo), bo->ctx_id, bo->vpu_addr,
(bool)bo->base.pages, (bool)bo->base.sgt, bo->mmu_mapped, bo->base.map_wc,
- (bool)drm_gem_is_imported(&bo->base.base));
+ drm_gem_is_imported(&bo->base.base));
}
static inline int ivpu_bo_lock(struct ivpu_bo *bo)
@@ -48,7 +48,7 @@ static struct sg_table *ivpu_bo_map_attachment(struct ivpu_device *vdev, struct
{
struct sg_table *sgt;
- drm_WARN_ON(&vdev->drm, !bo->base.base.import_attach);
+ drm_WARN_ON(&vdev->drm, !drm_gem_is_imported(&bo->base.base));
ivpu_bo_lock(bo);
@@ -81,7 +81,7 @@ int __must_check ivpu_bo_bind(struct ivpu_bo *bo)
ivpu_dbg_bo(vdev, bo, "bind");
- if (bo->base.base.import_attach)
+ if (drm_gem_is_imported(&bo->base.base))
sgt = ivpu_bo_map_attachment(vdev, bo);
else
sgt = drm_gem_shmem_get_pages_sgt(&bo->base);
@@ -157,7 +157,7 @@ static void ivpu_bo_unbind_locked(struct ivpu_bo *bo)
}
if (bo->base.sgt) {
- if (bo->base.base.import_attach) {
+ if (drm_gem_is_imported(&bo->base.base)) {
dma_buf_unmap_attachment(bo->base.base.import_attach,
bo->base.sgt, DMA_BIDIRECTIONAL);
} else {
@@ -195,7 +195,7 @@ struct drm_gem_object *ivpu_gem_create_object(struct drm_device *dev, size_t siz
if (size == 0 || !PAGE_ALIGNED(size))
return ERR_PTR(-EINVAL);
- bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+ bo = kzalloc_obj(*bo);
if (!bo)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/accel/ivpu/ivpu_hw_40xx_reg.h b/drivers/accel/ivpu/ivpu_hw_40xx_reg.h
index 421242acb184..fc0ee8d637f9 100644
--- a/drivers/accel/ivpu/ivpu_hw_40xx_reg.h
+++ b/drivers/accel/ivpu/ivpu_hw_40xx_reg.h
@@ -121,12 +121,6 @@
#define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY 0x0003006cu
#define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY_STATUS_DLY_MASK GENMASK(7, 0)
-#define VPU_40XX_HOST_SS_AON_RETENTION0 0x0003000cu
-#define VPU_40XX_HOST_SS_AON_RETENTION1 0x00030010u
-#define VPU_40XX_HOST_SS_AON_RETENTION2 0x00030014u
-#define VPU_40XX_HOST_SS_AON_RETENTION3 0x00030018u
-#define VPU_40XX_HOST_SS_AON_RETENTION4 0x0003001cu
-
#define VPU_40XX_HOST_SS_AON_IDLE_GEN 0x00030200u
#define VPU_40XX_HOST_SS_AON_IDLE_GEN_EN_MASK BIT_MASK(0)
#define VPU_40XX_HOST_SS_AON_IDLE_GEN_HW_PG_EN_MASK BIT_MASK(1)
diff --git a/drivers/accel/ivpu/ivpu_hw_ip.c b/drivers/accel/ivpu/ivpu_hw_ip.c
index 959984c54341..37f95a0551ed 100644
--- a/drivers/accel/ivpu/ivpu_hw_ip.c
+++ b/drivers/accel/ivpu/ivpu_hw_ip.c
@@ -931,7 +931,6 @@ static int soc_cpu_boot_40xx(struct ivpu_device *vdev)
static int soc_cpu_boot_60xx(struct ivpu_device *vdev)
{
- REGV_WR64(VPU_40XX_HOST_SS_AON_RETENTION1, vdev->fw->mem_bp->vpu_addr);
soc_cpu_set_entry_point_40xx(vdev, vdev->fw->cold_boot_entry_point);
return 0;
diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index bd3370b9a3f6..92865786cfc9 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -329,10 +329,7 @@ static struct dma_buf *cma_heap_allocate(struct dma_heap *heap,
struct page *page = cma_pages;
while (nr_clear_pages > 0) {
- void *vaddr = kmap_local_page(page);
-
- clear_page(vaddr);
- kunmap_local(vaddr);
+ clear_highpage(page);
/*
* Avoid wasting time zeroing memory if the process
* has been killed by SIGKILL.
@@ -343,7 +340,7 @@ static struct dma_buf *cma_heap_allocate(struct dma_heap *heap,
nr_clear_pages--;
}
} else {
- memset(page_address(cma_pages), 0, size);
+ clear_pages(page_address(cma_pages), pagecount);
}
buffer->pages = kmalloc_objs(*buffer->pages, pagecount);
diff --git a/drivers/gpu/buddy.c b/drivers/gpu/buddy.c
index da5a1222f46b..52686672e99f 100644
--- a/drivers/gpu/buddy.c
+++ b/drivers/gpu/buddy.c
@@ -53,6 +53,25 @@ gpu_buddy_block_is_split(struct gpu_buddy_block *block)
return gpu_buddy_block_state(block) == GPU_BUDDY_SPLIT;
}
+static unsigned int gpu_buddy_block_offset_alignment(struct gpu_buddy_block *block)
+{
+ u64 offset = gpu_buddy_block_offset(block);
+
+ if (!offset)
+ /*
+ * __ffs64(0) is undefined; offset 0 is maximally aligned, so return
+ * a value greater than any possible alignment.
+ */
+ return 64 + 1;
+
+ return __ffs64(offset);
+}
+
+RB_DECLARE_CALLBACKS_MAX(static, gpu_buddy_augment_cb,
+ struct gpu_buddy_block, rb,
+ unsigned int, subtree_max_alignment,
+ gpu_buddy_block_offset_alignment);
+
static struct gpu_buddy_block *gpu_block_alloc(struct gpu_buddy *mm,
struct gpu_buddy_block *parent,
unsigned int order,
@@ -106,26 +125,42 @@ static bool rbtree_is_empty(struct rb_root *root)
return RB_EMPTY_ROOT(root);
}
-static bool gpu_buddy_block_offset_less(const struct gpu_buddy_block *block,
- const struct gpu_buddy_block *node)
-{
- return gpu_buddy_block_offset(block) < gpu_buddy_block_offset(node);
-}
-
-static bool rbtree_block_offset_less(struct rb_node *block,
- const struct rb_node *node)
-{
- return gpu_buddy_block_offset_less(rbtree_get_free_block(block),
- rbtree_get_free_block(node));
-}
-
static void rbtree_insert(struct gpu_buddy *mm,
struct gpu_buddy_block *block,
enum gpu_buddy_free_tree tree)
{
- rb_add(&block->rb,
- &mm->free_trees[tree][gpu_buddy_block_order(block)],
- rbtree_block_offset_less);
+ struct rb_node **link, *parent = NULL;
+ unsigned int block_alignment, order;
+ struct gpu_buddy_block *node;
+ struct rb_root *root;
+
+ order = gpu_buddy_block_order(block);
+ block_alignment = gpu_buddy_block_offset_alignment(block);
+
+ root = &mm->free_trees[tree][order];
+ link = &root->rb_node;
+
+ while (*link) {
+ parent = *link;
+ node = rbtree_get_free_block(parent);
+ /*
+ * Manual augmentation update during insertion traversal. Required
+ * because rb_insert_augmented() only calls rotate callback during
+ * rotations. This ensures all ancestors on the insertion path have
+ * correct subtree_max_alignment values.
+ */
+ if (node->subtree_max_alignment < block_alignment)
+ node->subtree_max_alignment = block_alignment;
+
+ if (gpu_buddy_block_offset(block) < gpu_buddy_block_offset(node))
+ link = &parent->rb_left;
+ else
+ link = &parent->rb_right;
+ }
+
+ block->subtree_max_alignment = block_alignment;
+ rb_link_node(&block->rb, parent, link);
+ rb_insert_augmented(&block->rb, root, &gpu_buddy_augment_cb);
}
static void rbtree_remove(struct gpu_buddy *mm,
@@ -138,7 +173,7 @@ static void rbtree_remove(struct gpu_buddy *mm,
tree = get_block_tree(block);
root = &mm->free_trees[tree][order];
- rb_erase(&block->rb, root);
+ rb_erase_augmented(&block->rb, root, &gpu_buddy_augment_cb);
RB_CLEAR_NODE(&block->rb);
}
@@ -811,6 +846,127 @@ err_undo:
return ERR_PTR(err);
}
+static bool
+gpu_buddy_can_offset_align(u64 size, u64 min_block_size)
+{
+ return size < min_block_size && is_power_of_2(size);
+}
+
+static bool gpu_buddy_subtree_can_satisfy(struct rb_node *node,
+ unsigned int alignment)
+{
+ struct gpu_buddy_block *block;
+
+ block = rbtree_get_free_block(node);
+ return block->subtree_max_alignment >= alignment;
+}
+
+static struct gpu_buddy_block *
+gpu_buddy_find_block_aligned(struct gpu_buddy *mm,
+ enum gpu_buddy_free_tree tree,
+ unsigned int order,
+ unsigned int alignment,
+ unsigned long flags)
+{
+ struct rb_root *root = &mm->free_trees[tree][order];
+ struct rb_node *rb = root->rb_node;
+
+ while (rb) {
+ struct gpu_buddy_block *block = rbtree_get_free_block(rb);
+ struct rb_node *left_node = rb->rb_left, *right_node = rb->rb_right;
+
+ if (right_node) {
+ if (gpu_buddy_subtree_can_satisfy(right_node, alignment)) {
+ rb = right_node;
+ continue;
+ }
+ }
+
+ if (gpu_buddy_block_offset_alignment(block) >= alignment)
+ return block;
+
+ if (left_node) {
+ if (gpu_buddy_subtree_can_satisfy(left_node, alignment)) {
+ rb = left_node;
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ return NULL;
+}
+
+static struct gpu_buddy_block *
+gpu_buddy_offset_aligned_allocation(struct gpu_buddy *mm,
+ u64 size,
+ u64 min_block_size,
+ unsigned long flags)
+{
+ struct gpu_buddy_block *block = NULL;
+ unsigned int order, tmp, alignment;
+ struct gpu_buddy_block *buddy;
+ enum gpu_buddy_free_tree tree;
+ unsigned long pages;
+ int err;
+
+ alignment = ilog2(min_block_size);
+ pages = size >> ilog2(mm->chunk_size);
+ order = fls(pages) - 1;
+
+ tree = (flags & GPU_BUDDY_CLEAR_ALLOCATION) ?
+ GPU_BUDDY_CLEAR_TREE : GPU_BUDDY_DIRTY_TREE;
+
+ for (tmp = order; tmp <= mm->max_order; ++tmp) {
+ block = gpu_buddy_find_block_aligned(mm, tree, tmp,
+ alignment, flags);
+ if (!block) {
+ tree = (tree == GPU_BUDDY_CLEAR_TREE) ?
+ GPU_BUDDY_DIRTY_TREE : GPU_BUDDY_CLEAR_TREE;
+ block = gpu_buddy_find_block_aligned(mm, tree, tmp,
+ alignment, flags);
+ }
+
+ if (block)
+ break;
+ }
+
+ if (!block)
+ return ERR_PTR(-ENOSPC);
+
+ while (gpu_buddy_block_order(block) > order) {
+ struct gpu_buddy_block *left, *right;
+
+ err = split_block(mm, block);
+ if (unlikely(err))
+ goto err_undo;
+
+ left = block->left;
+ right = block->right;
+
+ if (gpu_buddy_block_offset_alignment(right) >= alignment)
+ block = right;
+ else
+ block = left;
+ }
+
+ return block;
+
+err_undo:
+ /*
+ * We really don't want to leave around a bunch of split blocks, since
+ * bigger is better, so make sure we merge everything back before we
+ * free the allocated blocks.
+ */
+ buddy = __get_buddy(block);
+ if (buddy &&
+ (gpu_buddy_block_is_free(block) &&
+ gpu_buddy_block_is_free(buddy)))
+ __gpu_buddy_free(mm, block, false);
+ return ERR_PTR(err);
+}
+
static int __alloc_range(struct gpu_buddy *mm,
struct list_head *dfs,
u64 start, u64 size,
@@ -1080,6 +1236,7 @@ EXPORT_SYMBOL(gpu_buddy_block_trim);
static struct gpu_buddy_block *
__gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
u64 start, u64 end,
+ u64 size, u64 min_block_size,
unsigned int order,
unsigned long flags)
{
@@ -1087,6 +1244,11 @@ __gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
/* Allocate traversing within the range */
return __gpu_buddy_alloc_range_bias(mm, start, end,
order, flags);
+ else if (size < min_block_size)
+ /* Allocate from an offset-aligned region without size rounding */
+ return gpu_buddy_offset_aligned_allocation(mm, size,
+ min_block_size,
+ flags);
else
/* Allocate from freetree */
return alloc_from_freetree(mm, order, flags);
@@ -1158,8 +1320,11 @@ int gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION) {
size = roundup_pow_of_two(size);
min_block_size = size;
- /* Align size value to min_block_size */
- } else if (!IS_ALIGNED(size, min_block_size)) {
+ /*
+ * Normalize the requested size to min_block_size for regular allocations.
+ * Offset-aligned allocations intentionally skip size rounding.
+ */
+ } else if (!gpu_buddy_can_offset_align(size, min_block_size)) {
size = round_up(size, min_block_size);
}
@@ -1179,43 +1344,60 @@ int gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
do {
order = min(order, (unsigned int)fls(pages) - 1);
BUG_ON(order > mm->max_order);
- BUG_ON(order < min_order);
+ /*
+ * Regular allocations must not allocate blocks smaller than min_block_size.
+ * Offset-aligned allocations deliberately bypass this constraint.
+ */
+ BUG_ON(size >= min_block_size && order < min_order);
do {
+ unsigned int fallback_order;
+
block = __gpu_buddy_alloc_blocks(mm, start,
end,
+ size,
+ min_block_size,
order,
flags);
if (!IS_ERR(block))
break;
- if (order-- == min_order) {
- /* Try allocation through force merge method */
- if (mm->clear_avail &&
- !__force_merge(mm, start, end, min_order)) {
- block = __gpu_buddy_alloc_blocks(mm, start,
- end,
- min_order,
- flags);
- if (!IS_ERR(block)) {
- order = min_order;
- break;
- }
- }
+ if (size < min_block_size) {
+ fallback_order = order;
+ } else if (order == min_order) {
+ fallback_order = min_order;
+ } else {
+ order--;
+ continue;
+ }
- /*
- * Try contiguous block allocation through
- * try harder method.
- */
- if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION &&
- !(flags & GPU_BUDDY_RANGE_ALLOCATION))
- return __alloc_contig_try_harder(mm,
- original_size,
- original_min_size,
- blocks);
- err = -ENOSPC;
- goto err_free;
+ /* Try allocation through force merge method */
+ if (mm->clear_avail &&
+ !__force_merge(mm, start, end, fallback_order)) {
+ block = __gpu_buddy_alloc_blocks(mm, start,
+ end,
+ size,
+ min_block_size,
+ fallback_order,
+ flags);
+ if (!IS_ERR(block)) {
+ order = fallback_order;
+ break;
+ }
}
+
+ /*
+ * Try contiguous block allocation through
+ * try harder method.
+ */
+ if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION &&
+ !(flags & GPU_BUDDY_RANGE_ALLOCATION))
+ return __alloc_contig_try_harder(mm,
+ original_size,
+ original_min_size,
+ blocks);
+ err = -ENOSPC;
+ goto err_free;
} while (1);
mark_allocated(mm, block);
diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig b/drivers/gpu/drm/bridge/analogix/Kconfig
index f3448b0631fe..03dc7ffe824a 100644
--- a/drivers/gpu/drm/bridge/analogix/Kconfig
+++ b/drivers/gpu/drm/bridge/analogix/Kconfig
@@ -34,7 +34,8 @@ config DRM_ANALOGIX_ANX7625
tristate "Analogix Anx7625 MIPI to DP interface support"
depends on DRM
depends on OF
- depends on TYPEC || !TYPEC
+ depends on TYPEC
+ depends on USB_ROLE_SWITCH
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDCP_HELPER
select DRM_DISPLAY_HELPER
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index c43519097a45..54b02242d6db 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -1363,6 +1363,18 @@ static void anx7625_configure_hpd(struct anx7625_data *ctx)
anx7625_hpd_timer_config(ctx);
}
+static bool anx7625_need_pd(struct anx7625_data *ctx)
+{
+ struct fwnode_handle *fwnode;
+
+ fwnode = device_get_named_child_node(ctx->dev, "connector");
+ if (!fwnode)
+ return false;
+
+ fwnode_handle_put(fwnode);
+ return true;
+}
+
static int anx7625_ocm_loading_check(struct anx7625_data *ctx)
{
int ret;
@@ -1378,7 +1390,7 @@ static int anx7625_ocm_loading_check(struct anx7625_data *ctx)
if ((ret & FLASH_LOAD_STA_CHK) != FLASH_LOAD_STA_CHK)
return -ENODEV;
- if (!ctx->typec_port)
+ if (!anx7625_need_pd(ctx))
anx7625_disable_pd_protocol(ctx);
anx7625_configure_hpd(ctx);
@@ -1483,7 +1495,6 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
DRM_DEV_DEBUG_DRIVER(dev, "Secure OCM version=%02x\n", ret);
}
-#if IS_REACHABLE(CONFIG_TYPEC)
static u8 anx7625_checksum(u8 *buf, u8 len)
{
u8 ret = 0;
@@ -1567,6 +1578,9 @@ static void anx7625_typec_set_status(struct anx7625_data *ctx,
unsigned int intr_status,
unsigned int intr_vector)
{
+ if (!ctx->typec_port)
+ return;
+
if (intr_vector & CC_STATUS)
anx7625_typec_set_orientation(ctx);
if (intr_vector & DATA_ROLE_STATUS) {
@@ -1635,22 +1649,6 @@ static void anx7625_typec_unregister(struct anx7625_data *ctx)
usb_role_switch_put(ctx->role_sw);
typec_unregister_port(ctx->typec_port);
}
-#else
-static void anx7625_typec_set_status(struct anx7625_data *ctx,
- unsigned int intr_status,
- unsigned int intr_vector)
-{
-}
-
-static int anx7625_typec_register(struct anx7625_data *ctx)
-{
- return 0;
-}
-
-static void anx7625_typec_unregister(struct anx7625_data *ctx)
-{
-}
-#endif
static int anx7625_read_hpd_status_p0(struct anx7625_data *ctx)
{
@@ -2924,12 +2922,7 @@ static int anx7625_i2c_probe(struct i2c_client *client)
}
if (!platform->pdata.low_power_mode) {
- struct fwnode_handle *fwnode;
-
- fwnode = device_get_named_child_node(dev, "connector");
- if (fwnode)
- fwnode_handle_put(fwnode);
- else
+ if (!anx7625_need_pd(platform))
anx7625_disable_pd_protocol(platform);
anx7625_configure_hpd(platform);
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
index 9392c226ff5b..945bb47c172b 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
@@ -739,12 +739,8 @@ static void cdns_mhdp_fw_cb(const struct firmware *fw, void *context)
spin_lock(&mhdp->start_lock);
bridge_attached = mhdp->bridge_attached;
spin_unlock(&mhdp->start_lock);
- if (bridge_attached) {
- if (mhdp->connector.dev)
- drm_kms_helper_hotplug_event(mhdp->bridge.dev);
- else
- drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp));
- }
+ if (bridge_attached)
+ drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp));
}
static int cdns_mhdp_load_firmware(struct cdns_mhdp_device *mhdp)
@@ -782,7 +778,7 @@ static ssize_t cdns_mhdp_transfer(struct drm_dp_aux *aux,
if (!ret)
continue;
- dev_err(mhdp->dev,
+ dev_dbg(mhdp->dev,
"Failed to write DPCD addr %u\n",
msg->address + i);
@@ -792,7 +788,7 @@ static ssize_t cdns_mhdp_transfer(struct drm_dp_aux *aux,
ret = cdns_mhdp_dpcd_read(mhdp, msg->address,
msg->buffer, msg->size);
if (ret) {
- dev_err(mhdp->dev,
+ dev_dbg(mhdp->dev,
"Failed to read DPCD addr %u\n",
msg->address);
@@ -1444,56 +1440,6 @@ static const struct drm_edid *cdns_mhdp_edid_read(struct cdns_mhdp_device *mhdp,
return drm_edid_read_custom(connector, cdns_mhdp_get_edid_block, mhdp);
}
-static int cdns_mhdp_get_modes(struct drm_connector *connector)
-{
- struct cdns_mhdp_device *mhdp = connector_to_mhdp(connector);
- const struct drm_edid *drm_edid;
- int num_modes;
-
- if (!mhdp->plugged)
- return 0;
-
- drm_edid = cdns_mhdp_edid_read(mhdp, connector);
-
- drm_edid_connector_update(connector, drm_edid);
-
- if (!drm_edid) {
- dev_err(mhdp->dev, "Failed to read EDID\n");
- return 0;
- }
-
- num_modes = drm_edid_connector_add_modes(connector);
- drm_edid_free(drm_edid);
-
- /*
- * HACK: Warn about unsupported display formats until we deal
- * with them correctly.
- */
- if (connector->display_info.color_formats &&
- !(connector->display_info.color_formats &
- mhdp->display_fmt.color_format))
- dev_warn(mhdp->dev,
- "%s: No supported color_format found (0x%08x)\n",
- __func__, connector->display_info.color_formats);
-
- if (connector->display_info.bpc &&
- connector->display_info.bpc < mhdp->display_fmt.bpc)
- dev_warn(mhdp->dev, "%s: Display bpc only %d < %d\n",
- __func__, connector->display_info.bpc,
- mhdp->display_fmt.bpc);
-
- return num_modes;
-}
-
-static int cdns_mhdp_connector_detect(struct drm_connector *conn,
- struct drm_modeset_acquire_ctx *ctx,
- bool force)
-{
- struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
-
- return cdns_mhdp_detect(mhdp);
-}
-
static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_display_fmt *fmt)
{
u32 bpp;
@@ -1547,114 +1493,6 @@ bool cdns_mhdp_bandwidth_ok(struct cdns_mhdp_device *mhdp,
return true;
}
-static
-enum drm_mode_status cdns_mhdp_mode_valid(struct drm_connector *conn,
- const struct drm_display_mode *mode)
-{
- struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
-
- mutex_lock(&mhdp->link_mutex);
-
- if (!cdns_mhdp_bandwidth_ok(mhdp, mode, mhdp->link.num_lanes,
- mhdp->link.rate)) {
- mutex_unlock(&mhdp->link_mutex);
- return MODE_CLOCK_HIGH;
- }
-
- mutex_unlock(&mhdp->link_mutex);
- return MODE_OK;
-}
-
-static int cdns_mhdp_connector_atomic_check(struct drm_connector *conn,
- struct drm_atomic_state *state)
-{
- struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
- struct drm_connector_state *old_state, *new_state;
- struct drm_crtc_state *crtc_state;
- u64 old_cp, new_cp;
-
- if (!mhdp->hdcp_supported)
- return 0;
-
- old_state = drm_atomic_get_old_connector_state(state, conn);
- new_state = drm_atomic_get_new_connector_state(state, conn);
- old_cp = old_state->content_protection;
- new_cp = new_state->content_protection;
-
- if (old_state->hdcp_content_type != new_state->hdcp_content_type &&
- new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
- new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
- goto mode_changed;
- }
-
- if (!new_state->crtc) {
- if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)
- new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
- return 0;
- }
-
- if (old_cp == new_cp ||
- (old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
- new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED))
- return 0;
-
-mode_changed:
- crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);
- crtc_state->mode_changed = true;
-
- return 0;
-}
-
-static const struct drm_connector_helper_funcs cdns_mhdp_conn_helper_funcs = {
- .detect_ctx = cdns_mhdp_connector_detect,
- .get_modes = cdns_mhdp_get_modes,
- .mode_valid = cdns_mhdp_mode_valid,
- .atomic_check = cdns_mhdp_connector_atomic_check,
-};
-
-static const struct drm_connector_funcs cdns_mhdp_conn_funcs = {
- .fill_modes = drm_helper_probe_single_connector_modes,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
- .reset = drm_atomic_helper_connector_reset,
- .destroy = drm_connector_cleanup,
-};
-
-static int cdns_mhdp_connector_init(struct cdns_mhdp_device *mhdp)
-{
- u32 bus_format = MEDIA_BUS_FMT_RGB121212_1X36;
- struct drm_connector *conn = &mhdp->connector;
- struct drm_bridge *bridge = &mhdp->bridge;
- int ret;
-
- conn->polled = DRM_CONNECTOR_POLL_HPD;
-
- ret = drm_connector_init(bridge->dev, conn, &cdns_mhdp_conn_funcs,
- DRM_MODE_CONNECTOR_DisplayPort);
- if (ret) {
- dev_err(mhdp->dev, "Failed to initialize connector with drm\n");
- return ret;
- }
-
- drm_connector_helper_add(conn, &cdns_mhdp_conn_helper_funcs);
-
- ret = drm_display_info_set_bus_formats(&conn->display_info,
- &bus_format, 1);
- if (ret)
- return ret;
-
- ret = drm_connector_attach_encoder(conn, bridge->encoder);
- if (ret) {
- dev_err(mhdp->dev, "Failed to attach connector to encoder\n");
- return ret;
- }
-
- if (mhdp->hdcp_supported)
- ret = drm_connector_attach_content_protection_property(conn, true);
-
- return ret;
-}
-
static int cdns_mhdp_attach(struct drm_bridge *bridge,
struct drm_encoder *encoder,
enum drm_bridge_attach_flags flags)
@@ -1671,9 +1509,11 @@ static int cdns_mhdp_attach(struct drm_bridge *bridge,
return ret;
if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) {
- ret = cdns_mhdp_connector_init(mhdp);
- if (ret)
- goto aux_unregister;
+ ret = -EINVAL;
+ dev_err(mhdp->dev,
+ "Connector initialisation not supported in bridge_attach %d\n",
+ ret);
+ goto aux_unregister;
}
spin_lock(&mhdp->start_lock);
@@ -1915,17 +1755,25 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
struct cdns_mhdp_bridge_state *mhdp_state;
struct drm_crtc_state *crtc_state;
- struct drm_connector *connector;
struct drm_connector_state *conn_state;
struct drm_bridge_state *new_state;
const struct drm_display_mode *mode;
u32 resp;
- int ret;
+ int ret = 0;
dev_dbg(mhdp->dev, "bridge enable\n");
mutex_lock(&mhdp->link_mutex);
+ mhdp->connector = drm_atomic_get_new_connector_for_encoder(state,
+ bridge->encoder);
+ if (WARN_ON(!mhdp->connector))
+ goto out;
+
+ conn_state = drm_atomic_get_new_connector_state(state, mhdp->connector);
+ if (WARN_ON(!conn_state))
+ goto out;
+
if (mhdp->plugged && !mhdp->link_up) {
ret = cdns_mhdp_link_up(mhdp);
if (ret < 0)
@@ -1945,15 +1793,6 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
resp | CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN);
- connector = drm_atomic_get_new_connector_for_encoder(state,
- bridge->encoder);
- if (WARN_ON(!connector))
- goto out;
-
- conn_state = drm_atomic_get_new_connector_state(state, connector);
- if (WARN_ON(!conn_state))
- goto out;
-
if (mhdp->hdcp_supported &&
mhdp->hw_state == MHDP_HW_READY &&
conn_state->content_protection ==
@@ -2030,6 +1869,7 @@ static void cdns_mhdp_atomic_disable(struct drm_bridge *bridge,
if (mhdp->info && mhdp->info->ops && mhdp->info->ops->disable)
mhdp->info->ops->disable(mhdp);
+ mhdp->connector = NULL;
mutex_unlock(&mhdp->link_mutex);
}
@@ -2122,6 +1962,10 @@ static int cdns_mhdp_atomic_check(struct drm_bridge *bridge,
{
struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
+ struct drm_connector_state *old_state, *new_state;
+ struct drm_atomic_state *state = crtc_state->state;
+ struct drm_connector *conn = mhdp->connector;
+ u64 old_cp, new_cp;
mutex_lock(&mhdp->link_mutex);
@@ -2141,6 +1985,25 @@ static int cdns_mhdp_atomic_check(struct drm_bridge *bridge,
if (mhdp->info)
bridge_state->input_bus_cfg.flags = *mhdp->info->input_bus_flags;
+ if (conn && mhdp->hdcp_supported) {
+ old_state = drm_atomic_get_old_connector_state(state, conn);
+ new_state = drm_atomic_get_new_connector_state(state, conn);
+ old_cp = old_state->content_protection;
+ new_cp = new_state->content_protection;
+
+ if (old_state->hdcp_content_type != new_state->hdcp_content_type &&
+ new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
+ new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);
+ crtc_state->mode_changed = true;
+ }
+
+ if (!new_state->crtc) {
+ if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)
+ new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ }
+ }
+
mutex_unlock(&mhdp->link_mutex);
return 0;
}
@@ -2161,6 +2024,25 @@ static const struct drm_edid *cdns_mhdp_bridge_edid_read(struct drm_bridge *brid
return cdns_mhdp_edid_read(mhdp, connector);
}
+static enum drm_mode_status
+cdns_mhdp_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_info *info,
+ const struct drm_display_mode *mode)
+{
+ struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
+
+ mutex_lock(&mhdp->link_mutex);
+
+ if (!cdns_mhdp_bandwidth_ok(mhdp, mode, mhdp->link.num_lanes,
+ mhdp->link.rate)) {
+ mutex_unlock(&mhdp->link_mutex);
+ return MODE_CLOCK_HIGH;
+ }
+
+ mutex_unlock(&mhdp->link_mutex);
+ return MODE_OK;
+}
+
static const struct drm_bridge_funcs cdns_mhdp_bridge_funcs = {
.atomic_enable = cdns_mhdp_atomic_enable,
.atomic_disable = cdns_mhdp_atomic_disable,
@@ -2175,6 +2057,7 @@ static const struct drm_bridge_funcs cdns_mhdp_bridge_funcs = {
.edid_read = cdns_mhdp_bridge_edid_read,
.hpd_enable = cdns_mhdp_bridge_hpd_enable,
.hpd_disable = cdns_mhdp_bridge_hpd_disable,
+ .mode_valid = cdns_mhdp_bridge_mode_valid,
};
static bool cdns_mhdp_detect_hpd(struct cdns_mhdp_device *mhdp, bool *hpd_pulse)
@@ -2296,7 +2179,7 @@ static void cdns_mhdp_modeset_retry_fn(struct work_struct *work)
mhdp = container_of(work, typeof(*mhdp), modeset_retry_work);
- conn = &mhdp->connector;
+ conn = mhdp->connector;
/* Grab the locks before changing connector property */
mutex_lock(&conn->dev->mode_config.mutex);
@@ -2370,17 +2253,9 @@ static void cdns_mhdp_hpd_work(struct work_struct *work)
struct cdns_mhdp_device *mhdp = container_of(work,
struct cdns_mhdp_device,
hpd_work);
- int ret;
+ cdns_mhdp_update_link_status(mhdp);
- ret = cdns_mhdp_update_link_status(mhdp);
- if (mhdp->connector.dev) {
- if (ret < 0)
- schedule_work(&mhdp->modeset_retry_work);
- else
- drm_kms_helper_hotplug_event(mhdp->bridge.dev);
- } else {
- drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp));
- }
+ drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp));
}
static int cdns_mhdp_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
index bad2fc0c7306..b297db53ba28 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
@@ -375,7 +375,7 @@ struct cdns_mhdp_device {
*/
struct mutex link_mutex;
- struct drm_connector connector;
+ struct drm_connector *connector;
struct drm_bridge bridge;
struct cdns_mhdp_link link;
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c
index 42248f179b69..5cd0b873e16f 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c
@@ -394,7 +394,7 @@ static int _cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp)
int ret;
dev_dbg(mhdp->dev, "[%s:%d] HDCP is being disabled...\n",
- mhdp->connector.name, mhdp->connector.base.id);
+ mhdp->connector->name, mhdp->connector->base.id);
ret = cdns_mhdp_hdcp_set_config(mhdp, 0, false);
@@ -436,6 +436,10 @@ static int cdns_mhdp_hdcp_check_link(struct cdns_mhdp_device *mhdp)
int ret = 0;
mutex_lock(&mhdp->hdcp.mutex);
+
+ if (!mhdp->connector)
+ goto out;
+
if (mhdp->hdcp.value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
goto out;
@@ -445,7 +449,7 @@ static int cdns_mhdp_hdcp_check_link(struct cdns_mhdp_device *mhdp)
dev_err(mhdp->dev,
"[%s:%d] HDCP link failed, retrying authentication\n",
- mhdp->connector.name, mhdp->connector.base.id);
+ mhdp->connector->name, mhdp->connector->base.id);
ret = _cdns_mhdp_hdcp_disable(mhdp);
if (ret) {
@@ -487,13 +491,19 @@ static void cdns_mhdp_hdcp_prop_work(struct work_struct *work)
struct cdns_mhdp_device *mhdp = container_of(hdcp,
struct cdns_mhdp_device,
hdcp);
- struct drm_device *dev = mhdp->connector.dev;
+ struct drm_device *dev = NULL;
struct drm_connector_state *state;
+ if (mhdp->connector)
+ dev = mhdp->connector->dev;
+
+ if (!dev)
+ return;
+
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
mutex_lock(&mhdp->hdcp.mutex);
if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
- state = mhdp->connector.state;
+ state = mhdp->connector->state;
state->content_protection = mhdp->hdcp.value;
}
mutex_unlock(&mhdp->hdcp.mutex);
diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 7b5a49935ae4..4500deef4127 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -265,6 +265,8 @@ void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem)
shmem->pages_mark_dirty_on_put,
shmem->pages_mark_accessed_on_put);
shmem->pages = NULL;
+ shmem->pages_mark_accessed_on_put = false;
+ shmem->pages_mark_dirty_on_put = false;
}
}
EXPORT_SYMBOL_GPL(drm_gem_shmem_put_pages_locked);
@@ -397,6 +399,8 @@ int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem,
} else {
iosys_map_set_vaddr(map, shmem->vaddr);
refcount_set(&shmem->vmap_use_count, 1);
+ shmem->pages_mark_accessed_on_put = true;
+ shmem->pages_mark_dirty_on_put = true;
}
}
@@ -550,59 +554,59 @@ int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev,
}
EXPORT_SYMBOL_GPL(drm_gem_shmem_dumb_create);
-static bool drm_gem_shmem_try_map_pmd(struct vm_fault *vmf, unsigned long addr,
- struct page *page)
+static vm_fault_t drm_gem_shmem_try_insert_pfn_pmd(struct vm_fault *vmf, unsigned long pfn)
{
#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
- unsigned long pfn = page_to_pfn(page);
unsigned long paddr = pfn << PAGE_SHIFT;
- bool aligned = (addr & ~PMD_MASK) == (paddr & ~PMD_MASK);
+ bool aligned = (vmf->address & ~PMD_MASK) == (paddr & ~PMD_MASK);
- if (aligned &&
- pmd_none(*vmf->pmd) &&
- folio_test_pmd_mappable(page_folio(page))) {
+ if (aligned && pmd_none(*vmf->pmd)) {
+ /* Read-only mapping; split upon write fault */
pfn &= PMD_MASK >> PAGE_SHIFT;
- if (vmf_insert_pfn_pmd(vmf, pfn, false) == VM_FAULT_NOPAGE)
- return true;
+ return vmf_insert_pfn_pmd(vmf, pfn, false);
}
#endif
- return false;
+ return 0;
}
static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
struct drm_gem_object *obj = vma->vm_private_data;
+ struct drm_device *dev = obj->dev;
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
loff_t num_pages = obj->size >> PAGE_SHIFT;
- vm_fault_t ret;
+ vm_fault_t ret = VM_FAULT_SIGBUS;
struct page **pages = shmem->pages;
- pgoff_t page_offset;
+ pgoff_t page_offset = vmf->pgoff - vma->vm_pgoff; /* page offset within VMA */
+ struct page *page;
+ struct folio *folio;
unsigned long pfn;
- /* Offset to faulty address in the VMA. */
- page_offset = vmf->pgoff - vma->vm_pgoff;
-
- dma_resv_lock(shmem->base.resv, NULL);
+ dma_resv_lock(obj->resv, NULL);
- if (page_offset >= num_pages ||
- drm_WARN_ON_ONCE(obj->dev, !shmem->pages) ||
- shmem->madv < 0) {
- ret = VM_FAULT_SIGBUS;
+ if (page_offset >= num_pages || drm_WARN_ON_ONCE(dev, !shmem->pages) ||
+ shmem->madv < 0)
goto out;
- }
- if (drm_gem_shmem_try_map_pmd(vmf, vmf->address, pages[page_offset])) {
- ret = VM_FAULT_NOPAGE;
+ page = pages[page_offset];
+ if (drm_WARN_ON_ONCE(dev, !page))
goto out;
- }
+ folio = page_folio(page);
- pfn = page_to_pfn(pages[page_offset]);
- ret = vmf_insert_pfn(vma, vmf->address, pfn);
+ pfn = page_to_pfn(page);
- out:
- dma_resv_unlock(shmem->base.resv);
+ if (folio_test_pmd_mappable(folio))
+ ret = drm_gem_shmem_try_insert_pfn_pmd(vmf, pfn);
+ if (ret != VM_FAULT_NOPAGE)
+ ret = vmf_insert_pfn(vma, vmf->address, pfn);
+
+ if (ret == VM_FAULT_NOPAGE)
+ folio_mark_accessed(folio);
+
+out:
+ dma_resv_unlock(obj->resv);
return ret;
}
@@ -641,10 +645,29 @@ static void drm_gem_shmem_vm_close(struct vm_area_struct *vma)
drm_gem_vm_close(vma);
}
+static vm_fault_t drm_gem_shmem_pfn_mkwrite(struct vm_fault *vmf)
+{
+ struct vm_area_struct *vma = vmf->vma;
+ struct drm_gem_object *obj = vma->vm_private_data;
+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+ loff_t num_pages = obj->size >> PAGE_SHIFT;
+ pgoff_t page_offset = vmf->pgoff - vma->vm_pgoff; /* page offset within VMA */
+
+ if (drm_WARN_ON(obj->dev, !shmem->pages || page_offset >= num_pages))
+ return VM_FAULT_SIGBUS;
+
+ file_update_time(vma->vm_file);
+
+ folio_mark_dirty(page_folio(shmem->pages[page_offset]));
+
+ return 0;
+}
+
const struct vm_operations_struct drm_gem_shmem_vm_ops = {
.fault = drm_gem_shmem_fault,
.open = drm_gem_shmem_vm_open,
.close = drm_gem_shmem_vm_close,
+ .pfn_mkwrite = drm_gem_shmem_pfn_mkwrite,
};
EXPORT_SYMBOL_GPL(drm_gem_shmem_vm_ops);
diff --git a/drivers/gpu/drm/imagination/pvr_gem.c b/drivers/gpu/drm/imagination/pvr_gem.c
index 686a3fe22986..d8660d6a8e01 100644
--- a/drivers/gpu/drm/imagination/pvr_gem.c
+++ b/drivers/gpu/drm/imagination/pvr_gem.c
@@ -25,7 +25,10 @@
static void pvr_gem_object_free(struct drm_gem_object *obj)
{
- drm_gem_shmem_object_free(obj);
+ struct drm_gem_shmem_object *shmem_obj = to_drm_gem_shmem_obj(obj);
+
+ shmem_obj->pages_mark_dirty_on_put = true;
+ drm_gem_shmem_free(shmem_obj);
}
static struct dma_buf *pvr_gem_export(struct drm_gem_object *obj, int flags)
@@ -363,7 +366,6 @@ pvr_gem_object_create(struct pvr_device *pvr_dev, size_t size, u64 flags)
if (IS_ERR(shmem_obj))
return ERR_CAST(shmem_obj);
- shmem_obj->pages_mark_dirty_on_put = true;
shmem_obj->map_wc = !(flags & PVR_BO_CPU_CACHED);
pvr_obj = shmem_gem_to_pvr_gem(shmem_obj);
pvr_obj->flags = flags;
diff --git a/drivers/gpu/drm/loongson/lsdc_drv.c b/drivers/gpu/drm/loongson/lsdc_drv.c
index abf5bf68eec2..1ece1ea42f78 100644
--- a/drivers/gpu/drm/loongson/lsdc_drv.c
+++ b/drivers/gpu/drm/loongson/lsdc_drv.c
@@ -13,6 +13,7 @@
#include <drm/drm_drv.h>
#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_modeset_helper.h>
#include <drm/drm_print.h>
@@ -45,7 +46,7 @@ static const struct drm_driver lsdc_drm_driver = {
.debugfs_init = lsdc_debugfs_init,
.dumb_create = lsdc_dumb_create,
- .dumb_map_offset = lsdc_dumb_map_offset,
+ .dumb_map_offset = drm_gem_ttm_dumb_map_offset,
.gem_prime_import_sg_table = lsdc_prime_import_sg_table,
DRM_FBDEV_TTM_DRIVER_OPS,
};
diff --git a/drivers/gpu/drm/loongson/lsdc_gem.c b/drivers/gpu/drm/loongson/lsdc_gem.c
index 6372db2d3093..2fb03487c983 100644
--- a/drivers/gpu/drm/loongson/lsdc_gem.c
+++ b/drivers/gpu/drm/loongson/lsdc_gem.c
@@ -234,21 +234,6 @@ int lsdc_dumb_create(struct drm_file *file, struct drm_device *ddev,
return 0;
}
-int lsdc_dumb_map_offset(struct drm_file *filp, struct drm_device *ddev,
- u32 handle, uint64_t *offset)
-{
- struct drm_gem_object *gobj;
-
- gobj = drm_gem_object_lookup(filp, handle);
- if (!gobj)
- return -ENOENT;
-
- *offset = drm_vma_node_offset_addr(&gobj->vma_node);
-
- drm_gem_object_put(gobj);
-
- return 0;
-}
void lsdc_gem_init(struct drm_device *ddev)
{
diff --git a/drivers/gpu/drm/loongson/lsdc_gem.h b/drivers/gpu/drm/loongson/lsdc_gem.h
index 92cbb10e6e13..96729b3eebec 100644
--- a/drivers/gpu/drm/loongson/lsdc_gem.h
+++ b/drivers/gpu/drm/loongson/lsdc_gem.h
@@ -14,10 +14,6 @@ lsdc_prime_import_sg_table(struct drm_device *ddev,
struct dma_buf_attachment *attach,
struct sg_table *sg);
-int lsdc_dumb_map_offset(struct drm_file *file,
- struct drm_device *dev,
- u32 handle,
- uint64_t *offset);
int lsdc_dumb_create(struct drm_file *file,
struct drm_device *ddev,
diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index fcb2a7517377..47da1d9336b9 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -149,15 +149,17 @@ static int lcdif_load(struct drm_device *drm)
lcdif->clk = devm_clk_get(drm->dev, "pix");
if (IS_ERR(lcdif->clk))
- return PTR_ERR(lcdif->clk);
+ return dev_err_probe(drm->dev, PTR_ERR(lcdif->clk), "Failed to get pix clock\n");
lcdif->clk_axi = devm_clk_get(drm->dev, "axi");
if (IS_ERR(lcdif->clk_axi))
- return PTR_ERR(lcdif->clk_axi);
+ return dev_err_probe(drm->dev, PTR_ERR(lcdif->clk_axi),
+ "Failed to get axi clock\n");
lcdif->clk_disp_axi = devm_clk_get(drm->dev, "disp_axi");
if (IS_ERR(lcdif->clk_disp_axi))
- return PTR_ERR(lcdif->clk_disp_axi);
+ return dev_err_probe(drm->dev, PTR_ERR(lcdif->clk_disp_axi),
+ "Failed to get disp_axi clock\n");
platform_set_drvdata(pdev, drm);
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 79264f7bbd0e..a99f2e2a49fe 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -443,6 +443,15 @@ config DRM_PANEL_LG_SW43408
pixel. It provides a MIPI DSI interface to the host and has a
built-in LED backlight.
+config DRM_PANEL_LXD_M9189A
+ tristate "LXD M9189A MIPI-DSI LCD panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y if you want to enable support for the LXD M9189A 4-Lane
+ 1024x600 MIPI DSI panel.
+
config DRM_PANEL_MAGNACHIP_D53E6EA8966
tristate "Magnachip D53E6EA8966 DSI panel"
depends on OF && SPI
@@ -465,6 +474,18 @@ config DRM_PANEL_MANTIX_MLAF057WE51
has a resolution of 720x1440 pixels, a built in backlight and touch
controller.
+config DRM_PANEL_MOTOROLA_MOT
+ tristate "Atrix 4G and Droid X2 540x960 DSI video mode panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ select VIDEOMODE_HELPERS
+ help
+ Say Y here if you want to enable support for the LCD panel module
+ for Motorola Atrix 4G or Droid X2. Exact panel vendor and model are
+ unknown. The panel has a 540x960 resolution and uses 24 bit RGB per
+ pixel.
+
config DRM_PANEL_NEC_NL8048HL11
tristate "NEC NL8048HL11 RGB panel"
depends on GPIOLIB && OF && SPI
@@ -554,6 +575,15 @@ config DRM_PANEL_NOVATEK_NT36672E
LCD panel module. The panel has a resolution of 1080x2408 and uses 24 bit
RGB per pixel.
+config DRM_PANEL_NOVATEK_NT37700F
+ tristate "Novatek NT37700F DSI panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y here if you want to enable support for Novatek NT37700F DSI
+ panel module. The panel has a resolution of 1080x2160.
+
config DRM_PANEL_NOVATEK_NT37801
tristate "Novatek NT37801/NT37810 AMOLED DSI panel"
depends on OF
@@ -689,6 +719,7 @@ config DRM_PANEL_RENESAS_R61307
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
+ select VIDEOMODE_HELPERS
help
Say Y here if you want to enable support for KOE tx13d100vm0eaa
IPS-LCD module with Renesas R69328 IC. The panel has a 1024x768
@@ -702,6 +733,7 @@ config DRM_PANEL_RENESAS_R69328
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
+ select VIDEOMODE_HELPERS
help
Say Y here if you want to enable support for JDI dx12d100vm0eaa
IPS-LCD module with Renesas R69328 IC. The panel has a 720x1280
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index aeffaa95666d..3336a2c0cd86 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -44,7 +44,9 @@ obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o
obj-$(CONFIG_DRM_PANEL_LG_LD070WX3) += panel-lg-ld070wx3.o
obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
obj-$(CONFIG_DRM_PANEL_LG_SW43408) += panel-lg-sw43408.o
+obj-$(CONFIG_DRM_PANEL_LXD_M9189A) += panel-lxd-m9189a.o
obj-$(CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966) += panel-magnachip-d53e6ea8966.o
+obj-$(CONFIG_DRM_PANEL_MOTOROLA_MOT) += panel-motorola-mot.o
obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3051D) += panel-newvision-nv3051d.o
obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3052C) += panel-newvision-nv3052c.o
@@ -54,6 +56,7 @@ obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35950) += panel-novatek-nt35950.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36523) += panel-novatek-nt36523.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672A) += panel-novatek-nt36672a.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672E) += panel-novatek-nt36672e.o
+obj-$(CONFIG_DRM_PANEL_NOVATEK_NT37700F) += panel-novatek-nt37700f.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT37801) += panel-novatek-nt37801.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o
obj-$(CONFIG_DRM_PANEL_MANTIX_MLAF057WE51) += panel-mantix-mlaf057we51.o
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
index 8b2bfb7d3638..5f4e0d82ee67 100644
--- a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
@@ -592,7 +592,7 @@ static int ili9882t_unprepare(struct drm_panel *panel)
{
struct ili9882t *ili = to_ili9882t(panel);
- gpiod_set_value(ili->enable_gpio, 0);
+ gpiod_set_value_cansleep(ili->enable_gpio, 0);
usleep_range(1000, 2000);
regulator_disable(ili->avee);
regulator_disable(ili->avdd);
@@ -608,7 +608,7 @@ static int ili9882t_prepare(struct drm_panel *panel)
struct ili9882t *ili = to_ili9882t(panel);
int ret;
- gpiod_set_value(ili->enable_gpio, 0);
+ gpiod_set_value_cansleep(ili->enable_gpio, 0);
usleep_range(1000, 1500);
ret = regulator_enable(ili->pp3300);
@@ -638,11 +638,11 @@ static int ili9882t_prepare(struct drm_panel *panel)
}
usleep_range(1000, 2000);
- gpiod_set_value(ili->enable_gpio, 1);
+ gpiod_set_value_cansleep(ili->enable_gpio, 1);
usleep_range(1000, 2000);
- gpiod_set_value(ili->enable_gpio, 0);
+ gpiod_set_value_cansleep(ili->enable_gpio, 0);
msleep(50);
- gpiod_set_value(ili->enable_gpio, 1);
+ gpiod_set_value_cansleep(ili->enable_gpio, 1);
usleep_range(6000, 10000);
ret = ili->desc->init(ili);
@@ -652,7 +652,7 @@ static int ili9882t_prepare(struct drm_panel *panel)
return 0;
poweroff:
- gpiod_set_value(ili->enable_gpio, 0);
+ gpiod_set_value_cansleep(ili->enable_gpio, 0);
regulator_disable(ili->avee);
poweroffavdd:
regulator_disable(ili->avdd);
@@ -793,7 +793,7 @@ static int ili9882t_add(struct ili9882t *ili)
return PTR_ERR(ili->enable_gpio);
}
- gpiod_set_value(ili->enable_gpio, 0);
+ gpiod_set_value_cansleep(ili->enable_gpio, 0);
err = of_drm_get_panel_orientation(dev->of_node, &ili->orientation);
if (err < 0) {
diff --git a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
index 5386a06fcd08..c33c611e03c0 100644
--- a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
+++ b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
@@ -1366,6 +1366,246 @@ static const struct jadard_panel_desc anbernic_rgds_display_desc = {
MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
};
+static int taiguan_xti05101_01a_init_cmds(struct jadard *jadard)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi };
+
+ jd9365da_switch_page(&dsi_ctx, 0x00);
+ jadard_enable_standard_cmds(&dsi_ctx);
+
+ jd9365da_switch_page(&dsi_ctx, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x74);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xd7);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xd7);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xfe);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x19);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x78);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x7f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x6a);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x15);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x7f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x58);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x35);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x27);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x2b);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x4d);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x36);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x7f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x58);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x35);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x27);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x2b);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x4d);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x36);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x02);
+
+ jd9365da_switch_page(&dsi_ctx, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x52);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x77);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x57);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x4c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x4a);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x53);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x77);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x57);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x4d);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x4b);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2c, 0x13);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2d, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2e, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x30, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x31, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x46, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x47, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4a, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4c, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4d, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4e, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4f, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x50, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x54, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x6c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x6c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x75);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0xb4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x6c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x6c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x88);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xbb);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x2a);
+
+ jd9365da_switch_page(&dsi_ctx, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0xb3);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x61);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x58);
+
+ jd9365da_switch_page(&dsi_ctx, 0x00);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
+
+ mipi_dsi_msleep(&dsi_ctx, 120);
+
+ mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
+
+ mipi_dsi_msleep(&dsi_ctx, 20);
+
+ return dsi_ctx.accum_err;
+};
+
+static const struct jadard_panel_desc taiguan_xti05101_01a_desc = {
+ .mode = {
+ .clock = (800 + 24 + 24 + 24) * (1280 + 30 + 4 + 8) * 60 / 1000,
+
+ .hdisplay = 800,
+ .hsync_start = 800 + 24,
+ .hsync_end = 800 + 24 + 24,
+ .htotal = 800 + 24 + 24 + 24,
+
+ .vdisplay = 1280,
+ .vsync_start = 1280 + 30,
+ .vsync_end = 1280 + 30 + 4,
+ .vtotal = 1280 + 30 + 4 + 8,
+
+ .width_mm = 135,
+ .height_mm = 216,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+ },
+ .lanes = 4,
+ .format = MIPI_DSI_FMT_RGB888,
+ .init = taiguan_xti05101_01a_init_cmds,
+ .lp11_before_reset = true,
+ .reset_before_power_off_vcioo = true,
+ .vcioo_to_lp11_delay_ms = 5,
+ .lp11_to_reset_delay_ms = 10,
+ .backlight_off_to_display_off_delay_ms = 3,
+ .display_off_to_enter_sleep_delay_ms = 50,
+ .enter_sleep_to_reset_down_delay_ms = 100,
+};
+
static int jadard_dsi_probe(struct mipi_dsi_device *dsi)
{
struct device *dev = &dsi->dev;
@@ -1463,6 +1703,10 @@ static const struct of_device_id jadard_of_match[] = {
.compatible = "radxa,display-8hd-ad002",
.data = &radxa_display_8hd_ad002_desc
},
+ {
+ .compatible = "taiguanck,xti05101-01a",
+ .data = &taiguan_xti05101_01a_desc
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, jadard_of_match);
diff --git a/drivers/gpu/drm/panel/panel-lxd-m9189a.c b/drivers/gpu/drm/panel/panel-lxd-m9189a.c
new file mode 100644
index 000000000000..68019e1e43a9
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-lxd-m9189a.c
@@ -0,0 +1,243 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree.
+ * Copyright (c) 2024 Luca Weiss <luca.weiss@fairphone.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+#include <linux/types.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
+
+/* Manufacturer specific DSI commands */
+#define EK79007AD3_GAMMA1 0x80
+#define EK79007AD3_GAMMA2 0x81
+#define EK79007AD3_GAMMA3 0x82
+#define EK79007AD3_GAMMA4 0x83
+#define EK79007AD3_GAMMA5 0x84
+#define EK79007AD3_GAMMA6 0x85
+#define EK79007AD3_GAMMA7 0x86
+#define EK79007AD3_PANEL_CTRL3 0xB2
+
+struct m9189_panel {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+ struct regulator *supply;
+ struct gpio_desc *reset_gpio;
+ struct gpio_desc *standby_gpio;
+};
+
+static inline struct m9189_panel *to_m9189_panel(struct drm_panel *panel)
+{
+ return container_of(panel, struct m9189_panel, panel);
+}
+
+static void m9189_reset(struct m9189_panel *m9189)
+{
+ gpiod_set_value_cansleep(m9189->reset_gpio, 0);
+ msleep(20);
+ gpiod_set_value_cansleep(m9189->reset_gpio, 1);
+ msleep(30);
+ gpiod_set_value_cansleep(m9189->reset_gpio, 0);
+ msleep(55);
+}
+
+static int m9189_on(struct m9189_panel *m9189)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = m9189->dsi };
+
+ ctx.dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ /* Gamma 2.2 */
+ mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA1, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA2, 0xB8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA3, 0x88);
+ mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA4, 0x88);
+ mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA5, 0x58);
+ mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA6, 0xD2);
+ mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA7, 0x88);
+ mipi_dsi_msleep(&ctx, 50);
+
+ /* 4 Lanes */
+ mipi_dsi_generic_write_multi(&ctx, (u8[]){ EK79007AD3_PANEL_CTRL3, 0x70 }, 2);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 120);
+
+ mipi_dsi_dcs_set_display_on_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 120);
+
+ return ctx.accum_err;
+}
+
+static int m9189_disable(struct drm_panel *panel)
+{
+ struct m9189_panel *m9189 = to_m9189_panel(panel);
+ struct mipi_dsi_multi_context ctx = { .dsi = m9189->dsi };
+
+ ctx.dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 120);
+
+ gpiod_set_value_cansleep(m9189->standby_gpio, 1);
+
+ return ctx.accum_err;
+}
+
+static int m9189_prepare(struct drm_panel *panel)
+{
+ struct m9189_panel *m9189 = to_m9189_panel(panel);
+ struct device *dev = &m9189->dsi->dev;
+ int ret;
+
+ ret = regulator_enable(m9189->supply);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable regulators: %d\n", ret);
+ return ret;
+ }
+
+ gpiod_set_value_cansleep(m9189->standby_gpio, 0);
+ msleep(20);
+ m9189_reset(m9189);
+
+ ret = m9189_on(m9189);
+ if (ret < 0) {
+ dev_err(dev, "Failed to initialize panel: %d\n", ret);
+ gpiod_set_value_cansleep(m9189->reset_gpio, 1);
+ regulator_disable(m9189->supply);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int m9189_unprepare(struct drm_panel *panel)
+{
+ struct m9189_panel *m9189 = to_m9189_panel(panel);
+
+ gpiod_set_value_cansleep(m9189->standby_gpio, 1);
+ msleep(50);
+
+ gpiod_set_value_cansleep(m9189->reset_gpio, 1);
+ regulator_disable(m9189->supply);
+
+ return 0;
+}
+
+static const struct drm_display_mode m9189_mode = {
+ .clock = (1024 + 160 + 160 + 10) * (600 + 12 + 23 + 1) * 60 / 1000,
+ .hdisplay = 1024,
+ .hsync_start = 1024 + 160,
+ .hsync_end = 1024 + 160 + 160,
+ .htotal = 1024 + 160 + 160 + 10,
+ .vdisplay = 600,
+ .vsync_start = 600 + 12,
+ .vsync_end = 600 + 12 + 23,
+ .vtotal = 600 + 12 + 23 + 1,
+ .width_mm = 154,
+ .height_mm = 86,
+};
+
+static int m9189_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ return drm_connector_helper_get_modes_fixed(connector, &m9189_mode);
+}
+
+static const struct drm_panel_funcs m9189_panel_funcs = {
+ .prepare = m9189_prepare,
+ .unprepare = m9189_unprepare,
+ .disable = m9189_disable,
+ .get_modes = m9189_get_modes,
+};
+
+static int lxd_m9189_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct m9189_panel *m9189;
+ int ret;
+
+ m9189 = devm_kzalloc(dev, sizeof(*m9189), GFP_KERNEL);
+ if (!m9189)
+ return -ENOMEM;
+
+ m9189->supply = devm_regulator_get(dev, "power");
+ if (IS_ERR(m9189->supply))
+ return dev_err_probe(dev, PTR_ERR(m9189->supply),
+ "Failed to get power-supply\n");
+
+ m9189->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(m9189->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(m9189->reset_gpio),
+ "Failed to get reset-gpios\n");
+
+ m9189->standby_gpio = devm_gpiod_get(dev, "standby", GPIOD_OUT_LOW);
+ if (IS_ERR(m9189->standby_gpio))
+ return dev_err_probe(dev, PTR_ERR(m9189->standby_gpio),
+ "Failed to get standby-gpios\n");
+
+ m9189->dsi = dsi;
+ mipi_dsi_set_drvdata(dsi, m9189);
+
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST;
+
+ drm_panel_init(&m9189->panel, dev, &m9189_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ m9189->panel.prepare_prev_first = true;
+
+ ret = drm_panel_of_backlight(&m9189->panel);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+ drm_panel_add(&m9189->panel);
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
+ drm_panel_remove(&m9189->panel);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void lxd_m9189_remove(struct mipi_dsi_device *dsi)
+{
+ struct m9189_panel *m9189 = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ ret = mipi_dsi_detach(dsi);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+ drm_panel_remove(&m9189->panel);
+}
+
+static const struct of_device_id lxd_m9189_of_match[] = {
+ { .compatible = "lxd,m9189a" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, lxd_m9189_of_match);
+
+static struct mipi_dsi_driver lxd_m9189_driver = {
+ .probe = lxd_m9189_probe,
+ .remove = lxd_m9189_remove,
+ .driver = {
+ .name = "panel-lxd-m9189a",
+ .of_match_table = lxd_m9189_of_match,
+ },
+};
+module_mipi_dsi_driver(lxd_m9189_driver);
+
+MODULE_DESCRIPTION("DRM driver for LXD M9189A MIPI-DSI panels");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c b/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c
index 13352cb4ad77..27e188bb2d7f 100644
--- a/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c
+++ b/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c
@@ -168,7 +168,7 @@ static const struct drm_display_mode default_mode_mantix = {
.vsync_start = 1440 + 130,
.vsync_end = 1440 + 130 + 8,
.vtotal = 1440 + 130 + 8 + 106,
- .clock = 85298,
+ .clock = 81237,
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
.width_mm = 65,
.height_mm = 130,
@@ -183,7 +183,7 @@ static const struct drm_display_mode default_mode_ys = {
.vsync_start = 1440 + 175,
.vsync_end = 1440 + 175 + 8,
.vtotal = 1440 + 175 + 8 + 50,
- .clock = 85298,
+ .clock = 80706,
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
.width_mm = 65,
.height_mm = 130,
@@ -295,20 +295,10 @@ static int mantix_probe(struct mipi_dsi_device *dsi)
return 0;
}
-static void mantix_shutdown(struct mipi_dsi_device *dsi)
-{
- struct mantix *ctx = mipi_dsi_get_drvdata(dsi);
-
- drm_panel_unprepare(&ctx->panel);
- drm_panel_disable(&ctx->panel);
-}
-
static void mantix_remove(struct mipi_dsi_device *dsi)
{
struct mantix *ctx = mipi_dsi_get_drvdata(dsi);
- mantix_shutdown(dsi);
-
mipi_dsi_detach(dsi);
drm_panel_remove(&ctx->panel);
}
@@ -323,7 +313,6 @@ MODULE_DEVICE_TABLE(of, mantix_of_match);
static struct mipi_dsi_driver mantix_driver = {
.probe = mantix_probe,
.remove = mantix_remove,
- .shutdown = mantix_shutdown,
.driver = {
.name = DRV_NAME,
.of_match_table = mantix_of_match,
diff --git a/drivers/gpu/drm/panel/panel-motorola-mot.c b/drivers/gpu/drm/panel/panel-motorola-mot.c
new file mode 100644
index 000000000000..eb1f86c3d704
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-motorola-mot.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/array_size.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
+
+static const struct regulator_bulk_data mot_panel_supplies[] = {
+ { .supply = "vddio" }, { .supply = "vdd" },
+};
+
+struct mot_panel {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+
+ struct gpio_desc *reset_gpio;
+
+ struct regulator_bulk_data *supplies;
+};
+
+static inline struct mot_panel *to_mot_panel(struct drm_panel *panel)
+{
+ return container_of(panel, struct mot_panel, panel);
+}
+
+static void mot_panel_reset(struct mot_panel *priv)
+{
+ gpiod_set_value_cansleep(priv->reset_gpio, 1);
+ usleep_range(50000, 51000);
+ gpiod_set_value_cansleep(priv->reset_gpio, 0);
+ usleep_range(10000, 11000);
+}
+
+static void mot_es2(struct mipi_dsi_multi_context *ctx)
+{
+ mipi_dsi_generic_write_seq_multi(ctx, 0x55, 0x01);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(ctx);
+ mipi_dsi_msleep(ctx, 120);
+
+ mipi_dsi_generic_write_seq_multi(ctx, 0xf4, 0x00, 0xbb, 0x46, 0x53, 0x0c, 0x49,
+ 0x74, 0x29, 0x12, 0x15, 0x2f, 0x2f, 0x04);
+ mipi_dsi_generic_write_seq_multi(ctx, 0xf8, 0x4b, 0x04, 0x10, 0x1a, 0x2c, 0x2c,
+ 0x2c, 0x2c, 0x14, 0x12);
+
+ mipi_dsi_generic_write_seq_multi(ctx, 0xb5, 0x03, 0x7f, 0x00, 0x80, 0xc7, 0x00);
+ mipi_dsi_generic_write_seq_multi(ctx, 0xb7, 0x66, 0xf6, 0x46, 0x9f, 0x90, 0x99,
+ 0xff, 0x80, 0x6d, 0x01);
+
+ /* Gamma R */
+ mipi_dsi_generic_write_seq_multi(ctx, 0xf9, 0x04);
+ mipi_dsi_generic_write_seq_multi(ctx, 0xfa, 0x00, 0x2f, 0x30, 0x12, 0x0e, 0x0c,
+ 0x22, 0x27, 0x31, 0x2e, 0x07, 0x0f);
+ mipi_dsi_generic_write_seq_multi(ctx, 0xfb, 0x00, 0x2f, 0x30, 0x12, 0x0e, 0x0c,
+ 0x22, 0x27, 0x31, 0x2e, 0x07, 0x0f);
+
+ /* Gamma G */
+ mipi_dsi_generic_write_seq_multi(ctx, 0xf9, 0x02);
+ mipi_dsi_generic_write_seq_multi(ctx, 0xfa, 0x00, 0x2f, 0x37, 0x15, 0x15, 0x11,
+ 0x1f, 0x25, 0x2d, 0x2a, 0x05, 0x0f);
+ mipi_dsi_generic_write_seq_multi(ctx, 0xfb, 0x00, 0x2f, 0x37, 0x15, 0x15, 0x11,
+ 0x1f, 0x25, 0x2d, 0x2a, 0x05, 0x0f);
+
+ /* Gamma B */
+ mipi_dsi_generic_write_seq_multi(ctx, 0xf9, 0x01);
+ mipi_dsi_generic_write_seq_multi(ctx, 0xfa, 0x00, 0x2f, 0x3f, 0x16, 0x1f, 0x15,
+ 0x1f, 0x25, 0x2d, 0x2b, 0x06, 0x0b);
+ mipi_dsi_generic_write_seq_multi(ctx, 0xfb, 0x00, 0x2f, 0x3f, 0x16, 0x1f, 0x15,
+ 0x1f, 0x25, 0x2d, 0x2b, 0x06, 0x0b);
+
+ /* Gamma W */
+ mipi_dsi_generic_write_seq_multi(ctx, 0xf9, 0x20);
+ mipi_dsi_generic_write_seq_multi(ctx, 0xfa, 0x00, 0x2f, 0x34, 0x15, 0x1a, 0x11,
+ 0x1f, 0x23, 0x2d, 0x29, 0x02, 0x08);
+ mipi_dsi_generic_write_seq_multi(ctx, 0xfb, 0x00, 0x2f, 0x34, 0x15, 0x1a, 0x11,
+ 0x1f, 0x23, 0x2d, 0x29, 0x02, 0x08);
+
+ mipi_dsi_generic_write_seq_multi(ctx, 0x53, 0x2c);
+ mipi_dsi_generic_write_seq_multi(ctx, 0x35, 0x00);
+}
+
+static int mot_panel_prepare(struct drm_panel *panel)
+{
+ struct mot_panel *priv = to_mot_panel(panel);
+ struct mipi_dsi_multi_context ctx = { .dsi = priv->dsi };
+ struct device *dev = panel->dev;
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(mot_panel_supplies), priv->supplies);
+ if (ret < 0) {
+ dev_err(dev, "failed to enable power supplies: %d\n", ret);
+ return ret;
+ }
+
+ mot_panel_reset(priv);
+
+ mipi_dsi_generic_write_seq_multi(&ctx, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_generic_write_seq_multi(&ctx, 0xf1, 0x5a, 0x5a);
+ mipi_dsi_generic_write_seq_multi(&ctx, 0xd0, 0x8e);
+
+ mot_es2(&ctx);
+
+ mipi_dsi_dcs_set_display_on_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 20);
+
+ return ctx.accum_err;
+}
+
+static int mot_panel_disable(struct drm_panel *panel)
+{
+ struct mot_panel *priv = to_mot_panel(panel);
+ struct mipi_dsi_multi_context ctx = { .dsi = priv->dsi };
+
+ mipi_dsi_dcs_set_display_off_multi(&ctx);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 70);
+
+ return ctx.accum_err;
+}
+
+static int mot_panel_unprepare(struct drm_panel *panel)
+{
+ struct mot_panel *priv = to_mot_panel(panel);
+
+ usleep_range(10000, 11000);
+
+ gpiod_set_value_cansleep(priv->reset_gpio, 1);
+ usleep_range(5000, 6000);
+
+ regulator_bulk_disable(ARRAY_SIZE(mot_panel_supplies), priv->supplies);
+
+ return 0;
+}
+
+static const struct drm_display_mode mot_panel_mode = {
+ .clock = (540 + 32 + 32 + 16) * (960 + 12 + 12 + 8) * 60 / 1000,
+ .hdisplay = 540,
+ .hsync_start = 540 + 32,
+ .hsync_end = 540 + 32 + 32,
+ .htotal = 540 + 32 + 32 + 16,
+ .vdisplay = 960,
+ .vsync_start = 960 + 12,
+ .vsync_end = 960 + 12 + 12,
+ .vtotal = 960 + 12 + 12 + 8,
+ .width_mm = 51,
+ .height_mm = 91,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static int mot_panel_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ return drm_connector_helper_get_modes_fixed(connector, &mot_panel_mode);
+}
+
+static const struct drm_panel_funcs mot_panel_panel_funcs = {
+ .prepare = mot_panel_prepare,
+ .disable = mot_panel_disable,
+ .unprepare = mot_panel_unprepare,
+ .get_modes = mot_panel_get_modes,
+};
+
+static int mot_panel_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct mot_panel *priv;
+ int ret;
+
+ priv = devm_drm_panel_alloc(dev, struct mot_panel, panel,
+ &mot_panel_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ if (IS_ERR(priv))
+ return PTR_ERR(priv);
+
+ ret = devm_regulator_bulk_get_const(dev, ARRAY_SIZE(mot_panel_supplies),
+ mot_panel_supplies, &priv->supplies);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to get supplies\n");
+
+ priv->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(priv->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(priv->reset_gpio),
+ "failed to get reset gpios\n");
+
+ priv->dsi = dsi;
+ mipi_dsi_set_drvdata(dsi, priv);
+
+ dsi->lanes = 2;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_LPM;
+
+ ret = drm_panel_of_backlight(&priv->panel);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to get backlight\n");
+
+ drm_panel_add(&priv->panel);
+
+ ret = devm_mipi_dsi_attach(dev, dsi);
+ if (ret < 0) {
+ drm_panel_remove(&priv->panel);
+ return dev_err_probe(dev, ret, "failed to attach to DSI host\n");
+ }
+
+ return 0;
+}
+
+static void mot_panel_remove(struct mipi_dsi_device *dsi)
+{
+ struct mot_panel *priv = mipi_dsi_get_drvdata(dsi);
+
+ drm_panel_remove(&priv->panel);
+}
+
+static const struct of_device_id mot_panel_of_match[] = {
+ { .compatible = "motorola,mot-panel" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mot_panel_of_match);
+
+static struct mipi_dsi_driver mot_panel_driver = {
+ .driver = {
+ .name = "panel-motorola-mot",
+ .of_match_table = mot_panel_of_match,
+ },
+ .probe = mot_panel_probe,
+ .remove = mot_panel_remove,
+};
+module_mipi_dsi_driver(mot_panel_driver);
+
+MODULE_AUTHOR("Svyatoslav Ryhel <clamor95@gmail.com>");
+MODULE_DESCRIPTION("Motorola MOT panel driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt37700f.c b/drivers/gpu/drm/panel/panel-novatek-nt37700f.c
new file mode 100644
index 000000000000..74f46a268c0f
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-novatek-nt37700f.c
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, The Linux Foundation. All rights reserved.
+ * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
+
+struct nt37700f_tianma {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+ struct regulator *supply;
+ struct gpio_desc *reset_gpio;
+};
+
+static inline
+struct nt37700f_tianma *to_nt37700f_tianma(struct drm_panel *panel)
+{
+ return container_of(panel, struct nt37700f_tianma, panel);
+}
+
+static void nt37700f_tianma_reset(struct nt37700f_tianma *ctx)
+{
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ usleep_range(1000, 2000);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ usleep_range(10000, 11000);
+}
+
+#define nt37700f_tianma_panel_switch_page(ctx, page) \
+ mipi_dsi_dcs_write_seq_multi((ctx), 0xf0, 0x55, 0xaa, 0x52, 0x08, (page))
+
+static int nt37700f_tianma_on(struct nt37700f_tianma *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
+
+ nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc0, 0x56);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xca, 0x52);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, 0x2b, 0x1a);
+ nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcd, 0x04, 0x82);
+ nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcc, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x55);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf6, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x56);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf6, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x81);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0x25);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x90, 0x01);
+
+ mipi_dsi_dcs_set_column_address_multi(&dsi_ctx, 0x0000, 1080 - 1);
+ mipi_dsi_dcs_set_page_address_multi(&dsi_ctx, 0x0000, 2160 - 1);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
+ mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+
+ nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc0, 0x56);
+ nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcd, 0x00);
+ nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd0, 0x11, 0x64);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, 0x20);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
+ mipi_dsi_msleep(&dsi_ctx, 120);
+ mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
+
+ return dsi_ctx.accum_err;
+}
+
+static int nt37700f_tianma_disable(struct drm_panel *panel)
+{
+ struct nt37700f_tianma *ctx = to_nt37700f_tianma(panel);
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
+
+ mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
+ mipi_dsi_msleep(&dsi_ctx, 50);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
+ mipi_dsi_msleep(&dsi_ctx, 100);
+
+ return dsi_ctx.accum_err;
+}
+
+static int nt37700f_tianma_prepare(struct drm_panel *panel)
+{
+ struct nt37700f_tianma *ctx = to_nt37700f_tianma(panel);
+ struct device *dev = &ctx->dsi->dev;
+ int ret;
+
+ ret = regulator_enable(ctx->supply);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable power supply: %d\n", ret);
+ return ret;
+ }
+
+ nt37700f_tianma_reset(ctx);
+
+ ret = nt37700f_tianma_on(ctx);
+ if (ret < 0) {
+ dev_err(dev, "Failed to initialize panel: %d\n", ret);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int nt37700f_tianma_unprepare(struct drm_panel *panel)
+{
+ struct nt37700f_tianma *ctx = to_nt37700f_tianma(panel);
+
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_disable(ctx->supply);
+
+ return 0;
+}
+
+static const struct drm_display_mode nt37700f_tianma_mode = {
+ .clock = (1080 + 32 + 32 + 98) * (2160 + 32 + 4 + 98) * 60 / 1000,
+ .hdisplay = 1080,
+ .hsync_start = 1080 + 32,
+ .hsync_end = 1080 + 32 + 32,
+ .htotal = 1080 + 32 + 32 + 98,
+ .vdisplay = 2160,
+ .vsync_start = 2160 + 32,
+ .vsync_end = 2160 + 32 + 4,
+ .vtotal = 2160 + 32 + 4 + 98,
+ .width_mm = 69,
+ .height_mm = 137,
+ .type = DRM_MODE_TYPE_DRIVER,
+};
+
+static int nt37700f_tianma_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ return drm_connector_helper_get_modes_fixed(connector, &nt37700f_tianma_mode);
+}
+
+static const struct drm_panel_funcs nt37700f_tianma_panel_funcs = {
+ .prepare = nt37700f_tianma_prepare,
+ .unprepare = nt37700f_tianma_unprepare,
+ .disable = nt37700f_tianma_disable,
+ .get_modes = nt37700f_tianma_get_modes,
+};
+
+static int nt37700f_tianma_bl_update_status(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ u16 brightness = backlight_get_brightness(bl);
+ int ret;
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
+ if (ret < 0)
+ return ret;
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ return 0;
+}
+
+static int nt37700f_tianma_bl_get_brightness(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ u16 brightness;
+ int ret;
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ ret = mipi_dsi_dcs_get_display_brightness_large(dsi, &brightness);
+ if (ret < 0)
+ return ret;
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ return brightness;
+}
+
+static const struct backlight_ops nt37700f_tianma_bl_ops = {
+ .update_status = nt37700f_tianma_bl_update_status,
+ .get_brightness = nt37700f_tianma_bl_get_brightness,
+};
+
+static struct backlight_device *
+nt37700f_tianma_create_backlight(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ const struct backlight_properties props = {
+ .type = BACKLIGHT_RAW,
+ .brightness = 2047,
+ .max_brightness = 2047,
+ };
+
+ return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+ &nt37700f_tianma_bl_ops, &props);
+}
+
+static int nt37700f_tianma_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct nt37700f_tianma *ctx;
+ int ret;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->supply = devm_regulator_get(dev, "power");
+ if (IS_ERR(ctx->supply))
+ return dev_err_probe(dev, PTR_ERR(ctx->supply),
+ "Failed to get power-supply\n");
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ctx->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+ "Failed to get reset-gpios\n");
+
+ ctx->dsi = dsi;
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST |
+ MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
+
+ drm_panel_init(&ctx->panel, dev, &nt37700f_tianma_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ ctx->panel.prepare_prev_first = true;
+
+ ctx->panel.backlight = nt37700f_tianma_create_backlight(dsi);
+ if (IS_ERR(ctx->panel.backlight))
+ return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
+ "Failed to create backlight\n");
+
+ drm_panel_add(&ctx->panel);
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ drm_panel_remove(&ctx->panel);
+ return dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
+ }
+
+ return 0;
+}
+
+static void nt37700f_tianma_remove(struct mipi_dsi_device *dsi)
+{
+ struct nt37700f_tianma *ctx = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ ret = mipi_dsi_detach(dsi);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+ drm_panel_remove(&ctx->panel);
+}
+
+static const struct of_device_id nt37700f_tianma_of_match[] = {
+ { .compatible = "novatek,nt37700f" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, nt37700f_tianma_of_match);
+
+static struct mipi_dsi_driver nt37700f_tianma_driver = {
+ .probe = nt37700f_tianma_probe,
+ .remove = nt37700f_tianma_remove,
+ .driver = {
+ .name = "panel-novatek-nt37700f",
+ .of_match_table = nt37700f_tianma_of_match,
+ },
+};
+module_mipi_dsi_driver(nt37700f_tianma_driver);
+
+MODULE_DESCRIPTION("DRM driver for nt37700f cmd mode dsi tianma panel");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-renesas-r61307.c b/drivers/gpu/drm/panel/panel-renesas-r61307.c
index 319415194839..d8185cc1b5d6 100644
--- a/drivers/gpu/drm/panel/panel-renesas-r61307.c
+++ b/drivers/gpu/drm/panel/panel-renesas-r61307.c
@@ -14,6 +14,7 @@
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
#define R61307_MACP 0xb0 /* Manufacturer CMD Protect */
#define R61307_MACP_ON 0x03
@@ -34,8 +35,6 @@ struct renesas_r61307 {
struct gpio_desc *reset_gpio;
- bool prepared;
-
bool dig_cont_adj;
bool inversion;
u32 gamma;
@@ -91,9 +90,6 @@ static int renesas_r61307_prepare(struct drm_panel *panel)
struct device *dev = &priv->dsi->dev;
int ret;
- if (priv->prepared)
- return 0;
-
ret = regulator_enable(priv->vcc_supply);
if (ret) {
dev_err(dev, "failed to enable vcc power supply\n");
@@ -112,7 +108,6 @@ static int renesas_r61307_prepare(struct drm_panel *panel)
renesas_r61307_reset(priv);
- priv->prepared = true;
return 0;
}
@@ -155,7 +150,7 @@ static int renesas_r61307_enable(struct drm_panel *panel)
mipi_dsi_dcs_set_display_on_multi(&ctx);
mipi_dsi_msleep(&ctx, 50);
- return 0;
+ return ctx.accum_err;
}
static int renesas_r61307_disable(struct drm_panel *panel)
@@ -167,16 +162,13 @@ static int renesas_r61307_disable(struct drm_panel *panel)
mipi_dsi_msleep(&ctx, 100);
mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
- return 0;
+ return ctx.accum_err;
}
static int renesas_r61307_unprepare(struct drm_panel *panel)
{
struct renesas_r61307 *priv = to_renesas_r61307(panel);
- if (!priv->prepared)
- return 0;
-
usleep_range(10000, 11000);
gpiod_set_value_cansleep(priv->reset_gpio, 1);
@@ -186,7 +178,6 @@ static int renesas_r61307_unprepare(struct drm_panel *panel)
usleep_range(2000, 3000);
regulator_disable(priv->vcc_supply);
- priv->prepared = false;
return 0;
}
@@ -202,25 +193,13 @@ static const struct drm_display_mode renesas_r61307_mode = {
.vtotal = 1024 + 24 + 8 + 2,
.width_mm = 76,
.height_mm = 101,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
};
static int renesas_r61307_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
- struct drm_display_mode *mode;
-
- mode = drm_mode_duplicate(connector->dev, &renesas_r61307_mode);
- if (!mode)
- return -ENOMEM;
-
- drm_mode_set_name(mode);
-
- mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
- connector->display_info.width_mm = mode->width_mm;
- connector->display_info.height_mm = mode->height_mm;
- drm_mode_probed_add(connector, mode);
-
- return 1;
+ return drm_connector_helper_get_modes_fixed(connector, &renesas_r61307_mode);
}
static const struct drm_panel_funcs renesas_r61307_panel_funcs = {
@@ -259,7 +238,7 @@ static int renesas_r61307_probe(struct mipi_dsi_device *dsi)
return dev_err_probe(dev, PTR_ERR(priv->reset_gpio),
"Failed to get reset gpios\n");
- if (device_property_read_bool(dev, "renesas,inversion"))
+ if (device_property_read_bool(dev, "renesas,column-inversion"))
priv->inversion = true;
if (device_property_read_bool(dev, "renesas,contrast"))
@@ -282,7 +261,7 @@ static int renesas_r61307_probe(struct mipi_dsi_device *dsi)
drm_panel_add(&priv->panel);
- ret = mipi_dsi_attach(dsi);
+ ret = devm_mipi_dsi_attach(dev, dsi);
if (ret) {
drm_panel_remove(&priv->panel);
return dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
@@ -294,11 +273,6 @@ static int renesas_r61307_probe(struct mipi_dsi_device *dsi)
static void renesas_r61307_remove(struct mipi_dsi_device *dsi)
{
struct renesas_r61307 *priv = mipi_dsi_get_drvdata(dsi);
- int ret;
-
- ret = mipi_dsi_detach(dsi);
- if (ret)
- dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
drm_panel_remove(&priv->panel);
}
diff --git a/drivers/gpu/drm/panel/panel-renesas-r69328.c b/drivers/gpu/drm/panel/panel-renesas-r69328.c
index 46287ab04c30..bfe2787f8f53 100644
--- a/drivers/gpu/drm/panel/panel-renesas-r69328.c
+++ b/drivers/gpu/drm/panel/panel-renesas-r69328.c
@@ -14,6 +14,7 @@
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
#define R69328_MACP 0xb0 /* Manufacturer Access CMD Protect */
#define R69328_MACP_ON 0x03
@@ -32,8 +33,6 @@ struct renesas_r69328 {
struct regulator *vdd_supply;
struct regulator *vddio_supply;
struct gpio_desc *reset_gpio;
-
- bool prepared;
};
static inline struct renesas_r69328 *to_renesas_r69328(struct drm_panel *panel)
@@ -55,9 +54,6 @@ static int renesas_r69328_prepare(struct drm_panel *panel)
struct device *dev = &priv->dsi->dev;
int ret;
- if (priv->prepared)
- return 0;
-
ret = regulator_enable(priv->vdd_supply);
if (ret) {
dev_err(dev, "failed to enable vdd power supply\n");
@@ -76,7 +72,6 @@ static int renesas_r69328_prepare(struct drm_panel *panel)
renesas_r69328_reset(priv);
- priv->prepared = true;
return 0;
}
@@ -122,7 +117,7 @@ static int renesas_r69328_enable(struct drm_panel *panel)
mipi_dsi_dcs_set_display_on_multi(&ctx);
mipi_dsi_msleep(&ctx, 50);
- return 0;
+ return ctx.accum_err;
}
static int renesas_r69328_disable(struct drm_panel *panel)
@@ -134,16 +129,13 @@ static int renesas_r69328_disable(struct drm_panel *panel)
mipi_dsi_msleep(&ctx, 60);
mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
- return 0;
+ return ctx.accum_err;
}
static int renesas_r69328_unprepare(struct drm_panel *panel)
{
struct renesas_r69328 *priv = to_renesas_r69328(panel);
- if (!priv->prepared)
- return 0;
-
gpiod_set_value_cansleep(priv->reset_gpio, 1);
usleep_range(5000, 6000);
@@ -151,7 +143,6 @@ static int renesas_r69328_unprepare(struct drm_panel *panel)
regulator_disable(priv->vddio_supply);
regulator_disable(priv->vdd_supply);
- priv->prepared = false;
return 0;
}
@@ -167,25 +158,13 @@ static const struct drm_display_mode renesas_r69328_mode = {
.vtotal = 1280 + 6 + 3 + 1,
.width_mm = 59,
.height_mm = 105,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
};
static int renesas_r69328_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
- struct drm_display_mode *mode;
-
- mode = drm_mode_duplicate(connector->dev, &renesas_r69328_mode);
- if (!mode)
- return -ENOMEM;
-
- drm_mode_set_name(mode);
-
- mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
- connector->display_info.width_mm = mode->width_mm;
- connector->display_info.height_mm = mode->height_mm;
- drm_mode_probed_add(connector, mode);
-
- return 1;
+ return drm_connector_helper_get_modes_fixed(connector, &renesas_r69328_mode);
}
static const struct drm_panel_funcs renesas_r69328_panel_funcs = {
@@ -238,7 +217,7 @@ static int renesas_r69328_probe(struct mipi_dsi_device *dsi)
drm_panel_add(&priv->panel);
- ret = mipi_dsi_attach(dsi);
+ ret = devm_mipi_dsi_attach(dev, dsi);
if (ret) {
drm_panel_remove(&priv->panel);
return dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
@@ -250,11 +229,6 @@ static int renesas_r69328_probe(struct mipi_dsi_device *dsi)
static void renesas_r69328_remove(struct mipi_dsi_device *dsi)
{
struct renesas_r69328 *priv = mipi_dsi_get_drvdata(dsi);
- int ret;
-
- ret = mipi_dsi_detach(dsi);
- if (ret)
- dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
drm_panel_remove(&priv->panel);
}
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index e5fc9b072404..e1d15434ea54 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -2096,6 +2096,35 @@ static const struct panel_desc edt_et057090dhu = {
.connector_type = DRM_MODE_CONNECTOR_DPI,
};
+static const struct display_timing edt_et057023udba_timing = {
+ .pixelclock = { 23200000, 24190000, 39640000 },
+ .hactive = { 640, 640, 640 },
+ .hfront_porch = { 20, 40, 200 },
+ .hback_porch = { 87, 40, 1 },
+ .hsync_len = { 1, 48, 87 },
+ .vactive = { 480, 480, 480 },
+ .vfront_porch = { 5, 13, 200 },
+ .vback_porch = { 31, 31, 29 },
+ .vsync_len = { 1, 1, 3 },
+ .flags = DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_HSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE |
+ DISPLAY_FLAGS_SYNC_POSEDGE,
+};
+
+static const struct panel_desc edt_et057023udba = {
+ .timings = &edt_et057023udba_timing,
+ .num_timings = 1,
+ .bpc = 8,
+ .size = {
+ .width = 115,
+ .height = 86,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE |
+ DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
+};
+
static const struct drm_display_mode edt_etm0700g0dh6_mode = {
.clock = 33260,
.hdisplay = 800,
@@ -4046,6 +4075,33 @@ static const struct panel_desc powertip_ph800480t013_idf02 = {
.connector_type = DRM_MODE_CONNECTOR_DPI,
};
+static const struct drm_display_mode powertip_ph800480t032_zhc19_mode = {
+ .clock = 27200,
+ .hdisplay = 800,
+ .hsync_start = 800 + 52,
+ .hsync_end = 800 + 52 + 2,
+ .htotal = 800 + 52 + 2 + 44,
+ .vdisplay = 480,
+ .vsync_start = 480 + 7,
+ .vsync_end = 480 + 7 + 2,
+ .vtotal = 480 + 7 + 2 + 2,
+};
+
+static const struct panel_desc powertip_ph800480t032_zhc19 = {
+ .modes = &powertip_ph800480t032_zhc19_mode,
+ .num_modes = 1,
+ .bpc = 8,
+ .size = {
+ .width = 152,
+ .height = 91,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH |
+ DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE |
+ DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
+};
+
static const struct drm_display_mode primeview_pm070wl4_mode = {
.clock = 32000,
.hdisplay = 800,
@@ -4976,6 +5032,33 @@ static const struct panel_desc vl050_8048nt_c01 = {
.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE,
};
+static const struct drm_display_mode waveshare_133inch_mode = {
+ .clock = 148500,
+ .hdisplay = 1920,
+ .hsync_start = 1920 + 88,
+ .hsync_end = 1920 + 88 + 44,
+ .htotal = 1920 + 88 + 44 + 148,
+ .vdisplay = 1080,
+ .vsync_start = 1080 + 4,
+ .vsync_end = 1080 + 4 + 5,
+ .vtotal = 1080 + 4 + 5 + 36,
+ .flags = DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_PHSYNC,
+};
+
+static const struct panel_desc waveshare_133inch = {
+ .modes = &waveshare_133inch_mode,
+ .num_modes = 1,
+ .bpc = 8,
+ .size = {
+ .width = 293,
+ .height = 163,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
+ .bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE |
+ DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE,
+};
+
static const struct drm_display_mode winstar_wf35ltiacd_mode = {
.clock = 6410,
.hdisplay = 320,
@@ -5226,6 +5309,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "edt,etm0430g0dh6",
.data = &edt_etm0430g0dh6,
}, {
+ .compatible = "edt,et057023udba",
+ .data = &edt_et057023udba,
+ }, {
.compatible = "edt,et057090dhu",
.data = &edt_et057090dhu,
}, {
@@ -5457,6 +5543,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "powertip,ph800480t013-idf02",
.data = &powertip_ph800480t013_idf02,
}, {
+ .compatible = "powertip,ph800480t032-zhc19",
+ .data = &powertip_ph800480t032_zhc19,
+ }, {
.compatible = "primeview,pm070wl4",
.data = &primeview_pm070wl4,
}, {
@@ -5574,6 +5663,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "vxt,vl050-8048nt-c01",
.data = &vl050_8048nt_c01,
}, {
+ .compatible = "waveshare,13.3inch-panel",
+ .data = &waveshare_133inch,
+ }, {
.compatible = "winstar,wf35ltiacd",
.data = &winstar_wf35ltiacd,
}, {
diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
index a70f1db0764e..2fe04d0f0e3a 100644
--- a/drivers/gpu/drm/panthor/panthor_sched.c
+++ b/drivers/gpu/drm/panthor/panthor_sched.c
@@ -3916,7 +3916,7 @@ static void job_release(struct kref *ref)
if (job->base.s_fence)
drm_sched_job_cleanup(&job->base);
- if (job->done_fence && job->done_fence->ops)
+ if (dma_fence_was_initialized(job->done_fence))
dma_fence_put(job->done_fence);
else
dma_fence_free(job->done_fence);
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 0765d69423d2..34ce53b4bdb9 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -222,10 +222,8 @@ static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo)
struct dma_fence *fence;
dma_resv_iter_begin(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP);
- dma_resv_for_each_fence_unlocked(&cursor, fence) {
- if (!fence->ops->signaled)
- dma_fence_enable_sw_signaling(fence);
- }
+ dma_resv_for_each_fence_unlocked(&cursor, fence)
+ dma_fence_enable_sw_signaling(fence);
dma_resv_iter_end(&cursor);
}
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 9ce90a694c3c..9898e5451a07 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -2449,17 +2449,23 @@ static int vc4_hdmi_hotplug_init(struct vc4_hdmi *vc4_hdmi)
int ret;
if (vc4_hdmi->variant->external_irq_controller) {
- unsigned int hpd_con = platform_get_irq_byname(pdev, "hpd-connected");
- unsigned int hpd_rm = platform_get_irq_byname(pdev, "hpd-removed");
+ int hpd = platform_get_irq_byname(pdev, "hpd-connected");
- ret = devm_request_threaded_irq(&pdev->dev, hpd_con,
+ if (hpd < 0)
+ return hpd;
+
+ ret = devm_request_threaded_irq(&pdev->dev, hpd,
NULL,
vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT,
"vc4 hdmi hpd connected", vc4_hdmi);
if (ret)
return ret;
- ret = devm_request_threaded_irq(&pdev->dev, hpd_rm,
+ hpd = platform_get_irq_byname(pdev, "hpd-removed");
+ if (hpd < 0)
+ return hpd;
+
+ ret = devm_request_threaded_irq(&pdev->dev, hpd,
NULL,
vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT,
"vc4 hdmi hpd disconnected", vc4_hdmi);
diff --git a/drivers/gpu/tests/gpu_buddy_test.c b/drivers/gpu/tests/gpu_buddy_test.c
index 5429010f34d3..7df5c2ae83bb 100644
--- a/drivers/gpu/tests/gpu_buddy_test.c
+++ b/drivers/gpu/tests/gpu_buddy_test.c
@@ -21,6 +21,170 @@ static inline u64 get_size(int order, u64 chunk_size)
return (1 << order) * chunk_size;
}
+static void gpu_test_buddy_subtree_offset_alignment_stress(struct kunit *test)
+{
+ struct gpu_buddy_block *block;
+ struct rb_node *node = NULL;
+ const u64 mm_size = SZ_2M;
+ const u64 alignments[] = {
+ SZ_1M,
+ SZ_512K,
+ SZ_256K,
+ SZ_128K,
+ SZ_64K,
+ SZ_32K,
+ SZ_16K,
+ SZ_8K,
+ };
+ struct list_head allocated[ARRAY_SIZE(alignments)];
+ unsigned int i, max_subtree_align = 0;
+ int ret, tree, order;
+ struct gpu_buddy mm;
+
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K),
+ "buddy_init failed\n");
+
+ for (i = 0; i < ARRAY_SIZE(allocated); i++)
+ INIT_LIST_HEAD(&allocated[i]);
+
+ /*
+ * Exercise subtree_max_alignment tracking by allocating blocks with descending
+ * alignment constraints and freeing them in reverse order. This verifies that
+ * free-tree augmentation correctly propagates the maximum offset alignment
+ * present in each subtree at every stage.
+ */
+
+ for (i = 0; i < ARRAY_SIZE(alignments); i++) {
+ struct gpu_buddy_block *root = NULL;
+ unsigned int expected;
+ u64 align;
+
+ align = alignments[i];
+ expected = ilog2(align) - 1;
+
+ for (;;) {
+ ret = gpu_buddy_alloc_blocks(&mm,
+ 0, mm_size,
+ SZ_4K, align,
+ &allocated[i],
+ 0);
+ if (ret)
+ break;
+
+ block = list_last_entry(&allocated[i],
+ struct gpu_buddy_block,
+ link);
+ KUNIT_EXPECT_TRUE(test, IS_ALIGNED(gpu_buddy_block_offset(block), align));
+ }
+
+ for (order = mm.max_order; order >= 0 && !root; order--) {
+ for (tree = 0; tree < 2; tree++) {
+ node = mm.free_trees[tree][order].rb_node;
+ if (node) {
+ root = container_of(node,
+ struct gpu_buddy_block,
+ rb);
+ break;
+ }
+ }
+ }
+
+ KUNIT_ASSERT_NOT_NULL(test, root);
+ KUNIT_EXPECT_EQ(test, root->subtree_max_alignment, expected);
+ }
+
+ for (i = ARRAY_SIZE(alignments); i-- > 0; ) {
+ gpu_buddy_free_list(&mm, &allocated[i], 0);
+
+ for (order = 0; order <= mm.max_order; order++) {
+ for (tree = 0; tree < 2; tree++) {
+ node = mm.free_trees[tree][order].rb_node;
+ if (!node)
+ continue;
+
+ block = container_of(node, struct gpu_buddy_block, rb);
+ max_subtree_align = max(max_subtree_align,
+ block->subtree_max_alignment);
+ }
+ }
+
+ KUNIT_EXPECT_GE(test, max_subtree_align, ilog2(alignments[i]));
+ }
+
+ gpu_buddy_fini(&mm);
+}
+
+static void gpu_test_buddy_offset_aligned_allocation(struct kunit *test)
+{
+ struct gpu_buddy_block *block, *tmp;
+ int num_blocks, i, count = 0;
+ LIST_HEAD(allocated);
+ struct gpu_buddy mm;
+ u64 mm_size = SZ_4M;
+ LIST_HEAD(freed);
+
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K),
+ "buddy_init failed\n");
+
+ num_blocks = mm_size / SZ_256K;
+ /*
+ * Allocate multiple sizes under a fixed offset alignment.
+ * Ensures alignment handling is independent of allocation size and
+ * exercises subtree max-alignment pruning for small requests.
+ */
+ for (i = 0; i < num_blocks; i++)
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_8K, SZ_256K,
+ &allocated, 0),
+ "buddy_alloc hit an error size=%u\n", SZ_8K);
+
+ list_for_each_entry(block, &allocated, link) {
+ /* Ensure the allocated block uses the expected 8 KB size */
+ KUNIT_EXPECT_EQ(test, gpu_buddy_block_size(&mm, block), SZ_8K);
+ /* Ensure the block starts at a 256 KB-aligned offset for proper alignment */
+ KUNIT_EXPECT_TRUE(test, IS_ALIGNED(gpu_buddy_block_offset(block), SZ_256K));
+ }
+ gpu_buddy_free_list(&mm, &allocated, 0);
+
+ for (i = 0; i < num_blocks; i++)
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_16K, SZ_256K,
+ &allocated, 0),
+ "buddy_alloc hit an error size=%u\n", SZ_16K);
+
+ list_for_each_entry(block, &allocated, link) {
+ /* Ensure the allocated block uses the expected 16 KB size */
+ KUNIT_EXPECT_EQ(test, gpu_buddy_block_size(&mm, block), SZ_16K);
+ /* Ensure the block starts at a 256 KB-aligned offset for proper alignment */
+ KUNIT_EXPECT_TRUE(test, IS_ALIGNED(gpu_buddy_block_offset(block), SZ_256K));
+ }
+
+ /*
+ * Free alternating aligned blocks to introduce fragmentation.
+ * Ensures offset-aligned allocations remain valid after frees and
+ * verifies subtree max-alignment metadata is correctly maintained.
+ */
+ list_for_each_entry_safe(block, tmp, &allocated, link) {
+ if (count % 2 == 0)
+ list_move_tail(&block->link, &freed);
+ count++;
+ }
+ gpu_buddy_free_list(&mm, &freed, 0);
+
+ for (i = 0; i < num_blocks / 2; i++)
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_16K, SZ_256K,
+ &allocated, 0),
+ "buddy_alloc hit an error size=%u\n", SZ_16K);
+
+ /*
+ * Allocate with offset alignment after all slots are used; must fail.
+ * Confirms that no aligned offsets remain.
+ */
+ KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_16K, SZ_256K,
+ &allocated, 0),
+ "buddy_alloc hit an error size=%u\n", SZ_16K);
+ gpu_buddy_free_list(&mm, &allocated, 0);
+ gpu_buddy_fini(&mm);
+}
+
static void gpu_test_buddy_fragmentation_performance(struct kunit *test)
{
struct gpu_buddy_block *block, *tmp;
@@ -362,6 +526,332 @@ static void gpu_test_buddy_alloc_range_bias(struct kunit *test)
gpu_buddy_fini(&mm);
}
+static void gpu_test_buddy_alloc_range(struct kunit *test)
+{
+ GPU_RND_STATE(prng, random_seed);
+ struct gpu_buddy_block *block;
+ struct gpu_buddy mm;
+ u32 mm_size, total;
+ LIST_HEAD(blocks);
+ LIST_HEAD(tmp);
+ u32 ps = SZ_4K;
+ int ret;
+
+ mm_size = SZ_16M;
+
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, ps),
+ "buddy_init failed\n");
+
+ /*
+ * Basic exact-range allocation.
+ * Allocate the entire mm as one exact range (start + size == end).
+ * This is the simplest case exercising __gpu_buddy_alloc_range.
+ */
+ ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size, mm_size, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ_MSG(test, ret, 0,
+ "exact-range alloc of full mm failed\n");
+
+ total = 0;
+ list_for_each_entry(block, &blocks, link) {
+ u64 offset = gpu_buddy_block_offset(block);
+ u64 bsize = gpu_buddy_block_size(&mm, block);
+
+ KUNIT_EXPECT_TRUE_MSG(test, offset + bsize <= (u64)mm_size,
+ "block [%llx, %llx) outside mm\n", offset, offset + bsize);
+ total += (u32)bsize;
+ }
+ KUNIT_EXPECT_EQ(test, total, mm_size);
+ KUNIT_EXPECT_EQ(test, mm.avail, 0ULL);
+
+ /* Full mm should be exhausted */
+ ret = gpu_buddy_alloc_blocks(&mm, 0, ps, ps, ps, &tmp, 0);
+ KUNIT_EXPECT_NE_MSG(test, ret, 0, "alloc should fail when mm is full\n");
+
+ gpu_buddy_free_list(&mm, &blocks, 0);
+ KUNIT_EXPECT_EQ(test, mm.avail, (u64)mm_size);
+ gpu_buddy_fini(&mm);
+
+ /*
+ * Exact-range allocation of sub-ranges.
+ * Split the mm into four equal quarters and allocate each as an exact
+ * range. Validates splitting and non-overlapping exact allocations.
+ */
+ KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+
+ {
+ u32 quarter = mm_size / 4;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ u32 start = i * quarter;
+ u32 end = start + quarter;
+
+ ret = gpu_buddy_alloc_blocks(&mm, start, end, quarter, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ_MSG(test, ret, 0,
+ "exact-range alloc quarter %d [%x, %x) failed\n",
+ i, start, end);
+ }
+ KUNIT_EXPECT_EQ(test, mm.avail, 0ULL);
+ gpu_buddy_free_list(&mm, &blocks, 0);
+ }
+
+ gpu_buddy_fini(&mm);
+
+ /*
+ * Minimum chunk-size exact range at various offsets.
+ * Allocate single-page exact ranges at the start, middle and end.
+ */
+ KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+
+ ret = gpu_buddy_alloc_blocks(&mm, 0, ps, ps, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ret = gpu_buddy_alloc_blocks(&mm, mm_size / 2, mm_size / 2 + ps, ps, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ret = gpu_buddy_alloc_blocks(&mm, mm_size - ps, mm_size, ps, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ total = 0;
+ list_for_each_entry(block, &blocks, link)
+ total += (u32)gpu_buddy_block_size(&mm, block);
+ KUNIT_EXPECT_EQ(test, total, 3 * ps);
+
+ gpu_buddy_free_list(&mm, &blocks, 0);
+ gpu_buddy_fini(&mm);
+
+ /*
+ * Non power-of-two mm size (multiple roots).
+ * Exact-range allocations that span root boundaries must still work.
+ */
+ mm_size = SZ_4M + SZ_2M + SZ_1M; /* 7 MiB, three roots */
+
+ KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+ KUNIT_EXPECT_GT(test, mm.n_roots, 1U);
+
+ /* Allocate first 4M root exactly */
+ ret = gpu_buddy_alloc_blocks(&mm, 0, SZ_4M, SZ_4M, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ /* Allocate second root (4M-6M) exactly */
+ ret = gpu_buddy_alloc_blocks(&mm, SZ_4M, SZ_4M + SZ_2M, SZ_2M, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ /* Allocate third root (6M-7M) exactly */
+ ret = gpu_buddy_alloc_blocks(&mm, SZ_4M + SZ_2M, mm_size, SZ_1M, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ KUNIT_EXPECT_EQ(test, mm.avail, 0ULL);
+ gpu_buddy_free_list(&mm, &blocks, 0);
+
+ /* Cross-root exact-range: the entire non-pot mm */
+ ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size, mm_size, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+ KUNIT_EXPECT_EQ(test, mm.avail, 0ULL);
+
+ gpu_buddy_free_list(&mm, &blocks, 0);
+ gpu_buddy_fini(&mm);
+
+ /*
+ * Randomized exact-range allocations.
+ * Divide the mm into N random-sized, contiguous, page-aligned slices
+ * and allocate each as an exact range in random order.
+ */
+ mm_size = SZ_16M;
+ KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+
+ {
+#define N_RAND_RANGES 16
+ u32 ranges[N_RAND_RANGES + 1]; /* boundaries */
+ u32 order_arr[N_RAND_RANGES];
+ u32 remaining = mm_size;
+ int i;
+
+ ranges[0] = 0;
+ for (i = 0; i < N_RAND_RANGES - 1; i++) {
+ u32 max_chunk = remaining - (N_RAND_RANGES - 1 - i) * ps;
+ u32 sz = max(round_up(prandom_u32_state(&prng) % max_chunk, ps), ps);
+
+ ranges[i + 1] = ranges[i] + sz;
+ remaining -= sz;
+ }
+ ranges[N_RAND_RANGES] = mm_size;
+
+ /* Create a random order */
+ for (i = 0; i < N_RAND_RANGES; i++)
+ order_arr[i] = i;
+ for (i = N_RAND_RANGES - 1; i > 0; i--) {
+ u32 j = prandom_u32_state(&prng) % (i + 1);
+ u32 tmp_val = order_arr[i];
+
+ order_arr[i] = order_arr[j];
+ order_arr[j] = tmp_val;
+ }
+
+ for (i = 0; i < N_RAND_RANGES; i++) {
+ u32 idx = order_arr[i];
+ u32 start = ranges[idx];
+ u32 end = ranges[idx + 1];
+ u32 sz = end - start;
+
+ ret = gpu_buddy_alloc_blocks(&mm, start, end, sz, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ_MSG(test, ret, 0,
+ "random exact-range [%x, %x) sz=%x failed\n",
+ start, end, sz);
+ }
+
+ KUNIT_EXPECT_EQ(test, mm.avail, 0ULL);
+ gpu_buddy_free_list(&mm, &blocks, 0);
+#undef N_RAND_RANGES
+ }
+
+ gpu_buddy_fini(&mm);
+
+ /*
+ * Negative case - partially allocated range.
+ * Allocate the first half, then try to exact-range allocate the full
+ * mm. This must fail because the first half is already occupied.
+ */
+ mm_size = SZ_16M;
+ KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+
+ ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size / 2, mm_size / 2, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size, mm_size, ps, &tmp, 0);
+ KUNIT_EXPECT_NE_MSG(test, ret, 0,
+ "exact-range alloc should fail when range is partially used\n");
+
+ /* Also try the already-occupied sub-range directly */
+ ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size / 2, mm_size / 2, ps, &tmp, 0);
+ KUNIT_EXPECT_NE_MSG(test, ret, 0,
+ "double alloc of same exact range should fail\n");
+
+ /* The free second half should still be allocatable */
+ ret = gpu_buddy_alloc_blocks(&mm, mm_size / 2, mm_size, mm_size / 2, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ KUNIT_EXPECT_EQ(test, mm.avail, 0ULL);
+ gpu_buddy_free_list(&mm, &blocks, 0);
+ gpu_buddy_fini(&mm);
+
+ /*
+ * Negative case - checkerboard partial allocation.
+ * Allocate every other page-sized chunk in a small mm, then try to
+ * exact-range allocate a range covering two pages (one allocated, one
+ * free). This must fail.
+ */
+ mm_size = SZ_64K;
+ KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+
+ {
+ u32 off;
+
+ for (off = 0; off < mm_size; off += 2 * ps) {
+ ret = gpu_buddy_alloc_blocks(&mm, off, off + ps, ps, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+ }
+
+ /* Try exact range over a pair [allocated, free] */
+ ret = gpu_buddy_alloc_blocks(&mm, 0, 2 * ps, 2 * ps, ps, &tmp, 0);
+ KUNIT_EXPECT_NE_MSG(test, ret, 0,
+ "exact-range over partially allocated pair should fail\n");
+
+ /* The free pages individually should still work */
+ ret = gpu_buddy_alloc_blocks(&mm, ps, 2 * ps, ps, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ gpu_buddy_free_list(&mm, &blocks, 0);
+ }
+
+ gpu_buddy_fini(&mm);
+
+ /* Negative case - misaligned start/end/size */
+ mm_size = SZ_16M;
+ KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+
+ /* start not aligned to chunk_size */
+ ret = gpu_buddy_alloc_blocks(&mm, ps / 2, ps / 2 + ps, ps, ps, &tmp, 0);
+ KUNIT_EXPECT_NE(test, ret, 0);
+
+ /* size not aligned */
+ ret = gpu_buddy_alloc_blocks(&mm, 0, ps + 1, ps + 1, ps, &tmp, 0);
+ KUNIT_EXPECT_NE(test, ret, 0);
+
+ /* end exceeds mm size */
+ ret = gpu_buddy_alloc_blocks(&mm, mm_size, mm_size + ps, ps, ps, &tmp, 0);
+ KUNIT_EXPECT_NE(test, ret, 0);
+
+ gpu_buddy_fini(&mm);
+
+ /*
+ * Free and re-allocate the same exact range.
+ * This exercises merge-on-free followed by exact-range re-split.
+ */
+ mm_size = SZ_16M;
+ KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+
+ {
+ int i;
+
+ for (i = 0; i < 5; i++) {
+ ret = gpu_buddy_alloc_blocks(&mm, SZ_4M, SZ_4M + SZ_2M,
+ SZ_2M, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ_MSG(test, ret, 0,
+ "re-alloc iteration %d failed\n", i);
+
+ total = 0;
+ list_for_each_entry(block, &blocks, link) {
+ u64 offset = gpu_buddy_block_offset(block);
+ u64 bsize = gpu_buddy_block_size(&mm, block);
+
+ KUNIT_EXPECT_GE(test, offset, (u64)SZ_4M);
+ KUNIT_EXPECT_LE(test, offset + bsize, (u64)(SZ_4M + SZ_2M));
+ total += (u32)bsize;
+ }
+ KUNIT_EXPECT_EQ(test, total, SZ_2M);
+
+ gpu_buddy_free_list(&mm, &blocks, 0);
+ }
+
+ KUNIT_EXPECT_EQ(test, mm.avail, (u64)mm_size);
+ }
+
+ gpu_buddy_fini(&mm);
+
+ /*
+ * Various power-of-two exact ranges within a large mm.
+ * Allocate non-overlapping power-of-two exact ranges at their natural
+ * alignment, validating that the allocator handles different orders.
+ */
+ mm_size = SZ_16M;
+ KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+
+ /* Allocate 4K at offset 0 */
+ ret = gpu_buddy_alloc_blocks(&mm, 0, SZ_4K, SZ_4K, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ /* Allocate 64K at offset 64K */
+ ret = gpu_buddy_alloc_blocks(&mm, SZ_64K, SZ_64K + SZ_64K, SZ_64K, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ /* Allocate 1M at offset 1M */
+ ret = gpu_buddy_alloc_blocks(&mm, SZ_1M, SZ_1M + SZ_1M, SZ_1M, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ /* Allocate 4M at offset 4M */
+ ret = gpu_buddy_alloc_blocks(&mm, SZ_4M, SZ_4M + SZ_4M, SZ_4M, ps, &blocks, 0);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ total = 0;
+ list_for_each_entry(block, &blocks, link)
+ total += (u32)gpu_buddy_block_size(&mm, block);
+ KUNIT_EXPECT_EQ(test, total, SZ_4K + SZ_64K + SZ_1M + SZ_4M);
+
+ gpu_buddy_free_list(&mm, &blocks, 0);
+ gpu_buddy_fini(&mm);
+}
+
static void gpu_test_buddy_alloc_clear(struct kunit *test)
{
unsigned long n_pages, total, i = 0;
@@ -909,9 +1399,12 @@ static struct kunit_case gpu_buddy_tests[] = {
KUNIT_CASE(gpu_test_buddy_alloc_pathological),
KUNIT_CASE(gpu_test_buddy_alloc_contiguous),
KUNIT_CASE(gpu_test_buddy_alloc_clear),
+ KUNIT_CASE(gpu_test_buddy_alloc_range),
KUNIT_CASE(gpu_test_buddy_alloc_range_bias),
KUNIT_CASE_SLOW(gpu_test_buddy_fragmentation_performance),
KUNIT_CASE(gpu_test_buddy_alloc_exceeds_max_order),
+ KUNIT_CASE(gpu_test_buddy_offset_aligned_allocation),
+ KUNIT_CASE(gpu_test_buddy_subtree_offset_alignment_stress),
{}
};
diff --git a/include/linux/gpu_buddy.h b/include/linux/gpu_buddy.h
index f1fb6eff604a..5fa917ba5450 100644
--- a/include/linux/gpu_buddy.h
+++ b/include/linux/gpu_buddy.h
@@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/rbtree.h>
+#include <linux/rbtree_augmented.h>
/**
* GPU_BUDDY_RANGE_ALLOCATION - Allocate within a specific address range
@@ -128,6 +129,7 @@ struct gpu_buddy_block {
};
/* private: */
struct list_head tmp_link;
+ unsigned int subtree_max_alignment;
};
/* Order-zero must be at least SZ_4K */
diff --git a/include/uapi/drm/amdxdna_accel.h b/include/uapi/drm/amdxdna_accel.h
index 9c44db2b3dcd..5bd13f4435f5 100644
--- a/include/uapi/drm/amdxdna_accel.h
+++ b/include/uapi/drm/amdxdna_accel.h
@@ -353,7 +353,8 @@ struct amdxdna_drm_query_clock_metadata {
};
enum amdxdna_sensor_type {
- AMDXDNA_SENSOR_TYPE_POWER
+ AMDXDNA_SENSOR_TYPE_POWER,
+ AMDXDNA_SENSOR_TYPE_COLUMN_UTILIZATION
};
/**