Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+2397 -565
+6
Documentation/devicetree/bindings/arm/qcom.yaml
··· 846 846 847 847 - items: 848 848 - enum: 849 + - google,bonito-tianma 850 + - const: google,bonito 851 + - const: qcom,sdm670 852 + 853 + - items: 854 + - enum: 849 855 - qcom,sdx55-mtp 850 856 - qcom,sdx55-telit-fn980-tlb 851 857 - qcom,sdx55-t55
-5
Documentation/devicetree/bindings/display/panel/abt,y030xx067a.yaml
··· 20 20 reg: 21 21 maxItems: 1 22 22 23 - backlight: true 24 - port: true 25 - power-supply: true 26 - reset-gpios: true 27 - 28 23 required: 29 24 - compatible 30 25 - reg
+2 -2
Documentation/devicetree/bindings/display/panel/advantech,idk-1110wr.yaml
··· 41 41 panel-timing: true 42 42 port: true 43 43 44 - additionalProperties: false 45 - 46 44 required: 47 45 - compatible 48 46 - data-mapping ··· 48 50 - height-mm 49 51 - panel-timing 50 52 - port 53 + 54 + additionalProperties: false 51 55 52 56 examples: 53 57 - |+
+2 -2
Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
··· 56 56 - port@0 57 57 - port@1 58 58 59 - additionalProperties: false 60 - 61 59 required: 62 60 - compatible 63 61 - width-mm 64 62 - height-mm 65 63 - data-mapping 66 64 - panel-timing 65 + 66 + additionalProperties: false 67 67 68 68 examples: 69 69 - |+
+2 -2
Documentation/devicetree/bindings/display/panel/bananapi,s070wv20-ct16.yaml
··· 22 22 enable-gpios: true 23 23 port: true 24 24 25 - additionalProperties: false 26 - 27 25 required: 28 26 - compatible 29 27 - power-supply 28 + 29 + additionalProperties: false 30 30 31 31 ...
+2 -2
Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.yaml
··· 22 22 backlight: true 23 23 port: true 24 24 25 - additionalProperties: false 26 - 27 25 required: 28 26 - compatible 29 27 - power-supply 28 + 29 + additionalProperties: false 30 30 31 31 ...
-2
Documentation/devicetree/bindings/display/panel/himax,hx83112a.yaml
··· 33 33 vsp-supply: 34 34 description: Negative source voltage rail 35 35 36 - port: true 37 - 38 36 required: 39 37 - compatible 40 38 - reg
+2 -2
Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml
··· 54 54 - vcc-supply 55 55 - iovcc-supply 56 56 57 - additionalProperties: false 58 - 59 57 allOf: 60 58 - $ref: panel-common.yaml# 61 59 - if: ··· 65 67 then: 66 68 required: 67 69 - reset-gpios 70 + 71 + additionalProperties: false 68 72 69 73 examples: 70 74 - |
-4
Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml
··· 34 34 maxItems: 1 35 35 description: Display data/command selection (D/CX) 36 36 37 - backlight: true 38 - reset-gpios: true 39 - rotation: true 40 - 41 37 required: 42 38 - compatible 43 39 - reg
-3
Documentation/devicetree/bindings/display/panel/ilitek,ili9322.yaml
··· 29 29 reg: 30 30 maxItems: 1 31 31 32 - reset-gpios: true 33 - port: true 34 - 35 32 vcc-supply: 36 33 description: Core voltage supply 37 34
+2 -4
Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
··· 40 40 spi-max-frequency: 41 41 const: 10000000 42 42 43 - port: true 44 - 45 43 vci-supply: 46 44 description: Analog voltage supply (2.5 .. 3.3V) 47 45 ··· 48 50 49 51 vddi-led-supply: 50 52 description: Voltage supply for the LED driver (1.65 .. 3.3 V) 51 - 52 - unevaluatedProperties: false 53 53 54 54 required: 55 55 - compatible ··· 63 67 then: 64 68 required: 65 69 - port 70 + 71 + unevaluatedProperties: false 66 72 67 73 examples: 68 74 - |+
-5
Documentation/devicetree/bindings/display/panel/innolux,ej030na.yaml
··· 20 20 reg: 21 21 maxItems: 1 22 22 23 - backlight: true 24 - port: true 25 - power-supply: true 26 - reset-gpios: true 27 - 28 23 required: 29 24 - compatible 30 25 - reg
+25 -1
Documentation/devicetree/bindings/display/panel/innolux,p097pfg.yaml
··· 10 10 - Lin Huang <hl@rock-chips.com> 11 11 12 12 allOf: 13 - - $ref: panel-common.yaml# 13 + - $ref: panel-common-dual.yaml# 14 14 15 15 properties: 16 16 compatible: ··· 27 27 28 28 avee-supply: 29 29 description: The regulator that provides negative voltage 30 + 31 + port: true 32 + ports: true 30 33 31 34 required: 32 35 - compatible ··· 55 52 avee-supply = <&avee>; 56 53 backlight = <&backlight>; 57 54 enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; 55 + 56 + ports { 57 + #address-cells = <1>; 58 + #size-cells = <0>; 59 + 60 + port@0 { 61 + reg = <0>; 62 + 63 + mipi_in_panel: endpoint { 64 + remote-endpoint = <&mipi_out_panel>; 65 + }; 66 + }; 67 + 68 + port@1 { 69 + reg = <1>; 70 + 71 + mipi1_in_panel: endpoint { 72 + remote-endpoint = <&mipi1_out_panel>; 73 + }; 74 + }; 75 + }; 58 76 }; 59 77 }; 60 78
+2 -2
Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml
··· 23 23 - melfas,lmfbx101117480 24 24 - radxa,display-10hd-ad001 25 25 - radxa,display-8hd-ad002 26 + - taiguanck,xti05101-01a 26 27 - const: jadard,jd9365da-h3 27 28 28 29 reg: ··· 36 35 description: supply regulator for VCCIO, usually 1.8V 37 36 38 37 reset-gpios: true 39 - 40 38 backlight: true 41 - 39 + rotation: true 42 40 port: true 43 41 44 42 required:
-5
Documentation/devicetree/bindings/display/panel/kingdisplay,kd035g6-54nt.yaml
··· 20 20 reg: 21 21 maxItems: 1 22 22 23 - backlight: true 24 - port: true 25 - power-supply: true 26 - reset-gpios: true 27 - 28 23 spi-3wire: true 29 24 30 25 required:
-4
Documentation/devicetree/bindings/display/panel/lgphilips,lb035q02.yaml
··· 20 20 reg: 21 21 maxItems: 1 22 22 23 - label: true 24 - enable-gpios: true 25 - port: true 26 - 27 23 spi-cpha: true 28 24 spi-cpol: true 29 25
+64
Documentation/devicetree/bindings/display/panel/lxd,m9189a.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/display/panel/lxd,m9189a.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: LXD M9189A DSI Display Panel 8 + 9 + maintainers: 10 + - Michael Tretter <m.tretter@pengutronix.de> 11 + 12 + allOf: 13 + - $ref: panel-common.yaml 14 + 15 + properties: 16 + compatible: 17 + const: lxd,m9189a 18 + 19 + reg: 20 + maxItems: 1 21 + 22 + standby-gpios: 23 + description: GPIO used for the standby pin 24 + maxItems: 1 25 + 26 + reset-gpios: true 27 + power-supply: true 28 + backlight: true 29 + port: true 30 + 31 + required: 32 + - compatible 33 + - reg 34 + - standby-gpios 35 + - reset-gpios 36 + - power-supply 37 + - backlight 38 + - port 39 + 40 + additionalProperties: false 41 + 42 + examples: 43 + - | 44 + #include <dt-bindings/gpio/gpio.h> 45 + 46 + dsi { 47 + #address-cells = <1>; 48 + #size-cells = <0>; 49 + 50 + panel@0 { 51 + compatible = "lxd,m9189a"; 52 + reg = <0>; 53 + backlight = <&backlight>; 54 + reset-gpios = <&gpio3 25 GPIO_ACTIVE_LOW>; 55 + standby-gpios = <&gpio5 22 GPIO_ACTIVE_LOW>; 56 + power-supply = <&reg_display_3v3>; 57 + 58 + port { 59 + mipi_panel_in: endpoint { 60 + remote-endpoint = <&mipi_dsi_out>; 61 + }; 62 + }; 63 + }; 64 + };
+2 -2
Documentation/devicetree/bindings/display/panel/mitsubishi,aa104xd12.yaml
··· 47 47 panel-timing: true 48 48 port: true 49 49 50 - additionalProperties: false 51 - 52 50 required: 53 51 - compatible 54 52 - data-mapping ··· 54 56 - height-mm 55 57 - panel-timing 56 58 - port 59 + 60 + additionalProperties: false 57 61 58 62 examples: 59 63 - |+
+2 -2
Documentation/devicetree/bindings/display/panel/mitsubishi,aa121td01.yaml
··· 44 44 panel-timing: true 45 45 port: true 46 46 47 - additionalProperties: false 48 - 49 47 required: 50 48 - compatible 51 49 - vcc-supply ··· 52 54 - height-mm 53 55 - panel-timing 54 56 - port 57 + 58 + additionalProperties: false 55 59 56 60 examples: 57 61 - |+
+69
Documentation/devicetree/bindings/display/panel/motorola,mot-panel.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/display/panel/motorola,mot-panel.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Atrix 4G and Droid X2 DSI Display Panel 8 + 9 + maintainers: 10 + - Svyatoslav Ryhel <clamor95@gmail.com> 11 + 12 + description: 13 + Atrix 4G and Droid X2 use the same 540x960 DSI video mode panel. Exact 14 + panel vendor and model are unknown hence generic compatible based on the 15 + board name "Mot" is used. 16 + 17 + allOf: 18 + - $ref: panel-common.yaml# 19 + 20 + properties: 21 + compatible: 22 + items: 23 + - const: motorola,mot-panel 24 + 25 + reg: 26 + maxItems: 1 27 + 28 + vdd-supply: 29 + description: Regulator for main power supply. 30 + 31 + vddio-supply: 32 + description: Regulator for 1.8V IO power supply. 33 + 34 + backlight: true 35 + reset-gpios: true 36 + port: true 37 + 38 + required: 39 + - compatible 40 + 41 + additionalProperties: false 42 + 43 + examples: 44 + - | 45 + #include <dt-bindings/gpio/gpio.h> 46 + 47 + dsi { 48 + #address-cells = <1>; 49 + #size-cells = <0>; 50 + 51 + panel@0 { 52 + compatible = "motorola,mot-panel"; 53 + reg = <0>; 54 + 55 + reset-gpios = <&gpio 35 GPIO_ACTIVE_LOW>; 56 + 57 + vdd-supply = <&vdd_5v0_panel>; 58 + vddio-supply = <&vdd_1v8_vio>; 59 + 60 + backlight = <&backlight>; 61 + 62 + port { 63 + panel_in: endpoint { 64 + remote-endpoint = <&dsi_out>; 65 + }; 66 + }; 67 + }; 68 + }; 69 + ...
-4
Documentation/devicetree/bindings/display/panel/nec,nl8048hl11.yaml
··· 24 24 reg: 25 25 maxItems: 1 26 26 27 - label: true 28 - port: true 29 - reset-gpios: true 30 - 31 27 spi-max-frequency: 32 28 maximum: 10000000 33 29
-3
Documentation/devicetree/bindings/display/panel/novatek,nt36523.yaml
··· 37 37 vddio-supply: 38 38 description: regulator that supplies the I/O voltage 39 39 40 - rotation: true 41 - backlight: true 42 - 43 40 required: 44 41 - compatible 45 42 - reg
-3
Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml
··· 47 47 vddneg-supply: 48 48 description: phandle of the negative boost supply regulator 49 49 50 - port: true 51 - backlight: true 52 - 53 50 required: 54 51 - compatible 55 52 - reg
+2 -2
Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.yaml
··· 31 31 reset-gpios: 32 32 maxItems: 1 33 33 34 - additionalProperties: false 35 - 36 34 required: 37 35 - compatible 38 36 - reg 37 + 38 + additionalProperties: false 39 39 40 40 examples: 41 41 - |
+2
Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
··· 49 49 - lg,lh500wx1-sd03 50 50 # Lincoln LCD197 5" 1080x1920 LCD panel 51 51 - lincolntech,lcd197 52 + # Novatek NT37700F 1080x2160 AMOLED panel 53 + - novatek,nt37700f 52 54 # One Stop Displays OSD101T2587-53TS 10.1" 1920x1200 panel 53 55 - osddisplays,osd101t2587-53ts 54 56 # Panasonic 10" WUXGA TFT LCD panel
+4
Documentation/devicetree/bindings/display/panel/panel-simple.yaml
··· 103 103 - dlc,dlc1010gig 104 104 # Emerging Display Technology Corp. 3.5" QVGA TFT LCD panel 105 105 - edt,et035012dm6 106 + # Emerging Display Technology Corp. 5.7" 24-bit VGA TFT LCD panel 107 + - edt,et057023udba 106 108 # Emerging Display Technology Corp. 5.7" VGA TFT LCD panel 107 109 - edt,et057090dhu 108 110 - edt,et070080dh6 ··· 268 266 - powertip,ph128800t006-zhc01 269 267 # POWERTIP PH800480T013-IDF2 7.0" WVGA TFT LCD panel 270 268 - powertip,ph800480t013-idf02 269 + # POWERTIP PH800480T032-ZHC19 7.0" WVGA TFT LCD panel 270 + - powertip,ph800480t032-zhc19 271 271 # PrimeView PM070WL4 7.0" 800x480 TFT LCD panel 272 272 - primeview,pm070wl4 273 273 # QiaoDian XianShi Corporation 4"3 TFT LCD panel
+2 -2
Documentation/devicetree/bindings/display/panel/pda,91-00156-a0.yaml
··· 21 21 backlight: true 22 22 port: true 23 23 24 - additionalProperties: false 25 - 26 24 required: 27 25 - compatible 28 26 - power-supply 29 27 - backlight 28 + 29 + additionalProperties: false 30 30 31 31 ...
+2 -2
Documentation/devicetree/bindings/display/panel/raydium,rm68200.yaml
··· 33 33 reset-gpios: 34 34 maxItems: 1 35 35 36 - additionalProperties: false 37 - 38 36 required: 39 37 - compatible 40 38 - power-supply 41 39 - reg 40 + 41 + additionalProperties: false 42 42 43 43 examples: 44 44 - |
-2
Documentation/devicetree/bindings/display/panel/raydium,rm692e5.yaml
··· 34 34 vddio-supply: 35 35 description: I/O voltage rail 36 36 37 - port: true 38 - 39 37 required: 40 38 - compatible 41 39 - reg
+2 -2
Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml
··· 43 43 no-hpd: true 44 44 hpd-gpios: true 45 45 46 - additionalProperties: false 47 - 48 46 required: 49 47 - compatible 50 48 - enable-gpios 51 49 - power-supply 50 + 51 + additionalProperties: false 52 52 53 53 examples: 54 54 - |
-4
Documentation/devicetree/bindings/display/panel/samsung,ld9040.yaml
··· 20 20 reg: 21 21 maxItems: 1 22 22 23 - display-timings: true 24 - port: true 25 - reset-gpios: true 26 - 27 23 vdd3-supply: 28 24 description: core voltage supply 29 25
-6
Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
··· 31 31 configuration. 32 32 maxItems: 1 33 33 34 - reset-gpios: true 35 - 36 34 vci-supply: 37 35 description: regulator that supplies the VCI analog voltage 38 36 usually around 3.0 V ··· 39 41 description: regulator that supplies the VCCIO voltage usually 40 42 around 1.8 V 41 43 42 - backlight: true 43 - 44 44 spi-cpha: true 45 45 46 46 spi-cpol: true 47 47 48 48 spi-max-frequency: 49 49 maximum: 1200000 50 - 51 - port: true 52 50 53 51 required: 54 52 - compatible
-6
Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
··· 23 23 reg: 24 24 maxItems: 1 25 25 26 - reset-gpios: true 27 - 28 26 vci-supply: 29 27 description: regulator that supplies the VCI analog voltage 30 28 usually around 3.0 V ··· 30 32 vccio-supply: 31 33 description: regulator that supplies the VCCIO voltage usually 32 34 around 1.8 V 33 - 34 - backlight: true 35 35 36 36 spi-cpha: true 37 37 ··· 39 43 description: inherited as a SPI client node, the datasheet specifies 40 44 maximum 300 ns minimum cycle which gives around 3 MHz max frequency 41 45 maximum: 3000000 42 - 43 - port: true 44 46 45 47 required: 46 48 - compatible
-6
Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml
··· 30 30 configuration. 31 31 maxItems: 1 32 32 33 - reset-gpios: true 34 - 35 33 vci-supply: 36 34 description: regulator that supplies the VCI analog voltage 37 35 usually around 3.0 V ··· 38 40 description: regulator that supplies the VCCIO voltage usually 39 41 around 1.8 V 40 42 41 - backlight: true 42 - 43 43 spi-cpha: true 44 44 45 45 spi-cpol: true 46 46 47 47 spi-max-frequency: 48 48 maximum: 1200000 49 - 50 - port: true 51 49 52 50 required: 53 51 - compatible
+8
Documentation/devicetree/bindings/display/panel/samsung,s6d7aa0.yaml
··· 44 44 vmipi-supply: 45 45 description: VMIPI supply, usually 1.8v. 46 46 47 + port: true 48 + 47 49 required: 48 50 - compatible 49 51 - reg ··· 67 65 power-supply = <&display_3v3_supply>; 68 66 reset-gpios = <&gpf0 4 GPIO_ACTIVE_LOW>; 69 67 backlight = <&backlight>; 68 + 69 + port { 70 + panel_in: endpoint { 71 + remote-endpoint = <&mdss_dsi0_out>; 72 + }; 73 + }; 70 74 }; 71 75 }; 72 76
-4
Documentation/devicetree/bindings/display/panel/samsung,s6e3ha8.yaml
··· 22 22 reg: 23 23 maxItems: 1 24 24 25 - reset-gpios: true 26 - 27 - port: true 28 - 29 25 vdd3-supply: 30 26 description: VDD regulator 31 27
-2
Documentation/devicetree/bindings/display/panel/samsung,s6e63m0.yaml
··· 21 21 reg: 22 22 maxItems: 1 23 23 24 - reset-gpios: true 25 - port: true 26 24 default-brightness: true 27 25 max-brightness: true 28 26
+2 -2
Documentation/devicetree/bindings/display/panel/sgd,gktw70sdae4se.yaml
··· 41 41 panel-timing: true 42 42 port: true 43 43 44 - additionalProperties: false 45 - 46 44 required: 47 45 - compatible 48 46 - port ··· 48 50 - width-mm 49 51 - height-mm 50 52 - panel-timing 53 + 54 + additionalProperties: false 51 55 52 56 examples: 53 57 - |+
-6
Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml
··· 49 49 If not set, the controller is in 3-line SPI mode. 50 50 Disallowed for DSI. 51 51 52 - port: true 53 - reset-gpios: true 54 - rotation: true 55 - 56 - backlight: true 57 - 58 52 required: 59 53 - compatible 60 54 - reg
-6
Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
··· 24 24 reg: 25 25 maxItems: 1 26 26 27 - reset-gpios: true 28 - power-supply: true 29 - backlight: true 30 - port: true 31 - rotation: true 32 - 33 27 spi-cpha: true 34 28 spi-cpol: true 35 29
-4
Documentation/devicetree/bindings/display/panel/sony,acx565akm.yaml
··· 20 20 reg: 21 21 maxItems: 1 22 22 23 - label: true 24 - reset-gpios: true 25 - port: true 26 - 27 23 required: 28 24 - compatible 29 25 - port
+2 -2
Documentation/devicetree/bindings/display/panel/startek,kd070fhfid015.yaml
··· 31 31 32 32 power-supply: true 33 33 34 - additionalProperties: false 35 - 36 34 required: 37 35 - compatible 38 36 - enable-gpios ··· 39 41 - reset-gpios 40 42 - port 41 43 - power-supply 44 + 45 + additionalProperties: false 42 46 43 47 examples: 44 48 - |
-5
Documentation/devicetree/bindings/display/panel/tpo,td.yaml
··· 25 25 reg: 26 26 maxItems: 1 27 27 28 - label: true 29 - reset-gpios: true 30 - backlight: true 31 - port: true 32 - 33 28 spi-cpha: true 34 29 spi-cpol: true 35 30
+2 -2
Documentation/devicetree/bindings/display/panel/visionox,r66451.yaml
··· 25 25 port: true 26 26 reset-gpios: true 27 27 28 - additionalProperties: false 29 - 30 28 required: 31 29 - compatible 32 30 - reg ··· 32 34 - vdd-supply 33 35 - reset-gpios 34 36 - port 37 + 38 + additionalProperties: false 35 39 36 40 examples: 37 41 - |
+2 -2
Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml
··· 36 36 port: true 37 37 reset-gpios: true 38 38 39 - additionalProperties: false 40 - 41 39 required: 42 40 - compatible 43 41 - reg ··· 43 45 - vdd3p3-supply 44 46 - reset-gpios 45 47 - port 48 + 49 + additionalProperties: false 46 50 47 51 examples: 48 52 - |
+2 -2
Documentation/devicetree/bindings/display/panel/visionox,vtdr6130.yaml
··· 26 26 port: true 27 27 reset-gpios: true 28 28 29 - additionalProperties: false 30 - 31 29 required: 32 30 - compatible 33 31 - reg ··· 34 36 - vdd-supply 35 37 - reset-gpios 36 38 - port 39 + 40 + additionalProperties: false 37 41 38 42 examples: 39 43 - |
+4
Documentation/devicetree/bindings/vendor-prefixes.yaml
··· 973 973 description: Liebherr-Werk Nenzing GmbH 974 974 "^lxa,.*": 975 975 description: Linux Automation GmbH 976 + "^lxd,.*": 977 + description: LXD Research & Display, LLC 976 978 "^m5stack,.*": 977 979 description: M5Stack 978 980 "^macnica,.*": ··· 1612 1610 "^synopsys,.*": 1613 1611 description: Synopsys, Inc. (deprecated, use snps) 1614 1612 deprecated: true 1613 + "^taiguanck,.*": 1614 + description: Shenzhen Top Group Technology Co., Ltd. 1615 1615 "^taos,.*": 1616 1616 description: Texas Advanced Optoelectronic Solutions Inc. 1617 1617 "^tbs,.*":
+8 -3
MAINTAINERS
··· 8059 8059 F: Documentation/devicetree/bindings/display/panel/panel-lvds.yaml 8060 8060 F: drivers/gpu/drm/panel/panel-lvds.c 8061 8061 8062 + DRM DRIVER FOR LXD M9189A PANELS 8063 + M: Michael Tretter <m.tretter@pengutronix.de> 8064 + S: Maintained 8065 + F: Documentation/devicetree/bindings/display/panel/lxd,m9189a.yaml 8066 + F: drivers/gpu/drm/panel/panel-lxd-m9189a.c 8067 + 8062 8068 DRM DRIVER FOR MANTIX MLAF057WE51 PANELS 8063 8069 M: Guido Günther <agx@sigxcpu.org> 8064 8070 R: Purism Kernel Team <kernel@puri.sm> ··· 8922 8916 L: dri-devel@lists.freedesktop.org 8923 8917 S: Maintained 8924 8918 T: git https://gitlab.freedesktop.org/drm/misc/kernel.git 8925 - F: drivers/gpu/drm_buddy.c 8926 8919 F: drivers/gpu/buddy.c 8920 + F: drivers/gpu/drm/drm_buddy.c 8927 8921 F: drivers/gpu/tests/gpu_buddy_test.c 8928 - F: include/linux/gpu_buddy.h 8929 8922 F: include/drm/drm_buddy.h 8923 + F: include/linux/gpu_buddy.h 8930 8924 8931 8925 DRM AUTOMATED TESTING 8932 8926 M: Helen Koike <helen.fornazier@gmail.com> ··· 12991 12985 12992 12986 INTEL KEEM BAY DRM DRIVER 12993 12987 M: Anitha Chrisanthus <anitha.chrisanthus@intel.com> 12994 - M: Edmund Dea <edmund.j.dea@intel.com> 12995 12988 S: Maintained 12996 12989 F: Documentation/devicetree/bindings/display/intel,keembay-display.yaml 12997 12990 F: drivers/gpu/drm/kmb/
+53
drivers/accel/amdxdna/aie2_pci.c
··· 10 10 #include <drm/drm_managed.h> 11 11 #include <drm/drm_print.h> 12 12 #include <drm/gpu_scheduler.h> 13 + #include <linux/amd-pmf-io.h> 13 14 #include <linux/cleanup.h> 14 15 #include <linux/errno.h> 15 16 #include <linux/firmware.h> ··· 792 791 return ret; 793 792 } 794 793 794 + static int aie2_get_sensors(struct amdxdna_client *client, 795 + struct amdxdna_drm_get_info *args) 796 + { 797 + struct amdxdna_dev_hdl *ndev = client->xdna->dev_handle; 798 + struct amdxdna_drm_query_sensor sensor = {}; 799 + struct amd_pmf_npu_metrics npu_metrics; 800 + u32 sensors_count = 0, i; 801 + int ret; 802 + 803 + ret = AIE2_GET_PMF_NPU_METRICS(&npu_metrics); 804 + if (ret) 805 + return ret; 806 + 807 + sensor.type = AMDXDNA_SENSOR_TYPE_POWER; 808 + sensor.input = npu_metrics.npu_power; 809 + sensor.unitm = -3; 810 + scnprintf(sensor.label, sizeof(sensor.label), "Total Power"); 811 + scnprintf(sensor.units, sizeof(sensor.units), "mW"); 812 + 813 + if (copy_to_user(u64_to_user_ptr(args->buffer), &sensor, sizeof(sensor))) 814 + return -EFAULT; 815 + 816 + sensors_count++; 817 + if (args->buffer_size <= sensors_count * sizeof(sensor)) 818 + goto out; 819 + 820 + for (i = 0; i < min_t(u32, ndev->total_col, 8); i++) { 821 + memset(&sensor, 0, sizeof(sensor)); 822 + sensor.input = npu_metrics.npu_busy[i]; 823 + sensor.type = AMDXDNA_SENSOR_TYPE_COLUMN_UTILIZATION; 824 + sensor.unitm = 0; 825 + scnprintf(sensor.label, sizeof(sensor.label), "Column %d Utilization", i); 826 + scnprintf(sensor.units, sizeof(sensor.units), "%%"); 827 + 828 + if (copy_to_user(u64_to_user_ptr(args->buffer) + sensors_count * sizeof(sensor), 829 + &sensor, sizeof(sensor))) 830 + return -EFAULT; 831 + 832 + sensors_count++; 833 + if (args->buffer_size <= sensors_count * sizeof(sensor)) 834 + goto out; 835 + } 836 + 837 + out: 838 + args->buffer_size = sensors_count * sizeof(sensor); 839 + 840 + return 0; 841 + } 842 + 795 843 static int aie2_hwctx_status_cb(struct amdxdna_hwctx *hwctx, void *arg) 796 844 { 797 845 struct amdxdna_drm_hwctx_entry *tmp __free(kfree) = NULL; ··· 1043 993 break; 1044 994 case DRM_AMDXDNA_QUERY_CLOCK_METADATA: 1045 995 ret = aie2_get_clock_metadata(client, args); 996 + break; 997 + case DRM_AMDXDNA_QUERY_SENSORS: 998 + ret = aie2_get_sensors(client, args); 1046 999 break; 1047 1000 case DRM_AMDXDNA_QUERY_HW_CONTEXTS: 1048 1001 ret = aie2_get_hwctx_status(client, args);
+28
drivers/accel/amdxdna/aie2_pci.h
··· 7 7 #define _AIE2_PCI_H_ 8 8 9 9 #include <drm/amdxdna_accel.h> 10 + #include <linux/limits.h> 10 11 #include <linux/semaphore.h> 11 12 12 13 #include "amdxdna_mailbox.h" ··· 46 45 ((_ndev)->priv->mbox_size) ? (_ndev)->priv->mbox_size : \ 47 46 pci_resource_len(NDEV2PDEV(_ndev), (_ndev)->xdna->dev_info->mbox_bar); \ 48 47 }) 48 + 49 + #if IS_ENABLED(CONFIG_AMD_PMF) 50 + #define AIE2_GET_PMF_NPU_METRICS(metrics) amd_pmf_get_npu_data(metrics) 51 + #define AIE2_GET_PMF_NPU_DATA(field, val) \ 52 + ({ \ 53 + struct amd_pmf_npu_metrics _npu_metrics; \ 54 + int _ret; \ 55 + \ 56 + _ret = amd_pmf_get_npu_data(&_npu_metrics); \ 57 + val = _ret ? U32_MAX : _npu_metrics.field; \ 58 + (_ret); \ 59 + }) 60 + #else 61 + #define AIE2_GET_PMF_NPU_METRICS(metrics) \ 62 + ({ \ 63 + typeof(metrics) _m = metrics; \ 64 + memset(_m, 0xff, sizeof(*_m)); \ 65 + (-EOPNOTSUPP); \ 66 + }) 67 + 68 + #define SENSOR_DEFAULT_npu_power U32_MAX 69 + #define AIE2_GET_PMF_NPU_DATA(field, val) \ 70 + ({ \ 71 + val = SENSOR_DEFAULT_##field; \ 72 + (-EOPNOTSUPP); \ 73 + }) 74 + #endif 49 75 50 76 enum aie2_smu_reg_idx { 51 77 SMU_CMD_REG = 0,
+3 -1
drivers/accel/amdxdna/amdxdna_pci_drv.c
··· 35 35 * 0.4: Support getting resource information 36 36 * 0.5: Support getting telemetry data 37 37 * 0.6: Support preemption 38 + * 0.7: Support getting power and utilization data 38 39 */ 39 40 #define AMDXDNA_DRIVER_MAJOR 0 40 - #define AMDXDNA_DRIVER_MINOR 6 41 + #define AMDXDNA_DRIVER_MINOR 7 41 42 42 43 /* 43 44 * Bind the driver base on (vendor_id, device_id) pair and later use the ··· 359 358 module_pci_driver(amdxdna_pci_driver); 360 359 361 360 MODULE_LICENSE("GPL"); 361 + MODULE_IMPORT_NS("AMD_PMF"); 362 362 MODULE_AUTHOR("XRT Team <runtimeca39d@amd.com>"); 363 363 MODULE_DESCRIPTION("amdxdna driver");
+6 -6
drivers/accel/ivpu/ivpu_gem.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 - * Copyright (C) 2020-2023 Intel Corporation 3 + * Copyright (C) 2020-2026 Intel Corporation 4 4 */ 5 5 6 6 #include <linux/dma-buf.h> ··· 31 31 "%6s: bo %8p size %9zu ctx %d vpu_addr %9llx pages %d sgt %d mmu_mapped %d wc %d imported %d\n", 32 32 action, bo, ivpu_bo_size(bo), bo->ctx_id, bo->vpu_addr, 33 33 (bool)bo->base.pages, (bool)bo->base.sgt, bo->mmu_mapped, bo->base.map_wc, 34 - (bool)drm_gem_is_imported(&bo->base.base)); 34 + drm_gem_is_imported(&bo->base.base)); 35 35 } 36 36 37 37 static inline int ivpu_bo_lock(struct ivpu_bo *bo) ··· 48 48 { 49 49 struct sg_table *sgt; 50 50 51 - drm_WARN_ON(&vdev->drm, !bo->base.base.import_attach); 51 + drm_WARN_ON(&vdev->drm, !drm_gem_is_imported(&bo->base.base)); 52 52 53 53 ivpu_bo_lock(bo); 54 54 ··· 81 81 82 82 ivpu_dbg_bo(vdev, bo, "bind"); 83 83 84 - if (bo->base.base.import_attach) 84 + if (drm_gem_is_imported(&bo->base.base)) 85 85 sgt = ivpu_bo_map_attachment(vdev, bo); 86 86 else 87 87 sgt = drm_gem_shmem_get_pages_sgt(&bo->base); ··· 157 157 } 158 158 159 159 if (bo->base.sgt) { 160 - if (bo->base.base.import_attach) { 160 + if (drm_gem_is_imported(&bo->base.base)) { 161 161 dma_buf_unmap_attachment(bo->base.base.import_attach, 162 162 bo->base.sgt, DMA_BIDIRECTIONAL); 163 163 } else { ··· 195 195 if (size == 0 || !PAGE_ALIGNED(size)) 196 196 return ERR_PTR(-EINVAL); 197 197 198 - bo = kzalloc(sizeof(*bo), GFP_KERNEL); 198 + bo = kzalloc_obj(*bo); 199 199 if (!bo) 200 200 return ERR_PTR(-ENOMEM); 201 201
-6
drivers/accel/ivpu/ivpu_hw_40xx_reg.h
··· 121 121 #define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY 0x0003006cu 122 122 #define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY_STATUS_DLY_MASK GENMASK(7, 0) 123 123 124 - #define VPU_40XX_HOST_SS_AON_RETENTION0 0x0003000cu 125 - #define VPU_40XX_HOST_SS_AON_RETENTION1 0x00030010u 126 - #define VPU_40XX_HOST_SS_AON_RETENTION2 0x00030014u 127 - #define VPU_40XX_HOST_SS_AON_RETENTION3 0x00030018u 128 - #define VPU_40XX_HOST_SS_AON_RETENTION4 0x0003001cu 129 - 130 124 #define VPU_40XX_HOST_SS_AON_IDLE_GEN 0x00030200u 131 125 #define VPU_40XX_HOST_SS_AON_IDLE_GEN_EN_MASK BIT_MASK(0) 132 126 #define VPU_40XX_HOST_SS_AON_IDLE_GEN_HW_PG_EN_MASK BIT_MASK(1)
-1
drivers/accel/ivpu/ivpu_hw_ip.c
··· 931 931 932 932 static int soc_cpu_boot_60xx(struct ivpu_device *vdev) 933 933 { 934 - REGV_WR64(VPU_40XX_HOST_SS_AON_RETENTION1, vdev->fw->mem_bp->vpu_addr); 935 934 soc_cpu_set_entry_point_40xx(vdev, vdev->fw->cold_boot_entry_point); 936 935 937 936 return 0;
+2 -5
drivers/dma-buf/heaps/cma_heap.c
··· 329 329 struct page *page = cma_pages; 330 330 331 331 while (nr_clear_pages > 0) { 332 - void *vaddr = kmap_local_page(page); 333 - 334 - clear_page(vaddr); 335 - kunmap_local(vaddr); 332 + clear_highpage(page); 336 333 /* 337 334 * Avoid wasting time zeroing memory if the process 338 335 * has been killed by SIGKILL. ··· 340 343 nr_clear_pages--; 341 344 } 342 345 } else { 343 - memset(page_address(cma_pages), 0, size); 346 + clear_pages(page_address(cma_pages), pagecount); 344 347 } 345 348 346 349 buffer->pages = kmalloc_objs(*buffer->pages, pagecount);
+228 -46
drivers/gpu/buddy.c
··· 53 53 return gpu_buddy_block_state(block) == GPU_BUDDY_SPLIT; 54 54 } 55 55 56 + static unsigned int gpu_buddy_block_offset_alignment(struct gpu_buddy_block *block) 57 + { 58 + u64 offset = gpu_buddy_block_offset(block); 59 + 60 + if (!offset) 61 + /* 62 + * __ffs64(0) is undefined; offset 0 is maximally aligned, so return 63 + * a value greater than any possible alignment. 64 + */ 65 + return 64 + 1; 66 + 67 + return __ffs64(offset); 68 + } 69 + 70 + RB_DECLARE_CALLBACKS_MAX(static, gpu_buddy_augment_cb, 71 + struct gpu_buddy_block, rb, 72 + unsigned int, subtree_max_alignment, 73 + gpu_buddy_block_offset_alignment); 74 + 56 75 static struct gpu_buddy_block *gpu_block_alloc(struct gpu_buddy *mm, 57 76 struct gpu_buddy_block *parent, 58 77 unsigned int order, ··· 125 106 return RB_EMPTY_ROOT(root); 126 107 } 127 108 128 - static bool gpu_buddy_block_offset_less(const struct gpu_buddy_block *block, 129 - const struct gpu_buddy_block *node) 130 - { 131 - return gpu_buddy_block_offset(block) < gpu_buddy_block_offset(node); 132 - } 133 - 134 - static bool rbtree_block_offset_less(struct rb_node *block, 135 - const struct rb_node *node) 136 - { 137 - return gpu_buddy_block_offset_less(rbtree_get_free_block(block), 138 - rbtree_get_free_block(node)); 139 - } 140 - 141 109 static void rbtree_insert(struct gpu_buddy *mm, 142 110 struct gpu_buddy_block *block, 143 111 enum gpu_buddy_free_tree tree) 144 112 { 145 - rb_add(&block->rb, 146 - &mm->free_trees[tree][gpu_buddy_block_order(block)], 147 - rbtree_block_offset_less); 113 + struct rb_node **link, *parent = NULL; 114 + unsigned int block_alignment, order; 115 + struct gpu_buddy_block *node; 116 + struct rb_root *root; 117 + 118 + order = gpu_buddy_block_order(block); 119 + block_alignment = gpu_buddy_block_offset_alignment(block); 120 + 121 + root = &mm->free_trees[tree][order]; 122 + link = &root->rb_node; 123 + 124 + while (*link) { 125 + parent = *link; 126 + node = rbtree_get_free_block(parent); 127 + /* 128 + * Manual augmentation update during insertion traversal. Required 129 + * because rb_insert_augmented() only calls rotate callback during 130 + * rotations. This ensures all ancestors on the insertion path have 131 + * correct subtree_max_alignment values. 132 + */ 133 + if (node->subtree_max_alignment < block_alignment) 134 + node->subtree_max_alignment = block_alignment; 135 + 136 + if (gpu_buddy_block_offset(block) < gpu_buddy_block_offset(node)) 137 + link = &parent->rb_left; 138 + else 139 + link = &parent->rb_right; 140 + } 141 + 142 + block->subtree_max_alignment = block_alignment; 143 + rb_link_node(&block->rb, parent, link); 144 + rb_insert_augmented(&block->rb, root, &gpu_buddy_augment_cb); 148 145 } 149 146 150 147 static void rbtree_remove(struct gpu_buddy *mm, ··· 173 138 tree = get_block_tree(block); 174 139 root = &mm->free_trees[tree][order]; 175 140 176 - rb_erase(&block->rb, root); 141 + rb_erase_augmented(&block->rb, root, &gpu_buddy_augment_cb); 177 142 RB_CLEAR_NODE(&block->rb); 178 143 } 179 144 ··· 846 811 return ERR_PTR(err); 847 812 } 848 813 814 + static bool 815 + gpu_buddy_can_offset_align(u64 size, u64 min_block_size) 816 + { 817 + return size < min_block_size && is_power_of_2(size); 818 + } 819 + 820 + static bool gpu_buddy_subtree_can_satisfy(struct rb_node *node, 821 + unsigned int alignment) 822 + { 823 + struct gpu_buddy_block *block; 824 + 825 + block = rbtree_get_free_block(node); 826 + return block->subtree_max_alignment >= alignment; 827 + } 828 + 829 + static struct gpu_buddy_block * 830 + gpu_buddy_find_block_aligned(struct gpu_buddy *mm, 831 + enum gpu_buddy_free_tree tree, 832 + unsigned int order, 833 + unsigned int alignment, 834 + unsigned long flags) 835 + { 836 + struct rb_root *root = &mm->free_trees[tree][order]; 837 + struct rb_node *rb = root->rb_node; 838 + 839 + while (rb) { 840 + struct gpu_buddy_block *block = rbtree_get_free_block(rb); 841 + struct rb_node *left_node = rb->rb_left, *right_node = rb->rb_right; 842 + 843 + if (right_node) { 844 + if (gpu_buddy_subtree_can_satisfy(right_node, alignment)) { 845 + rb = right_node; 846 + continue; 847 + } 848 + } 849 + 850 + if (gpu_buddy_block_offset_alignment(block) >= alignment) 851 + return block; 852 + 853 + if (left_node) { 854 + if (gpu_buddy_subtree_can_satisfy(left_node, alignment)) { 855 + rb = left_node; 856 + continue; 857 + } 858 + } 859 + 860 + break; 861 + } 862 + 863 + return NULL; 864 + } 865 + 866 + static struct gpu_buddy_block * 867 + gpu_buddy_offset_aligned_allocation(struct gpu_buddy *mm, 868 + u64 size, 869 + u64 min_block_size, 870 + unsigned long flags) 871 + { 872 + struct gpu_buddy_block *block = NULL; 873 + unsigned int order, tmp, alignment; 874 + struct gpu_buddy_block *buddy; 875 + enum gpu_buddy_free_tree tree; 876 + unsigned long pages; 877 + int err; 878 + 879 + alignment = ilog2(min_block_size); 880 + pages = size >> ilog2(mm->chunk_size); 881 + order = fls(pages) - 1; 882 + 883 + tree = (flags & GPU_BUDDY_CLEAR_ALLOCATION) ? 884 + GPU_BUDDY_CLEAR_TREE : GPU_BUDDY_DIRTY_TREE; 885 + 886 + for (tmp = order; tmp <= mm->max_order; ++tmp) { 887 + block = gpu_buddy_find_block_aligned(mm, tree, tmp, 888 + alignment, flags); 889 + if (!block) { 890 + tree = (tree == GPU_BUDDY_CLEAR_TREE) ? 891 + GPU_BUDDY_DIRTY_TREE : GPU_BUDDY_CLEAR_TREE; 892 + block = gpu_buddy_find_block_aligned(mm, tree, tmp, 893 + alignment, flags); 894 + } 895 + 896 + if (block) 897 + break; 898 + } 899 + 900 + if (!block) 901 + return ERR_PTR(-ENOSPC); 902 + 903 + while (gpu_buddy_block_order(block) > order) { 904 + struct gpu_buddy_block *left, *right; 905 + 906 + err = split_block(mm, block); 907 + if (unlikely(err)) 908 + goto err_undo; 909 + 910 + left = block->left; 911 + right = block->right; 912 + 913 + if (gpu_buddy_block_offset_alignment(right) >= alignment) 914 + block = right; 915 + else 916 + block = left; 917 + } 918 + 919 + return block; 920 + 921 + err_undo: 922 + /* 923 + * We really don't want to leave around a bunch of split blocks, since 924 + * bigger is better, so make sure we merge everything back before we 925 + * free the allocated blocks. 926 + */ 927 + buddy = __get_buddy(block); 928 + if (buddy && 929 + (gpu_buddy_block_is_free(block) && 930 + gpu_buddy_block_is_free(buddy))) 931 + __gpu_buddy_free(mm, block, false); 932 + return ERR_PTR(err); 933 + } 934 + 849 935 static int __alloc_range(struct gpu_buddy *mm, 850 936 struct list_head *dfs, 851 937 u64 start, u64 size, ··· 1236 1080 static struct gpu_buddy_block * 1237 1081 __gpu_buddy_alloc_blocks(struct gpu_buddy *mm, 1238 1082 u64 start, u64 end, 1083 + u64 size, u64 min_block_size, 1239 1084 unsigned int order, 1240 1085 unsigned long flags) 1241 1086 { ··· 1244 1087 /* Allocate traversing within the range */ 1245 1088 return __gpu_buddy_alloc_range_bias(mm, start, end, 1246 1089 order, flags); 1090 + else if (size < min_block_size) 1091 + /* Allocate from an offset-aligned region without size rounding */ 1092 + return gpu_buddy_offset_aligned_allocation(mm, size, 1093 + min_block_size, 1094 + flags); 1247 1095 else 1248 1096 /* Allocate from freetree */ 1249 1097 return alloc_from_freetree(mm, order, flags); ··· 1320 1158 if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION) { 1321 1159 size = roundup_pow_of_two(size); 1322 1160 min_block_size = size; 1323 - /* Align size value to min_block_size */ 1324 - } else if (!IS_ALIGNED(size, min_block_size)) { 1161 + /* 1162 + * Normalize the requested size to min_block_size for regular allocations. 1163 + * Offset-aligned allocations intentionally skip size rounding. 1164 + */ 1165 + } else if (!gpu_buddy_can_offset_align(size, min_block_size)) { 1325 1166 size = round_up(size, min_block_size); 1326 1167 } 1327 1168 ··· 1344 1179 do { 1345 1180 order = min(order, (unsigned int)fls(pages) - 1); 1346 1181 BUG_ON(order > mm->max_order); 1347 - BUG_ON(order < min_order); 1182 + /* 1183 + * Regular allocations must not allocate blocks smaller than min_block_size. 1184 + * Offset-aligned allocations deliberately bypass this constraint. 1185 + */ 1186 + BUG_ON(size >= min_block_size && order < min_order); 1348 1187 1349 1188 do { 1189 + unsigned int fallback_order; 1190 + 1350 1191 block = __gpu_buddy_alloc_blocks(mm, start, 1351 1192 end, 1193 + size, 1194 + min_block_size, 1352 1195 order, 1353 1196 flags); 1354 1197 if (!IS_ERR(block)) 1355 1198 break; 1356 1199 1357 - if (order-- == min_order) { 1358 - /* Try allocation through force merge method */ 1359 - if (mm->clear_avail && 1360 - !__force_merge(mm, start, end, min_order)) { 1361 - block = __gpu_buddy_alloc_blocks(mm, start, 1362 - end, 1363 - min_order, 1364 - flags); 1365 - if (!IS_ERR(block)) { 1366 - order = min_order; 1367 - break; 1368 - } 1369 - } 1370 - 1371 - /* 1372 - * Try contiguous block allocation through 1373 - * try harder method. 1374 - */ 1375 - if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION && 1376 - !(flags & GPU_BUDDY_RANGE_ALLOCATION)) 1377 - return __alloc_contig_try_harder(mm, 1378 - original_size, 1379 - original_min_size, 1380 - blocks); 1381 - err = -ENOSPC; 1382 - goto err_free; 1200 + if (size < min_block_size) { 1201 + fallback_order = order; 1202 + } else if (order == min_order) { 1203 + fallback_order = min_order; 1204 + } else { 1205 + order--; 1206 + continue; 1383 1207 } 1208 + 1209 + /* Try allocation through force merge method */ 1210 + if (mm->clear_avail && 1211 + !__force_merge(mm, start, end, fallback_order)) { 1212 + block = __gpu_buddy_alloc_blocks(mm, start, 1213 + end, 1214 + size, 1215 + min_block_size, 1216 + fallback_order, 1217 + flags); 1218 + if (!IS_ERR(block)) { 1219 + order = fallback_order; 1220 + break; 1221 + } 1222 + } 1223 + 1224 + /* 1225 + * Try contiguous block allocation through 1226 + * try harder method. 1227 + */ 1228 + if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION && 1229 + !(flags & GPU_BUDDY_RANGE_ALLOCATION)) 1230 + return __alloc_contig_try_harder(mm, 1231 + original_size, 1232 + original_min_size, 1233 + blocks); 1234 + err = -ENOSPC; 1235 + goto err_free; 1384 1236 } while (1); 1385 1237 1386 1238 mark_allocated(mm, block);
+2 -1
drivers/gpu/drm/bridge/analogix/Kconfig
··· 34 34 tristate "Analogix Anx7625 MIPI to DP interface support" 35 35 depends on DRM 36 36 depends on OF 37 - depends on TYPEC || !TYPEC 37 + depends on TYPEC 38 + depends on USB_ROLE_SWITCH 38 39 select DRM_DISPLAY_DP_HELPER 39 40 select DRM_DISPLAY_HDCP_HELPER 40 41 select DRM_DISPLAY_HELPER
+17 -24
drivers/gpu/drm/bridge/analogix/anx7625.c
··· 1363 1363 anx7625_hpd_timer_config(ctx); 1364 1364 } 1365 1365 1366 + static bool anx7625_need_pd(struct anx7625_data *ctx) 1367 + { 1368 + struct fwnode_handle *fwnode; 1369 + 1370 + fwnode = device_get_named_child_node(ctx->dev, "connector"); 1371 + if (!fwnode) 1372 + return false; 1373 + 1374 + fwnode_handle_put(fwnode); 1375 + return true; 1376 + } 1377 + 1366 1378 static int anx7625_ocm_loading_check(struct anx7625_data *ctx) 1367 1379 { 1368 1380 int ret; ··· 1390 1378 if ((ret & FLASH_LOAD_STA_CHK) != FLASH_LOAD_STA_CHK) 1391 1379 return -ENODEV; 1392 1380 1393 - if (!ctx->typec_port) 1381 + if (!anx7625_need_pd(ctx)) 1394 1382 anx7625_disable_pd_protocol(ctx); 1395 1383 anx7625_configure_hpd(ctx); 1396 1384 ··· 1495 1483 DRM_DEV_DEBUG_DRIVER(dev, "Secure OCM version=%02x\n", ret); 1496 1484 } 1497 1485 1498 - #if IS_REACHABLE(CONFIG_TYPEC) 1499 1486 static u8 anx7625_checksum(u8 *buf, u8 len) 1500 1487 { 1501 1488 u8 ret = 0; ··· 1578 1567 unsigned int intr_status, 1579 1568 unsigned int intr_vector) 1580 1569 { 1570 + if (!ctx->typec_port) 1571 + return; 1572 + 1581 1573 if (intr_vector & CC_STATUS) 1582 1574 anx7625_typec_set_orientation(ctx); 1583 1575 if (intr_vector & DATA_ROLE_STATUS) { ··· 1649 1635 usb_role_switch_put(ctx->role_sw); 1650 1636 typec_unregister_port(ctx->typec_port); 1651 1637 } 1652 - #else 1653 - static void anx7625_typec_set_status(struct anx7625_data *ctx, 1654 - unsigned int intr_status, 1655 - unsigned int intr_vector) 1656 - { 1657 - } 1658 - 1659 - static int anx7625_typec_register(struct anx7625_data *ctx) 1660 - { 1661 - return 0; 1662 - } 1663 - 1664 - static void anx7625_typec_unregister(struct anx7625_data *ctx) 1665 - { 1666 - } 1667 - #endif 1668 1638 1669 1639 static int anx7625_read_hpd_status_p0(struct anx7625_data *ctx) 1670 1640 { ··· 2922 2924 } 2923 2925 2924 2926 if (!platform->pdata.low_power_mode) { 2925 - struct fwnode_handle *fwnode; 2926 - 2927 - fwnode = device_get_named_child_node(dev, "connector"); 2928 - if (fwnode) 2929 - fwnode_handle_put(fwnode); 2930 - else 2927 + if (!anx7625_need_pd(platform)) 2931 2928 anx7625_disable_pd_protocol(platform); 2932 2929 2933 2930 anx7625_configure_hpd(platform);
+66 -191
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
··· 739 739 spin_lock(&mhdp->start_lock); 740 740 bridge_attached = mhdp->bridge_attached; 741 741 spin_unlock(&mhdp->start_lock); 742 - if (bridge_attached) { 743 - if (mhdp->connector.dev) 744 - drm_kms_helper_hotplug_event(mhdp->bridge.dev); 745 - else 746 - drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp)); 747 - } 742 + if (bridge_attached) 743 + drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp)); 748 744 } 749 745 750 746 static int cdns_mhdp_load_firmware(struct cdns_mhdp_device *mhdp) ··· 778 782 if (!ret) 779 783 continue; 780 784 781 - dev_err(mhdp->dev, 785 + dev_dbg(mhdp->dev, 782 786 "Failed to write DPCD addr %u\n", 783 787 msg->address + i); 784 788 ··· 788 792 ret = cdns_mhdp_dpcd_read(mhdp, msg->address, 789 793 msg->buffer, msg->size); 790 794 if (ret) { 791 - dev_err(mhdp->dev, 795 + dev_dbg(mhdp->dev, 792 796 "Failed to read DPCD addr %u\n", 793 797 msg->address); 794 798 ··· 1440 1444 return drm_edid_read_custom(connector, cdns_mhdp_get_edid_block, mhdp); 1441 1445 } 1442 1446 1443 - static int cdns_mhdp_get_modes(struct drm_connector *connector) 1444 - { 1445 - struct cdns_mhdp_device *mhdp = connector_to_mhdp(connector); 1446 - const struct drm_edid *drm_edid; 1447 - int num_modes; 1448 - 1449 - if (!mhdp->plugged) 1450 - return 0; 1451 - 1452 - drm_edid = cdns_mhdp_edid_read(mhdp, connector); 1453 - 1454 - drm_edid_connector_update(connector, drm_edid); 1455 - 1456 - if (!drm_edid) { 1457 - dev_err(mhdp->dev, "Failed to read EDID\n"); 1458 - return 0; 1459 - } 1460 - 1461 - num_modes = drm_edid_connector_add_modes(connector); 1462 - drm_edid_free(drm_edid); 1463 - 1464 - /* 1465 - * HACK: Warn about unsupported display formats until we deal 1466 - * with them correctly. 1467 - */ 1468 - if (connector->display_info.color_formats && 1469 - !(connector->display_info.color_formats & 1470 - mhdp->display_fmt.color_format)) 1471 - dev_warn(mhdp->dev, 1472 - "%s: No supported color_format found (0x%08x)\n", 1473 - __func__, connector->display_info.color_formats); 1474 - 1475 - if (connector->display_info.bpc && 1476 - connector->display_info.bpc < mhdp->display_fmt.bpc) 1477 - dev_warn(mhdp->dev, "%s: Display bpc only %d < %d\n", 1478 - __func__, connector->display_info.bpc, 1479 - mhdp->display_fmt.bpc); 1480 - 1481 - return num_modes; 1482 - } 1483 - 1484 - static int cdns_mhdp_connector_detect(struct drm_connector *conn, 1485 - struct drm_modeset_acquire_ctx *ctx, 1486 - bool force) 1487 - { 1488 - struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn); 1489 - 1490 - return cdns_mhdp_detect(mhdp); 1491 - } 1492 - 1493 1447 static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_display_fmt *fmt) 1494 1448 { 1495 1449 u32 bpp; ··· 1493 1547 return true; 1494 1548 } 1495 1549 1496 - static 1497 - enum drm_mode_status cdns_mhdp_mode_valid(struct drm_connector *conn, 1498 - const struct drm_display_mode *mode) 1499 - { 1500 - struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn); 1501 - 1502 - mutex_lock(&mhdp->link_mutex); 1503 - 1504 - if (!cdns_mhdp_bandwidth_ok(mhdp, mode, mhdp->link.num_lanes, 1505 - mhdp->link.rate)) { 1506 - mutex_unlock(&mhdp->link_mutex); 1507 - return MODE_CLOCK_HIGH; 1508 - } 1509 - 1510 - mutex_unlock(&mhdp->link_mutex); 1511 - return MODE_OK; 1512 - } 1513 - 1514 - static int cdns_mhdp_connector_atomic_check(struct drm_connector *conn, 1515 - struct drm_atomic_state *state) 1516 - { 1517 - struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn); 1518 - struct drm_connector_state *old_state, *new_state; 1519 - struct drm_crtc_state *crtc_state; 1520 - u64 old_cp, new_cp; 1521 - 1522 - if (!mhdp->hdcp_supported) 1523 - return 0; 1524 - 1525 - old_state = drm_atomic_get_old_connector_state(state, conn); 1526 - new_state = drm_atomic_get_new_connector_state(state, conn); 1527 - old_cp = old_state->content_protection; 1528 - new_cp = new_state->content_protection; 1529 - 1530 - if (old_state->hdcp_content_type != new_state->hdcp_content_type && 1531 - new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { 1532 - new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; 1533 - goto mode_changed; 1534 - } 1535 - 1536 - if (!new_state->crtc) { 1537 - if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED) 1538 - new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; 1539 - return 0; 1540 - } 1541 - 1542 - if (old_cp == new_cp || 1543 - (old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED && 1544 - new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)) 1545 - return 0; 1546 - 1547 - mode_changed: 1548 - crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc); 1549 - crtc_state->mode_changed = true; 1550 - 1551 - return 0; 1552 - } 1553 - 1554 - static const struct drm_connector_helper_funcs cdns_mhdp_conn_helper_funcs = { 1555 - .detect_ctx = cdns_mhdp_connector_detect, 1556 - .get_modes = cdns_mhdp_get_modes, 1557 - .mode_valid = cdns_mhdp_mode_valid, 1558 - .atomic_check = cdns_mhdp_connector_atomic_check, 1559 - }; 1560 - 1561 - static const struct drm_connector_funcs cdns_mhdp_conn_funcs = { 1562 - .fill_modes = drm_helper_probe_single_connector_modes, 1563 - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 1564 - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 1565 - .reset = drm_atomic_helper_connector_reset, 1566 - .destroy = drm_connector_cleanup, 1567 - }; 1568 - 1569 - static int cdns_mhdp_connector_init(struct cdns_mhdp_device *mhdp) 1570 - { 1571 - u32 bus_format = MEDIA_BUS_FMT_RGB121212_1X36; 1572 - struct drm_connector *conn = &mhdp->connector; 1573 - struct drm_bridge *bridge = &mhdp->bridge; 1574 - int ret; 1575 - 1576 - conn->polled = DRM_CONNECTOR_POLL_HPD; 1577 - 1578 - ret = drm_connector_init(bridge->dev, conn, &cdns_mhdp_conn_funcs, 1579 - DRM_MODE_CONNECTOR_DisplayPort); 1580 - if (ret) { 1581 - dev_err(mhdp->dev, "Failed to initialize connector with drm\n"); 1582 - return ret; 1583 - } 1584 - 1585 - drm_connector_helper_add(conn, &cdns_mhdp_conn_helper_funcs); 1586 - 1587 - ret = drm_display_info_set_bus_formats(&conn->display_info, 1588 - &bus_format, 1); 1589 - if (ret) 1590 - return ret; 1591 - 1592 - ret = drm_connector_attach_encoder(conn, bridge->encoder); 1593 - if (ret) { 1594 - dev_err(mhdp->dev, "Failed to attach connector to encoder\n"); 1595 - return ret; 1596 - } 1597 - 1598 - if (mhdp->hdcp_supported) 1599 - ret = drm_connector_attach_content_protection_property(conn, true); 1600 - 1601 - return ret; 1602 - } 1603 - 1604 1550 static int cdns_mhdp_attach(struct drm_bridge *bridge, 1605 1551 struct drm_encoder *encoder, 1606 1552 enum drm_bridge_attach_flags flags) ··· 1509 1671 return ret; 1510 1672 1511 1673 if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { 1512 - ret = cdns_mhdp_connector_init(mhdp); 1513 - if (ret) 1514 - goto aux_unregister; 1674 + ret = -EINVAL; 1675 + dev_err(mhdp->dev, 1676 + "Connector initialisation not supported in bridge_attach %d\n", 1677 + ret); 1678 + goto aux_unregister; 1515 1679 } 1516 1680 1517 1681 spin_lock(&mhdp->start_lock); ··· 1755 1915 struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); 1756 1916 struct cdns_mhdp_bridge_state *mhdp_state; 1757 1917 struct drm_crtc_state *crtc_state; 1758 - struct drm_connector *connector; 1759 1918 struct drm_connector_state *conn_state; 1760 1919 struct drm_bridge_state *new_state; 1761 1920 const struct drm_display_mode *mode; 1762 1921 u32 resp; 1763 - int ret; 1922 + int ret = 0; 1764 1923 1765 1924 dev_dbg(mhdp->dev, "bridge enable\n"); 1766 1925 1767 1926 mutex_lock(&mhdp->link_mutex); 1927 + 1928 + mhdp->connector = drm_atomic_get_new_connector_for_encoder(state, 1929 + bridge->encoder); 1930 + if (WARN_ON(!mhdp->connector)) 1931 + goto out; 1932 + 1933 + conn_state = drm_atomic_get_new_connector_state(state, mhdp->connector); 1934 + if (WARN_ON(!conn_state)) 1935 + goto out; 1768 1936 1769 1937 if (mhdp->plugged && !mhdp->link_up) { 1770 1938 ret = cdns_mhdp_link_up(mhdp); ··· 1792 1944 1793 1945 cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR, 1794 1946 resp | CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN); 1795 - 1796 - connector = drm_atomic_get_new_connector_for_encoder(state, 1797 - bridge->encoder); 1798 - if (WARN_ON(!connector)) 1799 - goto out; 1800 - 1801 - conn_state = drm_atomic_get_new_connector_state(state, connector); 1802 - if (WARN_ON(!conn_state)) 1803 - goto out; 1804 1947 1805 1948 if (mhdp->hdcp_supported && 1806 1949 mhdp->hw_state == MHDP_HW_READY && ··· 1869 2030 if (mhdp->info && mhdp->info->ops && mhdp->info->ops->disable) 1870 2031 mhdp->info->ops->disable(mhdp); 1871 2032 2033 + mhdp->connector = NULL; 1872 2034 mutex_unlock(&mhdp->link_mutex); 1873 2035 } 1874 2036 ··· 1962 2122 { 1963 2123 struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); 1964 2124 const struct drm_display_mode *mode = &crtc_state->adjusted_mode; 2125 + struct drm_connector_state *old_state, *new_state; 2126 + struct drm_atomic_state *state = crtc_state->state; 2127 + struct drm_connector *conn = mhdp->connector; 2128 + u64 old_cp, new_cp; 1965 2129 1966 2130 mutex_lock(&mhdp->link_mutex); 1967 2131 ··· 1984 2140 */ 1985 2141 if (mhdp->info) 1986 2142 bridge_state->input_bus_cfg.flags = *mhdp->info->input_bus_flags; 2143 + 2144 + if (conn && mhdp->hdcp_supported) { 2145 + old_state = drm_atomic_get_old_connector_state(state, conn); 2146 + new_state = drm_atomic_get_new_connector_state(state, conn); 2147 + old_cp = old_state->content_protection; 2148 + new_cp = new_state->content_protection; 2149 + 2150 + if (old_state->hdcp_content_type != new_state->hdcp_content_type && 2151 + new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { 2152 + new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; 2153 + crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc); 2154 + crtc_state->mode_changed = true; 2155 + } 2156 + 2157 + if (!new_state->crtc) { 2158 + if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED) 2159 + new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; 2160 + } 2161 + } 1987 2162 1988 2163 mutex_unlock(&mhdp->link_mutex); 1989 2164 return 0; ··· 2024 2161 return cdns_mhdp_edid_read(mhdp, connector); 2025 2162 } 2026 2163 2164 + static enum drm_mode_status 2165 + cdns_mhdp_bridge_mode_valid(struct drm_bridge *bridge, 2166 + const struct drm_display_info *info, 2167 + const struct drm_display_mode *mode) 2168 + { 2169 + struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); 2170 + 2171 + mutex_lock(&mhdp->link_mutex); 2172 + 2173 + if (!cdns_mhdp_bandwidth_ok(mhdp, mode, mhdp->link.num_lanes, 2174 + mhdp->link.rate)) { 2175 + mutex_unlock(&mhdp->link_mutex); 2176 + return MODE_CLOCK_HIGH; 2177 + } 2178 + 2179 + mutex_unlock(&mhdp->link_mutex); 2180 + return MODE_OK; 2181 + } 2182 + 2027 2183 static const struct drm_bridge_funcs cdns_mhdp_bridge_funcs = { 2028 2184 .atomic_enable = cdns_mhdp_atomic_enable, 2029 2185 .atomic_disable = cdns_mhdp_atomic_disable, ··· 2057 2175 .edid_read = cdns_mhdp_bridge_edid_read, 2058 2176 .hpd_enable = cdns_mhdp_bridge_hpd_enable, 2059 2177 .hpd_disable = cdns_mhdp_bridge_hpd_disable, 2178 + .mode_valid = cdns_mhdp_bridge_mode_valid, 2060 2179 }; 2061 2180 2062 2181 static bool cdns_mhdp_detect_hpd(struct cdns_mhdp_device *mhdp, bool *hpd_pulse) ··· 2179 2296 2180 2297 mhdp = container_of(work, typeof(*mhdp), modeset_retry_work); 2181 2298 2182 - conn = &mhdp->connector; 2299 + conn = mhdp->connector; 2183 2300 2184 2301 /* Grab the locks before changing connector property */ 2185 2302 mutex_lock(&conn->dev->mode_config.mutex); ··· 2253 2370 struct cdns_mhdp_device *mhdp = container_of(work, 2254 2371 struct cdns_mhdp_device, 2255 2372 hpd_work); 2256 - int ret; 2373 + cdns_mhdp_update_link_status(mhdp); 2257 2374 2258 - ret = cdns_mhdp_update_link_status(mhdp); 2259 - if (mhdp->connector.dev) { 2260 - if (ret < 0) 2261 - schedule_work(&mhdp->modeset_retry_work); 2262 - else 2263 - drm_kms_helper_hotplug_event(mhdp->bridge.dev); 2264 - } else { 2265 - drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp)); 2266 - } 2375 + drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp)); 2267 2376 } 2268 2377 2269 2378 static int cdns_mhdp_probe(struct platform_device *pdev)
+1 -1
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
··· 375 375 */ 376 376 struct mutex link_mutex; 377 377 378 - struct drm_connector connector; 378 + struct drm_connector *connector; 379 379 struct drm_bridge bridge; 380 380 381 381 struct cdns_mhdp_link link;
+14 -4
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c
··· 394 394 int ret; 395 395 396 396 dev_dbg(mhdp->dev, "[%s:%d] HDCP is being disabled...\n", 397 - mhdp->connector.name, mhdp->connector.base.id); 397 + mhdp->connector->name, mhdp->connector->base.id); 398 398 399 399 ret = cdns_mhdp_hdcp_set_config(mhdp, 0, false); 400 400 ··· 436 436 int ret = 0; 437 437 438 438 mutex_lock(&mhdp->hdcp.mutex); 439 + 440 + if (!mhdp->connector) 441 + goto out; 442 + 439 443 if (mhdp->hdcp.value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED) 440 444 goto out; 441 445 ··· 449 445 450 446 dev_err(mhdp->dev, 451 447 "[%s:%d] HDCP link failed, retrying authentication\n", 452 - mhdp->connector.name, mhdp->connector.base.id); 448 + mhdp->connector->name, mhdp->connector->base.id); 453 449 454 450 ret = _cdns_mhdp_hdcp_disable(mhdp); 455 451 if (ret) { ··· 491 487 struct cdns_mhdp_device *mhdp = container_of(hdcp, 492 488 struct cdns_mhdp_device, 493 489 hdcp); 494 - struct drm_device *dev = mhdp->connector.dev; 490 + struct drm_device *dev = NULL; 495 491 struct drm_connector_state *state; 492 + 493 + if (mhdp->connector) 494 + dev = mhdp->connector->dev; 495 + 496 + if (!dev) 497 + return; 496 498 497 499 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); 498 500 mutex_lock(&mhdp->hdcp.mutex); 499 501 if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { 500 - state = mhdp->connector.state; 502 + state = mhdp->connector->state; 501 503 state->content_protection = mhdp->hdcp.value; 502 504 } 503 505 mutex_unlock(&mhdp->hdcp.mutex);
+51 -28
drivers/gpu/drm/drm_gem_shmem_helper.c
··· 265 265 shmem->pages_mark_dirty_on_put, 266 266 shmem->pages_mark_accessed_on_put); 267 267 shmem->pages = NULL; 268 + shmem->pages_mark_accessed_on_put = false; 269 + shmem->pages_mark_dirty_on_put = false; 268 270 } 269 271 } 270 272 EXPORT_SYMBOL_GPL(drm_gem_shmem_put_pages_locked); ··· 399 397 } else { 400 398 iosys_map_set_vaddr(map, shmem->vaddr); 401 399 refcount_set(&shmem->vmap_use_count, 1); 400 + shmem->pages_mark_accessed_on_put = true; 401 + shmem->pages_mark_dirty_on_put = true; 402 402 } 403 403 } 404 404 ··· 554 550 } 555 551 EXPORT_SYMBOL_GPL(drm_gem_shmem_dumb_create); 556 552 557 - static bool drm_gem_shmem_try_map_pmd(struct vm_fault *vmf, unsigned long addr, 558 - struct page *page) 553 + static vm_fault_t drm_gem_shmem_try_insert_pfn_pmd(struct vm_fault *vmf, unsigned long pfn) 559 554 { 560 555 #ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP 561 - unsigned long pfn = page_to_pfn(page); 562 556 unsigned long paddr = pfn << PAGE_SHIFT; 563 - bool aligned = (addr & ~PMD_MASK) == (paddr & ~PMD_MASK); 557 + bool aligned = (vmf->address & ~PMD_MASK) == (paddr & ~PMD_MASK); 564 558 565 - if (aligned && 566 - pmd_none(*vmf->pmd) && 567 - folio_test_pmd_mappable(page_folio(page))) { 559 + if (aligned && pmd_none(*vmf->pmd)) { 560 + /* Read-only mapping; split upon write fault */ 568 561 pfn &= PMD_MASK >> PAGE_SHIFT; 569 - if (vmf_insert_pfn_pmd(vmf, pfn, false) == VM_FAULT_NOPAGE) 570 - return true; 562 + return vmf_insert_pfn_pmd(vmf, pfn, false); 571 563 } 572 564 #endif 573 565 574 - return false; 566 + return 0; 575 567 } 576 568 577 569 static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf) 578 570 { 579 571 struct vm_area_struct *vma = vmf->vma; 580 572 struct drm_gem_object *obj = vma->vm_private_data; 573 + struct drm_device *dev = obj->dev; 581 574 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); 582 575 loff_t num_pages = obj->size >> PAGE_SHIFT; 583 - vm_fault_t ret; 576 + vm_fault_t ret = VM_FAULT_SIGBUS; 584 577 struct page **pages = shmem->pages; 585 - pgoff_t page_offset; 578 + pgoff_t page_offset = vmf->pgoff - vma->vm_pgoff; /* page offset within VMA */ 579 + struct page *page; 580 + struct folio *folio; 586 581 unsigned long pfn; 587 582 588 - /* Offset to faulty address in the VMA. */ 589 - page_offset = vmf->pgoff - vma->vm_pgoff; 583 + dma_resv_lock(obj->resv, NULL); 590 584 591 - dma_resv_lock(shmem->base.resv, NULL); 592 - 593 - if (page_offset >= num_pages || 594 - drm_WARN_ON_ONCE(obj->dev, !shmem->pages) || 595 - shmem->madv < 0) { 596 - ret = VM_FAULT_SIGBUS; 585 + if (page_offset >= num_pages || drm_WARN_ON_ONCE(dev, !shmem->pages) || 586 + shmem->madv < 0) 597 587 goto out; 598 - } 599 588 600 - if (drm_gem_shmem_try_map_pmd(vmf, vmf->address, pages[page_offset])) { 601 - ret = VM_FAULT_NOPAGE; 589 + page = pages[page_offset]; 590 + if (drm_WARN_ON_ONCE(dev, !page)) 602 591 goto out; 603 - } 592 + folio = page_folio(page); 604 593 605 - pfn = page_to_pfn(pages[page_offset]); 606 - ret = vmf_insert_pfn(vma, vmf->address, pfn); 594 + pfn = page_to_pfn(page); 607 595 608 - out: 609 - dma_resv_unlock(shmem->base.resv); 596 + if (folio_test_pmd_mappable(folio)) 597 + ret = drm_gem_shmem_try_insert_pfn_pmd(vmf, pfn); 598 + if (ret != VM_FAULT_NOPAGE) 599 + ret = vmf_insert_pfn(vma, vmf->address, pfn); 600 + 601 + if (ret == VM_FAULT_NOPAGE) 602 + folio_mark_accessed(folio); 603 + 604 + out: 605 + dma_resv_unlock(obj->resv); 610 606 611 607 return ret; 612 608 } ··· 645 641 drm_gem_vm_close(vma); 646 642 } 647 643 644 + static vm_fault_t drm_gem_shmem_pfn_mkwrite(struct vm_fault *vmf) 645 + { 646 + struct vm_area_struct *vma = vmf->vma; 647 + struct drm_gem_object *obj = vma->vm_private_data; 648 + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); 649 + loff_t num_pages = obj->size >> PAGE_SHIFT; 650 + pgoff_t page_offset = vmf->pgoff - vma->vm_pgoff; /* page offset within VMA */ 651 + 652 + if (drm_WARN_ON(obj->dev, !shmem->pages || page_offset >= num_pages)) 653 + return VM_FAULT_SIGBUS; 654 + 655 + file_update_time(vma->vm_file); 656 + 657 + folio_mark_dirty(page_folio(shmem->pages[page_offset])); 658 + 659 + return 0; 660 + } 661 + 648 662 const struct vm_operations_struct drm_gem_shmem_vm_ops = { 649 663 .fault = drm_gem_shmem_fault, 650 664 .open = drm_gem_shmem_vm_open, 651 665 .close = drm_gem_shmem_vm_close, 666 + .pfn_mkwrite = drm_gem_shmem_pfn_mkwrite, 652 667 }; 653 668 EXPORT_SYMBOL_GPL(drm_gem_shmem_vm_ops); 654 669
+4 -2
drivers/gpu/drm/imagination/pvr_gem.c
··· 25 25 26 26 static void pvr_gem_object_free(struct drm_gem_object *obj) 27 27 { 28 - drm_gem_shmem_object_free(obj); 28 + struct drm_gem_shmem_object *shmem_obj = to_drm_gem_shmem_obj(obj); 29 + 30 + shmem_obj->pages_mark_dirty_on_put = true; 31 + drm_gem_shmem_free(shmem_obj); 29 32 } 30 33 31 34 static struct dma_buf *pvr_gem_export(struct drm_gem_object *obj, int flags) ··· 366 363 if (IS_ERR(shmem_obj)) 367 364 return ERR_CAST(shmem_obj); 368 365 369 - shmem_obj->pages_mark_dirty_on_put = true; 370 366 shmem_obj->map_wc = !(flags & PVR_BO_CPU_CACHED); 371 367 pvr_obj = shmem_gem_to_pvr_gem(shmem_obj); 372 368 pvr_obj->flags = flags;
+2 -1
drivers/gpu/drm/loongson/lsdc_drv.c
··· 13 13 #include <drm/drm_drv.h> 14 14 #include <drm/drm_fbdev_ttm.h> 15 15 #include <drm/drm_gem_framebuffer_helper.h> 16 + #include <drm/drm_gem_ttm_helper.h> 16 17 #include <drm/drm_ioctl.h> 17 18 #include <drm/drm_modeset_helper.h> 18 19 #include <drm/drm_print.h> ··· 46 45 47 46 .debugfs_init = lsdc_debugfs_init, 48 47 .dumb_create = lsdc_dumb_create, 49 - .dumb_map_offset = lsdc_dumb_map_offset, 48 + .dumb_map_offset = drm_gem_ttm_dumb_map_offset, 50 49 .gem_prime_import_sg_table = lsdc_prime_import_sg_table, 51 50 DRM_FBDEV_TTM_DRIVER_OPS, 52 51 };
-15
drivers/gpu/drm/loongson/lsdc_gem.c
··· 234 234 return 0; 235 235 } 236 236 237 - int lsdc_dumb_map_offset(struct drm_file *filp, struct drm_device *ddev, 238 - u32 handle, uint64_t *offset) 239 - { 240 - struct drm_gem_object *gobj; 241 - 242 - gobj = drm_gem_object_lookup(filp, handle); 243 - if (!gobj) 244 - return -ENOENT; 245 - 246 - *offset = drm_vma_node_offset_addr(&gobj->vma_node); 247 - 248 - drm_gem_object_put(gobj); 249 - 250 - return 0; 251 - } 252 237 253 238 void lsdc_gem_init(struct drm_device *ddev) 254 239 {
-4
drivers/gpu/drm/loongson/lsdc_gem.h
··· 14 14 struct dma_buf_attachment *attach, 15 15 struct sg_table *sg); 16 16 17 - int lsdc_dumb_map_offset(struct drm_file *file, 18 - struct drm_device *dev, 19 - u32 handle, 20 - uint64_t *offset); 21 17 22 18 int lsdc_dumb_create(struct drm_file *file, 23 19 struct drm_device *ddev,
+5 -3
drivers/gpu/drm/mxsfb/lcdif_drv.c
··· 149 149 150 150 lcdif->clk = devm_clk_get(drm->dev, "pix"); 151 151 if (IS_ERR(lcdif->clk)) 152 - return PTR_ERR(lcdif->clk); 152 + return dev_err_probe(drm->dev, PTR_ERR(lcdif->clk), "Failed to get pix clock\n"); 153 153 154 154 lcdif->clk_axi = devm_clk_get(drm->dev, "axi"); 155 155 if (IS_ERR(lcdif->clk_axi)) 156 - return PTR_ERR(lcdif->clk_axi); 156 + return dev_err_probe(drm->dev, PTR_ERR(lcdif->clk_axi), 157 + "Failed to get axi clock\n"); 157 158 158 159 lcdif->clk_disp_axi = devm_clk_get(drm->dev, "disp_axi"); 159 160 if (IS_ERR(lcdif->clk_disp_axi)) 160 - return PTR_ERR(lcdif->clk_disp_axi); 161 + return dev_err_probe(drm->dev, PTR_ERR(lcdif->clk_disp_axi), 162 + "Failed to get disp_axi clock\n"); 161 163 162 164 platform_set_drvdata(pdev, drm); 163 165
+32
drivers/gpu/drm/panel/Kconfig
··· 443 443 pixel. It provides a MIPI DSI interface to the host and has a 444 444 built-in LED backlight. 445 445 446 + config DRM_PANEL_LXD_M9189A 447 + tristate "LXD M9189A MIPI-DSI LCD panel" 448 + depends on OF 449 + depends on DRM_MIPI_DSI 450 + depends on BACKLIGHT_CLASS_DEVICE 451 + help 452 + Say Y if you want to enable support for the LXD M9189A 4-Lane 453 + 1024x600 MIPI DSI panel. 454 + 446 455 config DRM_PANEL_MAGNACHIP_D53E6EA8966 447 456 tristate "Magnachip D53E6EA8966 DSI panel" 448 457 depends on OF && SPI ··· 473 464 MLAF057WE51-X MIPI DSI panel as e.g. used in the Librem 5. It 474 465 has a resolution of 720x1440 pixels, a built in backlight and touch 475 466 controller. 467 + 468 + config DRM_PANEL_MOTOROLA_MOT 469 + tristate "Atrix 4G and Droid X2 540x960 DSI video mode panel" 470 + depends on OF 471 + depends on DRM_MIPI_DSI 472 + depends on BACKLIGHT_CLASS_DEVICE 473 + select VIDEOMODE_HELPERS 474 + help 475 + Say Y here if you want to enable support for the LCD panel module 476 + for Motorola Atrix 4G or Droid X2. Exact panel vendor and model are 477 + unknown. The panel has a 540x960 resolution and uses 24 bit RGB per 478 + pixel. 476 479 477 480 config DRM_PANEL_NEC_NL8048HL11 478 481 tristate "NEC NL8048HL11 RGB panel" ··· 574 553 Say Y here if you want to enable support for Novatek NT36672E DSI Video Mode 575 554 LCD panel module. The panel has a resolution of 1080x2408 and uses 24 bit 576 555 RGB per pixel. 556 + 557 + config DRM_PANEL_NOVATEK_NT37700F 558 + tristate "Novatek NT37700F DSI panel" 559 + depends on OF 560 + depends on DRM_MIPI_DSI 561 + depends on BACKLIGHT_CLASS_DEVICE 562 + help 563 + Say Y here if you want to enable support for Novatek NT37700F DSI 564 + panel module. The panel has a resolution of 1080x2160. 577 565 578 566 config DRM_PANEL_NOVATEK_NT37801 579 567 tristate "Novatek NT37801/NT37810 AMOLED DSI panel" ··· 719 689 depends on OF 720 690 depends on DRM_MIPI_DSI 721 691 depends on BACKLIGHT_CLASS_DEVICE 692 + select VIDEOMODE_HELPERS 722 693 help 723 694 Say Y here if you want to enable support for KOE tx13d100vm0eaa 724 695 IPS-LCD module with Renesas R69328 IC. The panel has a 1024x768 ··· 733 702 depends on OF 734 703 depends on DRM_MIPI_DSI 735 704 depends on BACKLIGHT_CLASS_DEVICE 705 + select VIDEOMODE_HELPERS 736 706 help 737 707 Say Y here if you want to enable support for JDI dx12d100vm0eaa 738 708 IPS-LCD module with Renesas R69328 IC. The panel has a 720x1280
+3
drivers/gpu/drm/panel/Makefile
··· 44 44 obj-$(CONFIG_DRM_PANEL_LG_LD070WX3) += panel-lg-ld070wx3.o 45 45 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o 46 46 obj-$(CONFIG_DRM_PANEL_LG_SW43408) += panel-lg-sw43408.o 47 + obj-$(CONFIG_DRM_PANEL_LXD_M9189A) += panel-lxd-m9189a.o 47 48 obj-$(CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966) += panel-magnachip-d53e6ea8966.o 49 + obj-$(CONFIG_DRM_PANEL_MOTOROLA_MOT) += panel-motorola-mot.o 48 50 obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o 49 51 obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3051D) += panel-newvision-nv3051d.o 50 52 obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3052C) += panel-newvision-nv3052c.o ··· 56 54 obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36523) += panel-novatek-nt36523.o 57 55 obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672A) += panel-novatek-nt36672a.o 58 56 obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672E) += panel-novatek-nt36672e.o 57 + obj-$(CONFIG_DRM_PANEL_NOVATEK_NT37700F) += panel-novatek-nt37700f.o 59 58 obj-$(CONFIG_DRM_PANEL_NOVATEK_NT37801) += panel-novatek-nt37801.o 60 59 obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o 61 60 obj-$(CONFIG_DRM_PANEL_MANTIX_MLAF057WE51) += panel-mantix-mlaf057we51.o
+7 -7
drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
··· 592 592 { 593 593 struct ili9882t *ili = to_ili9882t(panel); 594 594 595 - gpiod_set_value(ili->enable_gpio, 0); 595 + gpiod_set_value_cansleep(ili->enable_gpio, 0); 596 596 usleep_range(1000, 2000); 597 597 regulator_disable(ili->avee); 598 598 regulator_disable(ili->avdd); ··· 608 608 struct ili9882t *ili = to_ili9882t(panel); 609 609 int ret; 610 610 611 - gpiod_set_value(ili->enable_gpio, 0); 611 + gpiod_set_value_cansleep(ili->enable_gpio, 0); 612 612 usleep_range(1000, 1500); 613 613 614 614 ret = regulator_enable(ili->pp3300); ··· 638 638 } 639 639 usleep_range(1000, 2000); 640 640 641 - gpiod_set_value(ili->enable_gpio, 1); 641 + gpiod_set_value_cansleep(ili->enable_gpio, 1); 642 642 usleep_range(1000, 2000); 643 - gpiod_set_value(ili->enable_gpio, 0); 643 + gpiod_set_value_cansleep(ili->enable_gpio, 0); 644 644 msleep(50); 645 - gpiod_set_value(ili->enable_gpio, 1); 645 + gpiod_set_value_cansleep(ili->enable_gpio, 1); 646 646 usleep_range(6000, 10000); 647 647 648 648 ret = ili->desc->init(ili); ··· 652 652 return 0; 653 653 654 654 poweroff: 655 - gpiod_set_value(ili->enable_gpio, 0); 655 + gpiod_set_value_cansleep(ili->enable_gpio, 0); 656 656 regulator_disable(ili->avee); 657 657 poweroffavdd: 658 658 regulator_disable(ili->avdd); ··· 793 793 return PTR_ERR(ili->enable_gpio); 794 794 } 795 795 796 - gpiod_set_value(ili->enable_gpio, 0); 796 + gpiod_set_value_cansleep(ili->enable_gpio, 0); 797 797 798 798 err = of_drm_get_panel_orientation(dev->of_node, &ili->orientation); 799 799 if (err < 0) {
+244
drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
··· 1366 1366 MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM, 1367 1367 }; 1368 1368 1369 + static int taiguan_xti05101_01a_init_cmds(struct jadard *jadard) 1370 + { 1371 + struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi }; 1372 + 1373 + jd9365da_switch_page(&dsi_ctx, 0x00); 1374 + jadard_enable_standard_cmds(&dsi_ctx); 1375 + 1376 + jd9365da_switch_page(&dsi_ctx, 0x01); 1377 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x74); 1378 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00); 1379 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xd7); 1380 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x01); 1381 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00); 1382 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xd7); 1383 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x01); 1384 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xfe); 1385 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x19); 1386 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x28); 1387 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x05); 1388 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x08); 1389 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x12); 1390 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x78); 1391 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff); 1392 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff); 1393 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x7f); 1394 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x06); 1395 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0xa0); 1396 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1e); 1397 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0b); 1398 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02); 1399 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x6a); 1400 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a); 1401 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x2e); 1402 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x1a); 1403 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x15); 1404 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x7f); 1405 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x58); 1406 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x46); 1407 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x39); 1408 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x35); 1409 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x27); 1410 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x2b); 1411 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x16); 1412 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x30); 1413 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x2e); 1414 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x2f); 1415 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x4d); 1416 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x3c); 1417 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x43); 1418 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x36); 1419 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x31); 1420 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x24); 1421 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x14); 1422 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x02); 1423 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x7f); 1424 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x58); 1425 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x46); 1426 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x39); 1427 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x35); 1428 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x27); 1429 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x2b); 1430 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x16); 1431 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x30); 1432 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x2e); 1433 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x2f); 1434 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x4d); 1435 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x3c); 1436 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x43); 1437 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x36); 1438 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x31); 1439 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x24); 1440 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x14); 1441 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x02); 1442 + 1443 + jd9365da_switch_page(&dsi_ctx, 0x02); 1444 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x52); 1445 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x5f); 1446 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x5f); 1447 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x50); 1448 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x77); 1449 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x57); 1450 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x5f); 1451 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x4e); 1452 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x4c); 1453 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x5f); 1454 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x4a); 1455 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x48); 1456 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x5f); 1457 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x46); 1458 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x44); 1459 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x40); 1460 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x5f); 1461 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x5f); 1462 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x5f); 1463 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x5f); 1464 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x5f); 1465 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x5f); 1466 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x53); 1467 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x5f); 1468 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x5f); 1469 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x51); 1470 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x77); 1471 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x57); 1472 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x5f); 1473 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x4f); 1474 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x4d); 1475 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x5f); 1476 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x4b); 1477 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x49); 1478 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x5f); 1479 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x47); 1480 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x45); 1481 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x41); 1482 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x5f); 1483 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x5f); 1484 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x5f); 1485 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x5f); 1486 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x5f); 1487 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x5f); 1488 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2c, 0x13); 1489 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2d, 0x1f); 1490 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2e, 0x1f); 1491 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x01); 1492 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x30, 0x17); 1493 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x31, 0x17); 1494 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0x1f); 1495 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x0d); 1496 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x0f); 1497 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x1f); 1498 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x05); 1499 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x07); 1500 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x1f); 1501 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x09); 1502 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x0b); 1503 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x11); 1504 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x1f); 1505 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0x1f); 1506 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0x1f); 1507 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x1f); 1508 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x1f); 1509 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x1f); 1510 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x12); 1511 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1f); 1512 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x1f); 1513 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x00); 1514 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x46, 0x17); 1515 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x47, 0x17); 1516 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0x1f); 1517 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0x0c); 1518 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4a, 0x0e); 1519 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x1f); 1520 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4c, 0x04); 1521 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4d, 0x06); 1522 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4e, 0x1f); 1523 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4f, 0x08); 1524 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x50, 0x0a); 1525 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x10); 1526 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x1f); 1527 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x1f); 1528 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x54, 0x1f); 1529 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x1f); 1530 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x1f); 1531 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x1f); 1532 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40); 1533 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x10); 1534 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x06); 1535 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x40); 1536 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x00); 1537 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x00); 1538 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x40); 1539 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x03); 1540 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x04); 1541 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x6c); 1542 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x6c); 1543 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x75); 1544 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x08); 1545 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0xb4); 1546 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x08); 1547 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x6c); 1548 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x6c); 1549 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x0c); 1550 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x00); 1551 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x00); 1552 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x88); 1553 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xbb); 1554 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00); 1555 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x05); 1556 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x2a); 1557 + 1558 + jd9365da_switch_page(&dsi_ctx, 0x04); 1559 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x0e); 1560 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0xb3); 1561 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x61); 1562 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x48); 1563 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x0f); 1564 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x58); 1565 + 1566 + jd9365da_switch_page(&dsi_ctx, 0x00); 1567 + 1568 + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); 1569 + 1570 + mipi_dsi_msleep(&dsi_ctx, 120); 1571 + 1572 + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); 1573 + 1574 + mipi_dsi_msleep(&dsi_ctx, 20); 1575 + 1576 + return dsi_ctx.accum_err; 1577 + }; 1578 + 1579 + static const struct jadard_panel_desc taiguan_xti05101_01a_desc = { 1580 + .mode = { 1581 + .clock = (800 + 24 + 24 + 24) * (1280 + 30 + 4 + 8) * 60 / 1000, 1582 + 1583 + .hdisplay = 800, 1584 + .hsync_start = 800 + 24, 1585 + .hsync_end = 800 + 24 + 24, 1586 + .htotal = 800 + 24 + 24 + 24, 1587 + 1588 + .vdisplay = 1280, 1589 + .vsync_start = 1280 + 30, 1590 + .vsync_end = 1280 + 30 + 4, 1591 + .vtotal = 1280 + 30 + 4 + 8, 1592 + 1593 + .width_mm = 135, 1594 + .height_mm = 216, 1595 + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 1596 + }, 1597 + .lanes = 4, 1598 + .format = MIPI_DSI_FMT_RGB888, 1599 + .init = taiguan_xti05101_01a_init_cmds, 1600 + .lp11_before_reset = true, 1601 + .reset_before_power_off_vcioo = true, 1602 + .vcioo_to_lp11_delay_ms = 5, 1603 + .lp11_to_reset_delay_ms = 10, 1604 + .backlight_off_to_display_off_delay_ms = 3, 1605 + .display_off_to_enter_sleep_delay_ms = 50, 1606 + .enter_sleep_to_reset_down_delay_ms = 100, 1607 + }; 1608 + 1369 1609 static int jadard_dsi_probe(struct mipi_dsi_device *dsi) 1370 1610 { 1371 1611 struct device *dev = &dsi->dev; ··· 1702 1462 { 1703 1463 .compatible = "radxa,display-8hd-ad002", 1704 1464 .data = &radxa_display_8hd_ad002_desc 1465 + }, 1466 + { 1467 + .compatible = "taiguanck,xti05101-01a", 1468 + .data = &taiguan_xti05101_01a_desc 1705 1469 }, 1706 1470 { /* sentinel */ } 1707 1471 };
+243
drivers/gpu/drm/panel/panel-lxd-m9189a.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree. 4 + * Copyright (c) 2024 Luca Weiss <luca.weiss@fairphone.com> 5 + */ 6 + 7 + #include <linux/delay.h> 8 + #include <linux/gpio/consumer.h> 9 + #include <linux/module.h> 10 + #include <linux/of.h> 11 + #include <linux/regulator/consumer.h> 12 + #include <linux/types.h> 13 + 14 + #include <drm/drm_mipi_dsi.h> 15 + #include <drm/drm_modes.h> 16 + #include <drm/drm_panel.h> 17 + #include <drm/drm_probe_helper.h> 18 + 19 + /* Manufacturer specific DSI commands */ 20 + #define EK79007AD3_GAMMA1 0x80 21 + #define EK79007AD3_GAMMA2 0x81 22 + #define EK79007AD3_GAMMA3 0x82 23 + #define EK79007AD3_GAMMA4 0x83 24 + #define EK79007AD3_GAMMA5 0x84 25 + #define EK79007AD3_GAMMA6 0x85 26 + #define EK79007AD3_GAMMA7 0x86 27 + #define EK79007AD3_PANEL_CTRL3 0xB2 28 + 29 + struct m9189_panel { 30 + struct drm_panel panel; 31 + struct mipi_dsi_device *dsi; 32 + struct regulator *supply; 33 + struct gpio_desc *reset_gpio; 34 + struct gpio_desc *standby_gpio; 35 + }; 36 + 37 + static inline struct m9189_panel *to_m9189_panel(struct drm_panel *panel) 38 + { 39 + return container_of(panel, struct m9189_panel, panel); 40 + } 41 + 42 + static void m9189_reset(struct m9189_panel *m9189) 43 + { 44 + gpiod_set_value_cansleep(m9189->reset_gpio, 0); 45 + msleep(20); 46 + gpiod_set_value_cansleep(m9189->reset_gpio, 1); 47 + msleep(30); 48 + gpiod_set_value_cansleep(m9189->reset_gpio, 0); 49 + msleep(55); 50 + } 51 + 52 + static int m9189_on(struct m9189_panel *m9189) 53 + { 54 + struct mipi_dsi_multi_context ctx = { .dsi = m9189->dsi }; 55 + 56 + ctx.dsi->mode_flags |= MIPI_DSI_MODE_LPM; 57 + 58 + /* Gamma 2.2 */ 59 + mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA1, 0x48); 60 + mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA2, 0xB8); 61 + mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA3, 0x88); 62 + mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA4, 0x88); 63 + mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA5, 0x58); 64 + mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA6, 0xD2); 65 + mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA7, 0x88); 66 + mipi_dsi_msleep(&ctx, 50); 67 + 68 + /* 4 Lanes */ 69 + mipi_dsi_generic_write_multi(&ctx, (u8[]){ EK79007AD3_PANEL_CTRL3, 0x70 }, 2); 70 + 71 + mipi_dsi_dcs_exit_sleep_mode_multi(&ctx); 72 + mipi_dsi_msleep(&ctx, 120); 73 + 74 + mipi_dsi_dcs_set_display_on_multi(&ctx); 75 + mipi_dsi_msleep(&ctx, 120); 76 + 77 + return ctx.accum_err; 78 + } 79 + 80 + static int m9189_disable(struct drm_panel *panel) 81 + { 82 + struct m9189_panel *m9189 = to_m9189_panel(panel); 83 + struct mipi_dsi_multi_context ctx = { .dsi = m9189->dsi }; 84 + 85 + ctx.dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 86 + 87 + mipi_dsi_dcs_enter_sleep_mode_multi(&ctx); 88 + mipi_dsi_msleep(&ctx, 120); 89 + 90 + gpiod_set_value_cansleep(m9189->standby_gpio, 1); 91 + 92 + return ctx.accum_err; 93 + } 94 + 95 + static int m9189_prepare(struct drm_panel *panel) 96 + { 97 + struct m9189_panel *m9189 = to_m9189_panel(panel); 98 + struct device *dev = &m9189->dsi->dev; 99 + int ret; 100 + 101 + ret = regulator_enable(m9189->supply); 102 + if (ret < 0) { 103 + dev_err(dev, "Failed to enable regulators: %d\n", ret); 104 + return ret; 105 + } 106 + 107 + gpiod_set_value_cansleep(m9189->standby_gpio, 0); 108 + msleep(20); 109 + m9189_reset(m9189); 110 + 111 + ret = m9189_on(m9189); 112 + if (ret < 0) { 113 + dev_err(dev, "Failed to initialize panel: %d\n", ret); 114 + gpiod_set_value_cansleep(m9189->reset_gpio, 1); 115 + regulator_disable(m9189->supply); 116 + return ret; 117 + } 118 + 119 + return 0; 120 + } 121 + 122 + static int m9189_unprepare(struct drm_panel *panel) 123 + { 124 + struct m9189_panel *m9189 = to_m9189_panel(panel); 125 + 126 + gpiod_set_value_cansleep(m9189->standby_gpio, 1); 127 + msleep(50); 128 + 129 + gpiod_set_value_cansleep(m9189->reset_gpio, 1); 130 + regulator_disable(m9189->supply); 131 + 132 + return 0; 133 + } 134 + 135 + static const struct drm_display_mode m9189_mode = { 136 + .clock = (1024 + 160 + 160 + 10) * (600 + 12 + 23 + 1) * 60 / 1000, 137 + .hdisplay = 1024, 138 + .hsync_start = 1024 + 160, 139 + .hsync_end = 1024 + 160 + 160, 140 + .htotal = 1024 + 160 + 160 + 10, 141 + .vdisplay = 600, 142 + .vsync_start = 600 + 12, 143 + .vsync_end = 600 + 12 + 23, 144 + .vtotal = 600 + 12 + 23 + 1, 145 + .width_mm = 154, 146 + .height_mm = 86, 147 + }; 148 + 149 + static int m9189_get_modes(struct drm_panel *panel, 150 + struct drm_connector *connector) 151 + { 152 + return drm_connector_helper_get_modes_fixed(connector, &m9189_mode); 153 + } 154 + 155 + static const struct drm_panel_funcs m9189_panel_funcs = { 156 + .prepare = m9189_prepare, 157 + .unprepare = m9189_unprepare, 158 + .disable = m9189_disable, 159 + .get_modes = m9189_get_modes, 160 + }; 161 + 162 + static int lxd_m9189_probe(struct mipi_dsi_device *dsi) 163 + { 164 + struct device *dev = &dsi->dev; 165 + struct m9189_panel *m9189; 166 + int ret; 167 + 168 + m9189 = devm_kzalloc(dev, sizeof(*m9189), GFP_KERNEL); 169 + if (!m9189) 170 + return -ENOMEM; 171 + 172 + m9189->supply = devm_regulator_get(dev, "power"); 173 + if (IS_ERR(m9189->supply)) 174 + return dev_err_probe(dev, PTR_ERR(m9189->supply), 175 + "Failed to get power-supply\n"); 176 + 177 + m9189->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 178 + if (IS_ERR(m9189->reset_gpio)) 179 + return dev_err_probe(dev, PTR_ERR(m9189->reset_gpio), 180 + "Failed to get reset-gpios\n"); 181 + 182 + m9189->standby_gpio = devm_gpiod_get(dev, "standby", GPIOD_OUT_LOW); 183 + if (IS_ERR(m9189->standby_gpio)) 184 + return dev_err_probe(dev, PTR_ERR(m9189->standby_gpio), 185 + "Failed to get standby-gpios\n"); 186 + 187 + m9189->dsi = dsi; 188 + mipi_dsi_set_drvdata(dsi, m9189); 189 + 190 + dsi->lanes = 4; 191 + dsi->format = MIPI_DSI_FMT_RGB888; 192 + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST; 193 + 194 + drm_panel_init(&m9189->panel, dev, &m9189_panel_funcs, 195 + DRM_MODE_CONNECTOR_DSI); 196 + m9189->panel.prepare_prev_first = true; 197 + 198 + ret = drm_panel_of_backlight(&m9189->panel); 199 + if (ret) 200 + return dev_err_probe(dev, ret, "Failed to get backlight\n"); 201 + 202 + drm_panel_add(&m9189->panel); 203 + 204 + ret = mipi_dsi_attach(dsi); 205 + if (ret < 0) { 206 + dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); 207 + drm_panel_remove(&m9189->panel); 208 + return ret; 209 + } 210 + 211 + return 0; 212 + } 213 + 214 + static void lxd_m9189_remove(struct mipi_dsi_device *dsi) 215 + { 216 + struct m9189_panel *m9189 = mipi_dsi_get_drvdata(dsi); 217 + int ret; 218 + 219 + ret = mipi_dsi_detach(dsi); 220 + if (ret < 0) 221 + dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); 222 + 223 + drm_panel_remove(&m9189->panel); 224 + } 225 + 226 + static const struct of_device_id lxd_m9189_of_match[] = { 227 + { .compatible = "lxd,m9189a" }, 228 + { /* sentinel */ } 229 + }; 230 + MODULE_DEVICE_TABLE(of, lxd_m9189_of_match); 231 + 232 + static struct mipi_dsi_driver lxd_m9189_driver = { 233 + .probe = lxd_m9189_probe, 234 + .remove = lxd_m9189_remove, 235 + .driver = { 236 + .name = "panel-lxd-m9189a", 237 + .of_match_table = lxd_m9189_of_match, 238 + }, 239 + }; 240 + module_mipi_dsi_driver(lxd_m9189_driver); 241 + 242 + MODULE_DESCRIPTION("DRM driver for LXD M9189A MIPI-DSI panels"); 243 + MODULE_LICENSE("GPL");
+2 -13
drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c
··· 168 168 .vsync_start = 1440 + 130, 169 169 .vsync_end = 1440 + 130 + 8, 170 170 .vtotal = 1440 + 130 + 8 + 106, 171 - .clock = 85298, 171 + .clock = 81237, 172 172 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 173 173 .width_mm = 65, 174 174 .height_mm = 130, ··· 183 183 .vsync_start = 1440 + 175, 184 184 .vsync_end = 1440 + 175 + 8, 185 185 .vtotal = 1440 + 175 + 8 + 50, 186 - .clock = 85298, 186 + .clock = 80706, 187 187 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 188 188 .width_mm = 65, 189 189 .height_mm = 130, ··· 295 295 return 0; 296 296 } 297 297 298 - static void mantix_shutdown(struct mipi_dsi_device *dsi) 299 - { 300 - struct mantix *ctx = mipi_dsi_get_drvdata(dsi); 301 - 302 - drm_panel_unprepare(&ctx->panel); 303 - drm_panel_disable(&ctx->panel); 304 - } 305 - 306 298 static void mantix_remove(struct mipi_dsi_device *dsi) 307 299 { 308 300 struct mantix *ctx = mipi_dsi_get_drvdata(dsi); 309 - 310 - mantix_shutdown(dsi); 311 301 312 302 mipi_dsi_detach(dsi); 313 303 drm_panel_remove(&ctx->panel); ··· 313 323 static struct mipi_dsi_driver mantix_driver = { 314 324 .probe = mantix_probe, 315 325 .remove = mantix_remove, 316 - .shutdown = mantix_shutdown, 317 326 .driver = { 318 327 .name = DRV_NAME, 319 328 .of_match_table = mantix_of_match,
+244
drivers/gpu/drm/panel/panel-motorola-mot.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/array_size.h> 4 + #include <linux/delay.h> 5 + #include <linux/err.h> 6 + #include <linux/gpio/consumer.h> 7 + #include <linux/mod_devicetable.h> 8 + #include <linux/module.h> 9 + #include <linux/property.h> 10 + #include <linux/regulator/consumer.h> 11 + 12 + #include <video/mipi_display.h> 13 + 14 + #include <drm/drm_mipi_dsi.h> 15 + #include <drm/drm_modes.h> 16 + #include <drm/drm_panel.h> 17 + #include <drm/drm_probe_helper.h> 18 + 19 + static const struct regulator_bulk_data mot_panel_supplies[] = { 20 + { .supply = "vddio" }, { .supply = "vdd" }, 21 + }; 22 + 23 + struct mot_panel { 24 + struct drm_panel panel; 25 + struct mipi_dsi_device *dsi; 26 + 27 + struct gpio_desc *reset_gpio; 28 + 29 + struct regulator_bulk_data *supplies; 30 + }; 31 + 32 + static inline struct mot_panel *to_mot_panel(struct drm_panel *panel) 33 + { 34 + return container_of(panel, struct mot_panel, panel); 35 + } 36 + 37 + static void mot_panel_reset(struct mot_panel *priv) 38 + { 39 + gpiod_set_value_cansleep(priv->reset_gpio, 1); 40 + usleep_range(50000, 51000); 41 + gpiod_set_value_cansleep(priv->reset_gpio, 0); 42 + usleep_range(10000, 11000); 43 + } 44 + 45 + static void mot_es2(struct mipi_dsi_multi_context *ctx) 46 + { 47 + mipi_dsi_generic_write_seq_multi(ctx, 0x55, 0x01); 48 + 49 + mipi_dsi_dcs_exit_sleep_mode_multi(ctx); 50 + mipi_dsi_msleep(ctx, 120); 51 + 52 + mipi_dsi_generic_write_seq_multi(ctx, 0xf4, 0x00, 0xbb, 0x46, 0x53, 0x0c, 0x49, 53 + 0x74, 0x29, 0x12, 0x15, 0x2f, 0x2f, 0x04); 54 + mipi_dsi_generic_write_seq_multi(ctx, 0xf8, 0x4b, 0x04, 0x10, 0x1a, 0x2c, 0x2c, 55 + 0x2c, 0x2c, 0x14, 0x12); 56 + 57 + mipi_dsi_generic_write_seq_multi(ctx, 0xb5, 0x03, 0x7f, 0x00, 0x80, 0xc7, 0x00); 58 + mipi_dsi_generic_write_seq_multi(ctx, 0xb7, 0x66, 0xf6, 0x46, 0x9f, 0x90, 0x99, 59 + 0xff, 0x80, 0x6d, 0x01); 60 + 61 + /* Gamma R */ 62 + mipi_dsi_generic_write_seq_multi(ctx, 0xf9, 0x04); 63 + mipi_dsi_generic_write_seq_multi(ctx, 0xfa, 0x00, 0x2f, 0x30, 0x12, 0x0e, 0x0c, 64 + 0x22, 0x27, 0x31, 0x2e, 0x07, 0x0f); 65 + mipi_dsi_generic_write_seq_multi(ctx, 0xfb, 0x00, 0x2f, 0x30, 0x12, 0x0e, 0x0c, 66 + 0x22, 0x27, 0x31, 0x2e, 0x07, 0x0f); 67 + 68 + /* Gamma G */ 69 + mipi_dsi_generic_write_seq_multi(ctx, 0xf9, 0x02); 70 + mipi_dsi_generic_write_seq_multi(ctx, 0xfa, 0x00, 0x2f, 0x37, 0x15, 0x15, 0x11, 71 + 0x1f, 0x25, 0x2d, 0x2a, 0x05, 0x0f); 72 + mipi_dsi_generic_write_seq_multi(ctx, 0xfb, 0x00, 0x2f, 0x37, 0x15, 0x15, 0x11, 73 + 0x1f, 0x25, 0x2d, 0x2a, 0x05, 0x0f); 74 + 75 + /* Gamma B */ 76 + mipi_dsi_generic_write_seq_multi(ctx, 0xf9, 0x01); 77 + mipi_dsi_generic_write_seq_multi(ctx, 0xfa, 0x00, 0x2f, 0x3f, 0x16, 0x1f, 0x15, 78 + 0x1f, 0x25, 0x2d, 0x2b, 0x06, 0x0b); 79 + mipi_dsi_generic_write_seq_multi(ctx, 0xfb, 0x00, 0x2f, 0x3f, 0x16, 0x1f, 0x15, 80 + 0x1f, 0x25, 0x2d, 0x2b, 0x06, 0x0b); 81 + 82 + /* Gamma W */ 83 + mipi_dsi_generic_write_seq_multi(ctx, 0xf9, 0x20); 84 + mipi_dsi_generic_write_seq_multi(ctx, 0xfa, 0x00, 0x2f, 0x34, 0x15, 0x1a, 0x11, 85 + 0x1f, 0x23, 0x2d, 0x29, 0x02, 0x08); 86 + mipi_dsi_generic_write_seq_multi(ctx, 0xfb, 0x00, 0x2f, 0x34, 0x15, 0x1a, 0x11, 87 + 0x1f, 0x23, 0x2d, 0x29, 0x02, 0x08); 88 + 89 + mipi_dsi_generic_write_seq_multi(ctx, 0x53, 0x2c); 90 + mipi_dsi_generic_write_seq_multi(ctx, 0x35, 0x00); 91 + } 92 + 93 + static int mot_panel_prepare(struct drm_panel *panel) 94 + { 95 + struct mot_panel *priv = to_mot_panel(panel); 96 + struct mipi_dsi_multi_context ctx = { .dsi = priv->dsi }; 97 + struct device *dev = panel->dev; 98 + int ret; 99 + 100 + ret = regulator_bulk_enable(ARRAY_SIZE(mot_panel_supplies), priv->supplies); 101 + if (ret < 0) { 102 + dev_err(dev, "failed to enable power supplies: %d\n", ret); 103 + return ret; 104 + } 105 + 106 + mot_panel_reset(priv); 107 + 108 + mipi_dsi_generic_write_seq_multi(&ctx, 0xf0, 0x5a, 0x5a); 109 + mipi_dsi_generic_write_seq_multi(&ctx, 0xf1, 0x5a, 0x5a); 110 + mipi_dsi_generic_write_seq_multi(&ctx, 0xd0, 0x8e); 111 + 112 + mot_es2(&ctx); 113 + 114 + mipi_dsi_dcs_set_display_on_multi(&ctx); 115 + mipi_dsi_msleep(&ctx, 20); 116 + 117 + return ctx.accum_err; 118 + } 119 + 120 + static int mot_panel_disable(struct drm_panel *panel) 121 + { 122 + struct mot_panel *priv = to_mot_panel(panel); 123 + struct mipi_dsi_multi_context ctx = { .dsi = priv->dsi }; 124 + 125 + mipi_dsi_dcs_set_display_off_multi(&ctx); 126 + mipi_dsi_dcs_enter_sleep_mode_multi(&ctx); 127 + mipi_dsi_msleep(&ctx, 70); 128 + 129 + return ctx.accum_err; 130 + } 131 + 132 + static int mot_panel_unprepare(struct drm_panel *panel) 133 + { 134 + struct mot_panel *priv = to_mot_panel(panel); 135 + 136 + usleep_range(10000, 11000); 137 + 138 + gpiod_set_value_cansleep(priv->reset_gpio, 1); 139 + usleep_range(5000, 6000); 140 + 141 + regulator_bulk_disable(ARRAY_SIZE(mot_panel_supplies), priv->supplies); 142 + 143 + return 0; 144 + } 145 + 146 + static const struct drm_display_mode mot_panel_mode = { 147 + .clock = (540 + 32 + 32 + 16) * (960 + 12 + 12 + 8) * 60 / 1000, 148 + .hdisplay = 540, 149 + .hsync_start = 540 + 32, 150 + .hsync_end = 540 + 32 + 32, 151 + .htotal = 540 + 32 + 32 + 16, 152 + .vdisplay = 960, 153 + .vsync_start = 960 + 12, 154 + .vsync_end = 960 + 12 + 12, 155 + .vtotal = 960 + 12 + 12 + 8, 156 + .width_mm = 51, 157 + .height_mm = 91, 158 + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 159 + }; 160 + 161 + static int mot_panel_get_modes(struct drm_panel *panel, 162 + struct drm_connector *connector) 163 + { 164 + return drm_connector_helper_get_modes_fixed(connector, &mot_panel_mode); 165 + } 166 + 167 + static const struct drm_panel_funcs mot_panel_panel_funcs = { 168 + .prepare = mot_panel_prepare, 169 + .disable = mot_panel_disable, 170 + .unprepare = mot_panel_unprepare, 171 + .get_modes = mot_panel_get_modes, 172 + }; 173 + 174 + static int mot_panel_probe(struct mipi_dsi_device *dsi) 175 + { 176 + struct device *dev = &dsi->dev; 177 + struct mot_panel *priv; 178 + int ret; 179 + 180 + priv = devm_drm_panel_alloc(dev, struct mot_panel, panel, 181 + &mot_panel_panel_funcs, 182 + DRM_MODE_CONNECTOR_DSI); 183 + if (IS_ERR(priv)) 184 + return PTR_ERR(priv); 185 + 186 + ret = devm_regulator_bulk_get_const(dev, ARRAY_SIZE(mot_panel_supplies), 187 + mot_panel_supplies, &priv->supplies); 188 + if (ret < 0) 189 + return dev_err_probe(dev, ret, "failed to get supplies\n"); 190 + 191 + priv->reset_gpio = devm_gpiod_get_optional(dev, "reset", 192 + GPIOD_OUT_HIGH); 193 + if (IS_ERR(priv->reset_gpio)) 194 + return dev_err_probe(dev, PTR_ERR(priv->reset_gpio), 195 + "failed to get reset gpios\n"); 196 + 197 + priv->dsi = dsi; 198 + mipi_dsi_set_drvdata(dsi, priv); 199 + 200 + dsi->lanes = 2; 201 + dsi->format = MIPI_DSI_FMT_RGB888; 202 + dsi->mode_flags = MIPI_DSI_MODE_LPM; 203 + 204 + ret = drm_panel_of_backlight(&priv->panel); 205 + if (ret < 0) 206 + return dev_err_probe(dev, ret, "failed to get backlight\n"); 207 + 208 + drm_panel_add(&priv->panel); 209 + 210 + ret = devm_mipi_dsi_attach(dev, dsi); 211 + if (ret < 0) { 212 + drm_panel_remove(&priv->panel); 213 + return dev_err_probe(dev, ret, "failed to attach to DSI host\n"); 214 + } 215 + 216 + return 0; 217 + } 218 + 219 + static void mot_panel_remove(struct mipi_dsi_device *dsi) 220 + { 221 + struct mot_panel *priv = mipi_dsi_get_drvdata(dsi); 222 + 223 + drm_panel_remove(&priv->panel); 224 + } 225 + 226 + static const struct of_device_id mot_panel_of_match[] = { 227 + { .compatible = "motorola,mot-panel" }, 228 + { /* sentinel */ } 229 + }; 230 + MODULE_DEVICE_TABLE(of, mot_panel_of_match); 231 + 232 + static struct mipi_dsi_driver mot_panel_driver = { 233 + .driver = { 234 + .name = "panel-motorola-mot", 235 + .of_match_table = mot_panel_of_match, 236 + }, 237 + .probe = mot_panel_probe, 238 + .remove = mot_panel_remove, 239 + }; 240 + module_mipi_dsi_driver(mot_panel_driver); 241 + 242 + MODULE_AUTHOR("Svyatoslav Ryhel <clamor95@gmail.com>"); 243 + MODULE_DESCRIPTION("Motorola MOT panel driver"); 244 + MODULE_LICENSE("GPL");
+299
drivers/gpu/drm/panel/panel-novatek-nt37700f.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2024, The Linux Foundation. All rights reserved. 4 + * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree: 5 + * Copyright (c) 2013, The Linux Foundation. All rights reserved. 6 + */ 7 + 8 + #include <linux/backlight.h> 9 + #include <linux/delay.h> 10 + #include <linux/gpio/consumer.h> 11 + #include <linux/module.h> 12 + #include <linux/regulator/consumer.h> 13 + #include <linux/of.h> 14 + 15 + #include <video/mipi_display.h> 16 + 17 + #include <drm/drm_mipi_dsi.h> 18 + #include <drm/drm_modes.h> 19 + #include <drm/drm_panel.h> 20 + #include <drm/drm_probe_helper.h> 21 + 22 + struct nt37700f_tianma { 23 + struct drm_panel panel; 24 + struct mipi_dsi_device *dsi; 25 + struct regulator *supply; 26 + struct gpio_desc *reset_gpio; 27 + }; 28 + 29 + static inline 30 + struct nt37700f_tianma *to_nt37700f_tianma(struct drm_panel *panel) 31 + { 32 + return container_of(panel, struct nt37700f_tianma, panel); 33 + } 34 + 35 + static void nt37700f_tianma_reset(struct nt37700f_tianma *ctx) 36 + { 37 + gpiod_set_value_cansleep(ctx->reset_gpio, 1); 38 + usleep_range(1000, 2000); 39 + gpiod_set_value_cansleep(ctx->reset_gpio, 0); 40 + usleep_range(10000, 11000); 41 + } 42 + 43 + #define nt37700f_tianma_panel_switch_page(ctx, page) \ 44 + mipi_dsi_dcs_write_seq_multi((ctx), 0xf0, 0x55, 0xaa, 0x52, 0x08, (page)) 45 + 46 + static int nt37700f_tianma_on(struct nt37700f_tianma *ctx) 47 + { 48 + struct mipi_dsi_device *dsi = ctx->dsi; 49 + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; 50 + 51 + nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x00); 52 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc0, 0x56); 53 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xca, 0x52); 54 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x06); 55 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, 0x2b, 0x1a); 56 + nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x01); 57 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcd, 0x04, 0x82); 58 + nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x02); 59 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcc, 0x00); 60 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x80); 61 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x55); 62 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf6, 0x00); 63 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x56); 64 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf6, 0x00); 65 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x81); 66 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x07); 67 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0x07); 68 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x05); 69 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0x25); 70 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x90, 0x01); 71 + 72 + mipi_dsi_dcs_set_column_address_multi(&dsi_ctx, 0x0000, 1080 - 1); 73 + mipi_dsi_dcs_set_page_address_multi(&dsi_ctx, 0x0000, 2160 - 1); 74 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20); 75 + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); 76 + 77 + nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x00); 78 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc0, 0x56); 79 + nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x02); 80 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcd, 0x00); 81 + nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x04); 82 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd0, 0x11, 0x64); 83 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x09); 84 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, 0x20); 85 + 86 + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); 87 + mipi_dsi_msleep(&dsi_ctx, 120); 88 + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); 89 + 90 + return dsi_ctx.accum_err; 91 + } 92 + 93 + static int nt37700f_tianma_disable(struct drm_panel *panel) 94 + { 95 + struct nt37700f_tianma *ctx = to_nt37700f_tianma(panel); 96 + struct mipi_dsi_device *dsi = ctx->dsi; 97 + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; 98 + 99 + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); 100 + mipi_dsi_msleep(&dsi_ctx, 50); 101 + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); 102 + mipi_dsi_msleep(&dsi_ctx, 100); 103 + 104 + return dsi_ctx.accum_err; 105 + } 106 + 107 + static int nt37700f_tianma_prepare(struct drm_panel *panel) 108 + { 109 + struct nt37700f_tianma *ctx = to_nt37700f_tianma(panel); 110 + struct device *dev = &ctx->dsi->dev; 111 + int ret; 112 + 113 + ret = regulator_enable(ctx->supply); 114 + if (ret < 0) { 115 + dev_err(dev, "Failed to enable power supply: %d\n", ret); 116 + return ret; 117 + } 118 + 119 + nt37700f_tianma_reset(ctx); 120 + 121 + ret = nt37700f_tianma_on(ctx); 122 + if (ret < 0) { 123 + dev_err(dev, "Failed to initialize panel: %d\n", ret); 124 + gpiod_set_value_cansleep(ctx->reset_gpio, 1); 125 + return ret; 126 + } 127 + 128 + return 0; 129 + } 130 + 131 + static int nt37700f_tianma_unprepare(struct drm_panel *panel) 132 + { 133 + struct nt37700f_tianma *ctx = to_nt37700f_tianma(panel); 134 + 135 + gpiod_set_value_cansleep(ctx->reset_gpio, 1); 136 + regulator_disable(ctx->supply); 137 + 138 + return 0; 139 + } 140 + 141 + static const struct drm_display_mode nt37700f_tianma_mode = { 142 + .clock = (1080 + 32 + 32 + 98) * (2160 + 32 + 4 + 98) * 60 / 1000, 143 + .hdisplay = 1080, 144 + .hsync_start = 1080 + 32, 145 + .hsync_end = 1080 + 32 + 32, 146 + .htotal = 1080 + 32 + 32 + 98, 147 + .vdisplay = 2160, 148 + .vsync_start = 2160 + 32, 149 + .vsync_end = 2160 + 32 + 4, 150 + .vtotal = 2160 + 32 + 4 + 98, 151 + .width_mm = 69, 152 + .height_mm = 137, 153 + .type = DRM_MODE_TYPE_DRIVER, 154 + }; 155 + 156 + static int nt37700f_tianma_get_modes(struct drm_panel *panel, 157 + struct drm_connector *connector) 158 + { 159 + return drm_connector_helper_get_modes_fixed(connector, &nt37700f_tianma_mode); 160 + } 161 + 162 + static const struct drm_panel_funcs nt37700f_tianma_panel_funcs = { 163 + .prepare = nt37700f_tianma_prepare, 164 + .unprepare = nt37700f_tianma_unprepare, 165 + .disable = nt37700f_tianma_disable, 166 + .get_modes = nt37700f_tianma_get_modes, 167 + }; 168 + 169 + static int nt37700f_tianma_bl_update_status(struct backlight_device *bl) 170 + { 171 + struct mipi_dsi_device *dsi = bl_get_data(bl); 172 + u16 brightness = backlight_get_brightness(bl); 173 + int ret; 174 + 175 + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 176 + 177 + ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness); 178 + if (ret < 0) 179 + return ret; 180 + 181 + dsi->mode_flags |= MIPI_DSI_MODE_LPM; 182 + 183 + return 0; 184 + } 185 + 186 + static int nt37700f_tianma_bl_get_brightness(struct backlight_device *bl) 187 + { 188 + struct mipi_dsi_device *dsi = bl_get_data(bl); 189 + u16 brightness; 190 + int ret; 191 + 192 + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 193 + 194 + ret = mipi_dsi_dcs_get_display_brightness_large(dsi, &brightness); 195 + if (ret < 0) 196 + return ret; 197 + 198 + dsi->mode_flags |= MIPI_DSI_MODE_LPM; 199 + 200 + return brightness; 201 + } 202 + 203 + static const struct backlight_ops nt37700f_tianma_bl_ops = { 204 + .update_status = nt37700f_tianma_bl_update_status, 205 + .get_brightness = nt37700f_tianma_bl_get_brightness, 206 + }; 207 + 208 + static struct backlight_device * 209 + nt37700f_tianma_create_backlight(struct mipi_dsi_device *dsi) 210 + { 211 + struct device *dev = &dsi->dev; 212 + const struct backlight_properties props = { 213 + .type = BACKLIGHT_RAW, 214 + .brightness = 2047, 215 + .max_brightness = 2047, 216 + }; 217 + 218 + return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, 219 + &nt37700f_tianma_bl_ops, &props); 220 + } 221 + 222 + static int nt37700f_tianma_probe(struct mipi_dsi_device *dsi) 223 + { 224 + struct device *dev = &dsi->dev; 225 + struct nt37700f_tianma *ctx; 226 + int ret; 227 + 228 + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 229 + if (!ctx) 230 + return -ENOMEM; 231 + 232 + ctx->supply = devm_regulator_get(dev, "power"); 233 + if (IS_ERR(ctx->supply)) 234 + return dev_err_probe(dev, PTR_ERR(ctx->supply), 235 + "Failed to get power-supply\n"); 236 + 237 + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 238 + if (IS_ERR(ctx->reset_gpio)) 239 + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), 240 + "Failed to get reset-gpios\n"); 241 + 242 + ctx->dsi = dsi; 243 + mipi_dsi_set_drvdata(dsi, ctx); 244 + 245 + dsi->lanes = 4; 246 + dsi->format = MIPI_DSI_FMT_RGB888; 247 + dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST | 248 + MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM; 249 + 250 + drm_panel_init(&ctx->panel, dev, &nt37700f_tianma_panel_funcs, 251 + DRM_MODE_CONNECTOR_DSI); 252 + ctx->panel.prepare_prev_first = true; 253 + 254 + ctx->panel.backlight = nt37700f_tianma_create_backlight(dsi); 255 + if (IS_ERR(ctx->panel.backlight)) 256 + return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight), 257 + "Failed to create backlight\n"); 258 + 259 + drm_panel_add(&ctx->panel); 260 + 261 + ret = mipi_dsi_attach(dsi); 262 + if (ret < 0) { 263 + drm_panel_remove(&ctx->panel); 264 + return dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); 265 + } 266 + 267 + return 0; 268 + } 269 + 270 + static void nt37700f_tianma_remove(struct mipi_dsi_device *dsi) 271 + { 272 + struct nt37700f_tianma *ctx = mipi_dsi_get_drvdata(dsi); 273 + int ret; 274 + 275 + ret = mipi_dsi_detach(dsi); 276 + if (ret < 0) 277 + dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); 278 + 279 + drm_panel_remove(&ctx->panel); 280 + } 281 + 282 + static const struct of_device_id nt37700f_tianma_of_match[] = { 283 + { .compatible = "novatek,nt37700f" }, 284 + { /* sentinel */ } 285 + }; 286 + MODULE_DEVICE_TABLE(of, nt37700f_tianma_of_match); 287 + 288 + static struct mipi_dsi_driver nt37700f_tianma_driver = { 289 + .probe = nt37700f_tianma_probe, 290 + .remove = nt37700f_tianma_remove, 291 + .driver = { 292 + .name = "panel-novatek-nt37700f", 293 + .of_match_table = nt37700f_tianma_of_match, 294 + }, 295 + }; 296 + module_mipi_dsi_driver(nt37700f_tianma_driver); 297 + 298 + MODULE_DESCRIPTION("DRM driver for nt37700f cmd mode dsi tianma panel"); 299 + MODULE_LICENSE("GPL");
+7 -33
drivers/gpu/drm/panel/panel-renesas-r61307.c
··· 14 14 #include <drm/drm_mipi_dsi.h> 15 15 #include <drm/drm_modes.h> 16 16 #include <drm/drm_panel.h> 17 + #include <drm/drm_probe_helper.h> 17 18 18 19 #define R61307_MACP 0xb0 /* Manufacturer CMD Protect */ 19 20 #define R61307_MACP_ON 0x03 ··· 34 33 struct regulator *iovcc_supply; 35 34 36 35 struct gpio_desc *reset_gpio; 37 - 38 - bool prepared; 39 36 40 37 bool dig_cont_adj; 41 38 bool inversion; ··· 90 91 struct device *dev = &priv->dsi->dev; 91 92 int ret; 92 93 93 - if (priv->prepared) 94 - return 0; 95 - 96 94 ret = regulator_enable(priv->vcc_supply); 97 95 if (ret) { 98 96 dev_err(dev, "failed to enable vcc power supply\n"); ··· 108 112 109 113 renesas_r61307_reset(priv); 110 114 111 - priv->prepared = true; 112 115 return 0; 113 116 } 114 117 ··· 150 155 mipi_dsi_dcs_set_display_on_multi(&ctx); 151 156 mipi_dsi_msleep(&ctx, 50); 152 157 153 - return 0; 158 + return ctx.accum_err; 154 159 } 155 160 156 161 static int renesas_r61307_disable(struct drm_panel *panel) ··· 162 167 mipi_dsi_msleep(&ctx, 100); 163 168 mipi_dsi_dcs_enter_sleep_mode_multi(&ctx); 164 169 165 - return 0; 170 + return ctx.accum_err; 166 171 } 167 172 168 173 static int renesas_r61307_unprepare(struct drm_panel *panel) 169 174 { 170 175 struct renesas_r61307 *priv = to_renesas_r61307(panel); 171 - 172 - if (!priv->prepared) 173 - return 0; 174 176 175 177 usleep_range(10000, 11000); 176 178 ··· 178 186 usleep_range(2000, 3000); 179 187 regulator_disable(priv->vcc_supply); 180 188 181 - priv->prepared = false; 182 189 return 0; 183 190 } 184 191 ··· 193 202 .vtotal = 1024 + 24 + 8 + 2, 194 203 .width_mm = 76, 195 204 .height_mm = 101, 205 + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 196 206 }; 197 207 198 208 static int renesas_r61307_get_modes(struct drm_panel *panel, 199 209 struct drm_connector *connector) 200 210 { 201 - struct drm_display_mode *mode; 202 - 203 - mode = drm_mode_duplicate(connector->dev, &renesas_r61307_mode); 204 - if (!mode) 205 - return -ENOMEM; 206 - 207 - drm_mode_set_name(mode); 208 - 209 - mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 210 - connector->display_info.width_mm = mode->width_mm; 211 - connector->display_info.height_mm = mode->height_mm; 212 - drm_mode_probed_add(connector, mode); 213 - 214 - return 1; 211 + return drm_connector_helper_get_modes_fixed(connector, &renesas_r61307_mode); 215 212 } 216 213 217 214 static const struct drm_panel_funcs renesas_r61307_panel_funcs = { ··· 238 259 return dev_err_probe(dev, PTR_ERR(priv->reset_gpio), 239 260 "Failed to get reset gpios\n"); 240 261 241 - if (device_property_read_bool(dev, "renesas,inversion")) 262 + if (device_property_read_bool(dev, "renesas,column-inversion")) 242 263 priv->inversion = true; 243 264 244 265 if (device_property_read_bool(dev, "renesas,contrast")) ··· 261 282 262 283 drm_panel_add(&priv->panel); 263 284 264 - ret = mipi_dsi_attach(dsi); 285 + ret = devm_mipi_dsi_attach(dev, dsi); 265 286 if (ret) { 266 287 drm_panel_remove(&priv->panel); 267 288 return dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); ··· 273 294 static void renesas_r61307_remove(struct mipi_dsi_device *dsi) 274 295 { 275 296 struct renesas_r61307 *priv = mipi_dsi_get_drvdata(dsi); 276 - int ret; 277 - 278 - ret = mipi_dsi_detach(dsi); 279 - if (ret) 280 - dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); 281 297 282 298 drm_panel_remove(&priv->panel); 283 299 }
+6 -32
drivers/gpu/drm/panel/panel-renesas-r69328.c
··· 14 14 #include <drm/drm_mipi_dsi.h> 15 15 #include <drm/drm_modes.h> 16 16 #include <drm/drm_panel.h> 17 + #include <drm/drm_probe_helper.h> 17 18 18 19 #define R69328_MACP 0xb0 /* Manufacturer Access CMD Protect */ 19 20 #define R69328_MACP_ON 0x03 ··· 33 32 struct regulator *vdd_supply; 34 33 struct regulator *vddio_supply; 35 34 struct gpio_desc *reset_gpio; 36 - 37 - bool prepared; 38 35 }; 39 36 40 37 static inline struct renesas_r69328 *to_renesas_r69328(struct drm_panel *panel) ··· 54 55 struct device *dev = &priv->dsi->dev; 55 56 int ret; 56 57 57 - if (priv->prepared) 58 - return 0; 59 - 60 58 ret = regulator_enable(priv->vdd_supply); 61 59 if (ret) { 62 60 dev_err(dev, "failed to enable vdd power supply\n"); ··· 72 76 73 77 renesas_r69328_reset(priv); 74 78 75 - priv->prepared = true; 76 79 return 0; 77 80 } 78 81 ··· 117 122 mipi_dsi_dcs_set_display_on_multi(&ctx); 118 123 mipi_dsi_msleep(&ctx, 50); 119 124 120 - return 0; 125 + return ctx.accum_err; 121 126 } 122 127 123 128 static int renesas_r69328_disable(struct drm_panel *panel) ··· 129 134 mipi_dsi_msleep(&ctx, 60); 130 135 mipi_dsi_dcs_enter_sleep_mode_multi(&ctx); 131 136 132 - return 0; 137 + return ctx.accum_err; 133 138 } 134 139 135 140 static int renesas_r69328_unprepare(struct drm_panel *panel) 136 141 { 137 142 struct renesas_r69328 *priv = to_renesas_r69328(panel); 138 - 139 - if (!priv->prepared) 140 - return 0; 141 143 142 144 gpiod_set_value_cansleep(priv->reset_gpio, 1); 143 145 ··· 143 151 regulator_disable(priv->vddio_supply); 144 152 regulator_disable(priv->vdd_supply); 145 153 146 - priv->prepared = false; 147 154 return 0; 148 155 } 149 156 ··· 158 167 .vtotal = 1280 + 6 + 3 + 1, 159 168 .width_mm = 59, 160 169 .height_mm = 105, 170 + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 161 171 }; 162 172 163 173 static int renesas_r69328_get_modes(struct drm_panel *panel, 164 174 struct drm_connector *connector) 165 175 { 166 - struct drm_display_mode *mode; 167 - 168 - mode = drm_mode_duplicate(connector->dev, &renesas_r69328_mode); 169 - if (!mode) 170 - return -ENOMEM; 171 - 172 - drm_mode_set_name(mode); 173 - 174 - mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 175 - connector->display_info.width_mm = mode->width_mm; 176 - connector->display_info.height_mm = mode->height_mm; 177 - drm_mode_probed_add(connector, mode); 178 - 179 - return 1; 176 + return drm_connector_helper_get_modes_fixed(connector, &renesas_r69328_mode); 180 177 } 181 178 182 179 static const struct drm_panel_funcs renesas_r69328_panel_funcs = { ··· 217 238 218 239 drm_panel_add(&priv->panel); 219 240 220 - ret = mipi_dsi_attach(dsi); 241 + ret = devm_mipi_dsi_attach(dev, dsi); 221 242 if (ret) { 222 243 drm_panel_remove(&priv->panel); 223 244 return dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); ··· 229 250 static void renesas_r69328_remove(struct mipi_dsi_device *dsi) 230 251 { 231 252 struct renesas_r69328 *priv = mipi_dsi_get_drvdata(dsi); 232 - int ret; 233 - 234 - ret = mipi_dsi_detach(dsi); 235 - if (ret) 236 - dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); 237 253 238 254 drm_panel_remove(&priv->panel); 239 255 }
+92
drivers/gpu/drm/panel/panel-simple.c
··· 2096 2096 .connector_type = DRM_MODE_CONNECTOR_DPI, 2097 2097 }; 2098 2098 2099 + static const struct display_timing edt_et057023udba_timing = { 2100 + .pixelclock = { 23200000, 24190000, 39640000 }, 2101 + .hactive = { 640, 640, 640 }, 2102 + .hfront_porch = { 20, 40, 200 }, 2103 + .hback_porch = { 87, 40, 1 }, 2104 + .hsync_len = { 1, 48, 87 }, 2105 + .vactive = { 480, 480, 480 }, 2106 + .vfront_porch = { 5, 13, 200 }, 2107 + .vback_porch = { 31, 31, 29 }, 2108 + .vsync_len = { 1, 1, 3 }, 2109 + .flags = DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_HSYNC_LOW | 2110 + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE | 2111 + DISPLAY_FLAGS_SYNC_POSEDGE, 2112 + }; 2113 + 2114 + static const struct panel_desc edt_et057023udba = { 2115 + .timings = &edt_et057023udba_timing, 2116 + .num_timings = 1, 2117 + .bpc = 8, 2118 + .size = { 2119 + .width = 115, 2120 + .height = 86, 2121 + }, 2122 + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, 2123 + .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE | 2124 + DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE, 2125 + .connector_type = DRM_MODE_CONNECTOR_DPI, 2126 + }; 2127 + 2099 2128 static const struct drm_display_mode edt_etm0700g0dh6_mode = { 2100 2129 .clock = 33260, 2101 2130 .hdisplay = 800, ··· 4075 4046 .connector_type = DRM_MODE_CONNECTOR_DPI, 4076 4047 }; 4077 4048 4049 + static const struct drm_display_mode powertip_ph800480t032_zhc19_mode = { 4050 + .clock = 27200, 4051 + .hdisplay = 800, 4052 + .hsync_start = 800 + 52, 4053 + .hsync_end = 800 + 52 + 2, 4054 + .htotal = 800 + 52 + 2 + 44, 4055 + .vdisplay = 480, 4056 + .vsync_start = 480 + 7, 4057 + .vsync_end = 480 + 7 + 2, 4058 + .vtotal = 480 + 7 + 2 + 2, 4059 + }; 4060 + 4061 + static const struct panel_desc powertip_ph800480t032_zhc19 = { 4062 + .modes = &powertip_ph800480t032_zhc19_mode, 4063 + .num_modes = 1, 4064 + .bpc = 8, 4065 + .size = { 4066 + .width = 152, 4067 + .height = 91, 4068 + }, 4069 + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, 4070 + .bus_flags = DRM_BUS_FLAG_DE_HIGH | 4071 + DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE | 4072 + DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE, 4073 + .connector_type = DRM_MODE_CONNECTOR_DPI, 4074 + }; 4075 + 4078 4076 static const struct drm_display_mode primeview_pm070wl4_mode = { 4079 4077 .clock = 32000, 4080 4078 .hdisplay = 800, ··· 5032 4976 .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE, 5033 4977 }; 5034 4978 4979 + static const struct drm_display_mode waveshare_133inch_mode = { 4980 + .clock = 148500, 4981 + .hdisplay = 1920, 4982 + .hsync_start = 1920 + 88, 4983 + .hsync_end = 1920 + 88 + 44, 4984 + .htotal = 1920 + 88 + 44 + 148, 4985 + .vdisplay = 1080, 4986 + .vsync_start = 1080 + 4, 4987 + .vsync_end = 1080 + 4 + 5, 4988 + .vtotal = 1080 + 4 + 5 + 36, 4989 + .flags = DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_PHSYNC, 4990 + }; 4991 + 4992 + static const struct panel_desc waveshare_133inch = { 4993 + .modes = &waveshare_133inch_mode, 4994 + .num_modes = 1, 4995 + .bpc = 8, 4996 + .size = { 4997 + .width = 293, 4998 + .height = 163, 4999 + }, 5000 + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, 5001 + .connector_type = DRM_MODE_CONNECTOR_DPI, 5002 + .bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE | 5003 + DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE, 5004 + }; 5005 + 5035 5006 static const struct drm_display_mode winstar_wf35ltiacd_mode = { 5036 5007 .clock = 6410, 5037 5008 .hdisplay = 320, ··· 5309 5226 .compatible = "edt,etm0430g0dh6", 5310 5227 .data = &edt_etm0430g0dh6, 5311 5228 }, { 5229 + .compatible = "edt,et057023udba", 5230 + .data = &edt_et057023udba, 5231 + }, { 5312 5232 .compatible = "edt,et057090dhu", 5313 5233 .data = &edt_et057090dhu, 5314 5234 }, { ··· 5543 5457 .compatible = "powertip,ph800480t013-idf02", 5544 5458 .data = &powertip_ph800480t013_idf02, 5545 5459 }, { 5460 + .compatible = "powertip,ph800480t032-zhc19", 5461 + .data = &powertip_ph800480t032_zhc19, 5462 + }, { 5546 5463 .compatible = "primeview,pm070wl4", 5547 5464 .data = &primeview_pm070wl4, 5548 5465 }, { ··· 5662 5573 }, { 5663 5574 .compatible = "vxt,vl050-8048nt-c01", 5664 5575 .data = &vl050_8048nt_c01, 5576 + }, { 5577 + .compatible = "waveshare,13.3inch-panel", 5578 + .data = &waveshare_133inch, 5665 5579 }, { 5666 5580 .compatible = "winstar,wf35ltiacd", 5667 5581 .data = &winstar_wf35ltiacd,
+1 -1
drivers/gpu/drm/panthor/panthor_sched.c
··· 3916 3916 if (job->base.s_fence) 3917 3917 drm_sched_job_cleanup(&job->base); 3918 3918 3919 - if (job->done_fence && job->done_fence->ops) 3919 + if (dma_fence_was_initialized(job->done_fence)) 3920 3920 dma_fence_put(job->done_fence); 3921 3921 else 3922 3922 dma_fence_free(job->done_fence);
+2 -4
drivers/gpu/drm/ttm/ttm_bo.c
··· 222 222 struct dma_fence *fence; 223 223 224 224 dma_resv_iter_begin(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP); 225 - dma_resv_for_each_fence_unlocked(&cursor, fence) { 226 - if (!fence->ops->signaled) 227 - dma_fence_enable_sw_signaling(fence); 228 - } 225 + dma_resv_for_each_fence_unlocked(&cursor, fence) 226 + dma_fence_enable_sw_signaling(fence); 229 227 dma_resv_iter_end(&cursor); 230 228 } 231 229
+10 -4
drivers/gpu/drm/vc4/vc4_hdmi.c
··· 2449 2449 int ret; 2450 2450 2451 2451 if (vc4_hdmi->variant->external_irq_controller) { 2452 - unsigned int hpd_con = platform_get_irq_byname(pdev, "hpd-connected"); 2453 - unsigned int hpd_rm = platform_get_irq_byname(pdev, "hpd-removed"); 2452 + int hpd = platform_get_irq_byname(pdev, "hpd-connected"); 2454 2453 2455 - ret = devm_request_threaded_irq(&pdev->dev, hpd_con, 2454 + if (hpd < 0) 2455 + return hpd; 2456 + 2457 + ret = devm_request_threaded_irq(&pdev->dev, hpd, 2456 2458 NULL, 2457 2459 vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT, 2458 2460 "vc4 hdmi hpd connected", vc4_hdmi); 2459 2461 if (ret) 2460 2462 return ret; 2461 2463 2462 - ret = devm_request_threaded_irq(&pdev->dev, hpd_rm, 2464 + hpd = platform_get_irq_byname(pdev, "hpd-removed"); 2465 + if (hpd < 0) 2466 + return hpd; 2467 + 2468 + ret = devm_request_threaded_irq(&pdev->dev, hpd, 2463 2469 NULL, 2464 2470 vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT, 2465 2471 "vc4 hdmi hpd disconnected", vc4_hdmi);
+493
drivers/gpu/tests/gpu_buddy_test.c
··· 21 21 return (1 << order) * chunk_size; 22 22 } 23 23 24 + static void gpu_test_buddy_subtree_offset_alignment_stress(struct kunit *test) 25 + { 26 + struct gpu_buddy_block *block; 27 + struct rb_node *node = NULL; 28 + const u64 mm_size = SZ_2M; 29 + const u64 alignments[] = { 30 + SZ_1M, 31 + SZ_512K, 32 + SZ_256K, 33 + SZ_128K, 34 + SZ_64K, 35 + SZ_32K, 36 + SZ_16K, 37 + SZ_8K, 38 + }; 39 + struct list_head allocated[ARRAY_SIZE(alignments)]; 40 + unsigned int i, max_subtree_align = 0; 41 + int ret, tree, order; 42 + struct gpu_buddy mm; 43 + 44 + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K), 45 + "buddy_init failed\n"); 46 + 47 + for (i = 0; i < ARRAY_SIZE(allocated); i++) 48 + INIT_LIST_HEAD(&allocated[i]); 49 + 50 + /* 51 + * Exercise subtree_max_alignment tracking by allocating blocks with descending 52 + * alignment constraints and freeing them in reverse order. This verifies that 53 + * free-tree augmentation correctly propagates the maximum offset alignment 54 + * present in each subtree at every stage. 55 + */ 56 + 57 + for (i = 0; i < ARRAY_SIZE(alignments); i++) { 58 + struct gpu_buddy_block *root = NULL; 59 + unsigned int expected; 60 + u64 align; 61 + 62 + align = alignments[i]; 63 + expected = ilog2(align) - 1; 64 + 65 + for (;;) { 66 + ret = gpu_buddy_alloc_blocks(&mm, 67 + 0, mm_size, 68 + SZ_4K, align, 69 + &allocated[i], 70 + 0); 71 + if (ret) 72 + break; 73 + 74 + block = list_last_entry(&allocated[i], 75 + struct gpu_buddy_block, 76 + link); 77 + KUNIT_EXPECT_TRUE(test, IS_ALIGNED(gpu_buddy_block_offset(block), align)); 78 + } 79 + 80 + for (order = mm.max_order; order >= 0 && !root; order--) { 81 + for (tree = 0; tree < 2; tree++) { 82 + node = mm.free_trees[tree][order].rb_node; 83 + if (node) { 84 + root = container_of(node, 85 + struct gpu_buddy_block, 86 + rb); 87 + break; 88 + } 89 + } 90 + } 91 + 92 + KUNIT_ASSERT_NOT_NULL(test, root); 93 + KUNIT_EXPECT_EQ(test, root->subtree_max_alignment, expected); 94 + } 95 + 96 + for (i = ARRAY_SIZE(alignments); i-- > 0; ) { 97 + gpu_buddy_free_list(&mm, &allocated[i], 0); 98 + 99 + for (order = 0; order <= mm.max_order; order++) { 100 + for (tree = 0; tree < 2; tree++) { 101 + node = mm.free_trees[tree][order].rb_node; 102 + if (!node) 103 + continue; 104 + 105 + block = container_of(node, struct gpu_buddy_block, rb); 106 + max_subtree_align = max(max_subtree_align, 107 + block->subtree_max_alignment); 108 + } 109 + } 110 + 111 + KUNIT_EXPECT_GE(test, max_subtree_align, ilog2(alignments[i])); 112 + } 113 + 114 + gpu_buddy_fini(&mm); 115 + } 116 + 117 + static void gpu_test_buddy_offset_aligned_allocation(struct kunit *test) 118 + { 119 + struct gpu_buddy_block *block, *tmp; 120 + int num_blocks, i, count = 0; 121 + LIST_HEAD(allocated); 122 + struct gpu_buddy mm; 123 + u64 mm_size = SZ_4M; 124 + LIST_HEAD(freed); 125 + 126 + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K), 127 + "buddy_init failed\n"); 128 + 129 + num_blocks = mm_size / SZ_256K; 130 + /* 131 + * Allocate multiple sizes under a fixed offset alignment. 132 + * Ensures alignment handling is independent of allocation size and 133 + * exercises subtree max-alignment pruning for small requests. 134 + */ 135 + for (i = 0; i < num_blocks; i++) 136 + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_8K, SZ_256K, 137 + &allocated, 0), 138 + "buddy_alloc hit an error size=%u\n", SZ_8K); 139 + 140 + list_for_each_entry(block, &allocated, link) { 141 + /* Ensure the allocated block uses the expected 8 KB size */ 142 + KUNIT_EXPECT_EQ(test, gpu_buddy_block_size(&mm, block), SZ_8K); 143 + /* Ensure the block starts at a 256 KB-aligned offset for proper alignment */ 144 + KUNIT_EXPECT_TRUE(test, IS_ALIGNED(gpu_buddy_block_offset(block), SZ_256K)); 145 + } 146 + gpu_buddy_free_list(&mm, &allocated, 0); 147 + 148 + for (i = 0; i < num_blocks; i++) 149 + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_16K, SZ_256K, 150 + &allocated, 0), 151 + "buddy_alloc hit an error size=%u\n", SZ_16K); 152 + 153 + list_for_each_entry(block, &allocated, link) { 154 + /* Ensure the allocated block uses the expected 16 KB size */ 155 + KUNIT_EXPECT_EQ(test, gpu_buddy_block_size(&mm, block), SZ_16K); 156 + /* Ensure the block starts at a 256 KB-aligned offset for proper alignment */ 157 + KUNIT_EXPECT_TRUE(test, IS_ALIGNED(gpu_buddy_block_offset(block), SZ_256K)); 158 + } 159 + 160 + /* 161 + * Free alternating aligned blocks to introduce fragmentation. 162 + * Ensures offset-aligned allocations remain valid after frees and 163 + * verifies subtree max-alignment metadata is correctly maintained. 164 + */ 165 + list_for_each_entry_safe(block, tmp, &allocated, link) { 166 + if (count % 2 == 0) 167 + list_move_tail(&block->link, &freed); 168 + count++; 169 + } 170 + gpu_buddy_free_list(&mm, &freed, 0); 171 + 172 + for (i = 0; i < num_blocks / 2; i++) 173 + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_16K, SZ_256K, 174 + &allocated, 0), 175 + "buddy_alloc hit an error size=%u\n", SZ_16K); 176 + 177 + /* 178 + * Allocate with offset alignment after all slots are used; must fail. 179 + * Confirms that no aligned offsets remain. 180 + */ 181 + KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_16K, SZ_256K, 182 + &allocated, 0), 183 + "buddy_alloc hit an error size=%u\n", SZ_16K); 184 + gpu_buddy_free_list(&mm, &allocated, 0); 185 + gpu_buddy_fini(&mm); 186 + } 187 + 24 188 static void gpu_test_buddy_fragmentation_performance(struct kunit *test) 25 189 { 26 190 struct gpu_buddy_block *block, *tmp; ··· 523 359 KUNIT_EXPECT_EQ(test, gpu_buddy_block_is_clear(block), false); 524 360 525 361 gpu_buddy_free_list(&mm, &allocated, 0); 362 + gpu_buddy_fini(&mm); 363 + } 364 + 365 + static void gpu_test_buddy_alloc_range(struct kunit *test) 366 + { 367 + GPU_RND_STATE(prng, random_seed); 368 + struct gpu_buddy_block *block; 369 + struct gpu_buddy mm; 370 + u32 mm_size, total; 371 + LIST_HEAD(blocks); 372 + LIST_HEAD(tmp); 373 + u32 ps = SZ_4K; 374 + int ret; 375 + 376 + mm_size = SZ_16M; 377 + 378 + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, ps), 379 + "buddy_init failed\n"); 380 + 381 + /* 382 + * Basic exact-range allocation. 383 + * Allocate the entire mm as one exact range (start + size == end). 384 + * This is the simplest case exercising __gpu_buddy_alloc_range. 385 + */ 386 + ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size, mm_size, ps, &blocks, 0); 387 + KUNIT_ASSERT_EQ_MSG(test, ret, 0, 388 + "exact-range alloc of full mm failed\n"); 389 + 390 + total = 0; 391 + list_for_each_entry(block, &blocks, link) { 392 + u64 offset = gpu_buddy_block_offset(block); 393 + u64 bsize = gpu_buddy_block_size(&mm, block); 394 + 395 + KUNIT_EXPECT_TRUE_MSG(test, offset + bsize <= (u64)mm_size, 396 + "block [%llx, %llx) outside mm\n", offset, offset + bsize); 397 + total += (u32)bsize; 398 + } 399 + KUNIT_EXPECT_EQ(test, total, mm_size); 400 + KUNIT_EXPECT_EQ(test, mm.avail, 0ULL); 401 + 402 + /* Full mm should be exhausted */ 403 + ret = gpu_buddy_alloc_blocks(&mm, 0, ps, ps, ps, &tmp, 0); 404 + KUNIT_EXPECT_NE_MSG(test, ret, 0, "alloc should fail when mm is full\n"); 405 + 406 + gpu_buddy_free_list(&mm, &blocks, 0); 407 + KUNIT_EXPECT_EQ(test, mm.avail, (u64)mm_size); 408 + gpu_buddy_fini(&mm); 409 + 410 + /* 411 + * Exact-range allocation of sub-ranges. 412 + * Split the mm into four equal quarters and allocate each as an exact 413 + * range. Validates splitting and non-overlapping exact allocations. 414 + */ 415 + KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps)); 416 + 417 + { 418 + u32 quarter = mm_size / 4; 419 + int i; 420 + 421 + for (i = 0; i < 4; i++) { 422 + u32 start = i * quarter; 423 + u32 end = start + quarter; 424 + 425 + ret = gpu_buddy_alloc_blocks(&mm, start, end, quarter, ps, &blocks, 0); 426 + KUNIT_ASSERT_EQ_MSG(test, ret, 0, 427 + "exact-range alloc quarter %d [%x, %x) failed\n", 428 + i, start, end); 429 + } 430 + KUNIT_EXPECT_EQ(test, mm.avail, 0ULL); 431 + gpu_buddy_free_list(&mm, &blocks, 0); 432 + } 433 + 434 + gpu_buddy_fini(&mm); 435 + 436 + /* 437 + * Minimum chunk-size exact range at various offsets. 438 + * Allocate single-page exact ranges at the start, middle and end. 439 + */ 440 + KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps)); 441 + 442 + ret = gpu_buddy_alloc_blocks(&mm, 0, ps, ps, ps, &blocks, 0); 443 + KUNIT_ASSERT_EQ(test, ret, 0); 444 + 445 + ret = gpu_buddy_alloc_blocks(&mm, mm_size / 2, mm_size / 2 + ps, ps, ps, &blocks, 0); 446 + KUNIT_ASSERT_EQ(test, ret, 0); 447 + 448 + ret = gpu_buddy_alloc_blocks(&mm, mm_size - ps, mm_size, ps, ps, &blocks, 0); 449 + KUNIT_ASSERT_EQ(test, ret, 0); 450 + 451 + total = 0; 452 + list_for_each_entry(block, &blocks, link) 453 + total += (u32)gpu_buddy_block_size(&mm, block); 454 + KUNIT_EXPECT_EQ(test, total, 3 * ps); 455 + 456 + gpu_buddy_free_list(&mm, &blocks, 0); 457 + gpu_buddy_fini(&mm); 458 + 459 + /* 460 + * Non power-of-two mm size (multiple roots). 461 + * Exact-range allocations that span root boundaries must still work. 462 + */ 463 + mm_size = SZ_4M + SZ_2M + SZ_1M; /* 7 MiB, three roots */ 464 + 465 + KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps)); 466 + KUNIT_EXPECT_GT(test, mm.n_roots, 1U); 467 + 468 + /* Allocate first 4M root exactly */ 469 + ret = gpu_buddy_alloc_blocks(&mm, 0, SZ_4M, SZ_4M, ps, &blocks, 0); 470 + KUNIT_ASSERT_EQ(test, ret, 0); 471 + 472 + /* Allocate second root (4M-6M) exactly */ 473 + ret = gpu_buddy_alloc_blocks(&mm, SZ_4M, SZ_4M + SZ_2M, SZ_2M, ps, &blocks, 0); 474 + KUNIT_ASSERT_EQ(test, ret, 0); 475 + 476 + /* Allocate third root (6M-7M) exactly */ 477 + ret = gpu_buddy_alloc_blocks(&mm, SZ_4M + SZ_2M, mm_size, SZ_1M, ps, &blocks, 0); 478 + KUNIT_ASSERT_EQ(test, ret, 0); 479 + 480 + KUNIT_EXPECT_EQ(test, mm.avail, 0ULL); 481 + gpu_buddy_free_list(&mm, &blocks, 0); 482 + 483 + /* Cross-root exact-range: the entire non-pot mm */ 484 + ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size, mm_size, ps, &blocks, 0); 485 + KUNIT_ASSERT_EQ(test, ret, 0); 486 + KUNIT_EXPECT_EQ(test, mm.avail, 0ULL); 487 + 488 + gpu_buddy_free_list(&mm, &blocks, 0); 489 + gpu_buddy_fini(&mm); 490 + 491 + /* 492 + * Randomized exact-range allocations. 493 + * Divide the mm into N random-sized, contiguous, page-aligned slices 494 + * and allocate each as an exact range in random order. 495 + */ 496 + mm_size = SZ_16M; 497 + KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps)); 498 + 499 + { 500 + #define N_RAND_RANGES 16 501 + u32 ranges[N_RAND_RANGES + 1]; /* boundaries */ 502 + u32 order_arr[N_RAND_RANGES]; 503 + u32 remaining = mm_size; 504 + int i; 505 + 506 + ranges[0] = 0; 507 + for (i = 0; i < N_RAND_RANGES - 1; i++) { 508 + u32 max_chunk = remaining - (N_RAND_RANGES - 1 - i) * ps; 509 + u32 sz = max(round_up(prandom_u32_state(&prng) % max_chunk, ps), ps); 510 + 511 + ranges[i + 1] = ranges[i] + sz; 512 + remaining -= sz; 513 + } 514 + ranges[N_RAND_RANGES] = mm_size; 515 + 516 + /* Create a random order */ 517 + for (i = 0; i < N_RAND_RANGES; i++) 518 + order_arr[i] = i; 519 + for (i = N_RAND_RANGES - 1; i > 0; i--) { 520 + u32 j = prandom_u32_state(&prng) % (i + 1); 521 + u32 tmp_val = order_arr[i]; 522 + 523 + order_arr[i] = order_arr[j]; 524 + order_arr[j] = tmp_val; 525 + } 526 + 527 + for (i = 0; i < N_RAND_RANGES; i++) { 528 + u32 idx = order_arr[i]; 529 + u32 start = ranges[idx]; 530 + u32 end = ranges[idx + 1]; 531 + u32 sz = end - start; 532 + 533 + ret = gpu_buddy_alloc_blocks(&mm, start, end, sz, ps, &blocks, 0); 534 + KUNIT_ASSERT_EQ_MSG(test, ret, 0, 535 + "random exact-range [%x, %x) sz=%x failed\n", 536 + start, end, sz); 537 + } 538 + 539 + KUNIT_EXPECT_EQ(test, mm.avail, 0ULL); 540 + gpu_buddy_free_list(&mm, &blocks, 0); 541 + #undef N_RAND_RANGES 542 + } 543 + 544 + gpu_buddy_fini(&mm); 545 + 546 + /* 547 + * Negative case - partially allocated range. 548 + * Allocate the first half, then try to exact-range allocate the full 549 + * mm. This must fail because the first half is already occupied. 550 + */ 551 + mm_size = SZ_16M; 552 + KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps)); 553 + 554 + ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size / 2, mm_size / 2, ps, &blocks, 0); 555 + KUNIT_ASSERT_EQ(test, ret, 0); 556 + 557 + ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size, mm_size, ps, &tmp, 0); 558 + KUNIT_EXPECT_NE_MSG(test, ret, 0, 559 + "exact-range alloc should fail when range is partially used\n"); 560 + 561 + /* Also try the already-occupied sub-range directly */ 562 + ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size / 2, mm_size / 2, ps, &tmp, 0); 563 + KUNIT_EXPECT_NE_MSG(test, ret, 0, 564 + "double alloc of same exact range should fail\n"); 565 + 566 + /* The free second half should still be allocatable */ 567 + ret = gpu_buddy_alloc_blocks(&mm, mm_size / 2, mm_size, mm_size / 2, ps, &blocks, 0); 568 + KUNIT_ASSERT_EQ(test, ret, 0); 569 + 570 + KUNIT_EXPECT_EQ(test, mm.avail, 0ULL); 571 + gpu_buddy_free_list(&mm, &blocks, 0); 572 + gpu_buddy_fini(&mm); 573 + 574 + /* 575 + * Negative case - checkerboard partial allocation. 576 + * Allocate every other page-sized chunk in a small mm, then try to 577 + * exact-range allocate a range covering two pages (one allocated, one 578 + * free). This must fail. 579 + */ 580 + mm_size = SZ_64K; 581 + KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps)); 582 + 583 + { 584 + u32 off; 585 + 586 + for (off = 0; off < mm_size; off += 2 * ps) { 587 + ret = gpu_buddy_alloc_blocks(&mm, off, off + ps, ps, ps, &blocks, 0); 588 + KUNIT_ASSERT_EQ(test, ret, 0); 589 + } 590 + 591 + /* Try exact range over a pair [allocated, free] */ 592 + ret = gpu_buddy_alloc_blocks(&mm, 0, 2 * ps, 2 * ps, ps, &tmp, 0); 593 + KUNIT_EXPECT_NE_MSG(test, ret, 0, 594 + "exact-range over partially allocated pair should fail\n"); 595 + 596 + /* The free pages individually should still work */ 597 + ret = gpu_buddy_alloc_blocks(&mm, ps, 2 * ps, ps, ps, &blocks, 0); 598 + KUNIT_ASSERT_EQ(test, ret, 0); 599 + 600 + gpu_buddy_free_list(&mm, &blocks, 0); 601 + } 602 + 603 + gpu_buddy_fini(&mm); 604 + 605 + /* Negative case - misaligned start/end/size */ 606 + mm_size = SZ_16M; 607 + KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps)); 608 + 609 + /* start not aligned to chunk_size */ 610 + ret = gpu_buddy_alloc_blocks(&mm, ps / 2, ps / 2 + ps, ps, ps, &tmp, 0); 611 + KUNIT_EXPECT_NE(test, ret, 0); 612 + 613 + /* size not aligned */ 614 + ret = gpu_buddy_alloc_blocks(&mm, 0, ps + 1, ps + 1, ps, &tmp, 0); 615 + KUNIT_EXPECT_NE(test, ret, 0); 616 + 617 + /* end exceeds mm size */ 618 + ret = gpu_buddy_alloc_blocks(&mm, mm_size, mm_size + ps, ps, ps, &tmp, 0); 619 + KUNIT_EXPECT_NE(test, ret, 0); 620 + 621 + gpu_buddy_fini(&mm); 622 + 623 + /* 624 + * Free and re-allocate the same exact range. 625 + * This exercises merge-on-free followed by exact-range re-split. 626 + */ 627 + mm_size = SZ_16M; 628 + KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps)); 629 + 630 + { 631 + int i; 632 + 633 + for (i = 0; i < 5; i++) { 634 + ret = gpu_buddy_alloc_blocks(&mm, SZ_4M, SZ_4M + SZ_2M, 635 + SZ_2M, ps, &blocks, 0); 636 + KUNIT_ASSERT_EQ_MSG(test, ret, 0, 637 + "re-alloc iteration %d failed\n", i); 638 + 639 + total = 0; 640 + list_for_each_entry(block, &blocks, link) { 641 + u64 offset = gpu_buddy_block_offset(block); 642 + u64 bsize = gpu_buddy_block_size(&mm, block); 643 + 644 + KUNIT_EXPECT_GE(test, offset, (u64)SZ_4M); 645 + KUNIT_EXPECT_LE(test, offset + bsize, (u64)(SZ_4M + SZ_2M)); 646 + total += (u32)bsize; 647 + } 648 + KUNIT_EXPECT_EQ(test, total, SZ_2M); 649 + 650 + gpu_buddy_free_list(&mm, &blocks, 0); 651 + } 652 + 653 + KUNIT_EXPECT_EQ(test, mm.avail, (u64)mm_size); 654 + } 655 + 656 + gpu_buddy_fini(&mm); 657 + 658 + /* 659 + * Various power-of-two exact ranges within a large mm. 660 + * Allocate non-overlapping power-of-two exact ranges at their natural 661 + * alignment, validating that the allocator handles different orders. 662 + */ 663 + mm_size = SZ_16M; 664 + KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps)); 665 + 666 + /* Allocate 4K at offset 0 */ 667 + ret = gpu_buddy_alloc_blocks(&mm, 0, SZ_4K, SZ_4K, ps, &blocks, 0); 668 + KUNIT_ASSERT_EQ(test, ret, 0); 669 + 670 + /* Allocate 64K at offset 64K */ 671 + ret = gpu_buddy_alloc_blocks(&mm, SZ_64K, SZ_64K + SZ_64K, SZ_64K, ps, &blocks, 0); 672 + KUNIT_ASSERT_EQ(test, ret, 0); 673 + 674 + /* Allocate 1M at offset 1M */ 675 + ret = gpu_buddy_alloc_blocks(&mm, SZ_1M, SZ_1M + SZ_1M, SZ_1M, ps, &blocks, 0); 676 + KUNIT_ASSERT_EQ(test, ret, 0); 677 + 678 + /* Allocate 4M at offset 4M */ 679 + ret = gpu_buddy_alloc_blocks(&mm, SZ_4M, SZ_4M + SZ_4M, SZ_4M, ps, &blocks, 0); 680 + KUNIT_ASSERT_EQ(test, ret, 0); 681 + 682 + total = 0; 683 + list_for_each_entry(block, &blocks, link) 684 + total += (u32)gpu_buddy_block_size(&mm, block); 685 + KUNIT_EXPECT_EQ(test, total, SZ_4K + SZ_64K + SZ_1M + SZ_4M); 686 + 687 + gpu_buddy_free_list(&mm, &blocks, 0); 526 688 gpu_buddy_fini(&mm); 527 689 } 528 690 ··· 1399 909 KUNIT_CASE(gpu_test_buddy_alloc_pathological), 1400 910 KUNIT_CASE(gpu_test_buddy_alloc_contiguous), 1401 911 KUNIT_CASE(gpu_test_buddy_alloc_clear), 912 + KUNIT_CASE(gpu_test_buddy_alloc_range), 1402 913 KUNIT_CASE(gpu_test_buddy_alloc_range_bias), 1403 914 KUNIT_CASE_SLOW(gpu_test_buddy_fragmentation_performance), 1404 915 KUNIT_CASE(gpu_test_buddy_alloc_exceeds_max_order), 916 + KUNIT_CASE(gpu_test_buddy_offset_aligned_allocation), 917 + KUNIT_CASE(gpu_test_buddy_subtree_offset_alignment_stress), 1405 918 {} 1406 919 }; 1407 920
+2
include/linux/gpu_buddy.h
··· 11 11 #include <linux/slab.h> 12 12 #include <linux/sched.h> 13 13 #include <linux/rbtree.h> 14 + #include <linux/rbtree_augmented.h> 14 15 15 16 /** 16 17 * GPU_BUDDY_RANGE_ALLOCATION - Allocate within a specific address range ··· 129 128 }; 130 129 /* private: */ 131 130 struct list_head tmp_link; 131 + unsigned int subtree_max_alignment; 132 132 }; 133 133 134 134 /* Order-zero must be at least SZ_4K */
+2 -1
include/uapi/drm/amdxdna_accel.h
··· 353 353 }; 354 354 355 355 enum amdxdna_sensor_type { 356 - AMDXDNA_SENSOR_TYPE_POWER 356 + AMDXDNA_SENSOR_TYPE_POWER, 357 + AMDXDNA_SENSOR_TYPE_COLUMN_UTILIZATION 357 358 }; 358 359 359 360 /**