diff options
| author | Dave Airlie <airlied@redhat.com> | 2026-03-15 00:53:05 +0300 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2026-03-15 00:54:10 +0300 |
| commit | d9a4a2021d4a5ced93b7d9a6d1b13298c631dbdd (patch) | |
| tree | a024ee0aa3a8c5f3da518c7a9e15c6be131dd4f5 | |
| parent | 58351f46de26bcc4403f9972f7aed430d15cbd03 (diff) | |
| parent | f08ceb71c5a5615577e7c841e1e00a89f495ab51 (diff) | |
| download | linux-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
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 = <®_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 }; /** |
