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-26' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next

drm-misc-next for v7.1:

UAPI Changes:

amdxdna:
- support per-BO memory-usage queries

docs:
- Improve UAPI documentation

panthor:
- extend timestamp query with flags

Core Changes:

edid:
- provide enum drm_output_color_format; mass-convert drivers

gem-dma:
- use drm_dev_dma_dev() for DMA mappings
- set VM_DONTDUMP on mmap

mipi-dbi:
- drop simple-display; mass-convert drivers

prime:
- use drm_dev_dma_dev() for DMA mappings

ttm:
- improve handling of gfp_retry_mayfail

Driver Changes:

amdgpu:
- use atomic_create_state for private_obj

amdxdna:
- refactor GEM implementation
- fixes

bridge:
- provide clear-and-put helper for reliable cleanup
- analogix_dp: Use DP helpers for link training
- lontium-lt8713sx: Fix 64-bit division and Kconfig
- samsung-dsim: Use clear-and-put

imagination:
- improve power-off sequence
- support context-reset notification from firmware

komeda:
- support Arm China Linlon D6 plus DT bindings

mediatek:
- use drm_dev_dma_dev() for DMA mappings

panel:
- support Himax HX83121A plus DT bindings
- support JuTouch JT070TM041 plus DT bindings
- support Samsung S6E8FC0 plus DT bindings
- himax-hx83102c: support Samsung S6E8FC0 plus DT bindings; support backlight
- ili9806e: support Rocktech RK050HR345-CT106A plus DT bindings
- simple: support Tianma TM050RDH03 plus DT bindings

panthor:
- support various sources for timestamp queries
- fixes

omapdrm:
- use atomic_create_state for private_obj

rcar-du:
- fix suspend/resume wrt VSP interface
- fix leak of device_link
- clean up

sun4i:
- use drm_dev_dma_dev() for DMA mappings

tegra:
- use atomic_create_state for private_obj

xe:
- send 'none' recovery method for XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patch.msgid.link/20260326151812.GA76082@linux.fritz.box

+4881 -2198
+3 -1
Documentation/devicetree/bindings/display/arm,komeda.yaml
··· 19 19 compatible: 20 20 oneOf: 21 21 - items: 22 - - const: arm,mali-d32 22 + - enum: 23 + - arm,mali-d32 24 + - armchina,linlon-d6 23 25 - const: arm,mali-d71 24 26 - const: arm,mali-d71 25 27
+1
Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml
··· 33 33 oneOf: 34 34 - items: 35 35 - enum: 36 + - doestek,dtc34lm85am # For the Doestek DTC34LM85AM Flat Panel Display (FPD) Transmitter 36 37 - onnn,fin3385 # OnSemi FIN3385 37 38 - ti,ds90c185 # For the TI DS90C185 FPD-Link Serializer 38 39 - ti,ds90c187 # For the TI DS90C187 FPD-Link Serializer
-1
Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.yaml
··· 28 28 29 29 port: true 30 30 reset-gpios: true 31 - 32 31 backlight: true 33 32 34 33 required:
+2
Documentation/devicetree/bindings/display/panel/himax,hx83102.yaml
··· 20 20 - boe,nv110wum-l60 21 21 # CSOT pna957qt1-1 10.95" WUXGA TFT LCD panel 22 22 - csot,pna957qt1-1 23 + # Holitech HTF065H045 6.517" 720x1600 TFT LCD panel 24 + - holitech,htf065h045 23 25 # IVO t109nw41 11.0" WUXGA TFT LCD panel 24 26 - ivo,t109nw41 25 27 # KINGDISPLAY KD110N11-51IE 10.95" WUXGA TFT LCD panel
+91
Documentation/devicetree/bindings/display/panel/himax,hx83121a.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/himax,hx83121a.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Himax HX83121A based DSI display Panels 8 + 9 + maintainers: 10 + - Pengyu Luo <mitltlatltl@gmail.com> 11 + 12 + description: 13 + The Himax HX83121A is a generic DSI Panel IC used to drive dsi 14 + panels. Support video mode panels from China Star Optoelectronics 15 + Technology (CSOT) and BOE Technology. 16 + 17 + allOf: 18 + - $ref: panel-common-dual.yaml# 19 + 20 + properties: 21 + compatible: 22 + items: 23 + - enum: 24 + - boe,ppc357db1-4 25 + - csot,ppc357db1-4 26 + - const: himax,hx83121a 27 + 28 + reg: 29 + maxItems: 1 30 + 31 + reset-gpios: 32 + maxItems: 1 33 + 34 + avdd-supply: 35 + description: analog positive supply for IC 36 + 37 + avee-supply: 38 + description: analog negative supply for IC 39 + 40 + vddi-supply: 41 + description: power supply for IC 42 + 43 + backlight: true 44 + ports: true 45 + 46 + required: 47 + - compatible 48 + - reg 49 + - vddi-supply 50 + - reset-gpios 51 + - ports 52 + 53 + additionalProperties: false 54 + 55 + examples: 56 + - | 57 + #include <dt-bindings/gpio/gpio.h> 58 + 59 + dsi { 60 + #address-cells = <1>; 61 + #size-cells = <0>; 62 + 63 + panel@0 { 64 + compatible = "csot,ppc357db1-4", "himax,hx83121a"; 65 + reg = <0>; 66 + 67 + vddi-supply = <&vreg_l2b>; 68 + reset-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; 69 + 70 + ports { 71 + #address-cells = <1>; 72 + #size-cells = <0>; 73 + 74 + port@0 { 75 + reg = <0>; 76 + panel_in_0: endpoint { 77 + remote-endpoint = <&dsi0_out>; 78 + }; 79 + }; 80 + 81 + port@1{ 82 + reg = <1>; 83 + panel_in_1: endpoint { 84 + remote-endpoint = <&dsi1_out>; 85 + }; 86 + }; 87 + }; 88 + }; 89 + }; 90 + 91 + ...
-3
Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml
··· 33 33 maxItems: 1 34 34 35 35 reset-gpios: true 36 - 37 36 backlight: true 38 - 39 37 rotation: true 40 - 41 38 port: true 42 39 43 40 vcc-supply:
+36 -2
Documentation/devicetree/bindings/display/panel/ilitek,ili9806e.yaml
··· 4 4 $id: http://devicetree.org/schemas/display/panel/ilitek,ili9806e.yaml# 5 5 $schema: http://devicetree.org/meta-schemas/core.yaml# 6 6 7 - title: Ilitek ILI9806E based MIPI-DSI panels 7 + title: Ilitek ILI9806E based panels 8 8 9 9 maintainers: 10 10 - Michael Walle <mwalle@kernel.org> ··· 18 18 - enum: 19 19 - densitron,dmt028vghmcmi-1d 20 20 - ortustech,com35h3p70ulc 21 + - rocktech,rk050hr345-ct106a 21 22 - const: ilitek,ili9806e 22 23 23 24 reg: ··· 31 30 - compatible 32 31 - reg 33 32 - vdd-supply 34 - - vccio-supply 35 33 - reset-gpios 36 34 - backlight 37 35 - port 36 + 37 + if: 38 + properties: 39 + compatible: 40 + contains: 41 + enum: 42 + - rocktech,rk050hr345-ct106a 43 + then: 44 + $ref: /schemas/spi/spi-peripheral-props.yaml# 45 + required: 46 + - spi-max-frequency 47 + else: 48 + required: 49 + - vccio-supply 38 50 39 51 unevaluatedProperties: false 40 52 ··· 74 60 }; 75 61 }; 76 62 }; 63 + - | 64 + #include <dt-bindings/gpio/gpio.h> 77 65 66 + spi { 67 + #address-cells = <1>; 68 + #size-cells = <0>; 69 + 70 + panel@0 { 71 + compatible = "rocktech,rk050hr345-ct106a", "ilitek,ili9806e"; 72 + reg = <0>; 73 + vdd-supply = <&reg_vdd_panel>; 74 + spi-max-frequency = <10000000>; 75 + reset-gpios = <&gpiob 6 GPIO_ACTIVE_LOW>; 76 + backlight = <&backlight>; 77 + port { 78 + panel_in_rgb: endpoint { 79 + remote-endpoint = <&ltdc_out_rgb>; 80 + }; 81 + }; 82 + }; 83 + }; 78 84 ...
+1
Documentation/devicetree/bindings/display/panel/leadtek,ltk050h3146w.yaml
··· 25 25 backlight: true 26 26 port: true 27 27 reset-gpios: true 28 + 28 29 iovcc-supply: 29 30 description: regulator that supplies the iovcc voltage 30 31 vci-supply:
+1
Documentation/devicetree/bindings/display/panel/leadtek,ltk500hd1829.yaml
··· 24 24 backlight: true 25 25 port: true 26 26 reset-gpios: true 27 + 27 28 iovcc-supply: 28 29 description: regulator that supplies the iovcc voltage 29 30 vcc-supply:
+2 -3
Documentation/devicetree/bindings/display/panel/mantix,mlaf057we51-x.yaml
··· 22 22 - mantix,mlaf057we51-x 23 23 - ys,ys57pss36bh5gq 24 24 25 - port: true 26 25 reg: 27 26 maxItems: 1 28 27 description: DSI virtual channel ··· 35 36 vddi-supply: 36 37 description: 1.8V I/O voltage supply 37 38 38 - reset-gpios: true 39 - 40 39 mantix,tp-rstn-gpios: 41 40 maxItems: 1 42 41 description: second reset line that triggers DSI config load 43 42 44 43 backlight: true 44 + port: true 45 + reset-gpios: true 45 46 46 47 required: 47 48 - compatible
+2 -1
Documentation/devicetree/bindings/display/panel/novatek,nt35510.yaml
··· 28 28 reg: 29 29 maxItems: 1 30 30 31 - reset-gpios: true 32 31 vdd-supply: 33 32 description: regulator that supplies the vdd voltage 34 33 vddi-supply: 35 34 description: regulator that supplies the vddi voltage 35 + 36 36 backlight: true 37 37 port: true 38 + reset-gpios: true 38 39 39 40 required: 40 41 - compatible
+4
Documentation/devicetree/bindings/display/panel/panel-lvds.yaml
··· 58 58 - hydis,hv070wx2-1e0 59 59 # Jenson Display BL-JT60050-01A 7" WSVGA (1024x600) color TFT LCD LVDS panel 60 60 - jenson,bl-jt60050-01a 61 + # Samsung LTN070NL01 7.0" WSVGA (1024x600) TFT LCD LVDS panel 62 + - samsung,ltn070nl01 63 + # Samsung LTN101AL03 10.1" WXGA (800x1280) TFT LCD LVDS panel 64 + - samsung,ltn101al03 61 65 - tbs,a711-panel 62 66 # Winstar WF70A8SYJHLNGA 7" WSVGA (1024x600) color TFT LCD LVDS panel 63 67 - winstar,wf70a8syjhlnga
+4
Documentation/devicetree/bindings/display/panel/panel-simple.yaml
··· 188 188 - innolux,n156bge-l21 189 189 # Innolux Corporation 7.0" WSVGA (1024x600) TFT LCD panel 190 190 - innolux,zj070na-01p 191 + # JuTouch Technology Co.. 7" JT070TM041 WSVGA (1024 x 600) LVDS panel 192 + - jutouch,jt070tm041 191 193 # JuTouch Technology Co.. 10" JT101TM023 WXGA (1280 x 800) LVDS panel 192 194 - jutouch,jt101tm023 193 195 # Kaohsiung Opto-Electronics Inc. 5.7" QVGA (320 x 240) TFT LCD panel ··· 312 310 - team-source-display,tst043015cmhx 313 311 # Tianma Micro-electronics P0700WXF1MBAA 7.0" WXGA (1280x800) LVDS TFT LCD panel 314 312 - tianma,p0700wxf1mbaa 313 + # Tianma Micro-electronics TM050RDH03 5.0" WVGA TFT LCD panel 314 + - tianma,tm050rdh03 315 315 # Tianma Micro-electronics TM070JDHG30 7.0" WXGA TFT LCD panel 316 316 - tianma,tm070jdhg30 317 317 # Tianma Micro-electronics TM070JDHG34-00 7.0" WXGA (1280x800) LVDS TFT LCD panel
+1 -2
Documentation/devicetree/bindings/display/panel/renesas,r61307.yaml
··· 33 33 iovcc-supply: 34 34 description: Regulator for 1.8V IO power supply. 35 35 36 - backlight: true 37 - 38 36 renesas,gamma: 39 37 $ref: /schemas/types.yaml#/definitions/uint32 40 38 description: ··· 49 51 type: boolean 50 52 description: digital contrast adjustment 51 53 54 + backlight: true 52 55 reset-gpios: true 53 56 port: true 54 57
-1
Documentation/devicetree/bindings/display/panel/renesas,r69328.yaml
··· 33 33 description: Regulator for 1.8V IO power supply. 34 34 35 35 backlight: true 36 - 37 36 reset-gpios: true 38 37 port: true 39 38
+2 -3
Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml
··· 33 33 # Xingbangda XBD599 5.99" 720x1440 TFT LCD panel 34 34 - xingbangda,xbd599 35 35 36 - port: true 37 36 reg: 38 37 maxItems: 1 39 38 description: DSI virtual channel ··· 43 44 iovcc-supply: 44 45 description: I/O voltage supply 45 46 46 - reset-gpios: true 47 - 48 47 backlight: true 48 + port: true 49 + reset-gpios: true 49 50 rotation: true 50 51 51 52 required:
+4 -1
Documentation/devicetree/bindings/display/panel/samsung,s6e8aa5x01-ams561ra01.yaml
··· 8 8 9 9 maintainers: 10 10 - Kaustabh Chakraborty <kauschluss@disroot.org> 11 + - Yedaya Katsman <yedaya.ka@gmail.com> 11 12 12 13 allOf: 13 14 - $ref: panel-common.yaml# 14 15 15 16 properties: 16 17 compatible: 17 - const: samsung,s6e8aa5x01-ams561ra01 18 + enum: 19 + - samsung,s6e8aa5x01-ams561ra01 20 + - samsung,s6e8fc0-m1906f9 18 21 19 22 reg: 20 23 maxItems: 1
-2
Documentation/devicetree/bindings/display/panel/sony,tulip-truly-nt35521.yaml
··· 31 31 description: Negative 5V supply 32 32 33 33 reset-gpios: true 34 - 35 34 enable-gpios: true 36 - 37 35 port: true 38 36 39 37 required:
+2 -5
Documentation/devicetree/bindings/display/panel/startek,kd070fhfid015.yaml
··· 16 16 compatible: 17 17 const: startek,kd070fhfid015 18 18 19 - enable-gpios: true 20 - 21 19 iovcc-supply: 22 20 description: Reference to the regulator powering the panel IO pins. 23 21 ··· 23 25 maxItems: 1 24 26 description: DSI virtual channel 25 27 26 - reset-gpios: true 27 - 28 + enable-gpios: true 28 29 port: true 29 - 30 30 power-supply: true 31 + reset-gpios: true 31 32 32 33 required: 33 34 - compatible
+6
Documentation/devicetree/bindings/vendor-prefixes.yaml
··· 172 172 description: ARM Ltd. 173 173 "^armadeus,.*": 174 174 description: ARMadeus Systems SARL 175 + "^armchina,.*": 176 + description: Arm Technology (China) Co., Ltd. 175 177 "^armsom,.*": 176 178 description: ArmSoM Technology Co., Ltd. 177 179 "^arrow,.*": ··· 443 441 description: D-Link Corporation 444 442 "^dmo,.*": 445 443 description: Data Modul AG 444 + "^doestek,.*": 445 + description: Doestek Co., Ltd. 446 446 "^domintech,.*": 447 447 description: Domintech Co., Ltd. 448 448 "^dongwoon,.*": ··· 713 709 description: Hitex Development Tools 714 710 "^hitron,.*": 715 711 description: HiTRON Electronics Corporation 712 + "^holitech,.*": 713 + description: Jiangxi Holitech Technology Co., Ltd. 716 714 "^holt,.*": 717 715 description: Holt Integrated Circuits, Inc. 718 716 "^holtek,.*":
-12
Documentation/gpu/drm-kms-helpers.rst
··· 104 104 .. kernel-doc:: drivers/gpu/drm/drm_vblank_helper.c 105 105 :export: 106 106 107 - Simple KMS Helper Reference 108 - =========================== 109 - 110 - .. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c 111 - :doc: overview 112 - 113 - .. kernel-doc:: include/drm/drm_simple_kms_helper.h 114 - :internal: 115 - 116 - .. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c 117 - :export: 118 - 119 107 fbdev Helper Functions Reference 120 108 ================================ 121 109
+7 -7
Documentation/gpu/drm-uapi.rst
··· 438 438 unknown consumer policy 439 439 =============== ======================================== 440 440 441 - The only exception to this is ``WEDGED=none``, which signifies that the device 442 - was temporarily 'wedged' at some point but was recovered from driver context 443 - using device specific methods like reset. No explicit recovery is expected from 444 - the consumer in this case, but it can still take additional steps like gathering 445 - telemetry information (devcoredump, syslog). This is useful because the first 446 - hang is usually the most critical one which can result in consequential hangs or 447 - complete wedging. 441 + No Recovery 442 + ----------- 448 443 444 + Here ``WEDGED=none`` signifies that no recovery is expected from the consumer 445 + but it can still try to gather telemetry information (devcoredump, syslog) for 446 + debug purpose in order to root cause the hang. This is useful because the first 447 + hang is usually the most critical one which can result in consequential hangs 448 + or complete wedging. 449 449 450 450 Vendor Specific Recovery 451 451 ------------------------
-6
Documentation/gpu/introduction.rst
··· 119 119 The DRM subsystem contains a lot of helper functions to ease writing drivers for 120 120 simple graphic devices. For example, the `drivers/gpu/drm/tiny/` directory has a 121 121 set of drivers that are simple enough to be implemented in a single source file. 122 - 123 - These drivers make use of the `struct drm_simple_display_pipe_funcs`, that hides 124 - any complexity of the DRM subsystem and just requires drivers to implement a few 125 - functions needed to operate the device. This could be used for devices that just 126 - need a display pipeline with one full-screen scanout buffer feeding one output. 127 - 128 122 The tiny DRM drivers are good examples to understand how DRM drivers should look 129 123 like. Since are just a few hundreds lines of code, they are quite easy to read. 130 124
+32
Documentation/gpu/todo.rst
··· 29 29 Subsystem-wide refactorings 30 30 =========================== 31 31 32 + Open-code drm_simple_encoder_init() 33 + ----------------------------------- 34 + 35 + The helper drm_simple_encoder_init() was supposed to simplify encoder 36 + initialization. Instead it only added an intermediate layer between atomic 37 + modesetting and the DRM driver. 38 + 39 + The task here is to remove drm_simple_encoder_init(). Search for a driver 40 + that calls drm_simple_encoder_init() and inline the helper. The driver will 41 + also need its own instance of drm_encoder_funcs. 42 + 43 + Contact: Thomas Zimmermann, respective driver maintainer 44 + 45 + Level: Easy 46 + 47 + Replace struct drm_simple_display_pipe with regular atomic helpers 48 + ------------------------------------------------------------------ 49 + 50 + The data type struct drm_simple_display_pipe and its helpers were supposed 51 + to simplify driver development. Instead they only added an intermediate layer 52 + between atomic modesetting and the DRM driver. 53 + 54 + There are still drivers that use drm_simple_display_pipe. The task here is to 55 + convert them to use regular atomic helpers. Search for a driver that calls 56 + drm_simple_display_pipe_init() and inline all helpers from drm_simple_kms_helper.c 57 + into the driver, such that no simple-KMS interfaces are required. Please also 58 + rename all inlined fucntions according to driver conventions. 59 + 60 + Contact: Thomas Zimmermann, respective driver maintainer 61 + 62 + Level: Easy 63 + 32 64 Remove custom dumb_map_offset implementations 33 65 --------------------------------------------- 34 66
+7 -1
MAINTAINERS
··· 8027 8027 8028 8028 DRM DRIVER FOR ILITEK ILI9806E PANELS 8029 8029 M: Michael Walle <mwalle@kernel.org> 8030 + M: Dario Binacchi <dario.binacchi@amarulasolutions.com> 8030 8031 S: Maintained 8031 - F: drivers/gpu/drm/panel/panel-ilitek-ili9806e.c 8032 + F: drivers/gpu/drm/panel/panel-ilitek-ili9806e-* 8032 8033 8033 8034 DRM DRIVER FOR JADARD JD9365DA-H3 MIPI-DSI LCD PANELS 8034 8035 M: Jagan Teki <jagan@edgeble.ai> ··· 8301 8300 S: Maintained 8302 8301 F: Documentation/devicetree/bindings/display/panel/samsung,s6e3ha8.yaml 8303 8302 F: drivers/gpu/drm/panel/panel-samsung-s6e3ha8.c 8303 + 8304 + DRM DRIVER FOR SAMSUNG S6E8FC0 PANELS 8305 + M: Yedaya Katsman <yedaya.ka@gmail.com> 8306 + S: Maintained 8307 + F: drivers/gpu/drm/panel/panel-samsung-s6e8fc0-m1906f9.c 8304 8308 8305 8309 DRM DRIVER FOR SAMSUNG SOFEF00 DDIC 8306 8310 M: David Heidelberg <david@ixit.cz>
+4 -4
drivers/accel/amdxdna/aie2_ctx.c
··· 79 79 } 80 80 81 81 ret = aie2_map_host_buf(xdna->dev_handle, hwctx->fw_ctx_id, 82 - amdxdna_obj_dma_addr(hwctx->client, heap), 82 + amdxdna_obj_dma_addr(heap), 83 83 heap->mem.size); 84 84 if (ret) { 85 85 XDNA_ERR(xdna, "Map host buf failed, ret %d", ret); ··· 649 649 .size = MAX_CHAIN_CMDBUF_SIZE, 650 650 }; 651 651 652 - abo = amdxdna_drm_alloc_dev_bo(&xdna->ddev, &args, client->filp); 652 + abo = amdxdna_drm_create_dev_bo(&xdna->ddev, &args, client->filp); 653 653 if (IS_ERR(abo)) { 654 654 ret = PTR_ERR(abo); 655 655 goto free_cmd_bufs; 656 656 } 657 657 658 658 XDNA_DBG(xdna, "Command buf %d addr 0x%llx size 0x%lx", 659 - i, abo->mem.dev_addr, abo->mem.size); 659 + i, amdxdna_gem_dev_addr(abo), abo->mem.size); 660 660 priv->cmd_buf[i] = abo; 661 661 } 662 662 ··· 697 697 } 698 698 699 699 ret = aie2_map_host_buf(xdna->dev_handle, hwctx->fw_ctx_id, 700 - amdxdna_obj_dma_addr(hwctx->client, heap), 700 + amdxdna_obj_dma_addr(heap), 701 701 heap->mem.size); 702 702 if (ret) { 703 703 XDNA_ERR(xdna, "Map host buffer failed, ret %d", ret);
+25 -15
drivers/accel/amdxdna/aie2_message.c
··· 56 56 dma_addr_t *dma_addr) 57 57 { 58 58 struct amdxdna_dev *xdna = ndev->xdna; 59 + void *vaddr; 59 60 int order; 60 61 61 62 *size = max(*size, SZ_8K); ··· 68 67 if (amdxdna_iova_on(xdna)) 69 68 return amdxdna_iommu_alloc(xdna, *size, dma_addr); 70 69 71 - return dma_alloc_noncoherent(xdna->ddev.dev, *size, dma_addr, 70 + vaddr = dma_alloc_noncoherent(xdna->ddev.dev, *size, dma_addr, 72 71 DMA_FROM_DEVICE, GFP_KERNEL); 72 + if (!vaddr) 73 + return ERR_PTR(-ENOMEM); 74 + 75 + return vaddr; 73 76 } 74 77 75 78 void aie2_free_msg_buffer(struct amdxdna_dev_hdl *ndev, size_t size, ··· 553 548 } 554 549 555 550 req.cfgs[i] = FIELD_PREP(AIE2_MSG_CFG_CU_PDI_ADDR, 556 - abo->mem.dev_addr >> shift); 551 + amdxdna_gem_dev_addr(abo) >> shift); 557 552 req.cfgs[i] |= FIELD_PREP(AIE2_MSG_CFG_CU_FUNC, cu->cu_func); 558 553 XDNA_DBG(xdna, "CU %d full addr 0x%llx, cfg 0x%x", i, 559 - abo->mem.dev_addr, req.cfgs[i]); 554 + amdxdna_gem_dev_addr(abo), req.cfgs[i]); 560 555 drm_gem_object_put(gobj); 561 556 } 562 557 req.num_cus = hwctx->cus->num_cus; ··· 1003 998 struct mailbox_channel *chann = hwctx->priv->mbox_chann; 1004 999 struct amdxdna_client *client = hwctx->client; 1005 1000 struct amdxdna_gem_obj *cmd_abo = job->cmd_bo; 1001 + void *cmd_buf = amdxdna_gem_vmap(cmdbuf_abo); 1006 1002 struct amdxdna_dev *xdna = client->xdna; 1007 1003 struct amdxdna_cmd_chain *payload; 1008 1004 struct xdna_mailbox_msg msg; ··· 1014 1008 int ret; 1015 1009 u32 op; 1016 1010 u32 i; 1011 + 1012 + if (!cmd_buf) 1013 + return -ENOMEM; 1017 1014 1018 1015 op = amdxdna_cmd_get_op(cmd_abo); 1019 1016 payload = amdxdna_cmd_get_payload(cmd_abo, &payload_len); ··· 1041 1032 u32 boh = (u32)(payload->data[i]); 1042 1033 struct amdxdna_gem_obj *abo; 1043 1034 1044 - abo = amdxdna_gem_get_obj(client, boh, AMDXDNA_BO_CMD); 1035 + abo = amdxdna_gem_get_obj(client, boh, AMDXDNA_BO_SHARE); 1045 1036 if (!abo) { 1046 1037 XDNA_ERR(xdna, "Failed to find cmd BO %d", boh); 1047 1038 return -ENOENT; 1048 1039 } 1049 1040 1050 1041 size = cmdbuf_abo->mem.size - offset; 1051 - ret = aie2_cmdlist_fill_slot(cmdbuf_abo->mem.kva + offset, 1052 - abo, &size, &op); 1042 + ret = aie2_cmdlist_fill_slot(cmd_buf + offset, abo, &size, &op); 1053 1043 amdxdna_gem_put_obj(abo); 1054 1044 if (ret) 1055 1045 return ret; ··· 1058 1050 1059 1051 XDNA_DBG(xdna, "Total %d commands:", ccnt); 1060 1052 print_hex_dump_debug("cmdbufs: ", DUMP_PREFIX_OFFSET, 16, 4, 1061 - cmdbuf_abo->mem.kva, offset, false); 1053 + cmd_buf, offset, false); 1062 1054 1063 1055 msg.opcode = EXEC_MSG_OPS(xdna)->get_chain_msg_op(op); 1064 1056 if (msg.opcode == MSG_OP_MAX_OPCODE) 1065 1057 return -EOPNOTSUPP; 1066 1058 1067 1059 /* The offset is the accumulated total size of the cmd buffer */ 1068 - EXEC_MSG_OPS(xdna)->init_chain_req(&req, cmdbuf_abo->mem.dev_addr, 1060 + EXEC_MSG_OPS(xdna)->init_chain_req(&req, amdxdna_gem_dev_addr(cmdbuf_abo), 1069 1061 offset, ccnt); 1070 - drm_clflush_virt_range(cmdbuf_abo->mem.kva, offset); 1062 + drm_clflush_virt_range(cmd_buf, offset); 1071 1063 1072 1064 msg.handle = job; 1073 1065 msg.notify_cb = notify_cb; ··· 1092 1084 struct mailbox_channel *chann = hwctx->priv->mbox_chann; 1093 1085 struct amdxdna_dev *xdna = hwctx->client->xdna; 1094 1086 struct amdxdna_gem_obj *cmd_abo = job->cmd_bo; 1087 + void *cmd_buf = amdxdna_gem_vmap(cmdbuf_abo); 1095 1088 struct xdna_mailbox_msg msg; 1096 1089 union exec_chain_req req; 1097 1090 u32 op = ERT_INVALID_CMD; 1098 1091 size_t size; 1099 1092 int ret; 1100 1093 1094 + if (!cmd_buf) 1095 + return -ENOMEM; 1096 + 1101 1097 size = cmdbuf_abo->mem.size; 1102 - ret = aie2_cmdlist_fill_slot(cmdbuf_abo->mem.kva, cmd_abo, &size, &op); 1098 + ret = aie2_cmdlist_fill_slot(cmd_buf, cmd_abo, &size, &op); 1103 1099 if (ret) 1104 1100 return ret; 1105 1101 1106 - print_hex_dump_debug("cmdbuf: ", DUMP_PREFIX_OFFSET, 16, 4, 1107 - cmdbuf_abo->mem.kva, size, false); 1102 + print_hex_dump_debug("cmdbuf: ", DUMP_PREFIX_OFFSET, 16, 4, cmd_buf, size, false); 1108 1103 1109 1104 msg.opcode = EXEC_MSG_OPS(xdna)->get_chain_msg_op(op); 1110 1105 if (msg.opcode == MSG_OP_MAX_OPCODE) 1111 1106 return -EOPNOTSUPP; 1112 1107 1113 - EXEC_MSG_OPS(xdna)->init_chain_req(&req, cmdbuf_abo->mem.dev_addr, 1114 - size, 1); 1115 - drm_clflush_virt_range(cmdbuf_abo->mem.kva, size); 1108 + EXEC_MSG_OPS(xdna)->init_chain_req(&req, amdxdna_gem_dev_addr(cmdbuf_abo), size, 1); 1109 + drm_clflush_virt_range(cmd_buf, size); 1116 1110 1117 1111 msg.handle = job; 1118 1112 msg.notify_cb = notify_cb;
+4
drivers/accel/amdxdna/aie2_pci.c
··· 865 865 tmp->command_submissions = hwctx->priv->seq; 866 866 tmp->command_completions = hwctx->priv->completed; 867 867 tmp->pasid = hwctx->client->pasid; 868 + tmp->heap_usage = hwctx->client->heap_usage; 868 869 tmp->priority = hwctx->qos.priority; 869 870 tmp->gops = hwctx->qos.gops; 870 871 tmp->fps = hwctx->qos.fps; ··· 1148 1147 break; 1149 1148 case DRM_AMDXDNA_HW_LAST_ASYNC_ERR: 1150 1149 ret = aie2_get_array_async_error(xdna->dev_handle, args); 1150 + break; 1151 + case DRM_AMDXDNA_BO_USAGE: 1152 + ret = amdxdna_drm_get_bo_usage(&xdna->ddev, args); 1151 1153 break; 1152 1154 default: 1153 1155 XDNA_ERR(xdna, "Not supported request parameter %u", args->param);
+17 -6
drivers/accel/amdxdna/amdxdna_ctx.c
··· 95 95 96 96 void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size) 97 97 { 98 - struct amdxdna_cmd *cmd = abo->mem.kva; 98 + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo); 99 99 u32 num_masks, count; 100 + 101 + if (!cmd) 102 + return NULL; 100 103 101 104 if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN) 102 105 num_masks = 0; ··· 122 119 123 120 u32 amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo) 124 121 { 125 - struct amdxdna_cmd *cmd = abo->mem.kva; 122 + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo); 126 123 u32 num_masks, i; 127 124 u32 *cu_mask; 125 + 126 + if (!cmd) 127 + return INVALID_CU_IDX; 128 128 129 129 if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN) 130 130 return INVALID_CU_IDX; ··· 148 142 void *err_data, size_t size) 149 143 { 150 144 struct amdxdna_client *client = job->hwctx->client; 151 - struct amdxdna_cmd *cmd = abo->mem.kva; 145 + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo); 152 146 struct amdxdna_cmd_chain *cc = NULL; 147 + 148 + if (!cmd) 149 + return -ENOMEM; 153 150 154 151 cmd->header &= ~AMDXDNA_CMD_STATE; 155 152 cmd->header |= FIELD_PREP(AMDXDNA_CMD_STATE, error_state); ··· 160 151 if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN) { 161 152 cc = amdxdna_cmd_get_payload(abo, NULL); 162 153 cc->error_index = (cmd_idx < cc->command_count) ? cmd_idx : 0; 163 - abo = amdxdna_gem_get_obj(client, cc->data[0], AMDXDNA_BO_CMD); 154 + abo = amdxdna_gem_get_obj(client, cc->data[0], AMDXDNA_BO_SHARE); 164 155 if (!abo) 165 156 return -EINVAL; 166 - cmd = abo->mem.kva; 157 + cmd = amdxdna_gem_vmap(abo); 158 + if (!cmd) 159 + return -ENOMEM; 167 160 } 168 161 169 162 memset(cmd->data, 0xff, abo->mem.size - sizeof(*cmd)); ··· 485 474 job->drv_cmd = drv_cmd; 486 475 487 476 if (cmd_bo_hdl != AMDXDNA_INVALID_BO_HANDLE) { 488 - job->cmd_bo = amdxdna_gem_get_obj(client, cmd_bo_hdl, AMDXDNA_BO_CMD); 477 + job->cmd_bo = amdxdna_gem_get_obj(client, cmd_bo_hdl, AMDXDNA_BO_SHARE); 489 478 if (!job->cmd_bo) { 490 479 XDNA_ERR(xdna, "Failed to get cmd bo from %d", cmd_bo_hdl); 491 480 ret = -EINVAL;
+12 -3
drivers/accel/amdxdna/amdxdna_ctx.h
··· 158 158 static inline u32 159 159 amdxdna_cmd_get_op(struct amdxdna_gem_obj *abo) 160 160 { 161 - struct amdxdna_cmd *cmd = abo->mem.kva; 161 + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo); 162 + 163 + if (!cmd) 164 + return ERT_INVALID_CMD; 162 165 163 166 return FIELD_GET(AMDXDNA_CMD_OPCODE, cmd->header); 164 167 } ··· 169 166 static inline void 170 167 amdxdna_cmd_set_state(struct amdxdna_gem_obj *abo, enum ert_cmd_state s) 171 168 { 172 - struct amdxdna_cmd *cmd = abo->mem.kva; 169 + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo); 170 + 171 + if (!cmd) 172 + return; 173 173 174 174 cmd->header &= ~AMDXDNA_CMD_STATE; 175 175 cmd->header |= FIELD_PREP(AMDXDNA_CMD_STATE, s); ··· 181 175 static inline enum ert_cmd_state 182 176 amdxdna_cmd_get_state(struct amdxdna_gem_obj *abo) 183 177 { 184 - struct amdxdna_cmd *cmd = abo->mem.kva; 178 + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo); 179 + 180 + if (!cmd) 181 + return ERT_CMD_STATE_INVALID; 185 182 186 183 return FIELD_GET(AMDXDNA_CMD_STATE, cmd->header); 187 184 }
+298 -210
drivers/accel/amdxdna/amdxdna_gem.c
··· 30 30 struct amdxdna_dev *xdna = client->xdna; 31 31 struct amdxdna_mem *mem = &abo->mem; 32 32 struct amdxdna_gem_obj *heap; 33 - u64 offset; 34 33 u32 align; 35 34 int ret; 36 35 ··· 41 42 goto unlock_out; 42 43 } 43 44 44 - if (heap->mem.userptr == AMDXDNA_INVALID_ADDR) { 45 + if (amdxdna_gem_uva(heap) == AMDXDNA_INVALID_ADDR) { 45 46 XDNA_ERR(xdna, "Invalid dev heap userptr"); 46 47 ret = -EINVAL; 47 48 goto unlock_out; ··· 63 64 goto unlock_out; 64 65 } 65 66 66 - mem->dev_addr = abo->mm_node.start; 67 - offset = mem->dev_addr - heap->mem.dev_addr; 68 - mem->userptr = heap->mem.userptr + offset; 69 - mem->kva = heap->mem.kva + offset; 67 + client->heap_usage += mem->size; 70 68 71 69 drm_gem_object_get(to_gobj(heap)); 72 70 ··· 74 78 } 75 79 76 80 static void 81 + amdxdna_gem_heap_free(struct amdxdna_gem_obj *abo) 82 + { 83 + struct amdxdna_client *client = abo->client; 84 + struct amdxdna_gem_obj *heap; 85 + 86 + mutex_lock(&client->mm_lock); 87 + 88 + drm_mm_remove_node(&abo->mm_node); 89 + client->heap_usage -= abo->mem.size; 90 + heap = client->dev_heap; 91 + drm_gem_object_put(to_gobj(heap)); 92 + 93 + mutex_unlock(&client->mm_lock); 94 + } 95 + 96 + static struct amdxdna_gem_obj * 97 + amdxdna_gem_create_obj(struct drm_device *dev, size_t size) 98 + { 99 + struct amdxdna_gem_obj *abo; 100 + 101 + abo = kzalloc_obj(*abo); 102 + if (!abo) 103 + return ERR_PTR(-ENOMEM); 104 + 105 + abo->pinned = false; 106 + abo->assigned_hwctx = AMDXDNA_INVALID_CTX_HANDLE; 107 + mutex_init(&abo->lock); 108 + 109 + abo->mem.dma_addr = AMDXDNA_INVALID_ADDR; 110 + abo->mem.uva = AMDXDNA_INVALID_ADDR; 111 + abo->mem.size = size; 112 + abo->open_ref = 0; 113 + abo->internal = false; 114 + INIT_LIST_HEAD(&abo->mem.umap_list); 115 + 116 + return abo; 117 + } 118 + 119 + static void 77 120 amdxdna_gem_destroy_obj(struct amdxdna_gem_obj *abo) 78 121 { 79 122 mutex_destroy(&abo->lock); 80 123 kfree(abo); 81 124 } 82 125 83 - static void 84 - amdxdna_gem_heap_free(struct amdxdna_gem_obj *abo) 126 + /* 127 + * Obtains a kernel virtual address on the BO (usually of small size). 128 + * The mapping is established on the first call and stays valid until 129 + * amdxdna_gem_vunmap() is called. 130 + */ 131 + void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo) 85 132 { 86 - struct amdxdna_gem_obj *heap; 133 + struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL); 134 + int ret; 87 135 88 - mutex_lock(&abo->client->mm_lock); 136 + if (abo->mem.kva) 137 + return abo->mem.kva; 89 138 90 - drm_mm_remove_node(&abo->mm_node); 139 + /* The first call to get the kva, taking slow path. */ 140 + guard(mutex)(&abo->lock); 91 141 92 - heap = abo->client->dev_heap; 93 - drm_gem_object_put(to_gobj(heap)); 142 + if (!abo->mem.kva) { 143 + ret = drm_gem_vmap(to_gobj(abo), &map); 144 + if (ret) 145 + XDNA_ERR(abo->client->xdna, "Vmap bo failed, ret %d", ret); 146 + else 147 + abo->mem.kva = map.vaddr; 148 + } 149 + return abo->mem.kva; 150 + } 94 151 95 - mutex_unlock(&abo->client->mm_lock); 152 + /* 153 + * Free mapping established through amdxdna_gem_vmap() 154 + */ 155 + static void amdxdna_gem_vunmap(struct amdxdna_gem_obj *abo) 156 + { 157 + guard(mutex)(&abo->lock); 158 + 159 + if (abo->mem.kva) { 160 + struct iosys_map map = IOSYS_MAP_INIT_VADDR(abo->mem.kva); 161 + 162 + drm_gem_vunmap(to_gobj(abo), &map); 163 + abo->mem.kva = NULL; 164 + } 165 + } 166 + 167 + /* 168 + * Obtain the user virtual address for accessing the BO. 169 + * It can be used for device to access the BO when PASID is enabled. 170 + */ 171 + u64 amdxdna_gem_uva(struct amdxdna_gem_obj *abo) 172 + { 173 + if (abo->type == AMDXDNA_BO_DEV) { 174 + struct amdxdna_gem_obj *heap = abo->client->dev_heap; 175 + u64 off = amdxdna_dev_bo_offset(abo); 176 + 177 + if (amdxdna_gem_uva(heap) != AMDXDNA_INVALID_ADDR) 178 + return amdxdna_gem_uva(heap) + off; 179 + return AMDXDNA_INVALID_ADDR; 180 + } 181 + 182 + return abo->mem.uva; 183 + } 184 + 185 + /* 186 + * Obtain the address for device to access the BO. 187 + */ 188 + u64 amdxdna_gem_dev_addr(struct amdxdna_gem_obj *abo) 189 + { 190 + if (abo->type == AMDXDNA_BO_DEV_HEAP) 191 + return abo->client->xdna->dev_info->dev_mem_base; 192 + if (abo->type == AMDXDNA_BO_DEV) 193 + return abo->mm_node.start; 194 + return amdxdna_obj_dma_addr(abo); 96 195 } 97 196 98 197 static bool amdxdna_hmm_invalidate(struct mmu_interval_notifier *mni, ··· 252 161 static void amdxdna_umap_release(struct kref *ref) 253 162 { 254 163 struct amdxdna_umap *mapp = container_of(ref, struct amdxdna_umap, refcnt); 164 + struct amdxdna_gem_obj *abo = mapp->abo; 255 165 struct vm_area_struct *vma = mapp->vma; 256 166 struct amdxdna_dev *xdna; 257 167 258 168 mmu_interval_notifier_remove(&mapp->notifier); 259 - if (is_import_bo(mapp->abo) && vma->vm_file && vma->vm_file->f_mapping) 169 + if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping) 260 170 mapping_clear_unevictable(vma->vm_file->f_mapping); 261 171 262 172 xdna = to_xdna_dev(to_gobj(mapp->abo)->dev); 263 173 down_write(&xdna->notifier_lock); 264 174 list_del(&mapp->node); 175 + if (list_empty(&abo->mem.umap_list)) 176 + abo->mem.uva = AMDXDNA_INVALID_ADDR; 265 177 up_write(&xdna->notifier_lock); 266 178 267 179 kvfree(mapp->range.hmm_pfns); ··· 326 232 mapp->abo = abo; 327 233 kref_init(&mapp->refcnt); 328 234 329 - if (abo->mem.userptr == AMDXDNA_INVALID_ADDR) 330 - abo->mem.userptr = addr; 331 235 INIT_WORK(&mapp->hmm_unreg_work, amdxdna_hmm_unreg_work); 332 236 if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping) 333 237 mapping_set_unevictable(vma->vm_file->f_mapping); 334 238 335 239 down_write(&xdna->notifier_lock); 240 + if (list_empty(&abo->mem.umap_list)) 241 + abo->mem.uva = addr; 336 242 list_add_tail(&mapp->node, &abo->mem.umap_list); 337 243 up_write(&xdna->notifier_lock); 338 244 ··· 350 256 struct amdxdna_dev *xdna = to_xdna_dev(gobj->dev); 351 257 struct amdxdna_gem_obj *abo = to_xdna_obj(gobj); 352 258 353 - XDNA_DBG(xdna, "BO type %d xdna_addr 0x%llx", abo->type, abo->mem.dev_addr); 259 + XDNA_DBG(xdna, "BO type %d xdna_addr 0x%llx", abo->type, amdxdna_gem_dev_addr(abo)); 354 260 if (abo->pinned) 355 261 amdxdna_gem_unpin(abo); 356 262 263 + amdxdna_gem_vunmap(abo); 357 264 amdxdna_gem_heap_free(abo); 358 265 drm_gem_object_release(gobj); 359 266 amdxdna_gem_destroy_obj(abo); ··· 485 390 .vunmap = drm_gem_dmabuf_vunmap, 486 391 }; 487 392 488 - static int amdxdna_gem_obj_vmap(struct amdxdna_gem_obj *abo, void **vaddr) 489 - { 490 - struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL); 491 - int ret; 492 - 493 - if (is_import_bo(abo)) 494 - ret = dma_buf_vmap_unlocked(abo->dma_buf, &map); 495 - else 496 - ret = drm_gem_vmap(to_gobj(abo), &map); 497 - 498 - *vaddr = map.vaddr; 499 - return ret; 500 - } 501 - 502 - static void amdxdna_gem_obj_vunmap(struct amdxdna_gem_obj *abo) 503 - { 504 - struct iosys_map map; 505 - 506 - if (!abo->mem.kva) 507 - return; 508 - 509 - iosys_map_set_vaddr(&map, abo->mem.kva); 510 - 511 - if (is_import_bo(abo)) 512 - dma_buf_vunmap_unlocked(abo->dma_buf, &map); 513 - else 514 - drm_gem_vunmap(to_gobj(abo), &map); 515 - } 516 - 517 393 static struct dma_buf *amdxdna_gem_prime_export(struct drm_gem_object *gobj, int flags) 518 394 { 519 395 struct amdxdna_gem_obj *abo = to_xdna_obj(gobj); ··· 513 447 kfree(abo); 514 448 } 515 449 450 + static inline bool 451 + amdxdna_gem_skip_bo_usage(struct amdxdna_gem_obj *abo) 452 + { 453 + /* Do not count imported BOs since the buffer is not allocated by us. */ 454 + if (is_import_bo(abo)) 455 + return true; 456 + 457 + /* Already counted as part of HEAP BO */ 458 + if (abo->type == AMDXDNA_BO_DEV) 459 + return true; 460 + 461 + return false; 462 + } 463 + 464 + static void 465 + amdxdna_gem_add_bo_usage(struct amdxdna_gem_obj *abo) 466 + { 467 + struct amdxdna_client *client = abo->client; 468 + 469 + if (amdxdna_gem_skip_bo_usage(abo)) 470 + return; 471 + 472 + guard(mutex)(&client->mm_lock); 473 + 474 + client->total_bo_usage += abo->mem.size; 475 + if (abo->internal) 476 + client->total_int_bo_usage += abo->mem.size; 477 + } 478 + 479 + static void 480 + amdxdna_gem_del_bo_usage(struct amdxdna_gem_obj *abo) 481 + { 482 + struct amdxdna_client *client = abo->client; 483 + 484 + if (amdxdna_gem_skip_bo_usage(abo)) 485 + return; 486 + 487 + guard(mutex)(&client->mm_lock); 488 + 489 + client->total_bo_usage -= abo->mem.size; 490 + if (abo->internal) 491 + client->total_int_bo_usage -= abo->mem.size; 492 + } 493 + 516 494 static void amdxdna_gem_obj_free(struct drm_gem_object *gobj) 517 495 { 518 496 struct amdxdna_dev *xdna = to_xdna_dev(gobj->dev); 519 497 struct amdxdna_gem_obj *abo = to_xdna_obj(gobj); 520 - 521 - XDNA_DBG(xdna, "BO type %d xdna_addr 0x%llx", abo->type, abo->mem.dev_addr); 522 498 523 499 amdxdna_hmm_unregister(abo, NULL); 524 500 flush_workqueue(xdna->notifier_wq); ··· 571 463 if (abo->type == AMDXDNA_BO_DEV_HEAP) 572 464 drm_mm_takedown(&abo->mm); 573 465 574 - amdxdna_gem_obj_vunmap(abo); 466 + if (amdxdna_iova_on(xdna)) 467 + amdxdna_iommu_unmap_bo(xdna, abo); 468 + 469 + amdxdna_gem_vunmap(abo); 575 470 mutex_destroy(&abo->lock); 576 471 577 - if (is_import_bo(abo)) { 472 + if (is_import_bo(abo)) 578 473 amdxdna_imported_obj_free(abo); 579 - return; 580 - } 581 - 582 - drm_gem_shmem_free(&abo->base); 474 + else 475 + drm_gem_shmem_free(&abo->base); 583 476 } 584 477 585 478 static int amdxdna_gem_obj_open(struct drm_gem_object *gobj, struct drm_file *filp) ··· 590 481 int ret; 591 482 592 483 guard(mutex)(&abo->lock); 593 - if (abo->ref) { 594 - abo->ref++; 595 - return 0; 596 - } 484 + abo->open_ref++; 597 485 486 + if (abo->open_ref == 1) { 487 + /* Attached to the client when first opened by it. */ 488 + abo->client = filp->driver_priv; 489 + amdxdna_gem_add_bo_usage(abo); 490 + } 598 491 if (amdxdna_iova_on(xdna)) { 599 492 ret = amdxdna_iommu_map_bo(xdna, abo); 600 493 if (ret) 601 494 return ret; 602 495 } 603 - abo->ref++; 604 496 605 497 return 0; 606 498 } 607 499 608 500 static void amdxdna_gem_obj_close(struct drm_gem_object *gobj, struct drm_file *filp) 609 501 { 610 - struct amdxdna_dev *xdna = to_xdna_dev(gobj->dev); 611 502 struct amdxdna_gem_obj *abo = to_xdna_obj(gobj); 612 503 613 504 guard(mutex)(&abo->lock); 614 - abo->ref--; 615 - if (abo->ref) 616 - return; 505 + abo->open_ref--; 617 506 618 - if (amdxdna_iova_on(xdna)) 619 - amdxdna_iommu_unmap_bo(xdna, abo); 507 + if (abo->open_ref == 0) { 508 + amdxdna_gem_del_bo_usage(abo); 509 + /* Detach from the client when last closed by it. */ 510 + abo->client = NULL; 511 + } 512 + } 513 + 514 + static int amdxdna_gem_dev_obj_vmap(struct drm_gem_object *obj, struct iosys_map *map) 515 + { 516 + struct amdxdna_gem_obj *abo = to_xdna_obj(obj); 517 + void *base = amdxdna_gem_vmap(abo->client->dev_heap); 518 + u64 offset = amdxdna_dev_bo_offset(abo); 519 + 520 + if (!base) 521 + return -ENOMEM; 522 + iosys_map_set_vaddr(map, base + offset); 523 + return 0; 620 524 } 621 525 622 526 static const struct drm_gem_object_funcs amdxdna_gem_dev_obj_funcs = { 623 527 .free = amdxdna_gem_dev_obj_free, 528 + .vmap = amdxdna_gem_dev_obj_vmap, 624 529 }; 625 530 626 531 static const struct drm_gem_object_funcs amdxdna_gem_shmem_funcs = { ··· 652 529 .export = amdxdna_gem_prime_export, 653 530 }; 654 531 655 - static struct amdxdna_gem_obj * 656 - amdxdna_gem_create_obj(struct drm_device *dev, size_t size) 657 - { 658 - struct amdxdna_gem_obj *abo; 659 - 660 - abo = kzalloc_obj(*abo); 661 - if (!abo) 662 - return ERR_PTR(-ENOMEM); 663 - 664 - abo->pinned = false; 665 - abo->assigned_hwctx = AMDXDNA_INVALID_CTX_HANDLE; 666 - mutex_init(&abo->lock); 667 - 668 - abo->mem.userptr = AMDXDNA_INVALID_ADDR; 669 - abo->mem.dev_addr = AMDXDNA_INVALID_ADDR; 670 - abo->mem.dma_addr = AMDXDNA_INVALID_ADDR; 671 - abo->mem.size = size; 672 - INIT_LIST_HEAD(&abo->mem.umap_list); 673 - 674 - return abo; 675 - } 676 - 677 532 /* For drm_driver->gem_create_object callback */ 678 533 struct drm_gem_object * 679 - amdxdna_gem_create_object_cb(struct drm_device *dev, size_t size) 534 + amdxdna_gem_create_shmem_object_cb(struct drm_device *dev, size_t size) 680 535 { 681 536 struct amdxdna_gem_obj *abo; 682 537 ··· 668 567 } 669 568 670 569 static struct amdxdna_gem_obj * 671 - amdxdna_gem_create_shmem_object(struct drm_device *dev, size_t size) 570 + amdxdna_gem_create_shmem_object(struct drm_device *dev, struct amdxdna_drm_create_bo *args) 672 571 { 572 + size_t size = args->size; 673 573 struct drm_gem_shmem_object *shmem = drm_gem_shmem_create(dev, size); 674 574 675 575 if (IS_ERR(shmem)) ··· 684 582 amdxdna_gem_create_ubuf_object(struct drm_device *dev, struct amdxdna_drm_create_bo *args) 685 583 { 686 584 struct amdxdna_dev *xdna = to_xdna_dev(dev); 687 - enum amdxdna_ubuf_flag flags = 0; 688 585 struct amdxdna_drm_va_tbl va_tbl; 689 586 struct drm_gem_object *gobj; 690 587 struct dma_buf *dma_buf; ··· 694 593 } 695 594 696 595 if (va_tbl.num_entries) { 697 - if (args->type == AMDXDNA_BO_CMD) 698 - flags |= AMDXDNA_UBUF_FLAG_MAP_DMA; 699 - 700 - dma_buf = amdxdna_get_ubuf(dev, flags, va_tbl.num_entries, 596 + dma_buf = amdxdna_get_ubuf(dev, va_tbl.num_entries, 701 597 u64_to_user_ptr(args->vaddr + sizeof(va_tbl))); 702 598 } else { 703 599 dma_buf = dma_buf_get(va_tbl.dmabuf_fd); ··· 712 614 dma_buf_put(dma_buf); 713 615 714 616 return to_xdna_obj(gobj); 715 - } 716 - 717 - static struct amdxdna_gem_obj * 718 - amdxdna_gem_create_object(struct drm_device *dev, 719 - struct amdxdna_drm_create_bo *args) 720 - { 721 - size_t aligned_sz = PAGE_ALIGN(args->size); 722 - 723 - if (args->vaddr) 724 - return amdxdna_gem_create_ubuf_object(dev, args); 725 - 726 - return amdxdna_gem_create_shmem_object(dev, aligned_sz); 727 617 } 728 618 729 619 struct drm_gem_object * ··· 746 660 abo = to_xdna_obj(gobj); 747 661 abo->attach = attach; 748 662 abo->dma_buf = dma_buf; 749 - abo->type = AMDXDNA_BO_SHMEM; 663 + abo->type = AMDXDNA_BO_SHARE; 664 + gobj->resv = dma_buf->resv; 750 665 751 666 return gobj; 752 667 ··· 762 675 } 763 676 764 677 static struct amdxdna_gem_obj * 765 - amdxdna_drm_alloc_shmem(struct drm_device *dev, 766 - struct amdxdna_drm_create_bo *args, 767 - struct drm_file *filp) 678 + amdxdna_drm_create_share_bo(struct drm_device *dev, 679 + struct amdxdna_drm_create_bo *args, struct drm_file *filp) 768 680 { 769 - struct amdxdna_client *client = filp->driver_priv; 770 681 struct amdxdna_gem_obj *abo; 771 682 772 - abo = amdxdna_gem_create_object(dev, args); 683 + if (args->vaddr) 684 + abo = amdxdna_gem_create_ubuf_object(dev, args); 685 + else 686 + abo = amdxdna_gem_create_shmem_object(dev, args); 773 687 if (IS_ERR(abo)) 774 688 return ERR_CAST(abo); 775 689 776 - abo->client = client; 777 - abo->type = AMDXDNA_BO_SHMEM; 690 + if (args->type == AMDXDNA_BO_DEV_HEAP) { 691 + abo->type = AMDXDNA_BO_DEV_HEAP; 692 + abo->internal = true; 693 + } else { 694 + abo->type = AMDXDNA_BO_SHARE; 695 + abo->internal = args->type == AMDXDNA_BO_CMD; 696 + } 778 697 779 698 return abo; 780 699 } 781 700 782 701 static struct amdxdna_gem_obj * 783 - amdxdna_drm_create_dev_heap(struct drm_device *dev, 784 - struct amdxdna_drm_create_bo *args, 785 - struct drm_file *filp) 702 + amdxdna_drm_create_dev_heap_bo(struct drm_device *dev, 703 + struct amdxdna_drm_create_bo *args, struct drm_file *filp) 786 704 { 787 705 struct amdxdna_client *client = filp->driver_priv; 788 706 struct amdxdna_dev *xdna = to_xdna_dev(dev); 789 707 struct amdxdna_gem_obj *abo; 790 708 int ret; 791 709 792 - if (args->size > xdna->dev_info->dev_mem_size) { 793 - XDNA_DBG(xdna, "Invalid dev heap size 0x%llx, limit 0x%lx", 710 + WARN_ON(!is_power_of_2(xdna->dev_info->dev_mem_size)); 711 + XDNA_DBG(xdna, "Requested dev heap size 0x%llx", args->size); 712 + if (!args->size || !IS_ALIGNED(args->size, xdna->dev_info->dev_mem_size)) { 713 + XDNA_ERR(xdna, "The dev heap size 0x%llx is not multiple of 0x%lx", 794 714 args->size, xdna->dev_info->dev_mem_size); 795 715 return ERR_PTR(-EINVAL); 796 716 } 797 717 718 + /* HEAP BO is a special case of SHARE BO. */ 719 + abo = amdxdna_drm_create_share_bo(dev, args, filp); 720 + if (IS_ERR(abo)) 721 + return ERR_CAST(abo); 722 + 723 + /* Set up heap for this client. */ 798 724 mutex_lock(&client->mm_lock); 725 + 799 726 if (client->dev_heap) { 800 727 XDNA_DBG(client->xdna, "dev heap is already created"); 801 728 ret = -EBUSY; 802 729 goto mm_unlock; 803 730 } 804 - 805 - abo = amdxdna_gem_create_object(dev, args); 806 - if (IS_ERR(abo)) { 807 - ret = PTR_ERR(abo); 808 - goto mm_unlock; 809 - } 810 - 811 - abo->type = AMDXDNA_BO_DEV_HEAP; 812 - abo->client = client; 813 - abo->mem.dev_addr = client->xdna->dev_info->dev_mem_base; 814 - drm_mm_init(&abo->mm, abo->mem.dev_addr, abo->mem.size); 815 - 816 - ret = amdxdna_gem_obj_vmap(abo, &abo->mem.kva); 817 - if (ret) { 818 - XDNA_ERR(xdna, "Vmap heap bo failed, ret %d", ret); 819 - goto release_obj; 820 - } 821 - 822 731 client->dev_heap = abo; 823 732 drm_gem_object_get(to_gobj(abo)); 733 + 734 + drm_mm_init(&abo->mm, xdna->dev_info->dev_mem_base, abo->mem.size); 735 + 824 736 mutex_unlock(&client->mm_lock); 825 737 826 738 return abo; 827 739 828 - release_obj: 829 - drm_gem_object_put(to_gobj(abo)); 830 740 mm_unlock: 831 741 mutex_unlock(&client->mm_lock); 742 + drm_gem_object_put(to_gobj(abo)); 832 743 return ERR_PTR(ret); 833 744 } 834 745 835 746 struct amdxdna_gem_obj * 836 - amdxdna_drm_alloc_dev_bo(struct drm_device *dev, 837 - struct amdxdna_drm_create_bo *args, 838 - struct drm_file *filp) 747 + amdxdna_drm_create_dev_bo(struct drm_device *dev, 748 + struct amdxdna_drm_create_bo *args, struct drm_file *filp) 839 749 { 750 + size_t aligned_sz = PAGE_ALIGN(args->size); 840 751 struct amdxdna_client *client = filp->driver_priv; 841 752 struct amdxdna_dev *xdna = to_xdna_dev(dev); 842 - size_t aligned_sz = PAGE_ALIGN(args->size); 843 753 struct amdxdna_gem_obj *abo; 754 + struct drm_gem_object *gobj; 844 755 int ret; 845 756 846 - abo = amdxdna_gem_create_obj(&xdna->ddev, aligned_sz); 757 + if (!aligned_sz) { 758 + XDNA_ERR(xdna, "Invalid BO size 0x%llx", args->size); 759 + return ERR_PTR(-EINVAL); 760 + } 761 + 762 + abo = amdxdna_gem_create_obj(dev, aligned_sz); 847 763 if (IS_ERR(abo)) 848 764 return abo; 849 - 850 - to_gobj(abo)->funcs = &amdxdna_gem_dev_obj_funcs; 765 + gobj = to_gobj(abo); 766 + gobj->funcs = &amdxdna_gem_dev_obj_funcs; 851 767 abo->type = AMDXDNA_BO_DEV; 768 + abo->internal = true; 769 + /* 770 + * DEV BOs cannot be alive when client is gone, it's OK to 771 + * always establish the connection. 772 + */ 852 773 abo->client = client; 853 774 854 775 ret = amdxdna_gem_heap_alloc(abo); ··· 865 770 amdxdna_gem_destroy_obj(abo); 866 771 return ERR_PTR(ret); 867 772 } 868 - 869 - drm_gem_private_object_init(&xdna->ddev, to_gobj(abo), aligned_sz); 870 - 871 - return abo; 872 - } 873 - 874 - static struct amdxdna_gem_obj * 875 - amdxdna_drm_create_cmd_bo(struct drm_device *dev, 876 - struct amdxdna_drm_create_bo *args, 877 - struct drm_file *filp) 878 - { 879 - struct amdxdna_dev *xdna = to_xdna_dev(dev); 880 - struct amdxdna_gem_obj *abo; 881 - 882 - if (args->size < sizeof(struct amdxdna_cmd)) { 883 - XDNA_DBG(xdna, "Command BO size 0x%llx too small", args->size); 884 - return ERR_PTR(-EINVAL); 885 - } 886 - 887 - abo = amdxdna_gem_create_object(dev, args); 888 - if (IS_ERR(abo)) 889 - return ERR_CAST(abo); 890 - 891 - abo->type = AMDXDNA_BO_CMD; 892 - abo->client = filp->driver_priv; 773 + drm_gem_private_object_init(dev, gobj, aligned_sz); 893 774 894 775 return abo; 895 776 } ··· 883 812 XDNA_DBG(xdna, "BO arg type %d vaddr 0x%llx size 0x%llx flags 0x%llx", 884 813 args->type, args->vaddr, args->size, args->flags); 885 814 switch (args->type) { 886 - case AMDXDNA_BO_SHMEM: 887 - abo = amdxdna_drm_alloc_shmem(dev, args, filp); 815 + case AMDXDNA_BO_CMD: 816 + fallthrough; 817 + case AMDXDNA_BO_SHARE: 818 + abo = amdxdna_drm_create_share_bo(dev, args, filp); 888 819 break; 889 820 case AMDXDNA_BO_DEV_HEAP: 890 - abo = amdxdna_drm_create_dev_heap(dev, args, filp); 821 + abo = amdxdna_drm_create_dev_heap_bo(dev, args, filp); 891 822 break; 892 823 case AMDXDNA_BO_DEV: 893 - abo = amdxdna_drm_alloc_dev_bo(dev, args, filp); 894 - break; 895 - case AMDXDNA_BO_CMD: 896 - abo = amdxdna_drm_create_cmd_bo(dev, args, filp); 824 + abo = amdxdna_drm_create_dev_bo(dev, args, filp); 897 825 break; 898 826 default: 899 827 return -EINVAL; ··· 900 830 if (IS_ERR(abo)) 901 831 return PTR_ERR(abo); 902 832 903 - /* ready to publish object to userspace */ 833 + /* Ready to publish object to userspace and count for BO usage. */ 904 834 ret = drm_gem_handle_create(filp, to_gobj(abo), &args->handle); 905 835 if (ret) { 906 836 XDNA_ERR(xdna, "Create handle failed"); ··· 908 838 } 909 839 910 840 XDNA_DBG(xdna, "BO hdl %d type %d userptr 0x%llx xdna_addr 0x%llx size 0x%lx", 911 - args->handle, args->type, abo->mem.userptr, 912 - abo->mem.dev_addr, abo->mem.size); 841 + args->handle, args->type, amdxdna_gem_uva(abo), 842 + amdxdna_gem_dev_addr(abo), abo->mem.size); 913 843 put_obj: 914 844 /* Dereference object reference. Handle holds it now. */ 915 845 drm_gem_object_put(to_gobj(abo)); ··· 960 890 struct amdxdna_gem_obj *amdxdna_gem_get_obj(struct amdxdna_client *client, 961 891 u32 bo_hdl, u8 bo_type) 962 892 { 963 - struct amdxdna_dev *xdna = client->xdna; 964 893 struct amdxdna_gem_obj *abo; 965 894 struct drm_gem_object *gobj; 966 - int ret; 967 895 968 896 gobj = drm_gem_object_lookup(client->filp, bo_hdl); 969 897 if (!gobj) { 970 - XDNA_DBG(xdna, "Can not find bo %d", bo_hdl); 898 + XDNA_DBG(client->xdna, "Can not find bo %d", bo_hdl); 971 899 return NULL; 972 900 } 973 901 974 902 abo = to_xdna_obj(gobj); 975 - if (bo_type != AMDXDNA_BO_INVALID && abo->type != bo_type) 976 - goto put_obj; 977 - 978 - if (bo_type != AMDXDNA_BO_CMD || abo->mem.kva) 903 + if (bo_type == AMDXDNA_BO_INVALID || abo->type == bo_type) 979 904 return abo; 980 905 981 - if (abo->mem.size > SZ_32K) { 982 - XDNA_ERR(xdna, "Cmd bo is too big %ld", abo->mem.size); 983 - goto put_obj; 984 - } 985 - 986 - ret = amdxdna_gem_obj_vmap(abo, &abo->mem.kva); 987 - if (ret) { 988 - XDNA_ERR(xdna, "Vmap cmd bo failed, ret %d", ret); 989 - goto put_obj; 990 - } 991 - 992 - return abo; 993 - 994 - put_obj: 995 906 drm_gem_object_put(gobj); 996 907 return NULL; 997 908 } ··· 995 944 } 996 945 997 946 abo = to_xdna_obj(gobj); 998 - args->vaddr = abo->mem.userptr; 999 - if (abo->mem.dev_addr != AMDXDNA_INVALID_ADDR) 1000 - args->xdna_addr = abo->mem.dev_addr; 1001 - else 1002 - args->xdna_addr = abo->mem.dma_addr; 947 + args->vaddr = amdxdna_gem_uva(abo); 948 + args->xdna_addr = amdxdna_gem_dev_addr(abo); 1003 949 1004 950 if (abo->type != AMDXDNA_BO_DEV) 1005 951 args->map_offset = drm_vma_node_offset_addr(&gobj->vma_node); ··· 1041 993 1042 994 if (is_import_bo(abo)) 1043 995 drm_clflush_sg(abo->base.sgt); 1044 - else if (abo->mem.kva) 1045 - drm_clflush_virt_range(abo->mem.kva + args->offset, args->size); 996 + else if (amdxdna_gem_vmap(abo)) 997 + drm_clflush_virt_range(amdxdna_gem_vmap(abo) + args->offset, args->size); 1046 998 else if (abo->base.pages) 1047 999 drm_clflush_pages(abo->base.pages, gobj->size >> PAGE_SHIFT); 1048 1000 else ··· 1059 1011 put_obj: 1060 1012 drm_gem_object_put(gobj); 1061 1013 return ret; 1014 + } 1015 + 1016 + int amdxdna_drm_get_bo_usage(struct drm_device *dev, struct amdxdna_drm_get_array *args) 1017 + { 1018 + size_t min_sz = min(args->element_size, sizeof(struct amdxdna_drm_bo_usage)); 1019 + char __user *buf = u64_to_user_ptr(args->buffer); 1020 + struct amdxdna_dev *xdna = to_xdna_dev(dev); 1021 + struct amdxdna_client *tmp_client; 1022 + struct amdxdna_drm_bo_usage tmp; 1023 + 1024 + drm_WARN_ON(dev, !mutex_is_locked(&xdna->dev_lock)); 1025 + 1026 + if (args->num_element != 1) 1027 + return -EINVAL; 1028 + 1029 + if (copy_from_user(&tmp, buf, min_sz)) 1030 + return -EFAULT; 1031 + 1032 + if (!tmp.pid) 1033 + return -EINVAL; 1034 + 1035 + tmp.total_usage = 0; 1036 + tmp.internal_usage = 0; 1037 + tmp.heap_usage = 0; 1038 + 1039 + list_for_each_entry(tmp_client, &xdna->client_list, node) { 1040 + if (tmp.pid != tmp_client->pid) 1041 + continue; 1042 + 1043 + mutex_lock(&tmp_client->mm_lock); 1044 + tmp.total_usage += tmp_client->total_bo_usage; 1045 + tmp.internal_usage += tmp_client->total_int_bo_usage; 1046 + tmp.heap_usage += tmp_client->heap_usage; 1047 + mutex_unlock(&tmp_client->mm_lock); 1048 + } 1049 + 1050 + if (copy_to_user(buf, &tmp, min_sz)) 1051 + return -EFAULT; 1052 + 1053 + return 0; 1062 1054 }
+22 -15
drivers/accel/amdxdna/amdxdna_gem.h
··· 24 24 }; 25 25 26 26 struct amdxdna_mem { 27 - u64 userptr; 28 27 void *kva; 29 - u64 dev_addr; 30 28 u64 dma_addr; 31 29 size_t size; 32 - struct page **pages; 33 - u32 nr_pages; 34 30 struct list_head umap_list; 35 31 bool map_invalid; 32 + /* 33 + * Cache the first mmap uva as PASID addr, which can be accessed by driver 34 + * without taking notifier_lock. 35 + */ 36 + u64 uva; 36 37 }; 37 38 38 39 struct amdxdna_gem_obj { ··· 41 40 struct amdxdna_client *client; 42 41 u8 type; 43 42 bool pinned; 44 - struct mutex lock; /* Protects: pinned */ 43 + struct mutex lock; /* Protects: pinned, mem.kva, open_ref */ 45 44 struct amdxdna_mem mem; 46 - u32 ref; 45 + int open_ref; 47 46 48 - /* Below members is uninitialized when needed */ 47 + /* Below members are initialized when needed */ 49 48 struct drm_mm mm; /* For AMDXDNA_BO_DEV_HEAP */ 50 49 struct drm_mm_node mm_node; /* For AMDXDNA_BO_DEV */ 51 50 u32 assigned_hwctx; 52 51 struct dma_buf *dma_buf; 53 52 struct dma_buf_attachment *attach; 53 + 54 + /* True, if BO is managed by XRT, not application */ 55 + bool internal; 54 56 }; 55 57 56 58 #define to_gobj(obj) (&(obj)->base.base) ··· 71 67 drm_gem_object_put(to_gobj(abo)); 72 68 } 73 69 70 + void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo); 71 + u64 amdxdna_gem_uva(struct amdxdna_gem_obj *abo); 72 + u64 amdxdna_gem_dev_addr(struct amdxdna_gem_obj *abo); 73 + 74 74 static inline u64 amdxdna_dev_bo_offset(struct amdxdna_gem_obj *abo) 75 75 { 76 - return abo->mem.dev_addr - abo->client->dev_heap->mem.dev_addr; 76 + return amdxdna_gem_dev_addr(abo) - amdxdna_gem_dev_addr(abo->client->dev_heap); 77 77 } 78 78 79 - static inline u64 amdxdna_obj_dma_addr(struct amdxdna_client *client, 80 - struct amdxdna_gem_obj *abo) 79 + static inline u64 amdxdna_obj_dma_addr(struct amdxdna_gem_obj *abo) 81 80 { 82 - return amdxdna_pasid_on(client) ? abo->mem.userptr : abo->mem.dma_addr; 81 + return amdxdna_pasid_on(abo->client) ? amdxdna_gem_uva(abo) : abo->mem.dma_addr; 83 82 } 84 83 85 84 void amdxdna_umap_put(struct amdxdna_umap *mapp); 86 85 87 86 struct drm_gem_object * 88 - amdxdna_gem_create_object_cb(struct drm_device *dev, size_t size); 87 + amdxdna_gem_create_shmem_object_cb(struct drm_device *dev, size_t size); 89 88 struct drm_gem_object * 90 89 amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); 91 90 struct amdxdna_gem_obj * 92 - amdxdna_drm_alloc_dev_bo(struct drm_device *dev, 93 - struct amdxdna_drm_create_bo *args, 94 - struct drm_file *filp); 91 + amdxdna_drm_create_dev_bo(struct drm_device *dev, 92 + struct amdxdna_drm_create_bo *args, struct drm_file *filp); 95 93 96 94 int amdxdna_gem_pin_nolock(struct amdxdna_gem_obj *abo); 97 95 int amdxdna_gem_pin(struct amdxdna_gem_obj *abo); ··· 102 96 int amdxdna_drm_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); 103 97 int amdxdna_drm_get_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); 104 98 int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); 99 + int amdxdna_drm_get_bo_usage(struct drm_device *dev, struct amdxdna_drm_get_array *args); 105 100 106 101 #endif /* _AMDXDNA_GEM_H_ */
+1 -1
drivers/accel/amdxdna/amdxdna_mailbox.c
··· 499 499 int ret; 500 500 501 501 if (!is_power_of_2(x2i->rb_size) || !is_power_of_2(i2x->rb_size)) { 502 - pr_err("Ring buf size must be power of 2"); 502 + pr_err("Ring buf size must be power of 2\n"); 503 503 return -EINVAL; 504 504 } 505 505
+5 -3
drivers/accel/amdxdna/amdxdna_pci_drv.c
··· 36 36 * 0.5: Support getting telemetry data 37 37 * 0.6: Support preemption 38 38 * 0.7: Support getting power and utilization data 39 + * 0.8: Support BO usage query 39 40 */ 40 41 #define AMDXDNA_DRIVER_MAJOR 0 41 - #define AMDXDNA_DRIVER_MINOR 7 42 + #define AMDXDNA_DRIVER_MINOR 8 42 43 43 44 /* 44 45 * Bind the driver base on (vendor_id, device_id) pair and later use the ··· 121 120 amdxdna_hwctx_remove_all(client); 122 121 xa_destroy(&client->hwctx_xa); 123 122 cleanup_srcu_struct(&client->hwctx_srcu); 124 - mutex_destroy(&client->mm_lock); 125 123 126 124 if (client->dev_heap) 127 125 drm_gem_object_put(to_gobj(client->dev_heap)); 126 + 127 + mutex_destroy(&client->mm_lock); 128 128 129 129 if (!IS_ERR_OR_NULL(client->sva)) 130 130 iommu_sva_unbind_device(client->sva); ··· 247 245 .ioctls = amdxdna_drm_ioctls, 248 246 .num_ioctls = ARRAY_SIZE(amdxdna_drm_ioctls), 249 247 250 - .gem_create_object = amdxdna_gem_create_object_cb, 248 + .gem_create_object = amdxdna_gem_create_shmem_object_cb, 251 249 .gem_prime_import = amdxdna_gem_prime_import, 252 250 }; 253 251
+4
drivers/accel/amdxdna/amdxdna_pci_drv.h
··· 138 138 struct iommu_sva *sva; 139 139 int pasid; 140 140 struct mm_struct *mm; 141 + 142 + size_t heap_usage; 143 + size_t total_bo_usage; 144 + size_t total_int_bo_usage; 141 145 }; 142 146 143 147 #define amdxdna_for_each_hwctx(client, hwctx_id, entry) \
+4 -13
drivers/accel/amdxdna/amdxdna_ubuf.c
··· 17 17 struct amdxdna_ubuf_priv { 18 18 struct page **pages; 19 19 u64 nr_pages; 20 - enum amdxdna_ubuf_flag flags; 21 20 struct mm_struct *mm; 22 21 }; 23 22 ··· 36 37 if (ret) 37 38 goto err_free_sg; 38 39 39 - if (ubuf->flags & AMDXDNA_UBUF_FLAG_MAP_DMA) { 40 - ret = dma_map_sgtable(attach->dev, sg, direction, 0); 41 - if (ret) 42 - goto err_free_table; 43 - } 40 + ret = dma_map_sgtable(attach->dev, sg, direction, 0); 41 + if (ret) 42 + goto err_free_table; 44 43 45 44 return sg; 46 45 ··· 53 56 struct sg_table *sg, 54 57 enum dma_data_direction direction) 55 58 { 56 - struct amdxdna_ubuf_priv *ubuf = attach->dmabuf->priv; 57 - 58 - if (ubuf->flags & AMDXDNA_UBUF_FLAG_MAP_DMA) 59 - dma_unmap_sgtable(attach->dev, sg, direction, 0); 60 - 59 + dma_unmap_sgtable(attach->dev, sg, direction, 0); 61 60 sg_free_table(sg); 62 61 kfree(sg); 63 62 } ··· 126 133 }; 127 134 128 135 struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev, 129 - enum amdxdna_ubuf_flag flags, 130 136 u32 num_entries, void __user *va_entries) 131 137 { 132 138 struct amdxdna_dev *xdna = to_xdna_dev(dev); ··· 144 152 if (!ubuf) 145 153 return ERR_PTR(-ENOMEM); 146 154 147 - ubuf->flags = flags; 148 155 ubuf->mm = current->mm; 149 156 mmgrab(ubuf->mm); 150 157
-5
drivers/accel/amdxdna/amdxdna_ubuf.h
··· 8 8 #include <drm/drm_device.h> 9 9 #include <linux/dma-buf.h> 10 10 11 - enum amdxdna_ubuf_flag { 12 - AMDXDNA_UBUF_FLAG_MAP_DMA = 1, 13 - }; 14 - 15 11 struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev, 16 - enum amdxdna_ubuf_flag flags, 17 12 u32 num_entries, void __user *va_entries); 18 13 19 14 #endif /* _AMDXDNA_UBUF_H_ */
-1
drivers/gpu/drm/Kconfig.debug
··· 85 85 86 86 config DRM_TTM_KUNIT_TEST 87 87 tristate "KUnit tests for TTM" if !KUNIT_ALL_TESTS 88 - default n 89 88 depends on DRM && KUNIT && MMU && (UML || COMPILE_TEST) 90 89 select DRM_TTM 91 90 select DRM_BUDDY
+29 -26
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 4905 4905 kfree(dm_state); 4906 4906 } 4907 4907 4908 + static struct drm_private_state * 4909 + dm_atomic_create_state(struct drm_private_obj *obj) 4910 + { 4911 + struct amdgpu_device *adev = drm_to_adev(obj->dev); 4912 + struct dm_atomic_state *dm_state; 4913 + struct dc_state *context; 4914 + 4915 + dm_state = kzalloc_obj(*dm_state); 4916 + if (!dm_state) 4917 + return ERR_PTR(-ENOMEM); 4918 + 4919 + context = dc_state_create_current_copy(adev->dm.dc); 4920 + if (!context) { 4921 + kfree(dm_state); 4922 + return ERR_PTR(-ENOMEM); 4923 + } 4924 + 4925 + __drm_atomic_helper_private_obj_create_state(obj, &dm_state->base); 4926 + dm_state->context = context; 4927 + 4928 + return &dm_state->base; 4929 + } 4930 + 4908 4931 static struct drm_private_state_funcs dm_atomic_state_funcs = { 4932 + .atomic_create_state = dm_atomic_create_state, 4909 4933 .atomic_duplicate_state = dm_atomic_duplicate_state, 4910 4934 .atomic_destroy_state = dm_atomic_destroy_state, 4911 4935 }; 4912 4936 4913 4937 static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) 4914 4938 { 4915 - struct dm_atomic_state *state; 4916 4939 int r; 4917 4940 4918 4941 adev->mode_info.mode_config_initialized = true; ··· 4955 4932 /* indicates support for immediate flip */ 4956 4933 adev_to_drm(adev)->mode_config.async_page_flip = true; 4957 4934 4958 - state = kzalloc_obj(*state); 4959 - if (!state) 4960 - return -ENOMEM; 4961 - 4962 - state->context = dc_state_create_current_copy(adev->dm.dc); 4963 - if (!state->context) { 4964 - kfree(state); 4965 - return -ENOMEM; 4966 - } 4967 - 4968 4935 drm_atomic_private_obj_init(adev_to_drm(adev), 4969 4936 &adev->dm.atomic_obj, 4970 - &state->base, 4971 4937 &dm_atomic_state_funcs); 4972 4938 4973 4939 r = amdgpu_display_modeset_create_props(adev); 4974 - if (r) { 4975 - dc_state_release(state->context); 4976 - kfree(state); 4940 + if (r) 4977 4941 return r; 4978 - } 4979 4942 4980 4943 #ifdef AMD_PRIVATE_COLOR 4981 - if (amdgpu_dm_create_color_properties(adev)) { 4982 - dc_state_release(state->context); 4983 - kfree(state); 4944 + if (amdgpu_dm_create_color_properties(adev)) 4984 4945 return -ENOMEM; 4985 - } 4986 4946 #endif 4987 4947 4988 4948 r = amdgpu_dm_audio_init(adev); 4989 - if (r) { 4990 - dc_state_release(state->context); 4991 - kfree(state); 4949 + if (r) 4992 4950 return r; 4993 - } 4994 4951 4995 4952 return 0; 4996 4953 } ··· 6721 6718 && aconnector 6722 6719 && aconnector->force_yuv420_output) 6723 6720 timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; 6724 - else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR422) 6721 + else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422)) 6725 6722 && aconnector 6726 6723 && aconnector->force_yuv422_output) 6727 6724 timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR422; 6728 - else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR444) 6725 + else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444)) 6729 6726 && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) 6730 6727 timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444; 6731 6728 else
+1
drivers/gpu/drm/arm/display/include/malidp_product.h
··· 20 20 /* Mali-display product IDs */ 21 21 #define MALIDP_D71_PRODUCT_ID 0x0071 22 22 #define MALIDP_D32_PRODUCT_ID 0x0032 23 + #define LINLONDP_D6_PRODUCT_ID 0x0060 23 24 24 25 union komeda_config_id { 25 26 struct {
+7 -7
drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
··· 1080 1080 mask |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420; 1081 1081 1082 1082 /* config color format */ 1083 - if (st->color_format == DRM_COLOR_FORMAT_YCBCR420) 1083 + if (st->color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR420) 1084 1084 ctrl |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420; 1085 - else if (st->color_format == DRM_COLOR_FORMAT_YCBCR422) 1085 + else if (st->color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR422) 1086 1086 ctrl |= IPS_CTRL_YUV | IPS_CTRL_CHD422; 1087 - else if (st->color_format == DRM_COLOR_FORMAT_YCBCR444) 1087 + else if (st->color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR444) 1088 1088 ctrl |= IPS_CTRL_YUV; 1089 1089 1090 1090 malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl); ··· 1145 1145 1146 1146 improc = to_improc(c); 1147 1147 improc->supported_color_depths = BIT(8) | BIT(10); 1148 - improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 | 1149 - DRM_COLOR_FORMAT_YCBCR444 | 1150 - DRM_COLOR_FORMAT_YCBCR422; 1148 + improc->supported_color_formats = BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | 1149 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) | 1150 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422); 1151 1151 value = malidp_read32(reg, BLK_INFO); 1152 1152 if (value & IPS_INFO_CHD420) 1153 - improc->supported_color_formats |= DRM_COLOR_FORMAT_YCBCR420; 1153 + improc->supported_color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420); 1154 1154 1155 1155 improc->supports_csc = true; 1156 1156 improc->supports_gamma = true;
+1
drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
··· 628 628 switch (product_id) { 629 629 case MALIDP_D71_PRODUCT_ID: 630 630 case MALIDP_D32_PRODUCT_ID: 631 + case LINLONDP_D6_PRODUCT_ID: 631 632 funcs = &d71_chip_funcs; 632 633 break; 633 634 default:
+1 -1
drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
··· 40 40 41 41 /* connector doesn't config any color_format, use RGB444 as default */ 42 42 if (!conn_color_formats) 43 - conn_color_formats = DRM_COLOR_FORMAT_RGB444; 43 + conn_color_formats = BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444); 44 44 45 45 *color_depths = GENMASK(min_bpc, 0); 46 46 *color_formats = conn_color_formats;
+1
drivers/gpu/drm/arm/display/komeda/komeda_drv.c
··· 104 104 static const struct of_device_id komeda_of_match[] = { 105 105 { .compatible = "arm,mali-d71", .data = d71_identify, }, 106 106 { .compatible = "arm,mali-d32", .data = d71_identify, }, 107 + { .compatible = "armchina,linlon-d6", .data = d71_identify, }, 107 108 {}, 108 109 }; 109 110
+3 -2
drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
··· 319 319 320 320 struct komeda_improc { 321 321 struct komeda_component base; 322 - u32 supported_color_formats; /* DRM_RGB/YUV444/YUV420*/ 322 + u32 supported_color_formats; /* BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444/YUV444/YUV420) */ 323 323 u32 supported_color_depths; /* BIT(8) | BIT(10)*/ 324 324 u8 supports_degamma : 1; 325 325 u8 supports_csc : 1; ··· 328 328 329 329 struct komeda_improc_state { 330 330 struct komeda_component_state base; 331 - u8 color_format, color_depth; 331 + enum drm_output_color_format color_format; 332 + u8 color_depth; 332 333 u16 hsize, vsize; 333 334 u32 fgamma_coeffs[KOMEDA_N_GAMMA_COEFFS]; 334 335 u32 ctm_coeffs[KOMEDA_N_CTM_COEFFS];
+1 -1
drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
··· 799 799 } 800 800 801 801 st->color_depth = __fls(avail_depths); 802 - st->color_format = BIT(__ffs(avail_formats)); 802 + st->color_format = __ffs(avail_formats); 803 803 } 804 804 805 805 if (kcrtc_st->base.color_mgmt_changed) {
+8 -8
drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
··· 65 65 static int komeda_layer_obj_add(struct komeda_kms_dev *kms, 66 66 struct komeda_layer *layer) 67 67 { 68 - drm_atomic_private_obj_init(&kms->base, &layer->base.obj, NULL, 68 + drm_atomic_private_obj_init(&kms->base, &layer->base.obj, 69 69 &komeda_layer_obj_funcs); 70 70 return 0; 71 71 } ··· 118 118 struct komeda_scaler *scaler) 119 119 { 120 120 drm_atomic_private_obj_init(&kms->base, 121 - &scaler->base.obj, NULL, 121 + &scaler->base.obj, 122 122 &komeda_scaler_obj_funcs); 123 123 return 0; 124 124 } ··· 170 170 static int komeda_compiz_obj_add(struct komeda_kms_dev *kms, 171 171 struct komeda_compiz *compiz) 172 172 { 173 - drm_atomic_private_obj_init(&kms->base, &compiz->base.obj, NULL, 173 + drm_atomic_private_obj_init(&kms->base, &compiz->base.obj, 174 174 &komeda_compiz_obj_funcs); 175 175 176 176 return 0; ··· 224 224 struct komeda_splitter *splitter) 225 225 { 226 226 drm_atomic_private_obj_init(&kms->base, 227 - &splitter->base.obj, NULL, 227 + &splitter->base.obj, 228 228 &komeda_splitter_obj_funcs); 229 229 230 230 return 0; ··· 277 277 struct komeda_merger *merger) 278 278 { 279 279 drm_atomic_private_obj_init(&kms->base, 280 - &merger->base.obj, NULL, 280 + &merger->base.obj, 281 281 &komeda_merger_obj_funcs); 282 282 283 283 return 0; ··· 330 330 static int komeda_improc_obj_add(struct komeda_kms_dev *kms, 331 331 struct komeda_improc *improc) 332 332 { 333 - drm_atomic_private_obj_init(&kms->base, &improc->base.obj, NULL, 333 + drm_atomic_private_obj_init(&kms->base, &improc->base.obj, 334 334 &komeda_improc_obj_funcs); 335 335 336 336 return 0; ··· 383 383 static int komeda_timing_ctrlr_obj_add(struct komeda_kms_dev *kms, 384 384 struct komeda_timing_ctrlr *ctrlr) 385 385 { 386 - drm_atomic_private_obj_init(&kms->base, &ctrlr->base.obj, NULL, 386 + drm_atomic_private_obj_init(&kms->base, &ctrlr->base.obj, 387 387 &komeda_timing_ctrlr_obj_funcs); 388 388 389 389 return 0; ··· 437 437 static int komeda_pipeline_obj_add(struct komeda_kms_dev *kms, 438 438 struct komeda_pipeline *pipe) 439 439 { 440 - drm_atomic_private_obj_init(&kms->base, &pipe->obj, NULL, 440 + drm_atomic_private_obj_init(&kms->base, &pipe->obj, 441 441 &komeda_pipeline_obj_funcs); 442 442 443 443 return 0;
+1
drivers/gpu/drm/bridge/Kconfig
··· 194 194 config DRM_LONTIUM_LT8713SX 195 195 tristate "Lontium LT8713SX DP MST bridge" 196 196 depends on OF 197 + select CRC8 197 198 select REGMAP_I2C 198 199 help 199 200 Driver for Lontium LT8713SX DP MST bridge
+1 -1
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
··· 228 228 config.csc_coefficents = adv7511_csc_ycbcr_to_rgb; 229 229 230 230 if ((connector->display_info.color_formats & 231 - DRM_COLOR_FORMAT_YCBCR422) && 231 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422)) && 232 232 connector->display_info.is_hdmi) { 233 233 config.csc_enable = false; 234 234 output_format_422 = true;
+22 -113
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
··· 281 281 if (retval < 0) 282 282 return retval; 283 283 284 - for (lane = 0; lane < lane_count; lane++) 285 - buf[lane] = DP_TRAIN_PRE_EMPH_LEVEL_0 | 286 - DP_TRAIN_VOLTAGE_SWING_LEVEL_0; 287 - 288 - retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, buf, 289 - lane_count); 284 + retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, 285 + dp->link_train.training_lane, lane_count); 290 286 if (retval < 0) 291 287 return retval; 292 288 293 289 return 0; 294 - } 295 - 296 - static unsigned char analogix_dp_get_lane_status(u8 link_status[2], int lane) 297 - { 298 - int shift = (lane & 1) * 4; 299 - u8 link_value = link_status[lane >> 1]; 300 - 301 - return (link_value >> shift) & 0xf; 302 - } 303 - 304 - static int analogix_dp_clock_recovery_ok(u8 link_status[2], int lane_count) 305 - { 306 - int lane; 307 - u8 lane_status; 308 - 309 - for (lane = 0; lane < lane_count; lane++) { 310 - lane_status = analogix_dp_get_lane_status(link_status, lane); 311 - if ((lane_status & DP_LANE_CR_DONE) == 0) 312 - return -EINVAL; 313 - } 314 - return 0; 315 - } 316 - 317 - static int analogix_dp_channel_eq_ok(u8 link_status[2], u8 link_align, 318 - int lane_count) 319 - { 320 - int lane; 321 - u8 lane_status; 322 - 323 - if ((link_align & DP_INTERLANE_ALIGN_DONE) == 0) 324 - return -EINVAL; 325 - 326 - for (lane = 0; lane < lane_count; lane++) { 327 - lane_status = analogix_dp_get_lane_status(link_status, lane); 328 - lane_status &= DP_CHANNEL_EQ_BITS; 329 - if (lane_status != DP_CHANNEL_EQ_BITS) 330 - return -EINVAL; 331 - } 332 - 333 - return 0; 334 - } 335 - 336 - static unsigned char 337 - analogix_dp_get_adjust_request_voltage(u8 adjust_request[2], int lane) 338 - { 339 - int shift = (lane & 1) * 4; 340 - u8 link_value = adjust_request[lane >> 1]; 341 - 342 - return (link_value >> shift) & 0x3; 343 - } 344 - 345 - static unsigned char analogix_dp_get_adjust_request_pre_emphasis( 346 - u8 adjust_request[2], 347 - int lane) 348 - { 349 - int shift = (lane & 1) * 4; 350 - u8 link_value = adjust_request[lane >> 1]; 351 - 352 - return ((link_value >> shift) & 0xc) >> 2; 353 290 } 354 291 355 292 static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp) ··· 298 361 } 299 362 300 363 static void analogix_dp_get_adjust_training_lane(struct analogix_dp_device *dp, 301 - u8 adjust_request[2]) 364 + u8 link_status[DP_LINK_STATUS_SIZE]) 302 365 { 303 366 int lane, lane_count; 304 367 u8 voltage_swing, pre_emphasis, training_lane; 305 368 306 369 lane_count = dp->link_train.lane_count; 307 370 for (lane = 0; lane < lane_count; lane++) { 308 - voltage_swing = analogix_dp_get_adjust_request_voltage( 309 - adjust_request, lane); 310 - pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis( 311 - adjust_request, lane); 371 + voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane); 372 + pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane); 312 373 training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | 313 374 DPCD_PRE_EMPHASIS_SET(pre_emphasis); 314 375 ··· 323 388 { 324 389 int lane, lane_count, retval; 325 390 u8 voltage_swing, pre_emphasis, training_lane; 326 - u8 link_status[2], adjust_request[2]; 391 + u8 link_status[DP_LINK_STATUS_SIZE]; 327 392 328 393 usleep_range(100, 101); 329 394 330 395 lane_count = dp->link_train.lane_count; 331 396 332 - retval = drm_dp_dpcd_read(&dp->aux, DP_LANE0_1_STATUS, link_status, 2); 397 + retval = drm_dp_dpcd_read_link_status(&dp->aux, link_status); 333 398 if (retval < 0) 334 399 return retval; 335 400 336 - if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) { 401 + if (drm_dp_clock_recovery_ok(link_status, lane_count)) { 337 402 /* set training pattern 2 for EQ */ 338 403 analogix_dp_set_training_pattern(dp, TRAINING_PTN2); 339 404 ··· 349 414 return 0; 350 415 } 351 416 352 - retval = drm_dp_dpcd_read(&dp->aux, DP_ADJUST_REQUEST_LANE0_1, 353 - adjust_request, 2); 354 - if (retval < 0) 355 - return retval; 356 - 357 417 for (lane = 0; lane < lane_count; lane++) { 358 418 training_lane = analogix_dp_get_lane_link_training(dp, lane); 359 - voltage_swing = analogix_dp_get_adjust_request_voltage(adjust_request, lane); 360 - pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis(adjust_request, lane); 419 + voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane); 420 + pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane); 361 421 362 422 if (DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing && 363 423 DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis) ··· 369 439 } 370 440 } 371 441 372 - analogix_dp_get_adjust_training_lane(dp, adjust_request); 442 + analogix_dp_get_adjust_training_lane(dp, link_status); 373 443 analogix_dp_set_lane_link_training(dp); 374 444 375 445 retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, ··· 384 454 { 385 455 int lane_count, retval; 386 456 u32 reg; 387 - u8 link_align, link_status[2], adjust_request[2]; 457 + u8 link_status[DP_LINK_STATUS_SIZE]; 388 458 389 459 usleep_range(400, 401); 390 460 391 461 lane_count = dp->link_train.lane_count; 392 462 393 - retval = drm_dp_dpcd_read(&dp->aux, DP_LANE0_1_STATUS, link_status, 2); 463 + retval = drm_dp_dpcd_read_link_status(&dp->aux, link_status); 394 464 if (retval < 0) 395 465 return retval; 396 466 397 - if (analogix_dp_clock_recovery_ok(link_status, lane_count)) { 467 + if (!drm_dp_clock_recovery_ok(link_status, lane_count)) { 398 468 analogix_dp_reduce_link_rate(dp); 399 469 return -EIO; 400 470 } 401 471 402 - retval = drm_dp_dpcd_read(&dp->aux, DP_ADJUST_REQUEST_LANE0_1, 403 - adjust_request, 2); 404 - if (retval < 0) 405 - return retval; 472 + analogix_dp_get_adjust_training_lane(dp, link_status); 406 473 407 - retval = drm_dp_dpcd_readb(&dp->aux, DP_LANE_ALIGN_STATUS_UPDATED, 408 - &link_align); 409 - if (retval < 0) 410 - return retval; 411 - 412 - analogix_dp_get_adjust_training_lane(dp, adjust_request); 413 - 414 - if (!analogix_dp_channel_eq_ok(link_status, link_align, lane_count)) { 474 + if (drm_dp_channel_eq_ok(link_status, lane_count)) { 415 475 /* traing pattern Set to Normal */ 416 476 retval = analogix_dp_training_pattern_dis(dp); 417 477 if (retval < 0) ··· 539 619 static int analogix_dp_fast_link_train(struct analogix_dp_device *dp) 540 620 { 541 621 int ret; 542 - u8 link_align, link_status[2]; 622 + u8 link_status[DP_LINK_STATUS_SIZE]; 543 623 544 624 analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); 545 625 ret = analogix_dp_wait_pll_locked(dp); ··· 573 653 * speed 574 654 */ 575 655 if (verify_fast_training) { 576 - ret = drm_dp_dpcd_readb(&dp->aux, DP_LANE_ALIGN_STATUS_UPDATED, 577 - &link_align); 578 - if (ret < 0) { 579 - DRM_DEV_ERROR(dp->dev, "Read align status failed %d\n", 580 - ret); 581 - return ret; 582 - } 583 - 584 - ret = drm_dp_dpcd_read(&dp->aux, DP_LANE0_1_STATUS, link_status, 585 - 2); 656 + ret = drm_dp_dpcd_read_link_status(&dp->aux, link_status); 586 657 if (ret < 0) { 587 658 DRM_DEV_ERROR(dp->dev, "Read link status failed %d\n", 588 659 ret); 589 660 return ret; 590 661 } 591 662 592 - if (analogix_dp_clock_recovery_ok(link_status, 593 - dp->link_train.lane_count)) { 663 + if (!drm_dp_clock_recovery_ok(link_status, dp->link_train.lane_count)) { 594 664 DRM_DEV_ERROR(dp->dev, "Clock recovery failed\n"); 595 665 analogix_dp_reduce_link_rate(dp); 596 666 return -EIO; 597 667 } 598 668 599 - if (analogix_dp_channel_eq_ok(link_status, link_align, 600 - dp->link_train.lane_count)) { 669 + if (!drm_dp_channel_eq_ok(link_status, dp->link_train.lane_count)) { 601 670 DRM_DEV_ERROR(dp->dev, "Channel EQ failed\n"); 602 671 analogix_dp_reduce_link_rate(dp); 603 672 return -EIO; ··· 1132 1223 video->color_depth = COLOR_8; 1133 1224 break; 1134 1225 } 1135 - if (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR444) 1226 + if (display_info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444)) 1136 1227 video->color_space = COLOR_YCBCR444; 1137 - else if (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR422) 1228 + else if (display_info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422)) 1138 1229 video->color_space = COLOR_YCBCR422; 1139 1230 else 1140 1231 video->color_space = COLOR_RGB;
+12 -12
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
··· 1448 1448 return fmt->bpc; 1449 1449 1450 1450 switch (fmt->color_format) { 1451 - case DRM_COLOR_FORMAT_RGB444: 1452 - case DRM_COLOR_FORMAT_YCBCR444: 1451 + case DRM_OUTPUT_COLOR_FORMAT_RGB444: 1452 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR444: 1453 1453 bpp = fmt->bpc * 3; 1454 1454 break; 1455 - case DRM_COLOR_FORMAT_YCBCR422: 1455 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR422: 1456 1456 bpp = fmt->bpc * 2; 1457 1457 break; 1458 - case DRM_COLOR_FORMAT_YCBCR420: 1458 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR420: 1459 1459 bpp = fmt->bpc * 3 / 2; 1460 1460 break; 1461 1461 default: ··· 1552 1552 * If YCBCR supported and stream not SD, use ITU709 1553 1553 * Need to handle ITU version with YCBCR420 when supported 1554 1554 */ 1555 - if ((pxlfmt == DRM_COLOR_FORMAT_YCBCR444 || 1556 - pxlfmt == DRM_COLOR_FORMAT_YCBCR422) && mode->crtc_vdisplay >= 720) 1555 + if ((pxlfmt == DRM_OUTPUT_COLOR_FORMAT_YCBCR444 || 1556 + pxlfmt == DRM_OUTPUT_COLOR_FORMAT_YCBCR422) && mode->crtc_vdisplay >= 720) 1557 1557 misc0 = DP_YCBCR_COEFFICIENTS_ITU709; 1558 1558 1559 1559 bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt); 1560 1560 1561 1561 switch (pxlfmt) { 1562 - case DRM_COLOR_FORMAT_RGB444: 1562 + case DRM_OUTPUT_COLOR_FORMAT_RGB444: 1563 1563 pxl_repr = CDNS_DP_FRAMER_RGB << CDNS_DP_FRAMER_PXL_FORMAT; 1564 1564 misc0 |= DP_COLOR_FORMAT_RGB; 1565 1565 break; 1566 - case DRM_COLOR_FORMAT_YCBCR444: 1566 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR444: 1567 1567 pxl_repr = CDNS_DP_FRAMER_YCBCR444 << CDNS_DP_FRAMER_PXL_FORMAT; 1568 1568 misc0 |= DP_COLOR_FORMAT_YCbCr444 | DP_TEST_DYNAMIC_RANGE_CEA; 1569 1569 break; 1570 - case DRM_COLOR_FORMAT_YCBCR422: 1570 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR422: 1571 1571 pxl_repr = CDNS_DP_FRAMER_YCBCR422 << CDNS_DP_FRAMER_PXL_FORMAT; 1572 1572 misc0 |= DP_COLOR_FORMAT_YCbCr422 | DP_TEST_DYNAMIC_RANGE_CEA; 1573 1573 break; 1574 - case DRM_COLOR_FORMAT_YCBCR420: 1574 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR420: 1575 1575 pxl_repr = CDNS_DP_FRAMER_YCBCR420 << CDNS_DP_FRAMER_PXL_FORMAT; 1576 1576 break; 1577 1577 default: ··· 1667 1667 if (mhdp->display_fmt.y_only) 1668 1668 misc1 |= CDNS_DP_TEST_COLOR_FORMAT_RAW_Y_ONLY; 1669 1669 /* Use VSC SDP for Y420 */ 1670 - if (pxlfmt == DRM_COLOR_FORMAT_YCBCR420) 1670 + if (pxlfmt == DRM_OUTPUT_COLOR_FORMAT_YCBCR420) 1671 1671 misc1 = CDNS_DP_TEST_VSC_SDP; 1672 1672 1673 1673 cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_MISC(stream_id), ··· 2356 2356 2357 2357 /* The only currently supported format */ 2358 2358 mhdp->display_fmt.y_only = false; 2359 - mhdp->display_fmt.color_format = DRM_COLOR_FORMAT_RGB444; 2359 + mhdp->display_fmt.color_format = DRM_OUTPUT_COLOR_FORMAT_RGB444; 2360 2360 mhdp->display_fmt.bpc = 8; 2361 2361 2362 2362 mhdp->bridge.of_node = pdev->dev.of_node;
+1 -1
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
··· 306 306 }; 307 307 308 308 struct cdns_mhdp_display_fmt { 309 - u32 color_format; 309 + enum drm_output_color_format color_format; 310 310 u32 bpc; 311 311 bool y_only; 312 312 };
+3 -3
drivers/gpu/drm/bridge/inno-hdmi.c
··· 653 653 v_VIDEO_INPUT_CSP(0); 654 654 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value); 655 655 656 - if (conn_state->hdmi.output_format == HDMI_COLORSPACE_RGB) { 656 + if (conn_state->hdmi.output_format == DRM_OUTPUT_COLOR_FORMAT_RGB444) { 657 657 if (conn_state->hdmi.is_limited_range) { 658 658 csc_mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT; 659 659 auto_csc = AUTO_CSC_DISABLE; ··· 672 672 } 673 673 } else { 674 674 if (colorimetry == HDMI_COLORIMETRY_ITU_601) { 675 - if (conn_state->hdmi.output_format == HDMI_COLORSPACE_YUV444) { 675 + if (conn_state->hdmi.output_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR444) { 676 676 csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT; 677 677 auto_csc = AUTO_CSC_DISABLE; 678 678 c0_c2_change = C0_C2_CHANGE_DISABLE; 679 679 csc_enable = v_CSC_ENABLE; 680 680 } 681 681 } else { 682 - if (conn_state->hdmi.output_format == HDMI_COLORSPACE_YUV444) { 682 + if (conn_state->hdmi.output_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR444) { 683 683 csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT; 684 684 auto_csc = AUTO_CSC_DISABLE; 685 685 c0_c2_change = C0_C2_CHANGE_DISABLE;
+1 -1
drivers/gpu/drm/bridge/ite-it6263.c
··· 666 666 { 667 667 unsigned long long rate; 668 668 669 - rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB); 669 + rate = drm_hdmi_compute_mode_clock(mode, 8, DRM_OUTPUT_COLOR_FORMAT_RGB444); 670 670 if (rate == 0) 671 671 return MODE_NOCLOCK; 672 672
+1 -1
drivers/gpu/drm/bridge/lontium-lt8713sx.c
··· 100 100 static int lt8713sx_prepare_firmware_data(struct lt8713sx *lt8713sx) 101 101 { 102 102 int ret = 0; 103 - u64 sz_12k = 12 * SZ_1K; 103 + size_t sz_12k = 12 * SZ_1K; 104 104 105 105 ret = request_firmware(&lt8713sx->fw, FW_FILE, lt8713sx->dev); 106 106 if (ret < 0) {
+2 -5
drivers/gpu/drm/bridge/samsung-dsim.c
··· 1988 1988 return 0; 1989 1989 1990 1990 err_release_next_bridge: 1991 - drm_bridge_put(dsi->bridge.next_bridge); 1992 - dsi->bridge.next_bridge = NULL; 1993 - 1991 + drm_bridge_clear_and_put(&dsi->bridge.next_bridge); 1994 1992 if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) 1995 1993 samsung_dsim_unregister_te_irq(dsi); 1996 1994 err_remove_bridge: ··· 2005 2007 if (pdata->host_ops && pdata->host_ops->detach) 2006 2008 pdata->host_ops->detach(dsi, device); 2007 2009 2008 - drm_bridge_put(dsi->bridge.next_bridge); 2009 - dsi->bridge.next_bridge = NULL; 2010 + drm_bridge_clear_and_put(&dsi->bridge.next_bridge); 2010 2011 2011 2012 samsung_dsim_unregister_te_irq(dsi); 2012 2013
+36 -35
drivers/gpu/drm/bridge/synopsys/dw-dp.c
··· 379 379 380 380 struct dw_dp_output_format { 381 381 u32 bus_format; 382 - u32 color_format; 382 + enum drm_output_color_format color_format; 383 383 u8 video_mapping; 384 384 u8 bpc; 385 385 u8 bpp; ··· 388 388 #define to_dw_dp_bridge_state(s) container_of(s, struct dw_dp_bridge_state, base) 389 389 390 390 static const struct dw_dp_output_format dw_dp_output_formats[] = { 391 - { MEDIA_BUS_FMT_RGB101010_1X30, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_10BIT, 10, 30 }, 392 - { MEDIA_BUS_FMT_RGB888_1X24, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_8BIT, 8, 24 }, 393 - { MEDIA_BUS_FMT_YUV10_1X30, DRM_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_10BIT, 10, 30 }, 394 - { MEDIA_BUS_FMT_YUV8_1X24, DRM_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_8BIT, 8, 24}, 395 - { MEDIA_BUS_FMT_YUYV10_1X20, DRM_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_10BIT, 10, 20 }, 396 - { MEDIA_BUS_FMT_YUYV8_1X16, DRM_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_8BIT, 8, 16 }, 397 - { MEDIA_BUS_FMT_UYYVYY10_0_5X30, DRM_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_10BIT, 10, 15 }, 398 - { MEDIA_BUS_FMT_UYYVYY8_0_5X24, DRM_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_8BIT, 8, 12 }, 399 - { MEDIA_BUS_FMT_RGB666_1X24_CPADHI, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_6BIT, 6, 18 }, 391 + { MEDIA_BUS_FMT_RGB101010_1X30, DRM_OUTPUT_COLOR_FORMAT_RGB444, DW_DP_RGB_10BIT, 10, 30 }, 392 + { MEDIA_BUS_FMT_RGB888_1X24, DRM_OUTPUT_COLOR_FORMAT_RGB444, DW_DP_RGB_8BIT, 8, 24 }, 393 + { MEDIA_BUS_FMT_YUV10_1X30, DRM_OUTPUT_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_10BIT, 10, 30 }, 394 + { MEDIA_BUS_FMT_YUV8_1X24, DRM_OUTPUT_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_8BIT, 8, 24}, 395 + { MEDIA_BUS_FMT_YUYV10_1X20, DRM_OUTPUT_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_10BIT, 10, 20 }, 396 + { MEDIA_BUS_FMT_YUYV8_1X16, DRM_OUTPUT_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_8BIT, 8, 16 }, 397 + { MEDIA_BUS_FMT_UYYVYY10_0_5X30, DRM_OUTPUT_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_10BIT, 10, 15 }, 398 + { MEDIA_BUS_FMT_UYYVYY8_0_5X24, DRM_OUTPUT_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_8BIT, 8, 12 }, 399 + { MEDIA_BUS_FMT_RGB666_1X24_CPADHI, DRM_OUTPUT_COLOR_FORMAT_RGB444, DW_DP_RGB_6BIT, 6, 18 }, 400 400 }; 401 401 402 402 static const struct dw_dp_output_format *dw_dp_get_output_format(u32 bus_format) ··· 1091 1091 sdp.flags = DW_DP_SDP_VERTICAL_INTERVAL; 1092 1092 1093 1093 switch (state->color_format) { 1094 - case DRM_COLOR_FORMAT_YCBCR444: 1094 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR444: 1095 1095 vsc.pixelformat = DP_PIXELFORMAT_YUV444; 1096 1096 break; 1097 - case DRM_COLOR_FORMAT_YCBCR420: 1097 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR420: 1098 1098 vsc.pixelformat = DP_PIXELFORMAT_YUV420; 1099 1099 break; 1100 - case DRM_COLOR_FORMAT_YCBCR422: 1100 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR422: 1101 1101 vsc.pixelformat = DP_PIXELFORMAT_YUV422; 1102 1102 break; 1103 - case DRM_COLOR_FORMAT_RGB444: 1103 + case DRM_OUTPUT_COLOR_FORMAT_RGB444: 1104 1104 default: 1105 1105 vsc.pixelformat = DP_PIXELFORMAT_RGB; 1106 1106 break; 1107 1107 } 1108 1108 1109 - if (state->color_format == DRM_COLOR_FORMAT_RGB444) { 1109 + if (state->color_format == DRM_OUTPUT_COLOR_FORMAT_RGB444) { 1110 1110 vsc.colorimetry = DP_COLORIMETRY_DEFAULT; 1111 1111 vsc.dynamic_range = DP_DYNAMIC_RANGE_VESA; 1112 1112 } else { ··· 1148 1148 if (!link->vsc_sdp_supported) 1149 1149 return false; 1150 1150 1151 - if (state->color_format == DRM_COLOR_FORMAT_YCBCR420) 1151 + if (state->color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR420) 1152 1152 return true; 1153 1153 1154 1154 return false; 1155 1155 } 1156 1156 1157 - static int dw_dp_video_set_msa(struct dw_dp *dp, u8 color_format, u8 bpc, 1158 - u16 vstart, u16 hstart) 1157 + static int dw_dp_video_set_msa(struct dw_dp *dp, 1158 + enum drm_output_color_format color_format, 1159 + u8 bpc, u16 vstart, u16 hstart) 1159 1160 { 1160 1161 u16 misc = 0; 1161 1162 ··· 1164 1163 misc |= DP_MSA_MISC_COLOR_VSC_SDP; 1165 1164 1166 1165 switch (color_format) { 1167 - case DRM_COLOR_FORMAT_RGB444: 1166 + case DRM_OUTPUT_COLOR_FORMAT_RGB444: 1168 1167 misc |= DP_MSA_MISC_COLOR_RGB; 1169 1168 break; 1170 - case DRM_COLOR_FORMAT_YCBCR444: 1169 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR444: 1171 1170 misc |= DP_MSA_MISC_COLOR_YCBCR_444_BT709; 1172 1171 break; 1173 - case DRM_COLOR_FORMAT_YCBCR422: 1172 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR422: 1174 1173 misc |= DP_MSA_MISC_COLOR_YCBCR_422_BT709; 1175 1174 break; 1176 - case DRM_COLOR_FORMAT_YCBCR420: 1175 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR420: 1177 1176 break; 1178 1177 default: 1179 1178 return -EINVAL; ··· 1305 1304 if (dp->pixel_mode == DW_DP_MP_SINGLE_PIXEL) { 1306 1305 if (average_bytes_per_tu < 6) 1307 1306 init_threshold = 32; 1308 - else if (hblank <= 80 && color_format != DRM_COLOR_FORMAT_YCBCR420) 1307 + else if (hblank <= 80 && color_format != DRM_OUTPUT_COLOR_FORMAT_YCBCR420) 1309 1308 init_threshold = 12; 1310 - else if (hblank <= 40 && color_format == DRM_COLOR_FORMAT_YCBCR420) 1309 + else if (hblank <= 40 && color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR420) 1311 1310 init_threshold = 3; 1312 1311 else 1313 1312 init_threshold = 16; ··· 1319 1318 t1 = (4 * 1000 / 9) * link->lanes; 1320 1319 break; 1321 1320 case 8: 1322 - if (color_format == DRM_COLOR_FORMAT_YCBCR422) { 1321 + if (color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR422) { 1323 1322 t1 = (1000 / 2) * link->lanes; 1324 1323 } else { 1325 1324 if (dp->pixel_mode == DW_DP_MP_DUAL_PIXEL) ··· 1329 1328 } 1330 1329 break; 1331 1330 case 10: 1332 - if (color_format == DRM_COLOR_FORMAT_YCBCR422) 1331 + if (color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR422) 1333 1332 t1 = (2000 / 5) * link->lanes; 1334 1333 else 1335 1334 t1 = (4000 / 15) * link->lanes; 1336 1335 break; 1337 1336 case 12: 1338 - if (color_format == DRM_COLOR_FORMAT_YCBCR422) { 1337 + if (color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR422) { 1339 1338 if (dp->pixel_mode == DW_DP_MP_DUAL_PIXEL) 1340 1339 t1 = (1000 / 6) * link->lanes; 1341 1340 else ··· 1345 1344 } 1346 1345 break; 1347 1346 case 16: 1348 - if (color_format != DRM_COLOR_FORMAT_YCBCR422 && 1347 + if (color_format != DRM_OUTPUT_COLOR_FORMAT_YCBCR422 && 1349 1348 dp->pixel_mode == DW_DP_MP_DUAL_PIXEL) 1350 1349 t1 = (1000 / 6) * link->lanes; 1351 1350 else ··· 1355 1354 return -EINVAL; 1356 1355 } 1357 1356 1358 - if (color_format == DRM_COLOR_FORMAT_YCBCR420) 1357 + if (color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR420) 1359 1358 t2 = (link->rate / 4) * 1000 / (mode->clock / 2); 1360 1359 else 1361 1360 t2 = (link->rate / 4) * 1000 / mode->clock; ··· 1575 1574 struct dw_dp_link *link = &dp->link; 1576 1575 u32 min_bpp; 1577 1576 1578 - if (info->color_formats & DRM_COLOR_FORMAT_YCBCR420 && 1577 + if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420) && 1579 1578 link->vsc_sdp_supported && 1580 1579 (drm_mode_is_420_only(info, mode) || drm_mode_is_420_also(info, mode))) 1581 1580 min_bpp = 12; 1582 - else if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) 1581 + else if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422)) 1583 1582 min_bpp = 16; 1584 - else if (info->color_formats & DRM_COLOR_FORMAT_RGB444) 1583 + else if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444)) 1585 1584 min_bpp = 18; 1586 1585 else 1587 1586 min_bpp = 24; ··· 1778 1777 if (fmt->bpc > conn_state->max_bpc) 1779 1778 continue; 1780 1779 1781 - if (!(fmt->color_format & di->color_formats)) 1780 + if (!(BIT(fmt->color_format) & di->color_formats)) 1782 1781 continue; 1783 1782 1784 - if (fmt->color_format == DRM_COLOR_FORMAT_YCBCR420 && 1783 + if (fmt->color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR420 && 1785 1784 !link->vsc_sdp_supported) 1786 1785 continue; 1787 1786 1788 - if (fmt->color_format != DRM_COLOR_FORMAT_YCBCR420 && 1787 + if (fmt->color_format != DRM_OUTPUT_COLOR_FORMAT_YCBCR420 && 1789 1788 drm_mode_is_420_only(di, &mode)) 1790 1789 continue; 1791 1790
+8 -8
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
··· 2664 2664 struct drm_display_mode *mode = &crtc_state->mode; 2665 2665 u8 max_bpc = conn_state->max_requested_bpc; 2666 2666 bool is_hdmi2_sink = info->hdmi.scdc.supported || 2667 - (info->color_formats & DRM_COLOR_FORMAT_YCBCR420); 2667 + (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420)); 2668 2668 u32 *output_fmts; 2669 2669 unsigned int i = 0; 2670 2670 ··· 2723 2723 output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; 2724 2724 2725 2725 if (max_bpc >= 16 && info->bpc == 16) { 2726 - if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) 2726 + if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444)) 2727 2727 output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48; 2728 2728 2729 2729 output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; 2730 2730 } 2731 2731 2732 2732 if (max_bpc >= 12 && info->bpc >= 12) { 2733 - if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) 2733 + if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422)) 2734 2734 output_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24; 2735 2735 2736 - if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) 2736 + if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444)) 2737 2737 output_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36; 2738 2738 2739 2739 output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; 2740 2740 } 2741 2741 2742 2742 if (max_bpc >= 10 && info->bpc >= 10) { 2743 - if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) 2743 + if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422)) 2744 2744 output_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20; 2745 2745 2746 - if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) 2746 + if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444)) 2747 2747 output_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30; 2748 2748 2749 2749 output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; 2750 2750 } 2751 2751 2752 - if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) 2752 + if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422)) 2753 2753 output_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16; 2754 2754 2755 - if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) 2755 + if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444)) 2756 2756 output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24; 2757 2757 2758 2758 *num_output_fmts = i;
+2 -2
drivers/gpu/drm/display/drm_bridge_connector.c
··· 789 789 struct drm_connector *connector; 790 790 struct i2c_adapter *ddc = NULL; 791 791 struct drm_bridge *panel_bridge __free(drm_bridge_put) = NULL; 792 - unsigned int supported_formats = BIT(HDMI_COLORSPACE_RGB); 792 + unsigned int supported_formats = BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444); 793 793 unsigned int max_bpc = 8; 794 794 bool support_hdcp = false; 795 795 int connector_type; ··· 960 960 961 961 if (bridge_connector->bridge_hdmi) { 962 962 if (!connector->ycbcr_420_allowed) 963 - supported_formats &= ~BIT(HDMI_COLORSPACE_YUV420); 963 + supported_formats &= ~BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420); 964 964 965 965 bridge_connector->hdmi_funcs = drm_bridge_connector_hdmi_funcs; 966 966
-1
drivers/gpu/drm/display/drm_dp_mst_topology.c
··· 5765 5765 mgr->conn_base_id = conn_base_id; 5766 5766 5767 5767 drm_atomic_private_obj_init(dev, &mgr->base, 5768 - NULL, 5769 5768 &drm_dp_mst_topology_state_funcs); 5770 5769 5771 5770 return 0;
+1 -1
drivers/gpu/drm/display/drm_dp_tunnel.c
··· 1600 1600 group->available_bw = -1; 1601 1601 INIT_LIST_HEAD(&group->tunnels); 1602 1602 1603 - drm_atomic_private_obj_init(mgr->dev, &group->base, NULL, 1603 + drm_atomic_private_obj_init(mgr->dev, &group->base, 1604 1604 &tunnel_group_funcs); 1605 1605 1606 1606 return true;
+4 -3
drivers/gpu/drm/display/drm_hdmi_helper.c
··· 210 210 */ 211 211 unsigned long long 212 212 drm_hdmi_compute_mode_clock(const struct drm_display_mode *mode, 213 - unsigned int bpc, enum hdmi_colorspace fmt) 213 + unsigned int bpc, 214 + enum drm_output_color_format fmt) 214 215 { 215 216 unsigned long long clock = mode->clock * 1000ULL; 216 217 unsigned int vic = drm_match_cea_mode(mode); ··· 223 222 if (vic == 1 && bpc != 8) 224 223 return 0; 225 224 226 - if (fmt == HDMI_COLORSPACE_YUV422) { 225 + if (fmt == DRM_OUTPUT_COLOR_FORMAT_YCBCR422) { 227 226 /* 228 227 * HDMI 1.0 Spec, section 6.5 - Pixel Encoding states that 229 228 * YUV422 sends 24 bits over three channels, with Cb and Cr ··· 249 248 * specifies that YUV420 encoding is carried at a TMDS Character Rate 250 249 * equal to half the pixel clock rate. 251 250 */ 252 - if (fmt == HDMI_COLORSPACE_YUV420) 251 + if (fmt == DRM_OUTPUT_COLOR_FORMAT_YCBCR420) 253 252 clock = clock / 2; 254 253 255 254 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+41 -19
drivers/gpu/drm/display/drm_hdmi_state_helper.c
··· 326 326 } 327 327 EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset); 328 328 329 + static enum hdmi_colorspace 330 + output_color_format_to_hdmi_colorspace(const struct drm_connector *connector, 331 + enum drm_output_color_format fmt) 332 + { 333 + switch (fmt) { 334 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR420: 335 + return HDMI_COLORSPACE_YUV420; 336 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR422: 337 + return HDMI_COLORSPACE_YUV422; 338 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR444: 339 + return HDMI_COLORSPACE_YUV444; 340 + default: 341 + drm_warn(connector->dev, "Unsupported output color format. Defaulting to RGB."); 342 + fallthrough; 343 + case DRM_OUTPUT_COLOR_FORMAT_RGB444: 344 + return HDMI_COLORSPACE_RGB; 345 + } 346 + } 347 + 329 348 static const struct drm_display_mode * 330 349 connector_state_get_mode(const struct drm_connector_state *conn_state) 331 350 { ··· 379 360 * i915 just assumes limited range for YCbCr output, so let's 380 361 * just do the same. 381 362 */ 382 - if (conn_state->hdmi.output_format != HDMI_COLORSPACE_RGB) 363 + if (conn_state->hdmi.output_format != DRM_OUTPUT_COLOR_FORMAT_RGB444) 383 364 return true; 384 365 385 366 if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_FULL) ··· 398 379 sink_supports_format_bpc(const struct drm_connector *connector, 399 380 const struct drm_display_info *info, 400 381 const struct drm_display_mode *mode, 401 - unsigned int format, unsigned int bpc) 382 + enum drm_output_color_format format, 383 + unsigned int bpc) 402 384 { 403 385 struct drm_device *dev = connector->dev; 404 386 u8 vic = drm_match_cea_mode(mode); ··· 420 400 } 421 401 422 402 if (!info->is_hdmi && 423 - (format != HDMI_COLORSPACE_RGB || bpc != 8)) { 403 + (format != DRM_OUTPUT_COLOR_FORMAT_RGB444 || bpc != 8)) { 424 404 drm_dbg_kms(dev, "DVI Monitors require an RGB output at 8 bpc\n"); 425 405 return false; 426 406 } ··· 431 411 return false; 432 412 } 433 413 434 - if (drm_mode_is_420_only(info, mode) && format != HDMI_COLORSPACE_YUV420) { 414 + if (drm_mode_is_420_only(info, mode) && format != DRM_OUTPUT_COLOR_FORMAT_YCBCR420) { 435 415 drm_dbg_kms(dev, "Mode can be only supported in YUV420 format.\n"); 436 416 return false; 437 417 } 438 418 439 419 switch (format) { 440 - case HDMI_COLORSPACE_RGB: 420 + case DRM_OUTPUT_COLOR_FORMAT_RGB444: 441 421 drm_dbg_kms(dev, "RGB Format, checking the constraints.\n"); 442 422 443 423 /* ··· 448 428 * supported so we can keep things going and light up 449 429 * the display. 450 430 */ 451 - if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444)) 431 + if (!(info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444))) 452 432 drm_warn(dev, "HDMI Sink doesn't support RGB, something's wrong.\n"); 453 433 454 434 if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) { ··· 465 445 466 446 return true; 467 447 468 - case HDMI_COLORSPACE_YUV420: 448 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR420: 469 449 drm_dbg_kms(dev, "YUV420 format, checking the constraints.\n"); 470 450 471 - if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR420)) { 451 + if (!(info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420))) { 472 452 drm_dbg_kms(dev, "Sink doesn't support YUV420.\n"); 473 453 return false; 474 454 } ··· 497 477 498 478 return true; 499 479 500 - case HDMI_COLORSPACE_YUV422: 480 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR422: 501 481 drm_dbg_kms(dev, "YUV422 format, checking the constraints.\n"); 502 482 503 - if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) { 483 + if (!(info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))) { 504 484 drm_dbg_kms(dev, "Sink doesn't support YUV422.\n"); 505 485 return false; 506 486 } ··· 520 500 521 501 return true; 522 502 523 - case HDMI_COLORSPACE_YUV444: 503 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR444: 524 504 drm_dbg_kms(dev, "YUV444 format, checking the constraints.\n"); 525 505 526 - if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) { 506 + if (!(info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))) { 527 507 drm_dbg_kms(dev, "Sink doesn't support YUV444.\n"); 528 508 return false; 529 509 } ··· 573 553 hdmi_compute_clock(const struct drm_connector *connector, 574 554 struct drm_connector_state *conn_state, 575 555 const struct drm_display_mode *mode, 576 - unsigned int bpc, enum hdmi_colorspace fmt) 556 + unsigned int bpc, enum drm_output_color_format fmt) 577 557 { 578 558 enum drm_mode_status status; 579 559 unsigned long long clock; ··· 595 575 hdmi_try_format_bpc(const struct drm_connector *connector, 596 576 struct drm_connector_state *conn_state, 597 577 const struct drm_display_mode *mode, 598 - unsigned int bpc, enum hdmi_colorspace fmt) 578 + unsigned int bpc, enum drm_output_color_format fmt) 599 579 { 600 580 const struct drm_display_info *info = &connector->display_info; 601 581 struct drm_device *dev = connector->dev; ··· 631 611 hdmi_compute_format_bpc(const struct drm_connector *connector, 632 612 struct drm_connector_state *conn_state, 633 613 const struct drm_display_mode *mode, 634 - unsigned int max_bpc, enum hdmi_colorspace fmt) 614 + unsigned int max_bpc, enum drm_output_color_format fmt) 635 615 { 636 616 struct drm_device *dev = connector->dev; 637 617 unsigned int bpc; ··· 672 652 int ret; 673 653 674 654 ret = hdmi_compute_format_bpc(connector, conn_state, mode, max_bpc, 675 - HDMI_COLORSPACE_RGB); 655 + DRM_OUTPUT_COLOR_FORMAT_RGB444); 676 656 if (ret) { 677 657 if (connector->ycbcr_420_allowed) { 678 658 ret = hdmi_compute_format_bpc(connector, conn_state, 679 659 mode, max_bpc, 680 - HDMI_COLORSPACE_YUV420); 660 + DRM_OUTPUT_COLOR_FORMAT_YCBCR420); 681 661 if (ret) 682 662 drm_dbg_kms(connector->dev, 683 663 "YUV420 output format doesn't work.\n"); ··· 711 691 if (ret) 712 692 return ret; 713 693 714 - frame->colorspace = conn_state->hdmi.output_format; 694 + frame->colorspace = 695 + output_color_format_to_hdmi_colorspace(connector, 696 + conn_state->hdmi.output_format); 715 697 716 698 /* 717 699 * FIXME: drm_hdmi_avi_infoframe_quant_range() doesn't handle ··· 911 889 { 912 890 unsigned long long clock; 913 891 914 - clock = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB); 892 + clock = drm_hdmi_compute_mode_clock(mode, 8, DRM_OUTPUT_COLOR_FORMAT_RGB444); 915 893 if (!clock) 916 894 return MODE_ERROR; 917 895
+5 -17
drivers/gpu/drm/drm_atomic.c
··· 921 921 * drm_atomic_private_obj_init - initialize private object 922 922 * @dev: DRM device this object will be attached to 923 923 * @obj: private object 924 - * @state: initial private object state 925 924 * @funcs: pointer to the struct of function pointers that identify the object 926 925 * type 927 926 * ··· 932 933 */ 933 934 int drm_atomic_private_obj_init(struct drm_device *dev, 934 935 struct drm_private_obj *obj, 935 - struct drm_private_state *state, 936 936 const struct drm_private_state_funcs *funcs) 937 937 { 938 + struct drm_private_state *state; 938 939 memset(obj, 0, sizeof(*obj)); 939 940 940 941 drm_modeset_lock_init(&obj->lock); ··· 943 944 obj->funcs = funcs; 944 945 list_add_tail(&obj->head, &dev->mode_config.privobj_list); 945 946 946 - /* 947 - * Not all users of drm_atomic_private_obj_init have been 948 - * converted to using &drm_private_obj_funcs.atomic_create_state yet. 949 - * For the time being, let's only call reset if the passed state is 950 - * NULL. Otherwise, we will fallback to the previous behaviour. 951 - */ 952 - if (!state) { 953 - state = obj->funcs->atomic_create_state(obj); 954 - if (IS_ERR(state)) 955 - return PTR_ERR(state); 947 + state = obj->funcs->atomic_create_state(obj); 948 + if (IS_ERR(state)) 949 + return PTR_ERR(state); 956 950 957 - obj->state = state; 958 - } else { 959 - obj->state = state; 960 - state->obj = obj; 961 - } 951 + obj->state = state; 962 952 963 953 return 0; 964 954 }
+35 -2
drivers/gpu/drm/drm_bridge.c
··· 304 304 * 305 305 * This function decrements the bridge's reference count and frees the 306 306 * object if the reference count drops to zero. 307 + * 308 + * See also drm_bridge_clear_and_put() if you also need to set the pointer 309 + * to NULL 307 310 */ 308 311 void drm_bridge_put(struct drm_bridge *bridge) 309 312 { ··· 314 311 kref_put(&bridge->refcount, __drm_bridge_free); 315 312 } 316 313 EXPORT_SYMBOL(drm_bridge_put); 314 + 315 + /** 316 + * drm_bridge_clear_and_put - Given a bridge pointer, clear the pointer 317 + * then put the bridge 318 + * @bridge_pp: pointer to pointer to a struct drm_bridge; ``bridge_pp`` 319 + * must be non-NULL; if ``*bridge_pp`` is NULL this function 320 + * does nothing 321 + * 322 + * Helper to put a DRM bridge, but only after setting its pointer to 323 + * NULL. Useful when a struct drm_bridge reference must be dropped without 324 + * leaving a use-after-free window where the pointed bridge might have been 325 + * freed while still holding a pointer to it. 326 + * 327 + * For struct ``drm_bridge *some_bridge``, this code:: 328 + * 329 + * drm_bridge_clear_and_put(&some_bridge); 330 + * 331 + * is equivalent to the more complex:: 332 + * 333 + * struct drm_bridge *temp = some_bridge; 334 + * some_bridge = NULL; 335 + * drm_bridge_put(temp); 336 + */ 337 + void drm_bridge_clear_and_put(struct drm_bridge **bridge_pp) 338 + { 339 + struct drm_bridge *bridge = *bridge_pp; 340 + 341 + *bridge_pp = NULL; 342 + drm_bridge_put(bridge); 343 + } 344 + EXPORT_SYMBOL(drm_bridge_clear_and_put); 317 345 318 346 /** 319 347 * drm_bridge_put_void - wrapper to drm_bridge_put() taking a void pointer ··· 421 387 422 388 if (bridge->ops & DRM_BRIDGE_OP_HDMI) 423 389 bridge->ycbcr_420_allowed = !!(bridge->supported_formats & 424 - BIT(HDMI_COLORSPACE_YUV420)); 390 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420)); 425 391 426 392 mutex_lock(&bridge_lock); 427 393 list_add_tail(&bridge->list, &bridge_list); ··· 587 553 588 554 if (drm_bridge_is_atomic(bridge)) 589 555 drm_atomic_private_obj_init(bridge->dev, &bridge->base, 590 - NULL, 591 556 &drm_bridge_priv_state_funcs); 592 557 593 558 return 0;
+8 -8
drivers/gpu/drm/drm_connector.c
··· 552 552 * @hdmi_funcs: HDMI-related callbacks for this connector 553 553 * @connector_type: user visible type of the connector 554 554 * @ddc: optional pointer to the associated ddc adapter 555 - * @supported_formats: Bitmask of @hdmi_colorspace listing supported output formats 555 + * @supported_formats: Bitmask of @drm_output_color_format listing supported output formats 556 556 * @max_bpc: Maximum bits per char the HDMI connector supports 557 557 * 558 558 * Initialises a preallocated HDMI connector. Connectors can be ··· 591 591 connector_type == DRM_MODE_CONNECTOR_HDMIB)) 592 592 return -EINVAL; 593 593 594 - if (!supported_formats || !(supported_formats & BIT(HDMI_COLORSPACE_RGB))) 594 + if (!supported_formats || !(supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444))) 595 595 return -EINVAL; 596 596 597 - if (connector->ycbcr_420_allowed != !!(supported_formats & BIT(HDMI_COLORSPACE_YUV420))) 597 + if (connector->ycbcr_420_allowed != !!(supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420))) 598 598 return -EINVAL; 599 599 600 600 if (!(max_bpc == 8 || max_bpc == 10 || max_bpc == 12)) ··· 1431 1431 EXPORT_SYMBOL(drm_hdmi_connector_get_broadcast_rgb_name); 1432 1432 1433 1433 static const char * const output_format_str[] = { 1434 - [HDMI_COLORSPACE_RGB] = "RGB", 1435 - [HDMI_COLORSPACE_YUV420] = "YUV 4:2:0", 1436 - [HDMI_COLORSPACE_YUV422] = "YUV 4:2:2", 1437 - [HDMI_COLORSPACE_YUV444] = "YUV 4:4:4", 1434 + [DRM_OUTPUT_COLOR_FORMAT_RGB444] = "RGB", 1435 + [DRM_OUTPUT_COLOR_FORMAT_YCBCR420] = "YUV 4:2:0", 1436 + [DRM_OUTPUT_COLOR_FORMAT_YCBCR422] = "YUV 4:2:2", 1437 + [DRM_OUTPUT_COLOR_FORMAT_YCBCR444] = "YUV 4:4:4", 1438 1438 }; 1439 1439 1440 1440 /* ··· 1445 1445 * valid. 1446 1446 */ 1447 1447 const char * 1448 - drm_hdmi_connector_get_output_format_name(enum hdmi_colorspace fmt) 1448 + drm_hdmi_connector_get_output_format_name(enum drm_output_color_format fmt) 1449 1449 { 1450 1450 if (fmt >= ARRAY_SIZE(output_format_str)) 1451 1451 return NULL;
+2 -4
drivers/gpu/drm/drm_crtc.c
··· 340 340 * Inits a new object created as base part of a driver crtc object. Drivers 341 341 * should use this function instead of drm_crtc_init(), which is only provided 342 342 * for backwards compatibility with drivers which do not yet support universal 343 - * planes). For really simple hardware which has only 1 plane look at 344 - * drm_simple_display_pipe_init() instead. 343 + * planes). 345 344 * The &drm_crtc_funcs.destroy hook should call drm_crtc_cleanup() and kfree() 346 345 * the crtc structure. The crtc structure should not be allocated with 347 346 * devm_kzalloc(). ··· 423 424 * Inits a new object created as base part of a driver crtc object. Drivers 424 425 * should use this function instead of drm_crtc_init(), which is only provided 425 426 * for backwards compatibility with drivers which do not yet support universal 426 - * planes). For really simple hardware which has only 1 plane look at 427 - * drm_simple_display_pipe_init() instead. 427 + * planes). 428 428 * 429 429 * Cleanup is automatically handled through registering 430 430 * drmm_crtc_cleanup() with drmm_add_action(). The crtc structure should
+1 -1
drivers/gpu/drm/drm_drv.c
··· 587 587 snprintf(event_string, sizeof(event_string), "%s", "WEDGED=unknown"); 588 588 589 589 drm_info(dev, "device wedged, %s\n", method == DRM_WEDGE_RECOVERY_NONE ? 590 - "but recovered through reset" : "needs recovery"); 590 + "but no recovery needed" : "needs recovery"); 591 591 592 592 if (info && (info->comm[0] != '\0') && (info->pid >= 0)) { 593 593 snprintf(pid_string, sizeof(pid_string), "PID=%u", info->pid);
+9 -9
drivers/gpu/drm/drm_edid.c
··· 5316 5316 5317 5317 out: 5318 5318 if (map) 5319 - info->color_formats |= DRM_COLOR_FORMAT_YCBCR420; 5319 + info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420); 5320 5320 5321 5321 *y420cmdb_map = map; 5322 5322 } ··· 6092 6092 continue; 6093 6093 6094 6094 bitmap_set(hdmi->y420_vdb_modes, vic, 1); 6095 - info->color_formats |= DRM_COLOR_FORMAT_YCBCR420; 6095 + info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420); 6096 6096 } 6097 6097 } 6098 6098 ··· 6426 6426 info->cea_rev, edid_ext[1]); 6427 6427 6428 6428 /* The existence of a CTA extension should imply RGB support */ 6429 - info->color_formats = DRM_COLOR_FORMAT_RGB444; 6429 + info->color_formats = BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444); 6430 6430 if (edid_ext[3] & EDID_CEA_YCRCB444) 6431 - info->color_formats |= DRM_COLOR_FORMAT_YCBCR444; 6431 + info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444); 6432 6432 if (edid_ext[3] & EDID_CEA_YCRCB422) 6433 - info->color_formats |= DRM_COLOR_FORMAT_YCBCR422; 6433 + info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422); 6434 6434 if (edid_ext[3] & EDID_BASIC_AUDIO) 6435 6435 info->has_audio = true; 6436 6436 ··· 6698 6698 if (!drm_edid_is_digital(drm_edid)) 6699 6699 goto out; 6700 6700 6701 - info->color_formats |= DRM_COLOR_FORMAT_RGB444; 6701 + info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444); 6702 6702 drm_parse_cea_ext(connector, drm_edid); 6703 6703 6704 6704 update_displayid_info(connector, drm_edid); ··· 6752 6752 connector->base.id, connector->name, info->bpc); 6753 6753 6754 6754 if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444) 6755 - info->color_formats |= DRM_COLOR_FORMAT_YCBCR444; 6755 + info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444); 6756 6756 if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422) 6757 - info->color_formats |= DRM_COLOR_FORMAT_YCBCR422; 6757 + info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422); 6758 6758 6759 6759 drm_update_mso(connector, drm_edid); 6760 6760 ··· 7229 7229 return true; 7230 7230 7231 7231 return connector->display_info.hdmi.scdc.supported || 7232 - connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR420; 7232 + connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420); 7233 7233 } 7234 7234 7235 7235 static u8 drm_mode_hdmi_vic(const struct drm_connector *connector,
+6 -5
drivers/gpu/drm/drm_gem.c
··· 821 821 * Takes an array of userspace handles and returns a newly allocated array of 822 822 * GEM objects. 823 823 * 824 + * After a successful lookup GEM objects need to be released using 825 + * drm_gem_object_put() and the array returned in @objs_out must be freed using 826 + * kvfree(). 827 + * 824 828 * For a single handle lookup, use drm_gem_object_lookup(). 825 829 * 826 - * Returns: 827 - * @objs filled in with GEM object pointers. Returned GEM objects need to be 828 - * released with drm_gem_object_put(). -ENOENT is returned on a lookup 829 - * failure. 0 is returned on success. 830 - * 830 + * Return: 831 + * Zero on success or a negative error code. 831 832 */ 832 833 int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles, 833 834 int count, struct drm_gem_object ***objs_out)
-22
drivers/gpu/drm/drm_gem_atomic_helper.c
··· 87 87 * A mapping address for each of the framebuffer's buffer object is stored in 88 88 * struct &drm_shadow_plane_state.map. The mappings are valid while the state 89 89 * is being used. 90 - * 91 - * Drivers that use struct drm_simple_display_pipe can use 92 - * %DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS to initialize the rsp 93 - * callbacks. Access to shadow-buffer mappings is similar to regular 94 - * atomic_update. 95 - * 96 - * .. code-block:: c 97 - * 98 - * struct drm_simple_display_pipe_funcs driver_pipe_funcs = { 99 - * ..., 100 - * DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, 101 - * }; 102 - * 103 - * void driver_pipe_enable(struct drm_simple_display_pipe *pipe, 104 - * struct drm_crtc_state *crtc_state, 105 - * struct drm_plane_state *plane_state) 106 - * { 107 - * struct drm_shadow_plane_state *shadow_plane_state = 108 - * to_drm_shadow_plane_state(plane_state); 109 - * 110 - * // access shadow buffer via shadow_plane_state->map 111 - * } 112 90 */ 113 91 114 92 /*
+13 -10
drivers/gpu/drm/drm_gem_dma_helper.c
··· 146 146 return dma_obj; 147 147 148 148 if (dma_obj->map_noncoherent) { 149 - dma_obj->vaddr = dma_alloc_noncoherent(drm->dev, size, 149 + dma_obj->vaddr = dma_alloc_noncoherent(drm_dev_dma_dev(drm), 150 + size, 150 151 &dma_obj->dma_addr, 151 152 DMA_TO_DEVICE, 152 153 GFP_KERNEL | __GFP_NOWARN); 153 154 } else { 154 - dma_obj->vaddr = dma_alloc_wc(drm->dev, size, 155 + dma_obj->vaddr = dma_alloc_wc(drm_dev_dma_dev(drm), size, 155 156 &dma_obj->dma_addr, 156 157 GFP_KERNEL | __GFP_NOWARN); 157 158 } ··· 237 236 drm_prime_gem_destroy(gem_obj, dma_obj->sgt); 238 237 } else if (dma_obj->vaddr) { 239 238 if (dma_obj->map_noncoherent) 240 - dma_free_noncoherent(gem_obj->dev->dev, dma_obj->base.size, 239 + dma_free_noncoherent(drm_dev_dma_dev(gem_obj->dev), 240 + dma_obj->base.size, 241 241 dma_obj->vaddr, dma_obj->dma_addr, 242 242 DMA_TO_DEVICE); 243 243 else 244 - dma_free_wc(gem_obj->dev->dev, dma_obj->base.size, 245 - dma_obj->vaddr, dma_obj->dma_addr); 244 + dma_free_wc(drm_dev_dma_dev(gem_obj->dev), 245 + dma_obj->base.size, dma_obj->vaddr, 246 + dma_obj->dma_addr); 246 247 } 247 248 248 249 drm_gem_object_release(gem_obj); ··· 435 432 if (!sgt) 436 433 return ERR_PTR(-ENOMEM); 437 434 438 - ret = dma_get_sgtable(obj->dev->dev, sgt, dma_obj->vaddr, 435 + ret = dma_get_sgtable(drm_dev_dma_dev(obj->dev), sgt, dma_obj->vaddr, 439 436 dma_obj->dma_addr, obj->size); 440 437 if (ret < 0) 441 438 goto out; ··· 537 534 * the whole buffer. 538 535 */ 539 536 vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node); 540 - vm_flags_mod(vma, VM_DONTEXPAND, VM_PFNMAP); 537 + vm_flags_mod(vma, VM_DONTDUMP | VM_DONTEXPAND, VM_PFNMAP); 541 538 542 539 if (dma_obj->map_noncoherent) { 543 540 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); 544 541 545 - ret = dma_mmap_pages(dma_obj->base.dev->dev, 542 + ret = dma_mmap_pages(drm_dev_dma_dev(dma_obj->base.dev), 546 543 vma, vma->vm_end - vma->vm_start, 547 544 virt_to_page(dma_obj->vaddr)); 548 545 } else { 549 - ret = dma_mmap_wc(dma_obj->base.dev->dev, vma, dma_obj->vaddr, 550 - dma_obj->dma_addr, 546 + ret = dma_mmap_wc(drm_dev_dma_dev(dma_obj->base.dev), vma, 547 + dma_obj->vaddr, dma_obj->dma_addr, 551 548 vma->vm_end - vma->vm_start); 552 549 } 553 550 if (ret)
+129 -265
drivers/gpu/drm/drm_mipi_dbi.c
··· 14 14 #include <linux/regulator/consumer.h> 15 15 #include <linux/spi/spi.h> 16 16 17 - #include <drm/drm_connector.h> 17 + #include <drm/drm_atomic.h> 18 18 #include <drm/drm_damage_helper.h> 19 19 #include <drm/drm_drv.h> 20 20 #include <drm/drm_file.h> ··· 22 22 #include <drm/drm_fourcc.h> 23 23 #include <drm/drm_framebuffer.h> 24 24 #include <drm/drm_gem.h> 25 - #include <drm/drm_gem_atomic_helper.h> 26 - #include <drm/drm_gem_framebuffer_helper.h> 27 25 #include <drm/drm_mipi_dbi.h> 28 26 #include <drm/drm_modes.h> 29 27 #include <drm/drm_print.h> 30 - #include <drm/drm_probe_helper.h> 31 28 #include <drm/drm_rect.h> 32 29 #include <video/mipi_display.h> 33 30 ··· 314 317 } 315 318 316 319 /** 317 - * mipi_dbi_pipe_mode_valid - MIPI DBI mode-valid helper 318 - * @pipe: Simple display pipe 320 + * drm_mipi_dbi_crtc_helper_mode_valid - MIPI DBI mode-valid helper 321 + * @crtc: The CRTC 319 322 * @mode: The mode to test 320 323 * 321 324 * This function validates a given display mode against the MIPI DBI's hardware 322 - * display. Drivers can use this as their &drm_simple_display_pipe_funcs->mode_valid 325 + * display. Drivers can use this as their struct &drm_crtc_helper_funcs.mode_valid 323 326 * callback. 324 327 */ 325 - enum drm_mode_status mipi_dbi_pipe_mode_valid(struct drm_simple_display_pipe *pipe, 326 - const struct drm_display_mode *mode) 328 + enum drm_mode_status drm_mipi_dbi_crtc_helper_mode_valid(struct drm_crtc *crtc, 329 + const struct drm_display_mode *mode) 327 330 { 328 - struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); 331 + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(crtc->dev); 329 332 330 - return drm_crtc_helper_mode_valid_fixed(&pipe->crtc, mode, &dbidev->mode); 333 + return drm_crtc_helper_mode_valid_fixed(crtc, mode, &dbidev->mode); 331 334 } 332 - EXPORT_SYMBOL(mipi_dbi_pipe_mode_valid); 335 + EXPORT_SYMBOL(drm_mipi_dbi_crtc_helper_mode_valid); 333 336 334 337 /** 335 - * mipi_dbi_pipe_update - Display pipe update helper 336 - * @pipe: Simple display pipe 337 - * @old_state: Old plane state 338 + * drm_mipi_dbi_plane_helper_atomic_check - MIPI DBI plane check helper 339 + * @plane: Plane to check 340 + * @state: Atomic state 341 + * 342 + * This function performs the default checks on the primary plane 343 + * of a MIPI DBI device. Drivers can use this as their 344 + * struct &drm_crtc_helper_funcs.atomic_check callback. 345 + * 346 + * Returns: 347 + * 0 on success, or a negative errno code otherwise. 348 + */ 349 + int drm_mipi_dbi_plane_helper_atomic_check(struct drm_plane *plane, 350 + struct drm_atomic_state *state) 351 + { 352 + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); 353 + struct drm_crtc_state *new_crtc_state = NULL; 354 + int ret; 355 + 356 + if (new_plane_state->crtc) 357 + new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc); 358 + 359 + ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, 360 + DRM_PLANE_NO_SCALING, 361 + DRM_PLANE_NO_SCALING, 362 + false, false); 363 + if (ret) 364 + return ret; 365 + else if (!new_plane_state->visible) 366 + return 0; 367 + 368 + return 0; 369 + } 370 + EXPORT_SYMBOL(drm_mipi_dbi_plane_helper_atomic_check); 371 + 372 + /** 373 + * drm_mipi_dbi_plane_helper_atomic_update - Display update helper 374 + * @plane: Plane 375 + * @state: Atomic state 338 376 * 339 377 * This function handles framebuffer flushing and vblank events. Drivers can use 340 - * this as their &drm_simple_display_pipe_funcs->update callback. 378 + * this as their struct &drm_plane_helper_funcs.atomic_update callback. 341 379 */ 342 - void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe, 343 - struct drm_plane_state *old_state) 380 + void drm_mipi_dbi_plane_helper_atomic_update(struct drm_plane *plane, 381 + struct drm_atomic_state *state) 344 382 { 345 - struct drm_plane_state *state = pipe->plane.state; 346 - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state); 347 - struct drm_framebuffer *fb = state->fb; 383 + struct drm_plane_state *plane_state = plane->state; 384 + struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 385 + struct drm_framebuffer *fb = plane_state->fb; 386 + struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); 348 387 struct drm_rect rect; 349 388 int idx; 350 389 351 - if (!pipe->crtc.state->active) 390 + if (!fb) 352 391 return; 353 392 354 - if (WARN_ON(!fb)) 355 - return; 356 - 357 - if (!drm_dev_enter(fb->dev, &idx)) 358 - return; 359 - 360 - if (drm_atomic_helper_damage_merged(old_state, state, &rect)) 361 - mipi_dbi_fb_dirty(&shadow_plane_state->data[0], fb, &rect, 362 - &shadow_plane_state->fmtcnv_state); 363 - 364 - drm_dev_exit(idx); 393 + if (drm_dev_enter(plane->dev, &idx)) { 394 + if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &rect)) 395 + mipi_dbi_fb_dirty(&shadow_plane_state->data[0], fb, &rect, 396 + &shadow_plane_state->fmtcnv_state); 397 + drm_dev_exit(idx); 398 + } 365 399 } 366 - EXPORT_SYMBOL(mipi_dbi_pipe_update); 367 - 368 - /** 369 - * mipi_dbi_enable_flush - MIPI DBI enable helper 370 - * @dbidev: MIPI DBI device structure 371 - * @crtc_state: CRTC state 372 - * @plane_state: Plane state 373 - * 374 - * Flushes the whole framebuffer and enables the backlight. Drivers can use this 375 - * in their &drm_simple_display_pipe_funcs->enable callback. 376 - * 377 - * Note: Drivers which don't use mipi_dbi_pipe_update() because they have custom 378 - * framebuffer flushing, can't use this function since they both use the same 379 - * flushing code. 380 - */ 381 - void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev, 382 - struct drm_crtc_state *crtc_state, 383 - struct drm_plane_state *plane_state) 384 - { 385 - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 386 - struct drm_framebuffer *fb = plane_state->fb; 387 - struct drm_rect rect = { 388 - .x1 = 0, 389 - .x2 = fb->width, 390 - .y1 = 0, 391 - .y2 = fb->height, 392 - }; 393 - int idx; 394 - 395 - if (!drm_dev_enter(&dbidev->drm, &idx)) 396 - return; 397 - 398 - mipi_dbi_fb_dirty(&shadow_plane_state->data[0], fb, &rect, 399 - &shadow_plane_state->fmtcnv_state); 400 - backlight_enable(dbidev->backlight); 401 - 402 - drm_dev_exit(idx); 403 - } 404 - EXPORT_SYMBOL(mipi_dbi_enable_flush); 400 + EXPORT_SYMBOL(drm_mipi_dbi_plane_helper_atomic_update); 405 401 406 402 static void mipi_dbi_blank(struct mipi_dbi_dev *dbidev) 407 403 { ··· 422 432 } 423 433 424 434 /** 425 - * mipi_dbi_pipe_disable - MIPI DBI pipe disable helper 426 - * @pipe: Display pipe 435 + * drm_mipi_dbi_crtc_helper_atomic_check - MIPI DBI CRTC check helper 436 + * @crtc: CRTC to check 437 + * @state: Atomic state 438 + * 439 + * This function performs the default checks on the CRTC of a MIPI DBI 440 + * device and ensures that the primary plane as been set up correctly. 441 + * Drivers can use this as their struct &drm_crtc_helper_funcs.atomic_check 442 + * callback. 443 + * 444 + * Returns: 445 + * 0 on success, or a negative errno code otherwise. 446 + */ 447 + int drm_mipi_dbi_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) 448 + { 449 + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 450 + int ret; 451 + 452 + if (!crtc_state->enable) 453 + goto out; 454 + 455 + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); 456 + if (ret) 457 + return ret; 458 + 459 + out: 460 + return drm_atomic_add_affected_planes(state, crtc); 461 + } 462 + EXPORT_SYMBOL(drm_mipi_dbi_crtc_helper_atomic_check); 463 + 464 + /** 465 + * drm_mipi_dbi_crtc_helper_atomic_disable - MIPI DBI CRTC disable helper 466 + * @crtc: CRTC to disable 467 + * @state: Atomic state 427 468 * 428 469 * This function disables backlight if present, if not the display memory is 429 470 * blanked. The regulator is disabled if in use. Drivers can use this as their 430 - * &drm_simple_display_pipe_funcs->disable callback. 471 + * struct &drm_crtc_helper_funcs.atomic_disable callback. 431 472 */ 432 - void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe) 473 + void drm_mipi_dbi_crtc_helper_atomic_disable(struct drm_crtc *crtc, 474 + struct drm_atomic_state *state) 433 475 { 434 - struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); 435 - 436 - DRM_DEBUG_KMS("\n"); 476 + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(crtc->dev); 437 477 438 478 if (dbidev->backlight) 439 479 backlight_disable(dbidev->backlight); ··· 475 455 if (dbidev->io_regulator) 476 456 regulator_disable(dbidev->io_regulator); 477 457 } 478 - EXPORT_SYMBOL(mipi_dbi_pipe_disable); 458 + EXPORT_SYMBOL(drm_mipi_dbi_crtc_helper_atomic_disable); 479 459 480 460 /** 481 - * mipi_dbi_pipe_begin_fb_access - MIPI DBI pipe begin-access helper 482 - * @pipe: Display pipe 483 - * @plane_state: Plane state 461 + * drm_mipi_dbi_connector_helper_get_modes - Duplicates the MIPI DBI mode for the connector 462 + * @connector: The connector 484 463 * 485 - * This function implements struct &drm_simple_display_funcs.begin_fb_access. 486 - * 487 - * See drm_gem_begin_shadow_fb_access() for details and mipi_dbi_pipe_cleanup_fb() 488 - * for cleanup. 464 + * Sets the connecto rmodes from the MIPI DBI mode. Drivers can use this as their 465 + * &drm_connector_helper_funcs->get_mods callback. See drm_gem_destroy_shadow_plane_state() 466 + * for additional details. 489 467 * 490 468 * Returns: 491 - * 0 on success, or a negative errno code otherwise. 469 + * The number of created modes. 492 470 */ 493 - int mipi_dbi_pipe_begin_fb_access(struct drm_simple_display_pipe *pipe, 494 - struct drm_plane_state *plane_state) 495 - { 496 - return drm_gem_begin_shadow_fb_access(&pipe->plane, plane_state); 497 - } 498 - EXPORT_SYMBOL(mipi_dbi_pipe_begin_fb_access); 499 - 500 - /** 501 - * mipi_dbi_pipe_end_fb_access - MIPI DBI pipe end-access helper 502 - * @pipe: Display pipe 503 - * @plane_state: Plane state 504 - * 505 - * This function implements struct &drm_simple_display_funcs.end_fb_access. 506 - * 507 - * See mipi_dbi_pipe_begin_fb_access(). 508 - */ 509 - void mipi_dbi_pipe_end_fb_access(struct drm_simple_display_pipe *pipe, 510 - struct drm_plane_state *plane_state) 511 - { 512 - drm_gem_end_shadow_fb_access(&pipe->plane, plane_state); 513 - } 514 - EXPORT_SYMBOL(mipi_dbi_pipe_end_fb_access); 515 - 516 - /** 517 - * mipi_dbi_pipe_reset_plane - MIPI DBI plane-reset helper 518 - * @pipe: Display pipe 519 - * 520 - * This function implements struct &drm_simple_display_funcs.reset_plane 521 - * for MIPI DBI planes. 522 - */ 523 - void mipi_dbi_pipe_reset_plane(struct drm_simple_display_pipe *pipe) 524 - { 525 - drm_gem_reset_shadow_plane(&pipe->plane); 526 - } 527 - EXPORT_SYMBOL(mipi_dbi_pipe_reset_plane); 528 - 529 - /** 530 - * mipi_dbi_pipe_duplicate_plane_state - duplicates MIPI DBI plane state 531 - * @pipe: Display pipe 532 - * 533 - * This function implements struct &drm_simple_display_funcs.duplicate_plane_state 534 - * for MIPI DBI planes. 535 - * 536 - * See drm_gem_duplicate_shadow_plane_state() for additional details. 537 - * 538 - * Returns: 539 - * A pointer to a new plane state on success, or NULL otherwise. 540 - */ 541 - struct drm_plane_state *mipi_dbi_pipe_duplicate_plane_state(struct drm_simple_display_pipe *pipe) 542 - { 543 - return drm_gem_duplicate_shadow_plane_state(&pipe->plane); 544 - } 545 - EXPORT_SYMBOL(mipi_dbi_pipe_duplicate_plane_state); 546 - 547 - /** 548 - * mipi_dbi_pipe_destroy_plane_state - cleans up MIPI DBI plane state 549 - * @pipe: Display pipe 550 - * @plane_state: Plane state 551 - * 552 - * This function implements struct drm_simple_display_funcs.destroy_plane_state 553 - * for MIPI DBI planes. 554 - * 555 - * See drm_gem_destroy_shadow_plane_state() for additional details. 556 - */ 557 - void mipi_dbi_pipe_destroy_plane_state(struct drm_simple_display_pipe *pipe, 558 - struct drm_plane_state *plane_state) 559 - { 560 - drm_gem_destroy_shadow_plane_state(&pipe->plane, plane_state); 561 - } 562 - EXPORT_SYMBOL(mipi_dbi_pipe_destroy_plane_state); 563 - 564 - static int mipi_dbi_connector_get_modes(struct drm_connector *connector) 471 + int drm_mipi_dbi_connector_helper_get_modes(struct drm_connector *connector) 565 472 { 566 473 struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(connector->dev); 567 474 568 475 return drm_connector_helper_get_modes_fixed(connector, &dbidev->mode); 569 476 } 570 - 571 - static const struct drm_connector_helper_funcs mipi_dbi_connector_hfuncs = { 572 - .get_modes = mipi_dbi_connector_get_modes, 573 - }; 574 - 575 - static const struct drm_connector_funcs mipi_dbi_connector_funcs = { 576 - .reset = drm_atomic_helper_connector_reset, 577 - .fill_modes = drm_helper_probe_single_connector_modes, 578 - .destroy = drm_connector_cleanup, 579 - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 580 - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 581 - }; 477 + EXPORT_SYMBOL(drm_mipi_dbi_connector_helper_get_modes); 582 478 583 479 static int mipi_dbi_rotate_mode(struct drm_display_mode *mode, 584 480 unsigned int rotation) ··· 513 577 } 514 578 } 515 579 516 - static const struct drm_mode_config_funcs mipi_dbi_mode_config_funcs = { 517 - .fb_create = drm_gem_fb_create_with_dirty, 518 - .atomic_check = drm_atomic_helper_check, 519 - .atomic_commit = drm_atomic_helper_commit, 520 - }; 521 - 522 - static const uint32_t mipi_dbi_formats[] = { 523 - DRM_FORMAT_RGB565, 524 - DRM_FORMAT_XRGB8888, 525 - }; 526 - 527 580 /** 528 - * mipi_dbi_dev_init_with_formats - MIPI DBI device initialization with custom formats 581 + * drm_mipi_dbi_dev_init - MIPI DBI device initialization 529 582 * @dbidev: MIPI DBI device structure to initialize 530 - * @funcs: Display pipe functions 531 - * @formats: Array of supported formats (DRM_FORMAT\_\*). 532 - * @format_count: Number of elements in @formats 533 - * @mode: Display mode 583 + * @mode: Hardware display mode 584 + * @format: Hardware color format (DRM_FORMAT\_\*). 534 585 * @rotation: Initial rotation in degrees Counter Clock Wise 535 - * @tx_buf_size: Allocate a transmit buffer of this size. 586 + * @tx_buf_size: Allocate a transmit buffer of at least this size. 536 587 * 537 - * This function sets up a &drm_simple_display_pipe with a &drm_connector that 538 - * has one fixed &drm_display_mode which is rotated according to @rotation. 539 - * This mode is used to set the mode config min/max width/height properties. 540 - * 541 - * Use mipi_dbi_dev_init() if you want native RGB565 and emulated XRGB8888 format. 542 - * 543 - * Note: 544 - * Some of the helper functions expects RGB565 to be the default format and the 545 - * transmit buffer sized to fit that. 588 + * Initializes a MIPI-DBI device. The minimum size of the transmit buffer 589 + * in @tx_buf_size is optional. Pass 0 to allocate enough memory to transmit 590 + * a single scanline of the display. 546 591 * 547 592 * Returns: 548 593 * Zero on success, negative error code on failure. 549 594 */ 550 - int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev, 551 - const struct drm_simple_display_pipe_funcs *funcs, 552 - const uint32_t *formats, unsigned int format_count, 553 - const struct drm_display_mode *mode, 554 - unsigned int rotation, size_t tx_buf_size) 595 + int drm_mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev, const struct drm_display_mode *mode, 596 + u32 format, unsigned int rotation, size_t tx_buf_size) 555 597 { 556 - static const uint64_t modifiers[] = { 557 - DRM_FORMAT_MOD_LINEAR, 558 - DRM_FORMAT_MOD_INVALID 559 - }; 560 598 struct drm_device *drm = &dbidev->drm; 561 599 int ret; 562 600 563 601 if (!dbidev->dbi.command) 564 602 return -EINVAL; 565 603 566 - ret = drmm_mode_config_init(drm); 567 - if (ret) 568 - return ret; 604 + if (!tx_buf_size) { 605 + const struct drm_format_info *info = drm_format_info(format); 606 + 607 + tx_buf_size = drm_format_info_min_pitch(info, 0, mode->hdisplay) * 608 + mode->vdisplay; 609 + } 569 610 570 611 dbidev->tx_buf = devm_kmalloc(drm->dev, tx_buf_size, GFP_KERNEL); 571 612 if (!dbidev->tx_buf) ··· 551 638 drm_mode_copy(&dbidev->mode, mode); 552 639 ret = mipi_dbi_rotate_mode(&dbidev->mode, rotation); 553 640 if (ret) { 554 - DRM_ERROR("Illegal rotation value %u\n", rotation); 641 + drm_err(drm, "Illegal rotation value %u\n", rotation); 555 642 return -EINVAL; 556 643 } 557 644 558 - drm_connector_helper_add(&dbidev->connector, &mipi_dbi_connector_hfuncs); 559 - ret = drm_connector_init(drm, &dbidev->connector, &mipi_dbi_connector_funcs, 560 - DRM_MODE_CONNECTOR_SPI); 561 - if (ret) 562 - return ret; 563 - 564 - ret = drm_simple_display_pipe_init(drm, &dbidev->pipe, funcs, formats, format_count, 565 - modifiers, &dbidev->connector); 566 - if (ret) 567 - return ret; 568 - 569 - drm_plane_enable_fb_damage_clips(&dbidev->pipe.plane); 570 - 571 - drm->mode_config.funcs = &mipi_dbi_mode_config_funcs; 572 - drm->mode_config.min_width = dbidev->mode.hdisplay; 573 - drm->mode_config.max_width = dbidev->mode.hdisplay; 574 - drm->mode_config.min_height = dbidev->mode.vdisplay; 575 - drm->mode_config.max_height = dbidev->mode.vdisplay; 576 645 dbidev->rotation = rotation; 577 - dbidev->pixel_format = formats[0]; 578 - if (formats[0] == DRM_FORMAT_RGB888) 579 - dbidev->dbi.write_memory_bpw = 8; 646 + drm_dbg(drm, "rotation = %u\n", rotation); 580 647 581 - DRM_DEBUG_KMS("rotation = %u\n", rotation); 648 + dbidev->pixel_format = format; 649 + if (dbidev->pixel_format == DRM_FORMAT_RGB888) 650 + dbidev->dbi.write_memory_bpw = 8; 582 651 583 652 return 0; 584 653 } 585 - EXPORT_SYMBOL(mipi_dbi_dev_init_with_formats); 586 - 587 - /** 588 - * mipi_dbi_dev_init - MIPI DBI device initialization 589 - * @dbidev: MIPI DBI device structure to initialize 590 - * @funcs: Display pipe functions 591 - * @mode: Display mode 592 - * @rotation: Initial rotation in degrees Counter Clock Wise 593 - * 594 - * This function sets up a &drm_simple_display_pipe with a &drm_connector that 595 - * has one fixed &drm_display_mode which is rotated according to @rotation. 596 - * This mode is used to set the mode config min/max width/height properties. 597 - * Additionally &mipi_dbi.tx_buf is allocated. 598 - * 599 - * Supported formats: Native RGB565 and emulated XRGB8888. 600 - * 601 - * Returns: 602 - * Zero on success, negative error code on failure. 603 - */ 604 - int mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev, 605 - const struct drm_simple_display_pipe_funcs *funcs, 606 - const struct drm_display_mode *mode, unsigned int rotation) 607 - { 608 - size_t bufsize = (u32)mode->vdisplay * mode->hdisplay * sizeof(u16); 609 - 610 - dbidev->drm.mode_config.preferred_depth = 16; 611 - 612 - return mipi_dbi_dev_init_with_formats(dbidev, funcs, mipi_dbi_formats, 613 - ARRAY_SIZE(mipi_dbi_formats), mode, 614 - rotation, bufsize); 615 - } 616 - EXPORT_SYMBOL(mipi_dbi_dev_init); 654 + EXPORT_SYMBOL(drm_mipi_dbi_dev_init); 617 655 618 656 /** 619 657 * mipi_dbi_hw_reset - Hardware reset of controller
-3
drivers/gpu/drm/drm_modeset_helper.c
··· 135 135 * 136 136 * This is purely a backwards compatibility helper for old drivers. Drivers 137 137 * should instead implement their own primary plane. Atomic drivers must do so. 138 - * Drivers with the above hardware restriction can look into using &struct 139 - * drm_simple_display_pipe, which encapsulates the above limitations into a nice 140 - * interface. 141 138 * 142 139 * Returns: 143 140 * Zero on success, error code on failure.
+1 -1
drivers/gpu/drm/drm_prime.c
··· 859 859 return ERR_PTR(-ENOMEM); 860 860 861 861 if (dev) 862 - max_segment = dma_max_mapping_size(dev->dev); 862 + max_segment = dma_max_mapping_size(drm_dev_dma_dev(dev)); 863 863 if (max_segment == 0) 864 864 max_segment = UINT_MAX; 865 865 err = sg_alloc_table_from_pages_segment(sg, pages, nr_pages, 0,
-83
drivers/gpu/drm/drm_simple_kms_helper.c
··· 16 16 #include <drm/drm_probe_helper.h> 17 17 #include <drm/drm_simple_kms_helper.h> 18 18 19 - /** 20 - * DOC: overview 21 - * 22 - * This helper library provides helpers for drivers for simple display 23 - * hardware. 24 - * 25 - * drm_simple_display_pipe_init() initializes a simple display pipeline 26 - * which has only one full-screen scanout buffer feeding one output. The 27 - * pipeline is represented by &struct drm_simple_display_pipe and binds 28 - * together &drm_plane, &drm_crtc and &drm_encoder structures into one fixed 29 - * entity. Some flexibility for code reuse is provided through a separately 30 - * allocated &drm_connector object and supporting optional &drm_bridge 31 - * encoder drivers. 32 - * 33 - * Many drivers require only a very simple encoder that fulfills the minimum 34 - * requirements of the display pipeline and does not add additional 35 - * functionality. The function drm_simple_encoder_init() provides an 36 - * implementation of such an encoder. 37 - */ 38 - 39 19 static const struct drm_encoder_funcs drm_simple_encoder_funcs_cleanup = { 40 20 .destroy = drm_encoder_cleanup, 41 21 }; 42 22 43 - /** 44 - * drm_simple_encoder_init - Initialize a preallocated encoder with 45 - * basic functionality. 46 - * @dev: drm device 47 - * @encoder: the encoder to initialize 48 - * @encoder_type: user visible type of the encoder 49 - * 50 - * Initialises a preallocated encoder that has no further functionality. 51 - * Settings for possible CRTC and clones are left to their initial values. 52 - * The encoder will be cleaned up automatically as part of the mode-setting 53 - * cleanup. 54 - * 55 - * The caller of drm_simple_encoder_init() is responsible for freeing 56 - * the encoder's memory after the encoder has been cleaned up. At the 57 - * moment this only works reliably if the encoder data structure is 58 - * stored in the device structure. Free the encoder's memory as part of 59 - * the device release function. 60 - * 61 - * Note: consider using drmm_simple_encoder_alloc() instead of 62 - * drm_simple_encoder_init() to let the DRM managed resource infrastructure 63 - * take care of cleanup and deallocation. 64 - * 65 - * Returns: 66 - * Zero on success, error code on failure. 67 - */ 68 23 int drm_simple_encoder_init(struct drm_device *dev, 69 24 struct drm_encoder *encoder, 70 25 int encoder_type) ··· 325 370 .format_mod_supported = drm_simple_kms_format_mod_supported, 326 371 }; 327 372 328 - /** 329 - * drm_simple_display_pipe_attach_bridge - Attach a bridge to the display pipe 330 - * @pipe: simple display pipe object 331 - * @bridge: bridge to attach 332 - * 333 - * Makes it possible to still use the drm_simple_display_pipe helpers when 334 - * a DRM bridge has to be used. 335 - * 336 - * Note that you probably want to initialize the pipe by passing a NULL 337 - * connector to drm_simple_display_pipe_init(). 338 - * 339 - * Returns: 340 - * Zero on success, negative error code on failure. 341 - */ 342 373 int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe, 343 374 struct drm_bridge *bridge) 344 375 { ··· 332 391 } 333 392 EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge); 334 393 335 - /** 336 - * drm_simple_display_pipe_init - Initialize a simple display pipeline 337 - * @dev: DRM device 338 - * @pipe: simple display pipe object to initialize 339 - * @funcs: callbacks for the display pipe (optional) 340 - * @formats: array of supported formats (DRM_FORMAT\_\*) 341 - * @format_count: number of elements in @formats 342 - * @format_modifiers: array of formats modifiers 343 - * @connector: connector to attach and register (optional) 344 - * 345 - * Sets up a display pipeline which consist of a really simple 346 - * plane-crtc-encoder pipe. 347 - * 348 - * If a connector is supplied, the pipe will be coupled with the provided 349 - * connector. You may supply a NULL connector when using drm bridges, that 350 - * handle connectors themselves (see drm_simple_display_pipe_attach_bridge()). 351 - * 352 - * Teardown of a simple display pipe is all handled automatically by the drm 353 - * core through calling drm_mode_config_cleanup(). Drivers afterwards need to 354 - * release the memory for the structure themselves. 355 - * 356 - * Returns: 357 - * Zero on success, negative error code on failure. 358 - */ 359 394 int drm_simple_display_pipe_init(struct drm_device *dev, 360 395 struct drm_simple_display_pipe *pipe, 361 396 const struct drm_simple_display_pipe_funcs *funcs,
+1
drivers/gpu/drm/imagination/Makefile
··· 8 8 pvr_device.o \ 9 9 pvr_device_info.o \ 10 10 pvr_drv.o \ 11 + pvr_dump.o \ 11 12 pvr_free_list.o \ 12 13 pvr_fw.o \ 13 14 pvr_fw_meta.o \
+5
drivers/gpu/drm/imagination/pvr_ccb.c
··· 4 4 #include "pvr_ccb.h" 5 5 #include "pvr_device.h" 6 6 #include "pvr_drv.h" 7 + #include "pvr_dump.h" 7 8 #include "pvr_free_list.h" 8 9 #include "pvr_fw.h" 9 10 #include "pvr_gem.h" ··· 165 164 * stats. It may be added in the future, but for now just 166 165 * suppress the "unknown" warning when receiving this command. 167 166 */ 167 + break; 168 + case ROGUE_FWIF_FWCCB_CMD_CONTEXT_RESET_NOTIFICATION: 169 + pvr_dump_context_reset_notification(pvr_dev, 170 + &cmd->cmd_data.cmd_context_reset_notification); 168 171 break; 169 172 170 173 default:
+113
drivers/gpu/drm/imagination/pvr_dump.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 OR MIT 2 + /* Copyright (c) 2026 Imagination Technologies Ltd. */ 3 + 4 + #include "pvr_device.h" 5 + #include "pvr_dump.h" 6 + #include "pvr_rogue_fwif.h" 7 + 8 + #include <drm/drm_print.h> 9 + #include <linux/types.h> 10 + 11 + static const char * 12 + get_reset_reason_desc(enum rogue_context_reset_reason reason) 13 + { 14 + switch (reason) { 15 + case ROGUE_CONTEXT_RESET_REASON_NONE: 16 + return "None"; 17 + case ROGUE_CONTEXT_RESET_REASON_GUILTY_LOCKUP: 18 + return "Guilty lockup"; 19 + case ROGUE_CONTEXT_RESET_REASON_INNOCENT_LOCKUP: 20 + return "Innocent lockup"; 21 + case ROGUE_CONTEXT_RESET_REASON_GUILTY_OVERRUNING: 22 + return "Guilty overrunning"; 23 + case ROGUE_CONTEXT_RESET_REASON_INNOCENT_OVERRUNING: 24 + return "Innocent overrunning"; 25 + case ROGUE_CONTEXT_RESET_REASON_HARD_CONTEXT_SWITCH: 26 + return "Hard context switch"; 27 + case ROGUE_CONTEXT_RESET_REASON_WGP_CHECKSUM: 28 + return "CDM Mission/safety checksum mismatch"; 29 + case ROGUE_CONTEXT_RESET_REASON_TRP_CHECKSUM: 30 + return "TRP checksum mismatch"; 31 + case ROGUE_CONTEXT_RESET_REASON_GPU_ECC_OK: 32 + return "GPU ECC error (corrected, OK)"; 33 + case ROGUE_CONTEXT_RESET_REASON_GPU_ECC_HWR: 34 + return "GPU ECC error (uncorrected, HWR)"; 35 + case ROGUE_CONTEXT_RESET_REASON_FW_ECC_OK: 36 + return "Firmware ECC error (corrected, OK)"; 37 + case ROGUE_CONTEXT_RESET_REASON_FW_ECC_ERR: 38 + return "Firmware ECC error (uncorrected, ERR)"; 39 + case ROGUE_CONTEXT_RESET_REASON_FW_WATCHDOG: 40 + return "Firmware watchdog"; 41 + case ROGUE_CONTEXT_RESET_REASON_FW_PAGEFAULT: 42 + return "Firmware pagefault"; 43 + case ROGUE_CONTEXT_RESET_REASON_FW_EXEC_ERR: 44 + return "Firmware execution error"; 45 + case ROGUE_CONTEXT_RESET_REASON_HOST_WDG_FW_ERR: 46 + return "Host watchdog"; 47 + case ROGUE_CONTEXT_GEOM_OOM_DISABLED: 48 + return "Geometry OOM disabled"; 49 + 50 + default: 51 + return "Unknown"; 52 + } 53 + } 54 + 55 + static const char * 56 + get_dm_name(u32 dm) 57 + { 58 + switch (dm) { 59 + case PVR_FWIF_DM_GP: 60 + return "General purpose"; 61 + /* PVR_FWIF_DM_TDM has the same index, but is discriminated by a device feature */ 62 + case PVR_FWIF_DM_2D: 63 + return "2D or TDM"; 64 + case PVR_FWIF_DM_GEOM: 65 + return "Geometry"; 66 + case PVR_FWIF_DM_FRAG: 67 + return "Fragment"; 68 + case PVR_FWIF_DM_CDM: 69 + return "Compute"; 70 + case PVR_FWIF_DM_RAY: 71 + return "Raytracing"; 72 + case PVR_FWIF_DM_GEOM2: 73 + return "Geometry 2"; 74 + case PVR_FWIF_DM_GEOM3: 75 + return "Geometry 3"; 76 + case PVR_FWIF_DM_GEOM4: 77 + return "Geometry 4"; 78 + 79 + default: 80 + return "Unknown"; 81 + } 82 + } 83 + 84 + /** 85 + * pvr_dump_context_reset_notification() - Handle context reset notification from FW 86 + * @pvr_dev: Device pointer. 87 + * @data: Data provided by FW. 88 + * 89 + * This will decode the data structure provided by FW and print the results via drm_info(). 90 + */ 91 + void 92 + pvr_dump_context_reset_notification(struct pvr_device *pvr_dev, 93 + struct rogue_fwif_fwccb_cmd_context_reset_data *data) 94 + { 95 + struct drm_device *drm_dev = from_pvr_device(pvr_dev); 96 + 97 + if (data->flags & ROGUE_FWIF_FWCCB_CMD_CONTEXT_RESET_FLAG_ALL_CTXS) { 98 + drm_info(drm_dev, "Received context reset notification for all contexts\n"); 99 + } else { 100 + drm_info(drm_dev, "Received context reset notification on context %u\n", 101 + data->server_common_context_id); 102 + } 103 + 104 + drm_info(drm_dev, " Reset reason=%u (%s)\n", data->reset_reason, 105 + get_reset_reason_desc((enum rogue_context_reset_reason)data->reset_reason)); 106 + drm_info(drm_dev, " Data Master=%u (%s)\n", data->dm, get_dm_name(data->dm)); 107 + drm_info(drm_dev, " Job ref=%u\n", data->reset_job_ref); 108 + 109 + if (data->flags & ROGUE_FWIF_FWCCB_CMD_CONTEXT_RESET_FLAG_PF) { 110 + drm_info(drm_dev, " Page fault occurred, fault address=%llx\n", 111 + data->fault_address); 112 + } 113 + }
+17
drivers/gpu/drm/imagination/pvr_dump.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 OR MIT */ 2 + /* Copyright (c) 2026 Imagination Technologies Ltd. */ 3 + 4 + #ifndef PVR_DUMP_H 5 + #define PVR_DUMP_H 6 + 7 + /* Forward declaration from pvr_device.h. */ 8 + struct pvr_device; 9 + 10 + /* Forward declaration from pvr_rogue_fwif.h. */ 11 + struct rogue_fwif_fwccb_cmd_context_reset_data; 12 + 13 + void 14 + pvr_dump_context_reset_notification(struct pvr_device *pvr_dev, 15 + struct rogue_fwif_fwccb_cmd_context_reset_data *data); 16 + 17 + #endif /* PVR_DUMP_H */
+66 -34
drivers/gpu/drm/imagination/pvr_fw_startstop.c
··· 209 209 ROGUE_CR_SIDEKICK_IDLE_SOCIF_EN | 210 210 ROGUE_CR_SIDEKICK_IDLE_HOSTIF_EN); 211 211 bool skip_garten_idle = false; 212 + u64 layout_mars_value = 0; 213 + bool layout_mars = false; 214 + bool meta_fw = pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_META; 212 215 u32 reg_value; 213 216 int err; 214 217 218 + if (PVR_FEATURE_VALUE(pvr_dev, layout_mars, &layout_mars_value) == 0) 219 + layout_mars = layout_mars_value > 0; 220 + 215 221 /* 216 - * Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper. 217 - * For cores with the LAYOUT_MARS feature, SIDEKICK would have been 222 + * For cores with the LAYOUT_MARS feature, SIDEKICK and SLC would have been 218 223 * powered down by the FW. 219 224 */ 220 - err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask, 221 - sidekick_idle_mask, POLL_TIMEOUT_USEC); 222 - if (err) 223 - return err; 225 + if (!layout_mars) { 226 + /* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper. */ 227 + err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask, 228 + sidekick_idle_mask, POLL_TIMEOUT_USEC); 229 + if (err) 230 + return err; 231 + 232 + /* Wait for SLC to signal IDLE. */ 233 + err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SLC_IDLE, ROGUE_CR_SLC_IDLE_MASKFULL, 234 + ROGUE_CR_SLC_IDLE_MASKFULL, POLL_TIMEOUT_USEC); 235 + if (err) 236 + return err; 237 + } 224 238 225 239 /* Unset MTS DM association with threads. */ 226 240 pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_INTCTX_THREAD0_DM_ASSOC, ··· 243 229 pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_BGCTX_THREAD0_DM_ASSOC, 244 230 ROGUE_CR_MTS_BGCTX_THREAD0_DM_ASSOC_MASKFULL & 245 231 ROGUE_CR_MTS_BGCTX_THREAD0_DM_ASSOC_DM_ASSOC_CLRMSK); 246 - pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC, 247 - ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC_MASKFULL & 248 - ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK); 249 - pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC, 250 - ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC_MASKFULL & 251 - ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK); 232 + 233 + if (meta_fw) { 234 + pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC, 235 + ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC_MASKFULL & 236 + ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK); 237 + pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC, 238 + ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC_MASKFULL & 239 + ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK); 240 + } 252 241 253 242 /* Extra Idle checks. */ 254 243 err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_BIF_STATUS_MMU, 0, ··· 287 270 return err; 288 271 289 272 /* 290 - * Wait for SLC to signal IDLE. 291 - * For cores with the LAYOUT_MARS feature, SLC would have been powered 292 - * down by the FW. 273 + * For cores with the LAYOUT_MARS feature, SIDEKICK and SLC would have been 274 + * powered down by the FW. 293 275 */ 294 - err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SLC_IDLE, 295 - ROGUE_CR_SLC_IDLE_MASKFULL, 296 - ROGUE_CR_SLC_IDLE_MASKFULL, POLL_TIMEOUT_USEC); 297 - if (err) 298 - return err; 276 + if (!layout_mars) { 277 + /* Wait for SLC to signal IDLE. */ 278 + err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SLC_IDLE, 279 + ROGUE_CR_SLC_IDLE_MASKFULL, 280 + ROGUE_CR_SLC_IDLE_MASKFULL, POLL_TIMEOUT_USEC); 281 + if (err) 282 + return err; 299 283 300 - /* 301 - * Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper. 302 - * For cores with the LAYOUT_MARS feature, SIDEKICK would have been powered 303 - * down by the FW. 304 - */ 305 - err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask, 306 - sidekick_idle_mask, POLL_TIMEOUT_USEC); 307 - if (err) 308 - return err; 284 + /* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper. */ 285 + err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask, 286 + sidekick_idle_mask, POLL_TIMEOUT_USEC); 287 + if (err) 288 + return err; 289 + } 309 290 310 - if (pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_META) { 291 + if (meta_fw) { 311 292 err = pvr_meta_cr_read32(pvr_dev, META_CR_TxVECINT_BHALT, &reg_value); 312 293 if (err) 313 294 return err; ··· 319 304 skip_garten_idle = true; 320 305 } 321 306 322 - if (!skip_garten_idle) { 323 - err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, 324 - ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN, 325 - ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN, 307 + if (meta_fw || !layout_mars) { 308 + if (!skip_garten_idle) { 309 + err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, 310 + ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN, 311 + ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN, 312 + POLL_TIMEOUT_USEC); 313 + if (err) 314 + return err; 315 + } 316 + } else { 317 + /* 318 + * As FW core has been moved from SIDEKICK to the new MARS domain, checking 319 + * idle bits for CPU & System Arbiter excluding SOCIF which will never be 320 + * idle if Host polling on this register 321 + */ 322 + err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_MARS_IDLE, 323 + ROGUE_CR_MARS_IDLE_CPU_EN | 324 + ROGUE_CR_MARS_IDLE_MH_SYSARB0_EN, 325 + ROGUE_CR_MARS_IDLE_CPU_EN | 326 + ROGUE_CR_MARS_IDLE_MH_SYSARB0_EN, 326 327 POLL_TIMEOUT_USEC); 328 + 327 329 if (err) 328 330 return err; 329 331 }
+6 -2
drivers/gpu/drm/imagination/pvr_rogue_fwif.h
··· 1347 1347 struct rogue_fwif_fwccb_cmd_context_reset_data { 1348 1348 /* Context affected by the reset */ 1349 1349 u32 server_common_context_id; 1350 - /* Reason for reset */ 1351 - enum rogue_context_reset_reason reset_reason; 1350 + /* 1351 + * Reason for reset 1352 + * The valid values for reset_reason are the ones from 1353 + * enum rogue_context_reset_reason 1354 + */ 1355 + u32 reset_reason; 1352 1356 /* Data Master affected by the reset */ 1353 1357 u32 dm; 1354 1358 /* Job ref running at the time of reset */
+17 -1
drivers/gpu/drm/imagination/pvr_rogue_fwif_shared.h
··· 236 236 ROGUE_CONTEXT_RESET_REASON_INNOCENT_OVERRUNING = 4, 237 237 /* Forced reset to ensure scheduling requirements */ 238 238 ROGUE_CONTEXT_RESET_REASON_HARD_CONTEXT_SWITCH = 5, 239 + /* CDM Mission/safety checksum mismatch */ 240 + ROGUE_CONTEXT_RESET_REASON_WGP_CHECKSUM = 6, 241 + /* TRP checksum mismatch */ 242 + ROGUE_CONTEXT_RESET_REASON_TRP_CHECKSUM = 7, 243 + /* GPU ECC error (corrected, OK) */ 244 + ROGUE_CONTEXT_RESET_REASON_GPU_ECC_OK = 8, 245 + /* GPU ECC error (uncorrected, HWR) */ 246 + ROGUE_CONTEXT_RESET_REASON_GPU_ECC_HWR = 9, 247 + /* FW ECC error (corrected, OK) */ 248 + ROGUE_CONTEXT_RESET_REASON_FW_ECC_OK = 10, 249 + /* FW ECC error (uncorrected, ERR) */ 250 + ROGUE_CONTEXT_RESET_REASON_FW_ECC_ERR = 11, 239 251 /* FW Safety watchdog triggered */ 240 252 ROGUE_CONTEXT_RESET_REASON_FW_WATCHDOG = 12, 241 253 /* FW page fault (no HWR) */ ··· 261 249 }; 262 250 263 251 struct rogue_context_reset_reason_data { 264 - enum rogue_context_reset_reason reset_reason; 252 + /* 253 + * The valid values for reset_reason are the ones from 254 + * enum rogue_context_reset_reason 255 + */ 256 + u32 reset_reason; 265 257 u32 reset_ext_job_ref; 266 258 }; 267 259
+1 -1
drivers/gpu/drm/ingenic/ingenic-drm-drv.c
··· 1401 1401 goto err_devclk_disable; 1402 1402 } 1403 1403 1404 - drm_atomic_private_obj_init(drm, &priv->private_obj, NULL, 1404 + drm_atomic_private_obj_init(drm, &priv->private_obj, 1405 1405 &ingenic_drm_private_state_funcs); 1406 1406 1407 1407 ret = drmm_add_action_or_reset(drm, ingenic_drm_atomic_private_obj_fini,
+1 -1
drivers/gpu/drm/ingenic/ingenic-ipu.c
··· 901 901 return err; 902 902 } 903 903 904 - drm_atomic_private_obj_init(drm, &ipu->private_obj, NULL, 904 + drm_atomic_private_obj_init(drm, &ipu->private_obj, 905 905 &ingenic_ipu_private_state_funcs); 906 906 907 907 return 0;
-1
drivers/gpu/drm/mediatek/Makefile
··· 14 14 mtk_dsi.o \ 15 15 mtk_dpi.o \ 16 16 mtk_ethdr.o \ 17 - mtk_gem.o \ 18 17 mtk_mdp_rdma.o \ 19 18 mtk_padding.o \ 20 19 mtk_plane.o
-1
drivers/gpu/drm/mediatek/mtk_crtc.c
··· 23 23 #include "mtk_crtc.h" 24 24 #include "mtk_ddp_comp.h" 25 25 #include "mtk_drm_drv.h" 26 - #include "mtk_gem.h" 27 26 #include "mtk_plane.h" 28 27 29 28 /*
+2 -2
drivers/gpu/drm/mediatek/mtk_dp.c
··· 2454 2454 const struct drm_display_mode *mode) 2455 2455 { 2456 2456 struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); 2457 - u32 bpp = info->color_formats & DRM_COLOR_FORMAT_YCBCR422 ? 16 : 24; 2457 + u32 bpp = info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) ? 16 : 24; 2458 2458 u32 lane_count_min = mtk_dp->train_info.lane_count; 2459 2459 u32 rate = drm_dp_bw_code_to_link_rate(mtk_dp->train_info.link_rate) * 2460 2460 lane_count_min; ··· 2521 2521 */ 2522 2522 if (((rate * 97 / 100) < (mode->clock * 24 / 8)) && 2523 2523 ((rate * 97 / 100) > (mode->clock * 16 / 8)) && 2524 - (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) { 2524 + (display_info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))) { 2525 2525 input_fmts = kcalloc(1, sizeof(*input_fmts), GFP_KERNEL); 2526 2526 if (!input_fmts) 2527 2527 return NULL;
+3 -18
drivers/gpu/drm/mediatek/mtk_drm_drv.c
··· 19 19 #include <drm/drm_fbdev_dma.h> 20 20 #include <drm/drm_fourcc.h> 21 21 #include <drm/drm_gem.h> 22 + #include <drm/drm_gem_dma_helper.h> 22 23 #include <drm/drm_gem_framebuffer_helper.h> 23 24 #include <drm/drm_ioctl.h> 24 25 #include <drm/drm_of.h> ··· 30 29 #include "mtk_ddp_comp.h" 31 30 #include "mtk_disp_drv.h" 32 31 #include "mtk_drm_drv.h" 33 - #include "mtk_gem.h" 34 32 35 33 #define DRIVER_NAME "mediatek" 36 34 #define DRIVER_DESC "Mediatek SoC DRM" ··· 565 565 goto err_component_unbind; 566 566 } 567 567 568 - for (i = 0; i < private->data->mmsys_dev_num; i++) 569 - private->all_drm_private[i]->dma_dev = dma_dev; 568 + drm_dev_set_dma_dev(drm, dma_dev); 570 569 571 570 /* 572 571 * Configure the DMA segment size to make sure we get contiguous IOVA ··· 599 600 600 601 DEFINE_DRM_GEM_FOPS(mtk_drm_fops); 601 602 602 - /* 603 - * We need to override this because the device used to import the memory is 604 - * not dev->dev, as drm_gem_prime_import() expects. 605 - */ 606 - static struct drm_gem_object *mtk_gem_prime_import(struct drm_device *dev, 607 - struct dma_buf *dma_buf) 608 - { 609 - struct mtk_drm_private *private = dev->dev_private; 610 - 611 - return drm_gem_prime_import_dev(dev, dma_buf, private->dma_dev); 612 - } 613 - 614 603 static const struct drm_driver mtk_drm_driver = { 615 604 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, 616 605 617 - .dumb_create = mtk_gem_dumb_create, 606 + DRM_GEM_DMA_DRIVER_OPS, 618 607 DRM_FBDEV_DMA_DRIVER_OPS, 619 608 620 - .gem_prime_import = mtk_gem_prime_import, 621 - .gem_prime_import_sg_table = mtk_gem_prime_import_sg_table, 622 609 .fops = &mtk_drm_fops, 623 610 624 611 .name = DRIVER_NAME,
-1
drivers/gpu/drm/mediatek/mtk_drm_drv.h
··· 54 54 55 55 struct mtk_drm_private { 56 56 struct drm_device *drm; 57 - struct device *dma_dev; 58 57 bool mtk_drm_bound; 59 58 bool drm_master; 60 59 struct device *dev;
-231
drivers/gpu/drm/mediatek/mtk_gem.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * Copyright (c) 2015 MediaTek Inc. 4 - * Copyright (c) 2025 Collabora Ltd. 5 - * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> 6 - */ 7 - 8 - #include <linux/dma-buf.h> 9 - #include <linux/vmalloc.h> 10 - 11 - #include <drm/drm.h> 12 - #include <drm/drm_device.h> 13 - #include <drm/drm_gem.h> 14 - #include <drm/drm_gem_dma_helper.h> 15 - #include <drm/drm_prime.h> 16 - #include <drm/drm_print.h> 17 - 18 - #include "mtk_drm_drv.h" 19 - #include "mtk_gem.h" 20 - 21 - static int mtk_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); 22 - 23 - static void mtk_gem_free_object(struct drm_gem_object *obj) 24 - { 25 - struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj); 26 - struct mtk_drm_private *priv = obj->dev->dev_private; 27 - 28 - if (dma_obj->sgt) 29 - drm_prime_gem_destroy(obj, dma_obj->sgt); 30 - else 31 - dma_free_wc(priv->dma_dev, dma_obj->base.size, 32 - dma_obj->vaddr, dma_obj->dma_addr); 33 - 34 - /* release file pointer to gem object. */ 35 - drm_gem_object_release(obj); 36 - 37 - kfree(dma_obj); 38 - } 39 - 40 - /* 41 - * Allocate a sg_table for this GEM object. 42 - * Note: Both the table's contents, and the sg_table itself must be freed by 43 - * the caller. 44 - * Returns a pointer to the newly allocated sg_table, or an ERR_PTR() error. 45 - */ 46 - static struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj) 47 - { 48 - struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj); 49 - struct mtk_drm_private *priv = obj->dev->dev_private; 50 - struct sg_table *sgt; 51 - int ret; 52 - 53 - sgt = kzalloc_obj(*sgt); 54 - if (!sgt) 55 - return ERR_PTR(-ENOMEM); 56 - 57 - ret = dma_get_sgtable(priv->dma_dev, sgt, dma_obj->vaddr, 58 - dma_obj->dma_addr, obj->size); 59 - if (ret) { 60 - DRM_ERROR("failed to allocate sgt, %d\n", ret); 61 - kfree(sgt); 62 - return ERR_PTR(ret); 63 - } 64 - 65 - return sgt; 66 - } 67 - 68 - static const struct drm_gem_object_funcs mtk_gem_object_funcs = { 69 - .free = mtk_gem_free_object, 70 - .print_info = drm_gem_dma_object_print_info, 71 - .get_sg_table = mtk_gem_prime_get_sg_table, 72 - .vmap = drm_gem_dma_object_vmap, 73 - .mmap = mtk_gem_object_mmap, 74 - .vm_ops = &drm_gem_dma_vm_ops, 75 - }; 76 - 77 - static struct drm_gem_dma_object *mtk_gem_init(struct drm_device *dev, 78 - unsigned long size, bool private) 79 - { 80 - struct drm_gem_dma_object *dma_obj; 81 - int ret; 82 - 83 - size = round_up(size, PAGE_SIZE); 84 - 85 - if (size == 0) 86 - return ERR_PTR(-EINVAL); 87 - 88 - dma_obj = kzalloc_obj(*dma_obj); 89 - if (!dma_obj) 90 - return ERR_PTR(-ENOMEM); 91 - 92 - dma_obj->base.funcs = &mtk_gem_object_funcs; 93 - 94 - if (private) { 95 - ret = 0; 96 - drm_gem_private_object_init(dev, &dma_obj->base, size); 97 - } else { 98 - ret = drm_gem_object_init(dev, &dma_obj->base, size); 99 - } 100 - if (ret) { 101 - DRM_ERROR("failed to initialize gem object\n"); 102 - kfree(dma_obj); 103 - return ERR_PTR(ret); 104 - } 105 - 106 - return dma_obj; 107 - } 108 - 109 - static struct drm_gem_dma_object *mtk_gem_create(struct drm_device *dev, size_t size) 110 - { 111 - struct mtk_drm_private *priv = dev->dev_private; 112 - struct drm_gem_dma_object *dma_obj; 113 - struct drm_gem_object *obj; 114 - int ret; 115 - 116 - dma_obj = mtk_gem_init(dev, size, false); 117 - if (IS_ERR(dma_obj)) 118 - return ERR_CAST(dma_obj); 119 - 120 - obj = &dma_obj->base; 121 - 122 - dma_obj->vaddr = dma_alloc_wc(priv->dma_dev, obj->size, 123 - &dma_obj->dma_addr, 124 - GFP_KERNEL | __GFP_NOWARN); 125 - if (!dma_obj->vaddr) { 126 - DRM_ERROR("failed to allocate %zx byte dma buffer", obj->size); 127 - ret = -ENOMEM; 128 - goto err_gem_free; 129 - } 130 - 131 - DRM_DEBUG_DRIVER("vaddr = %p dma_addr = %pad size = %zu\n", 132 - dma_obj->vaddr, &dma_obj->dma_addr, 133 - size); 134 - 135 - return dma_obj; 136 - 137 - err_gem_free: 138 - drm_gem_object_release(obj); 139 - kfree(dma_obj); 140 - return ERR_PTR(ret); 141 - } 142 - 143 - int mtk_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev, 144 - struct drm_mode_create_dumb *args) 145 - { 146 - struct drm_gem_dma_object *dma_obj; 147 - int ret; 148 - 149 - args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8); 150 - 151 - /* 152 - * Multiply 2 variables of different types, 153 - * for example: args->size = args->spacing * args->height; 154 - * may cause coverity issue with unintentional overflow. 155 - */ 156 - args->size = args->pitch; 157 - args->size *= args->height; 158 - 159 - dma_obj = mtk_gem_create(dev, args->size); 160 - if (IS_ERR(dma_obj)) 161 - return PTR_ERR(dma_obj); 162 - 163 - /* 164 - * allocate a id of idr table where the obj is registered 165 - * and handle has the id what user can see. 166 - */ 167 - ret = drm_gem_handle_create(file_priv, &dma_obj->base, &args->handle); 168 - if (ret) 169 - goto err_handle_create; 170 - 171 - /* drop reference from allocate - handle holds it now. */ 172 - drm_gem_object_put(&dma_obj->base); 173 - 174 - return 0; 175 - 176 - err_handle_create: 177 - mtk_gem_free_object(&dma_obj->base); 178 - return ret; 179 - } 180 - 181 - static int mtk_gem_object_mmap(struct drm_gem_object *obj, 182 - struct vm_area_struct *vma) 183 - 184 - { 185 - struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj); 186 - struct mtk_drm_private *priv = obj->dev->dev_private; 187 - int ret; 188 - 189 - /* 190 - * Set vm_pgoff (used as a fake buffer offset by DRM) to 0 and map the 191 - * whole buffer from the start. 192 - */ 193 - vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node); 194 - 195 - /* 196 - * dma_alloc_attrs() allocated a struct page table for mtk_gem, so clear 197 - * VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap(). 198 - */ 199 - vm_flags_mod(vma, VM_IO | VM_DONTEXPAND | VM_DONTDUMP, VM_PFNMAP); 200 - 201 - vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); 202 - vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 203 - 204 - ret = dma_mmap_wc(priv->dma_dev, vma, dma_obj->vaddr, 205 - dma_obj->dma_addr, obj->size); 206 - if (ret) 207 - drm_gem_vm_close(vma); 208 - 209 - return ret; 210 - } 211 - 212 - struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev, 213 - struct dma_buf_attachment *attach, struct sg_table *sgt) 214 - { 215 - struct drm_gem_dma_object *dma_obj; 216 - 217 - /* check if the entries in the sg_table are contiguous */ 218 - if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size) { 219 - DRM_ERROR("sg_table is not contiguous"); 220 - return ERR_PTR(-EINVAL); 221 - } 222 - 223 - dma_obj = mtk_gem_init(dev, attach->dmabuf->size, true); 224 - if (IS_ERR(dma_obj)) 225 - return ERR_CAST(dma_obj); 226 - 227 - dma_obj->dma_addr = sg_dma_address(sgt->sgl); 228 - dma_obj->sgt = sgt; 229 - 230 - return &dma_obj->base; 231 - }
-17
drivers/gpu/drm/mediatek/mtk_gem.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0-only */ 2 - /* 3 - * Copyright (c) 2015 MediaTek Inc. 4 - */ 5 - 6 - #ifndef _MTK_GEM_H_ 7 - #define _MTK_GEM_H_ 8 - 9 - #include <drm/drm_gem.h> 10 - #include <drm/drm_gem_dma_helper.h> 11 - 12 - int mtk_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev, 13 - struct drm_mode_create_dumb *args); 14 - struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev, 15 - struct dma_buf_attachment *attach, struct sg_table *sg); 16 - 17 - #endif
+4 -4
drivers/gpu/drm/mediatek/mtk_hdmi_v2.c
··· 747 747 748 748 switch (conn_state->hdmi.output_format) { 749 749 default: 750 - case HDMI_COLORSPACE_RGB: 751 - case HDMI_COLORSPACE_YUV444: 750 + case DRM_OUTPUT_COLOR_FORMAT_RGB444: 751 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR444: 752 752 /* Disable YUV420 downsampling for RGB and YUV444 */ 753 753 mtk_hdmi_yuv420_downsampling(hdmi, false); 754 754 break; 755 - case HDMI_COLORSPACE_YUV422: 755 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR422: 756 756 /* 757 757 * YUV420 downsampling is special and needs a bit of setup 758 758 * so we disable everything there before doing anything else. ··· 763 763 regmap_set_bits(hdmi->regs, VID_DOWNSAMPLE_CONFIG, 764 764 C444_C422_CONFIG_ENABLE); 765 765 break; 766 - case HDMI_COLORSPACE_YUV420: 766 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR420: 767 767 mtk_hdmi_yuv420_downsampling(hdmi, true); 768 768 break; 769 769 }
-1
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
··· 1161 1161 dev->mode_config.cursor_height = 512; 1162 1162 1163 1163 drm_atomic_private_obj_init(dpu_kms->dev, &dpu_kms->global_state, 1164 - NULL, 1165 1164 &dpu_kms_global_state_funcs); 1166 1165 1167 1166 atomic_set(&dpu_kms->bandwidth_ref, 0);
-1
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
··· 717 717 mdp5_kms->dev = dev; 718 718 719 719 drm_atomic_private_obj_init(mdp5_kms->dev, &mdp5_kms->glob_state, 720 - NULL, 721 720 &mdp5_global_state_funcs); 722 721 723 722 /* we need to set a default rate before enabling. Set a safe
+16 -6
drivers/gpu/drm/omapdrm/omap_drv.c
··· 275 275 kfree(omap_state); 276 276 } 277 277 278 + static struct drm_private_state * 279 + omap_global_atomic_create_state(struct drm_private_obj *obj) 280 + { 281 + struct omap_global_state *state; 282 + 283 + state = kzalloc_obj(*state); 284 + if (!state) 285 + return ERR_PTR(-ENOMEM); 286 + 287 + __drm_atomic_helper_private_obj_create_state(obj, &state->base); 288 + 289 + return &state->base; 290 + } 291 + 278 292 static const struct drm_private_state_funcs omap_global_state_funcs = { 293 + .atomic_create_state = omap_global_atomic_create_state, 279 294 .atomic_duplicate_state = omap_global_duplicate_state, 280 295 .atomic_destroy_state = omap_global_destroy_state, 281 296 }; ··· 298 283 static int omap_global_obj_init(struct drm_device *dev) 299 284 { 300 285 struct omap_drm_private *priv = dev->dev_private; 301 - struct omap_global_state *state; 302 286 303 - state = kzalloc_obj(*state); 304 - if (!state) 305 - return -ENOMEM; 306 - 307 - drm_atomic_private_obj_init(dev, &priv->glob_obj, &state->base, 287 + drm_atomic_private_obj_init(dev, &priv->glob_obj, 308 288 &omap_global_state_funcs); 309 289 return 0; 310 290 }
+43 -3
drivers/gpu/drm/panel/Kconfig
··· 203 203 Say Y here if you want to enable support for Himax HX83112B-based 204 204 display panels, such as the one found in the Fairphone 3 smartphone. 205 205 206 + config DRM_PANEL_HIMAX_HX83121A 207 + tristate "Himax HX83121A-based DSI panel" 208 + depends on OF 209 + depends on DRM_MIPI_DSI 210 + depends on BACKLIGHT_CLASS_DEVICE 211 + select DRM_KMS_HELPER 212 + help 213 + Say Y here if you want to enable support for Himax HX83121A-based 214 + display panels, such as the one found in the HUAWEI Matebook E Go 215 + series. 216 + 206 217 config DRM_PANEL_HIMAX_HX8394 207 218 tristate "HIMAX HX8394 MIPI-DSI LCD panels" 208 219 depends on OF ··· 268 257 Say Y if you want to enable support for panels based on the 269 258 Ilitek ILI9805 controller. 270 259 271 - config DRM_PANEL_ILITEK_ILI9806E 272 - tristate "Ilitek ILI9806E-based panels" 260 + config DRM_PANEL_ILITEK_ILI9806E_CORE 261 + tristate 262 + 263 + config DRM_PANEL_ILITEK_ILI9806E_DSI 264 + tristate "Ilitek ILI9806E-based DSI panels" 273 265 depends on OF 274 266 depends on DRM_MIPI_DSI 275 267 depends on BACKLIGHT_CLASS_DEVICE 268 + select DRM_PANEL_ILITEK_ILI9806E_CORE 276 269 help 277 270 Say Y if you want to enable support for panels based on the 278 - Ilitek ILI9806E controller. 271 + Ilitek ILI9806E controller using DSI. 272 + 273 + config DRM_PANEL_ILITEK_ILI9806E_SPI 274 + tristate "Ilitek ILI9806E-based RGB SPI panel" 275 + depends on OF 276 + depends on SPI 277 + depends on BACKLIGHT_CLASS_DEVICE 278 + select DRM_MIPI_DBI 279 + select VIDEOMODE_HELPERS 280 + select DRM_PANEL_ILITEK_ILI9806E_CORE 281 + help 282 + Say Y if you want to enable support for panels based on the 283 + Ilitek ILI9806E controller using SPI. 279 284 280 285 config DRM_PANEL_ILITEK_ILI9881C 281 286 tristate "Ilitek ILI9881C-based panels" ··· 965 938 panel, which uses Samsung's S6E8AA5X01 controller. The panel has a 966 939 ~5.6 inch AMOLED display, and the controller is driven by the MIPI 967 940 DSI protocol with 4 lanes. 941 + 942 + config DRM_PANEL_SAMSUNG_S6E8FC0 943 + tristate "Samsung S6E8FC0 DSI controller" 944 + depends on OF 945 + depends on BACKLIGHT_CLASS_DEVICE 946 + select DRM_MIPI_DSI 947 + help 948 + Say Y or M here if you want to enable support for the Samsung 949 + S6E8FC0 DSI controller and connected panel. 950 + Currently supported panels: 951 + 952 + M1906F9 (M1906F9SH or M1906F9SI), 6.09 inch 720x1560, found 953 + in the Xiaomi Mi A3 smartphone (xiaomi-laurel). 968 954 969 955 config DRM_PANEL_SAMSUNG_SOFEF00 970 956 tristate "Samsung SOFEF00 DSI panel controller"
+5 -1
drivers/gpu/drm/panel/Makefile
··· 21 21 obj-$(CONFIG_DRM_PANEL_HIMAX_HX83102) += panel-himax-hx83102.o 22 22 obj-$(CONFIG_DRM_PANEL_HIMAX_HX83112A) += panel-himax-hx83112a.o 23 23 obj-$(CONFIG_DRM_PANEL_HIMAX_HX83112B) += panel-himax-hx83112b.o 24 + obj-$(CONFIG_DRM_PANEL_HIMAX_HX83121A) += panel-himax-hx83121a.o 24 25 obj-$(CONFIG_DRM_PANEL_HIMAX_HX8394) += panel-himax-hx8394.o 25 26 obj-$(CONFIG_DRM_PANEL_HYDIS_HV101HD1) += panel-hydis-hv101hd1.o 26 27 obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o 27 28 obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9341) += panel-ilitek-ili9341.o 28 29 obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9805) += panel-ilitek-ili9805.o 29 - obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9806E) += panel-ilitek-ili9806e.o 30 + obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9806E_CORE) += panel-ilitek-ili9806e-core.o 31 + obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9806E_DSI) += panel-ilitek-ili9806e-dsi.o 32 + obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9806E_SPI) += panel-ilitek-ili9806e-spi.o 30 33 obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o 31 34 obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9882T) += panel-ilitek-ili9882t.o 32 35 obj-$(CONFIG_DRM_PANEL_INNOLUX_EJ030NA) += panel-innolux-ej030na.o ··· 98 95 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01) += panel-samsung-s6e88a0-ams452ef01.o 99 96 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o 100 97 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA5X01_AMS561RA01) += panel-samsung-s6e8aa5x01-ams561ra01.o 98 + obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8FC0) += panel-samsung-s6e8fc0-m1906f9.o 101 99 obj-$(CONFIG_DRM_PANEL_SAMSUNG_SOFEF00) += panel-samsung-sofef00.o 102 100 obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) += panel-seiko-43wvf1g.o 103 101 obj-$(CONFIG_DRM_PANEL_SHARP_LQ079L1SX01) += panel-sharp-lq079l1sx01.o
+151
drivers/gpu/drm/panel/panel-himax-hx83102.c
··· 7 7 * Based on drivers/gpu/drm/panel/panel-himax-hx8394.c 8 8 */ 9 9 10 + #include <linux/backlight.h> 10 11 #include <linux/delay.h> 11 12 #include <linux/gpio/consumer.h> 12 13 #include <linux/module.h> ··· 76 75 unsigned int width_mm; 77 76 unsigned int height_mm; 78 77 } size; 78 + 79 + bool has_backlight; 79 80 80 81 int (*init)(struct hx83102 *ctx); 81 82 }; ··· 704 701 return dsi_ctx.accum_err; 705 702 } 706 703 704 + static int holitech_htf065h045_init(struct hx83102 *ctx) 705 + { 706 + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; 707 + 708 + msleep(50); 709 + 710 + hx83102_enable_extended_cmds(&dsi_ctx, true); 711 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x22, 0x44, 0x27, 0x27, 0x32, 712 + 0x52, 0x57, 0x39, 0x08, 0x08, 0x08); 713 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x00, 0x06, 0x40, 0x00, 714 + 0x0e, 0xae, 0x38, 0x00, 0x00, 0x00, 0x00, 0xf4, 0xa0); 715 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x01, 0x58, 0x01, 0x58, 0x01, 716 + 0x58, 0x03, 0x58, 0x03, 0xff, 0x01, 0x20, 0x00, 0xff); 717 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02); 718 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00, 0x00, 0x00, 0x00, 0x00, 719 + 0x10, 0x00, 0x17, 0x00, 0x63, 0x37, 0x0e, 0x0e, 0x00, 0x00, 720 + 0x32, 0x10, 0x08, 0x00, 0x08, 0x32, 0x16, 0x4e, 0x06, 0x4e); 721 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x04, 0x0c, 0xb2, 0x01); 722 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x24, 0x25, 0x18, 0x18, 0x19, 723 + 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 724 + 0x18, 0x18, 0x18, 0x06, 0x07, 0x04, 0x05, 0x18, 0x18, 0x18, 725 + 0x18, 0x02, 0x03, 0x00, 0x01, 0x20, 0x21, 0x18, 0x18, 0x18, 726 + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18); 727 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP2, 0x00, 0x09, 0x16, 0x1f, 0x28, 728 + 0x4b, 0x65, 0x6d, 0x74, 0x70, 0x89, 0x8d, 0x91, 0xa0, 0x9e, 729 + 0xa8, 0xb2, 0xc8, 0xc9, 0x65, 0x6d, 0x78, 0x7f, 0x00, 0x09, 730 + 0x16, 0x1f, 0x28, 0x4b, 0x65, 0x6d, 0x74, 0x70, 0x89, 0x8d, 731 + 0x91, 0xa0, 0x9e, 0xa8, 0xb2, 0xc8, 0xc9, 0x65, 0x6d, 0x78, 732 + 0x7f); 733 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xff, 0x14, 0x00, 0x00); 734 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); 735 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x01); 736 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02); 737 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xff, 0xff, 0xff, 738 + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0); 739 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03); 740 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 741 + 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0xaa, 0xaa, 0xaa, 742 + 0xaa, 0xaa, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0); 743 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); 744 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x70, 0x23, 0xa8, 0x93, 0xb2, 745 + 0xc0, 0xc0, 0x01, 0x10, 0x00, 0x00, 0x00, 0x0d, 0x3d, 0x82, 746 + 0x77, 0x04, 0x01, 0x04); 747 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); 748 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x01); 749 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); 750 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x00, 0x53, 0x00, 0x02, 0x59); 751 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0x00, 0x04, 0x9e, 0xf6, 752 + 0x00, 0x5d); 753 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02); 754 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x42, 0x00, 0x33, 0x00, 0x33, 755 + 0x88, 0xb3, 0x00); 756 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); 757 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x20, 0x01); 758 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02); 759 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x7f, 0x03, 0xf5); 760 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); 761 + 762 + return dsi_ctx.accum_err; 763 + } 764 + 707 765 static const struct drm_display_mode starry_mode = { 708 766 .clock = 162680, 709 767 .hdisplay = 1200, ··· 895 831 .height_mm = 235, 896 832 }, 897 833 .init = starry_2082109qfh040022_50e_init, 834 + }; 835 + 836 + static const struct drm_display_mode holitech_htf065h045_default_mode = { 837 + .clock = 90720, 838 + .hdisplay = 720, 839 + .hsync_start = 720 + 40, 840 + .hsync_end = 720 + 40 + 40, 841 + .htotal = 720 + 40 + 40 + 40, 842 + .vdisplay = 1600, 843 + .vsync_start = 1600 + 186, 844 + .vsync_end = 1600 + 186 + 2, 845 + .vtotal = 1600 + 186 + 2 + 12, 846 + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 847 + }; 848 + 849 + static const struct hx83102_panel_desc holitech_htf065h045_desc = { 850 + .modes = &holitech_htf065h045_default_mode, 851 + .size = { 852 + .width_mm = 68, 853 + .height_mm = 151, 854 + }, 855 + .has_backlight = true, 856 + .init = holitech_htf065h045_init, 898 857 }; 899 858 900 859 static int hx83102_enable(struct drm_panel *panel) ··· 1053 966 .get_orientation = hx83102_get_orientation, 1054 967 }; 1055 968 969 + static int hx83102_bl_update_status(struct backlight_device *bl) 970 + { 971 + struct mipi_dsi_device *dsi = bl_get_data(bl); 972 + u16 brightness = backlight_get_brightness(bl); 973 + int ret; 974 + 975 + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 976 + 977 + ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness); 978 + if (ret < 0) 979 + return ret; 980 + 981 + dsi->mode_flags |= MIPI_DSI_MODE_LPM; 982 + 983 + return 0; 984 + } 985 + 986 + static int hx83102_bl_get_brightness(struct backlight_device *bl) 987 + { 988 + struct mipi_dsi_device *dsi = bl_get_data(bl); 989 + u16 brightness; 990 + int ret; 991 + 992 + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 993 + 994 + ret = mipi_dsi_dcs_get_display_brightness_large(dsi, &brightness); 995 + if (ret < 0) 996 + return ret; 997 + 998 + dsi->mode_flags |= MIPI_DSI_MODE_LPM; 999 + 1000 + return brightness; 1001 + } 1002 + 1003 + static const struct backlight_ops hx83102_bl_ops = { 1004 + .update_status = hx83102_bl_update_status, 1005 + .get_brightness = hx83102_bl_get_brightness, 1006 + }; 1007 + 1008 + static struct backlight_device * 1009 + hx83102_create_dcs_backlight(struct mipi_dsi_device *dsi) 1010 + { 1011 + struct device *dev = &dsi->dev; 1012 + const struct backlight_properties props = { 1013 + .type = BACKLIGHT_RAW, 1014 + .brightness = 4095, 1015 + .max_brightness = 4095, 1016 + }; 1017 + 1018 + return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, 1019 + &hx83102_bl_ops, &props); 1020 + } 1021 + 1056 1022 static int hx83102_panel_add(struct hx83102 *ctx) 1057 1023 { 1058 1024 struct device *dev = &ctx->dsi->dev; ··· 1136 996 err = drm_panel_of_backlight(&ctx->base); 1137 997 if (err) 1138 998 return err; 999 + 1000 + /* Use DSI-based backlight as fallback if available */ 1001 + if (ctx->desc->has_backlight && !ctx->base.backlight) { 1002 + ctx->base.backlight = hx83102_create_dcs_backlight(ctx->dsi); 1003 + if (IS_ERR(ctx->base.backlight)) 1004 + return dev_err_probe(dev, PTR_ERR(ctx->base.backlight), 1005 + "Failed to create backlight\n"); 1006 + } 1139 1007 1140 1008 ctx->base.funcs = &hx83102_drm_funcs; 1141 1009 ctx->base.dev = &ctx->dsi->dev; ··· 1216 1068 }, 1217 1069 { .compatible = "starry,himax83102-j02", 1218 1070 .data = &starry_desc 1071 + }, 1072 + { .compatible = "holitech,htf065h045", 1073 + .data = &holitech_htf065h045_desc 1219 1074 }, 1220 1075 { /* sentinel */ } 1221 1076 };
+749
drivers/gpu/drm/panel/panel-himax-hx83121a.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Himax HX83121A DriverIC panels driver 4 + * Copyright (c) 2024-2026 Pengyu Luo <mitltlatltl@gmail.com> 5 + * 6 + * Multiple panels handling based on panel-novatek-nt36523.c 7 + */ 8 + 9 + #include <linux/backlight.h> 10 + #include <linux/delay.h> 11 + #include <linux/gpio/consumer.h> 12 + #include <linux/mod_devicetable.h> 13 + #include <linux/module.h> 14 + #include <linux/of.h> 15 + #include <linux/of_graph.h> 16 + #include <linux/regulator/consumer.h> 17 + 18 + #include <drm/display/drm_dsc.h> 19 + #include <drm/display/drm_dsc_helper.h> 20 + #include <drm/drm_mipi_dsi.h> 21 + #include <drm/drm_modes.h> 22 + #include <drm/drm_panel.h> 23 + 24 + #include <video/mipi_display.h> 25 + 26 + static bool enable_dsc; 27 + module_param(enable_dsc, bool, 0); 28 + MODULE_PARM_DESC(enable_dsc, "enable DSC on the panel (default: false)"); 29 + 30 + struct himax { 31 + struct drm_panel panel; 32 + struct mipi_dsi_device *dsi[2]; 33 + const struct panel_desc *desc; 34 + struct drm_dsc_config dsc; 35 + struct gpio_desc *reset_gpio; 36 + struct regulator_bulk_data *supplies; 37 + struct backlight_device *backlight; 38 + }; 39 + 40 + struct panel_desc { 41 + unsigned int width_mm; 42 + unsigned int height_mm; 43 + unsigned int bpc; 44 + unsigned int lanes; 45 + enum mipi_dsi_pixel_format format; 46 + unsigned long mode_flags; 47 + const struct drm_dsc_config *dsc_cfg; 48 + const struct drm_display_mode *dsc_modes; 49 + unsigned int num_dsc_modes; 50 + 51 + const struct drm_display_mode *modes; 52 + unsigned int num_modes; 53 + 54 + int (*init_sequence_dsc)(struct mipi_dsi_multi_context *dsi_ctx); 55 + int (*init_sequence)(struct mipi_dsi_multi_context *dsi_ctx); 56 + 57 + bool is_dual_dsi; 58 + bool has_dcs_backlight; 59 + }; 60 + 61 + static const struct regulator_bulk_data himax_supplies[] = { 62 + { .supply = "vddi" }, 63 + { .supply = "avdd" }, 64 + { .supply = "avee" }, 65 + }; 66 + 67 + static inline struct himax *to_himax(struct drm_panel *panel) 68 + { 69 + return container_of(panel, struct himax, panel); 70 + } 71 + 72 + static inline struct mipi_dsi_device *to_primary_dsi(struct himax *ctx) 73 + { 74 + /* Sync on DSI1 for dual dsi */ 75 + return ctx->desc->is_dual_dsi ? ctx->dsi[1] : ctx->dsi[0]; 76 + } 77 + 78 + static void himax_reset(struct himax *ctx) 79 + { 80 + gpiod_set_value_cansleep(ctx->reset_gpio, 1); 81 + usleep_range(4000, 4100); 82 + gpiod_set_value_cansleep(ctx->reset_gpio, 0); 83 + msleep(20); 84 + } 85 + 86 + static int himax_prepare(struct drm_panel *panel) 87 + { 88 + struct himax *ctx = to_himax(panel); 89 + struct mipi_dsi_device *dsi = to_primary_dsi(ctx); 90 + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; 91 + struct drm_dsc_picture_parameter_set pps; 92 + int ret; 93 + 94 + ret = regulator_bulk_enable(ARRAY_SIZE(himax_supplies), 95 + ctx->supplies); 96 + if (ret < 0) 97 + return ret; 98 + 99 + himax_reset(ctx); 100 + 101 + if (enable_dsc && ctx->desc->init_sequence_dsc) 102 + ret = ctx->desc->init_sequence_dsc(&dsi_ctx); 103 + else if (ctx->desc->init_sequence) 104 + ret = ctx->desc->init_sequence(&dsi_ctx); 105 + else 106 + ret = -EOPNOTSUPP; 107 + 108 + if (ret < 0) { 109 + gpiod_set_value_cansleep(ctx->reset_gpio, 1); 110 + regulator_bulk_disable(ARRAY_SIZE(himax_supplies), 111 + ctx->supplies); 112 + return ret; 113 + } 114 + 115 + if (enable_dsc) { 116 + drm_dsc_pps_payload_pack(&pps, &ctx->dsc); 117 + mipi_dsi_picture_parameter_set_multi(&dsi_ctx, &pps); 118 + mipi_dsi_compression_mode_multi(&dsi_ctx, true); 119 + } 120 + 121 + return backlight_enable(ctx->backlight); 122 + } 123 + 124 + static int himax_off(struct mipi_dsi_multi_context *dsi_ctx) 125 + { 126 + mipi_dsi_dcs_enter_sleep_mode_multi(dsi_ctx); 127 + mipi_dsi_msleep(dsi_ctx, 120); 128 + 129 + return dsi_ctx->accum_err; 130 + } 131 + 132 + static int himax_unprepare(struct drm_panel *panel) 133 + { 134 + struct himax *ctx = to_himax(panel); 135 + struct mipi_dsi_device *dsi = to_primary_dsi(ctx); 136 + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; 137 + struct device *dev = &dsi->dev; 138 + int ret; 139 + 140 + ret = himax_off(&dsi_ctx); 141 + if (ret < 0) 142 + dev_err(dev, "panel failed to off: %d\n", ret); 143 + 144 + gpiod_set_value_cansleep(ctx->reset_gpio, 1); 145 + regulator_bulk_disable(ARRAY_SIZE(himax_supplies), ctx->supplies); 146 + 147 + return 0; 148 + } 149 + 150 + static int himax_get_modes(struct drm_panel *panel, 151 + struct drm_connector *connector) 152 + { 153 + struct himax *ctx = to_himax(panel); 154 + const struct panel_desc *desc = ctx->desc; 155 + const struct drm_display_mode *modes; 156 + int num_modes; 157 + int i; 158 + 159 + modes = enable_dsc ? desc->dsc_modes : desc->modes; 160 + num_modes = enable_dsc ? desc->num_dsc_modes : desc->num_modes; 161 + 162 + for (i = 0; i < num_modes; i++) { 163 + const struct drm_display_mode *m = &modes[i]; 164 + struct drm_display_mode *mode; 165 + 166 + mode = drm_mode_duplicate(connector->dev, m); 167 + if (!mode) { 168 + dev_err(panel->dev, "failed to add mode %ux%u@%u\n", 169 + m->hdisplay, m->vdisplay, drm_mode_vrefresh(m)); 170 + return -ENOMEM; 171 + } 172 + 173 + mode->type = DRM_MODE_TYPE_DRIVER; 174 + if (i == 0) 175 + mode->type |= DRM_MODE_TYPE_PREFERRED; 176 + 177 + drm_mode_set_name(mode); 178 + drm_mode_probed_add(connector, mode); 179 + } 180 + 181 + connector->display_info.width_mm = desc->width_mm; 182 + connector->display_info.height_mm = desc->height_mm; 183 + connector->display_info.bpc = desc->bpc; 184 + 185 + return num_modes; 186 + } 187 + 188 + static const struct drm_panel_funcs himax_panel_funcs = { 189 + .prepare = himax_prepare, 190 + .unprepare = himax_unprepare, 191 + .get_modes = himax_get_modes, 192 + }; 193 + 194 + static int himax_bl_update_status(struct backlight_device *bl) 195 + { 196 + struct mipi_dsi_device *dsi = bl_get_data(bl); 197 + u16 brightness = backlight_get_brightness(bl); 198 + /* TODO: brightness to raw map table */ 199 + return mipi_dsi_dcs_set_display_brightness_large(dsi, brightness); 200 + } 201 + 202 + static const struct backlight_ops himax_bl_ops = { 203 + .options = BL_CORE_SUSPENDRESUME, 204 + .update_status = himax_bl_update_status, 205 + }; 206 + 207 + static struct backlight_device * 208 + himax_create_backlight(struct mipi_dsi_device *dsi) 209 + { 210 + struct device *dev = &dsi->dev; 211 + const struct backlight_properties props = { 212 + .type = BACKLIGHT_RAW, 213 + .brightness = 512, 214 + .max_brightness = 4095, 215 + .scale = BACKLIGHT_SCALE_NON_LINEAR, 216 + }; 217 + 218 + return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, 219 + &himax_bl_ops, &props); 220 + } 221 + 222 + static int boe_ppc357db1_4_dsc_init_seq(struct mipi_dsi_multi_context *dsi_ctx) 223 + { 224 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x83, 0x12, 0x1a, 0x55, 0x00); 225 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24); 226 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2, 0x00); 227 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03); 228 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe1, 0x01); 229 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00); 230 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc7); 231 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2, 0x98); 232 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 233 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x02); 234 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7, 235 + 0x01, 0x07, 0x01, 0x07, 0x01, 0x07, 0x06, 0x06, 236 + 0x06, 0x16, 0x00, 0x16, 0x81, 0x02, 0x40, 0x00, 237 + 0x1a, 0x4a, 0x05, 0x04, 0x03, 0x02, 0x01); 238 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01); 239 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc6); 240 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd2, 0x00, 0x30); 241 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 242 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc9); 243 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd3, 0x04); 244 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 245 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc6); 246 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2, 0x42); 247 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 248 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00); 249 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xd0); 250 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2, 0xf5); 251 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 252 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xcd, 253 + 0x81, 0x00, 0x80, 0x77, 0x00, 0x01, 0x00); 254 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01); 255 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4, 256 + 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 257 + 0xc7, 0xb2, 0xa0, 0x90, 0x81, 0x75, 0x69, 0x5f, 258 + 0x55, 0x4c, 0x44, 0x3d, 0x36, 0x2f, 0x2a, 0x24, 259 + 0x1e, 0x19, 0x14, 0x10, 0x09, 0x08, 0x07, 0x54, 260 + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55); 261 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03); 262 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4, 263 + 0xaa, 0xd4, 0xff, 0x2a, 0x55, 0x7f, 0xaa, 0xd4, 264 + 0xff, 0xea, 0xff, 0x03); 265 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00); 266 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc8); 267 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb1, 0x25); 268 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 269 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbe, 0x01, 0x35, 0x00); 270 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd9, 0x5f); 271 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x00, 0x00, 0x00); 272 + 273 + mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx); 274 + mipi_dsi_msleep(dsi_ctx, 140); 275 + mipi_dsi_dcs_set_display_on_multi(dsi_ctx); 276 + 277 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x01); 278 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24); 279 + mipi_dsi_msleep(dsi_ctx, 20); 280 + 281 + return dsi_ctx->accum_err; 282 + } 283 + 284 + static int boe_ppc357db1_4_init_seq(struct mipi_dsi_multi_context *dsi_ctx) 285 + { 286 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x83, 0x12, 0x1a, 0x55, 0x00); 287 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24); 288 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd1, 0x37, 0x03, 0x0c, 0xfd); 289 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2, 0x20); 290 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03); 291 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe1, 0x00); 292 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00); 293 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc7); 294 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2, 0xa6); 295 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 296 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x02); 297 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7, 298 + 0x01, 0x07, 0x01, 0x07, 0x01, 0x07, 0x06, 0x06, 299 + 0x06, 0x16, 0x00, 0x16, 0x81, 0x02, 0x40, 0x00, 300 + 0x1a, 0x4a, 0x05, 0x04, 0x03, 0x02, 0x01); 301 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2, 302 + 0x02, 0x68, 0x02, 0x68, 0x02, 0x68, 0x02, 0x68, 303 + 0x02, 0x6f, 0x03, 0x04, 0x2d, 0x09, 0x09, 0x00, 304 + 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 305 + 0x01, 0x10, 0x10, 0x1c, 0x25, 0x3c, 0x00, 0x23, 306 + 0x5d, 0x02, 0x02, 0x00, 0x00, 0x58, 0x01, 0xac, 307 + 0x0f, 0xa9, 0x10, 0x00, 0x2d, 0x6f, 0x00, 0x70, 308 + 0x00, 0x0a, 0xcb, 0x01); 309 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01); 310 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc6); 311 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd2, 0x09, 0x85); 312 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 313 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc9); 314 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd3, 0x04); 315 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 316 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00); 317 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xd0); 318 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2, 0xf5); 319 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 320 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01); 321 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4, 322 + 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 323 + 0xc7, 0xb2, 0xa0, 0x90, 0x81, 0x75, 0x69, 0x5f, 324 + 0x55, 0x4c, 0x44, 0x3d, 0x36, 0x2f, 0x2a, 0x24, 325 + 0x1e, 0x19, 0x14, 0x10, 0x09, 0x08, 0x07, 0x54, 326 + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55); 327 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03); 328 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4, 329 + 0xaa, 0xd4, 0xff, 0x2a, 0x55, 0x7f, 0xaa, 0xd4, 330 + 0xff, 0xea, 0xff, 0x03); 331 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00); 332 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc8); 333 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb1, 0x25); 334 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 335 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbe, 0x01, 0x35, 0x00); 336 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd9, 0x5f); 337 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x00, 0x00, 0x00); 338 + 339 + mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx); 340 + mipi_dsi_msleep(dsi_ctx, 140); 341 + mipi_dsi_dcs_set_display_on_multi(dsi_ctx); 342 + 343 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x01); 344 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24); 345 + mipi_dsi_msleep(dsi_ctx, 31); 346 + 347 + return dsi_ctx->accum_err; 348 + } 349 + 350 + static int csot_ppc357db1_4_dsc_init_seq(struct mipi_dsi_multi_context *dsi_ctx) 351 + { 352 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x83, 0x12, 0x1a, 0x55, 0x00); 353 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00); 354 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24); 355 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb1, 356 + 0x1c, 0x6b, 0x6b, 0x27, 0xe7, 0x00, 0x1b, 0x25, 357 + 0x21, 0x21, 0x2d, 0x2d, 0x17, 0x33, 0x31, 0x40, 358 + 0xcd, 0xff, 0x1a, 0x05, 0x15, 0x98, 0x00, 0x88, 359 + 0x7f, 0xff, 0xff, 0xcf, 0x1a, 0xcc, 0x02, 0x00); 360 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd1, 0x37, 0x03, 0x0c, 0xfd); 361 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2, 362 + 0x00, 0x6a, 0x40, 0x00, 0x00, 0x14, 0x98, 0x60, 363 + 0x3c, 0x02, 0x80, 0x21, 0x21, 0x00, 0x00, 0xf0, 364 + 0x27); 365 + /* 366 + * NOTE: Register 0xE2 configuration (based on downstream reference): 367 + * - 0x00: 120Hz with DSC enabled 368 + * - 0x10: 60Hz with DSC enabled 369 + * - 0x20: 60Hz with DSC disabled 370 + * 371 + * Both 0x00 and 0x10 are compatible with 60Hz/120Hz when DSC is active. 372 + * We use a fixed DSC-on value to remain refresh-rate agnostic. 373 + */ 374 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2, 0x00); 375 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xc0, 0x23, 0x23, 0xcc, 0x22, 0x99, 0xd8); 376 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb4, 377 + 0x46, 0x06, 0x0c, 0xbe, 0x0c, 0xbe, 0x09, 0x46, 378 + 0x0f, 0x57, 0x0f, 0x57, 0x03, 0x4a, 0x00, 0x00, 379 + 0x04, 0x0c, 0x00, 0x18, 0x01, 0x06, 0x08, 0x00, 380 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 381 + 0x00, 0x00, 0xff, 0x00, 0xff, 0x10, 0x00, 0x02, 382 + 0x14, 0x14, 0x14, 0x14); 383 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03); 384 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe1, 0x01, 0x3f); 385 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00); 386 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xe2); 387 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7, 0x49); 388 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 389 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd3, 390 + 0x00, 0xc0, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 391 + 0x16, 0x02, 0x07, 0x07, 0x07, 0x31, 0x13, 0x19, 392 + 0x12, 0x12, 0x03, 0x03, 0x03, 0x32, 0x10, 0x18, 393 + 0x00, 0x11, 0x32, 0x10, 0x03, 0x00, 0x03, 0x32, 394 + 0x10, 0x03, 0x00, 0x03, 0x00, 0x00, 0xff, 0x00); 395 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe1, 396 + 0x11, 0x00, 0x00, 0x89, 0x30, 0x80, 0x0a, 0x00, 397 + 0x03, 0x20, 0x00, 0x14, 0x03, 0x20, 0x03, 0x20, 398 + 0x02, 0x00, 0x02, 0x91, 0x00, 0x20, 0x02, 0x47, 399 + 0x00, 0x0b, 0x00, 0x0c, 0x05, 0x0e, 0x03, 0x68, 400 + 0x18, 0x00, 0x10, 0xe0, 0x03, 0x0c, 0x20, 0x00, 401 + 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38, 402 + 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, 403 + 0x7d, 0x7e, 0x01, 0x02, 0x01, 0x00, 0x09); 404 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7, 405 + 0x17, 0x08, 0x08, 0x2c, 0x46, 0x1e, 0x02, 0x23, 406 + 0x5d, 0x02, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x12, 407 + 0x05, 0x02, 0x02, 0x07, 0x10, 0x10, 0x00, 0x1d, 408 + 0xb9, 0x23, 0xb9, 0x00, 0x33, 0x02, 0x88); 409 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01); 410 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7, 411 + 0x02, 0x00, 0xb2, 0x01, 0x56, 0x07, 0x56, 0x08, 412 + 0x48, 0x14, 0xfd, 0x26); 413 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x02); 414 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7, 415 + 0x08, 0x08, 0x01, 0x03, 0x01, 0x03, 0x07, 0x02, 416 + 0x02, 0x47, 0x00, 0x47, 0x81, 0x02, 0x40, 0x00, 417 + 0x18, 0x4a, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 418 + 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 419 + 0x00, 0x00); 420 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00); 421 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbf, 422 + 0xfd, 0x00, 0x80, 0x9c, 0x36, 0x00, 0x81, 0x0c); 423 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xcd, 424 + 0x81, 0x00, 0x80, 0x77, 0x00, 0x01, 0x00); 425 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01); 426 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4, 427 + 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 428 + 0xc7, 0xb2, 0xa0, 0x90, 0x81, 0x75, 0x69, 0x5f, 429 + 0x55, 0x4c, 0x44, 0x3d, 0x36, 0x2f, 0x2a, 0x24, 430 + 0x1e, 0x19, 0x14, 0x10, 0x09, 0x08, 0x07, 0x54, 431 + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55); 432 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03); 433 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4, 434 + 0xaa, 0xd4, 0xff, 0x2a, 0x55, 0x7f, 0xaa, 0xd4, 435 + 0xff, 0xea, 0xff, 0x03); 436 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00); 437 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbe, 0x01, 0x35, 0x00); 438 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd9, 0x5f); 439 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x00, 0x00, 0x00); 440 + 441 + mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx); 442 + mipi_dsi_msleep(dsi_ctx, 140); 443 + mipi_dsi_dcs_set_display_on_multi(dsi_ctx); 444 + 445 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x01); 446 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24); 447 + mipi_dsi_msleep(dsi_ctx, 20); 448 + 449 + return dsi_ctx->accum_err; 450 + } 451 + 452 + static int csot_ppc357db1_4_init_seq(struct mipi_dsi_multi_context *dsi_ctx) 453 + { 454 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x83, 0x12, 0x1a, 0x55, 0x00); 455 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24); 456 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00); 457 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb1, 458 + 0x1c, 0x6b, 0x6b, 0x27, 0xe7, 0x00, 0x1b, 0x11, 459 + 0x21, 0x21, 0x2d, 0x2d, 0x17, 0x33, 0x31, 0x40, 460 + 0xcd, 0xff, 0x1a, 0x05, 0x15, 0x98, 0x00, 0x88, 461 + 0x7f, 0xff, 0xff, 0xcf, 0x1a, 0xcc, 0x02, 0x00); 462 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd1, 0x37, 0x03, 0x0c, 0xfd); 463 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2, 0x20); 464 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2, 465 + 0x00, 0x6a, 0x40, 0x00, 0x00, 0x14, 0x98, 0x60, 466 + 0x3c, 0x02, 0x80, 0x21, 0x21, 0x00, 0x00, 0x10, 467 + 0x27); 468 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03); 469 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe1, 0x00, 0x3f); 470 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00); 471 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xe2); 472 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7, 0x49); 473 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 474 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd3, 475 + 0x00, 0xc0, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 476 + 0x16, 0x02, 0x07, 0x07, 0x07, 0x31, 0x13, 0x16, 477 + 0x12, 0x12, 0x03, 0x03, 0x03, 0x32, 0x10, 0x15, 478 + 0x00, 0x11, 0x32, 0x10, 0x03, 0x00, 0x03, 0x32, 479 + 0x10, 0x03, 0x00, 0x03, 0x00, 0x00, 0xff, 0x00); 480 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x02); 481 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2, 482 + 0x80, 0x05, 0x1c, 0xbe, 0x09, 0x8d, 0x0f, 0x57, 483 + 0x03, 0x87, 0x06, 0x10, 0x32, 0x06, 0x15, 0x00, 484 + 0x00, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 485 + 0x01, 0x10, 0x10, 0x16, 0x28, 0x3c, 0x03, 0x23, 486 + 0x5d, 0x02, 0x02, 0x00, 0x00, 0x48, 0x01, 0xac, 487 + 0x0f, 0xab, 0x10, 0x00, 0x32, 0x87, 0x00, 0xa1, 488 + 0x00, 0x0a, 0xcb, 0x00); 489 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01); 490 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7, 491 + 0x02, 0x00, 0xb2, 0x01, 0x56, 0x07, 0x56, 0x08, 492 + 0x48, 0x14, 0x00, 0x26); 493 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x02); 494 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7, 495 + 0x05, 0x05, 0x01, 0x05, 0x01, 0x05, 0x04, 0x04, 496 + 0x04, 0x24, 0x00, 0x24, 0x81, 0x02, 0x40, 0x00, 497 + 0x32, 0x87, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 498 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 499 + 0x00, 0x00); 500 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00); 501 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xd0); 502 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2, 0xf0); 503 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 504 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbf, 505 + 0xfd, 0x00, 0x80, 0x9c, 0x10, 0x00, 0x81, 0x0c); 506 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01); 507 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4, 508 + 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 509 + 0xc7, 0xb2, 0xa0, 0x90, 0x81, 0x75, 0x69, 0x5f, 510 + 0x55, 0x4c, 0x44, 0x3d, 0x36, 0x2f, 0x2a, 0x24, 511 + 0x1e, 0x19, 0x14, 0x10, 0x09, 0x08, 0x07, 0x54, 512 + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55); 513 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03); 514 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4, 515 + 0xaa, 0xd4, 0xff, 0x2a, 0x55, 0x7f, 0xaa, 0xd4, 516 + 0xff, 0xea, 0xff, 0x03); 517 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00); 518 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc8); 519 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb1, 0x25); 520 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f); 521 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbe, 0x01, 0x35, 0x00); 522 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd9, 0x5f); 523 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x00, 0x00, 0x00); 524 + 525 + mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx); 526 + mipi_dsi_msleep(dsi_ctx, 140); 527 + mipi_dsi_dcs_set_display_on_multi(dsi_ctx); 528 + 529 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x01); 530 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24); 531 + mipi_dsi_msleep(dsi_ctx, 31); 532 + 533 + return dsi_ctx->accum_err; 534 + } 535 + 536 + static struct drm_dsc_config ppc357db1_4_dsc_cfg = { 537 + .dsc_version_major = 1, 538 + .dsc_version_minor = 1, 539 + .slice_height = 20, 540 + .slice_width = 800, 541 + .slice_count = 1, 542 + .bits_per_component = 8, 543 + .bits_per_pixel = 8 << 4, 544 + .block_pred_enable = true, 545 + }; 546 + 547 + static const struct drm_display_mode ppc357db1_4_dsc_modes[] = { 548 + { 549 + .clock = (800 + 60 + 40 + 40) * 2 * (2560 + 154 + 4 + 18) * 120 / 1000, 550 + .hdisplay = 800 * 2, 551 + .hsync_start = (800 + 60) * 2, 552 + .hsync_end = (800 + 60 + 40) * 2, 553 + .htotal = (800 + 60 + 40 + 40) * 2, 554 + .vdisplay = 2560, 555 + .vsync_start = 2560 + 154, 556 + .vsync_end = 2560 + 154 + 4, 557 + .vtotal = 2560 + 154 + 4 + 18, 558 + }, 559 + { 560 + .clock = (800 + 60 + 40 + 40) * 2 * (2560 + 2890 + 4 + 18) * 60 / 1000, 561 + .hdisplay = 800 * 2, 562 + .hsync_start = (800 + 60) * 2, 563 + .hsync_end = (800 + 60 + 40) * 2, 564 + .htotal = (800 + 60 + 40 + 40) * 2, 565 + .vdisplay = 2560, 566 + .vsync_start = 2560 + 2890, 567 + .vsync_end = 2560 + 2890 + 4, 568 + .vtotal = 2560 + 2890 + 4 + 18, 569 + }, 570 + }; 571 + 572 + static const struct drm_display_mode ppc357db1_4_modes[] = { 573 + { 574 + .clock = (800 + 60 + 20 + 40) * 2 * (2560 + 154 + 4 + 18) * 60 / 1000, 575 + .hdisplay = 800 * 2, 576 + .hsync_start = (800 + 60) * 2, 577 + .hsync_end = (800 + 60 + 20) * 2, 578 + .htotal = (800 + 60 + 20 + 40) * 2, 579 + .vdisplay = 2560, 580 + .vsync_start = 2560 + 168, 581 + .vsync_end = 2560 + 168 + 4, 582 + .vtotal = 2560 + 168 + 4 + 18, 583 + }, 584 + }; 585 + 586 + static int himax_probe(struct mipi_dsi_device *dsi) 587 + { 588 + struct mipi_dsi_device_info dsi_info = {"dsi-secondary", 0, NULL}; 589 + struct mipi_dsi_host *dsi1_host; 590 + struct device *dev = &dsi->dev; 591 + const struct panel_desc *desc; 592 + struct device_node *dsi1; 593 + struct himax *ctx; 594 + int num_dsi = 1; 595 + int ret, i; 596 + 597 + ctx = devm_drm_panel_alloc(dev, struct himax, panel, &himax_panel_funcs, 598 + DRM_MODE_CONNECTOR_DSI); 599 + if (!ctx) 600 + return -ENOMEM; 601 + 602 + ret = devm_regulator_bulk_get_const(&dsi->dev, 603 + ARRAY_SIZE(himax_supplies), 604 + himax_supplies, &ctx->supplies); 605 + if (ret < 0) 606 + return ret; 607 + 608 + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 609 + if (IS_ERR(ctx->reset_gpio)) 610 + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), 611 + "Failed to get reset-gpios\n"); 612 + 613 + desc = of_device_get_match_data(dev); 614 + if (!desc) 615 + return -ENODEV; 616 + ctx->desc = desc; 617 + ctx->dsc = *desc->dsc_cfg; 618 + 619 + if (desc->is_dual_dsi) { 620 + num_dsi = 2; 621 + dsi1 = of_graph_get_remote_node(dsi->dev.of_node, 1, -1); 622 + if (!dsi1) { 623 + dev_err(dev, "cannot get secondary DSI node.\n"); 624 + return -ENODEV; 625 + } 626 + 627 + dsi1_host = of_find_mipi_dsi_host_by_node(dsi1); 628 + of_node_put(dsi1); 629 + if (!dsi1_host) 630 + return dev_err_probe(dev, -EPROBE_DEFER, 631 + "cannot get secondary DSI host\n"); 632 + 633 + ctx->dsi[1] = devm_mipi_dsi_device_register_full(dev, dsi1_host, 634 + &dsi_info); 635 + if (IS_ERR(ctx->dsi[1])) { 636 + dev_err(dev, "cannot get secondary DSI device\n"); 637 + return PTR_ERR(ctx->dsi[1]); 638 + } 639 + 640 + mipi_dsi_set_drvdata(ctx->dsi[1], ctx); 641 + } 642 + 643 + ctx->dsi[0] = dsi; 644 + mipi_dsi_set_drvdata(dsi, ctx); 645 + 646 + ctx->panel.prepare_prev_first = true; 647 + 648 + if (desc->has_dcs_backlight) { 649 + ctx->backlight = himax_create_backlight(to_primary_dsi(ctx)); 650 + if (IS_ERR(ctx->backlight)) 651 + return dev_err_probe(dev, PTR_ERR(ctx->backlight), 652 + "Failed to create backlight\n"); 653 + } else { 654 + ret = drm_panel_of_backlight(&ctx->panel); 655 + if (ret) 656 + return dev_err_probe(dev, ret, "Failed to get backlight\n"); 657 + } 658 + 659 + drm_panel_add(&ctx->panel); 660 + 661 + for (i = 0; i < num_dsi; i++) { 662 + ctx->dsi[i]->lanes = desc->lanes; 663 + ctx->dsi[i]->format = desc->format; 664 + ctx->dsi[i]->mode_flags = desc->mode_flags; 665 + ctx->dsi[i]->dsc = enable_dsc ? &ctx->dsc : NULL; 666 + ret = devm_mipi_dsi_attach(dev, ctx->dsi[i]); 667 + if (ret < 0) { 668 + drm_panel_remove(&ctx->panel); 669 + return dev_err_probe(dev, ret, 670 + "Failed to attach to DSI host\n"); 671 + } 672 + } 673 + 674 + return 0; 675 + } 676 + 677 + static void himax_remove(struct mipi_dsi_device *dsi) 678 + { 679 + struct himax *ctx = mipi_dsi_get_drvdata(dsi); 680 + 681 + drm_panel_remove(&ctx->panel); 682 + } 683 + 684 + /* Model name: BOE PPC357DB1-4 */ 685 + static const struct panel_desc boe_ppc357db1_4_desc = { 686 + .width_mm = 266, 687 + .height_mm = 166, 688 + .lanes = 4, 689 + .format = MIPI_DSI_FMT_RGB888, 690 + .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS | 691 + MIPI_DSI_MODE_LPM, 692 + .dsc_cfg = &ppc357db1_4_dsc_cfg, 693 + .dsc_modes = ppc357db1_4_dsc_modes, 694 + .num_dsc_modes = ARRAY_SIZE(ppc357db1_4_dsc_modes), 695 + .modes = ppc357db1_4_modes, 696 + .num_modes = ARRAY_SIZE(ppc357db1_4_modes), 697 + .init_sequence_dsc = boe_ppc357db1_4_dsc_init_seq, 698 + .init_sequence = boe_ppc357db1_4_init_seq, 699 + .is_dual_dsi = true, 700 + .has_dcs_backlight = true, 701 + }; 702 + 703 + /* Model name: CSOT PPC357DB1-4 */ 704 + static const struct panel_desc csot_ppc357db1_4_desc = { 705 + .width_mm = 266, 706 + .height_mm = 166, 707 + .lanes = 4, 708 + .format = MIPI_DSI_FMT_RGB888, 709 + .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS | 710 + MIPI_DSI_MODE_LPM, 711 + .dsc_cfg = &ppc357db1_4_dsc_cfg, 712 + .dsc_modes = ppc357db1_4_dsc_modes, 713 + .num_dsc_modes = ARRAY_SIZE(ppc357db1_4_dsc_modes), 714 + .modes = ppc357db1_4_modes, 715 + .num_modes = ARRAY_SIZE(ppc357db1_4_modes), 716 + .init_sequence_dsc = csot_ppc357db1_4_dsc_init_seq, 717 + .init_sequence = csot_ppc357db1_4_init_seq, 718 + .is_dual_dsi = true, 719 + .has_dcs_backlight = true, 720 + }; 721 + 722 + /* 723 + * Known panels with HX83121A: 724 + * CSOT PNC357DB1-4: on MI Book S 12.4 725 + * CSOT PPC357DB1-1: on SAMSUNG Galaxy Tab S7 FE 726 + * BOE/CSOT PPC357DB1-4: on HUAWEI Matebook E Go 727 + * CSOT PPC357DB1-5: on MI Pad 5 Pro 12.4 728 + */ 729 + 730 + static const struct of_device_id himax_of_match[] = { 731 + { .compatible = "boe,ppc357db1-4", .data = &boe_ppc357db1_4_desc }, 732 + { .compatible = "csot,ppc357db1-4", .data = &csot_ppc357db1_4_desc }, 733 + { /* sentinel */ } 734 + }; 735 + MODULE_DEVICE_TABLE(of, himax_of_match); 736 + 737 + static struct mipi_dsi_driver himax_driver = { 738 + .probe = himax_probe, 739 + .remove = himax_remove, 740 + .driver = { 741 + .name = "panel-himax-hx83121a", 742 + .of_match_table = himax_of_match, 743 + }, 744 + }; 745 + module_mipi_dsi_driver(himax_driver); 746 + 747 + MODULE_AUTHOR("Pengyu Luo <mitltlatltl0@gmail.com>"); 748 + MODULE_DESCRIPTION("Himax HX83121A DriverIC panels driver"); 749 + MODULE_LICENSE("GPL");
+134
drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Ilitek ILI9806E core driver. 4 + * 5 + * Copyright (c) 2026 Amarula Solutions, Dario Binacchi <dario.binacchi@amarulasolutions.com> 6 + */ 7 + 8 + #include <drm/drm_panel.h> 9 + 10 + #include <linux/delay.h> 11 + #include <linux/export.h> 12 + #include <linux/gpio/consumer.h> 13 + #include <linux/module.h> 14 + #include <linux/of.h> 15 + #include <linux/property.h> 16 + #include <linux/regulator/consumer.h> 17 + 18 + #include "panel-ilitek-ili9806e-core.h" 19 + 20 + struct ili9806e { 21 + void *transport; 22 + struct drm_panel panel; 23 + 24 + unsigned int num_supplies; 25 + struct regulator_bulk_data supplies[2]; 26 + struct gpio_desc *reset_gpio; 27 + }; 28 + 29 + void *ili9806e_get_transport(struct drm_panel *panel) 30 + { 31 + struct ili9806e *ctx = container_of(panel, struct ili9806e, panel); 32 + 33 + return ctx->transport; 34 + } 35 + EXPORT_SYMBOL_GPL(ili9806e_get_transport); 36 + 37 + int ili9806e_power_on(struct device *dev) 38 + { 39 + struct ili9806e *ctx = dev_get_drvdata(dev); 40 + int ret; 41 + 42 + gpiod_set_value(ctx->reset_gpio, 1); 43 + 44 + ret = regulator_bulk_enable(ctx->num_supplies, ctx->supplies); 45 + if (ret) { 46 + dev_err(dev, "regulator bulk enable failed: %d\n", ret); 47 + return ret; 48 + } 49 + 50 + usleep_range(10000, 20000); 51 + gpiod_set_value(ctx->reset_gpio, 0); 52 + usleep_range(10000, 20000); 53 + 54 + return 0; 55 + } 56 + EXPORT_SYMBOL_GPL(ili9806e_power_on); 57 + 58 + int ili9806e_power_off(struct device *dev) 59 + { 60 + struct ili9806e *ctx = dev_get_drvdata(dev); 61 + int ret; 62 + 63 + gpiod_set_value(ctx->reset_gpio, 1); 64 + 65 + ret = regulator_bulk_disable(ctx->num_supplies, ctx->supplies); 66 + if (ret) 67 + dev_err(dev, "regulator bulk disable failed: %d\n", ret); 68 + 69 + return ret; 70 + } 71 + EXPORT_SYMBOL_GPL(ili9806e_power_off); 72 + 73 + int ili9806e_probe(struct device *dev, void *transport, 74 + const struct drm_panel_funcs *funcs, 75 + int connector_type) 76 + { 77 + struct ili9806e *ctx; 78 + bool set_prepare_prev_first = false; 79 + int ret; 80 + 81 + ctx = devm_kzalloc(dev, sizeof(struct ili9806e), GFP_KERNEL); 82 + if (!ctx) 83 + return -ENOMEM; 84 + 85 + dev_set_drvdata(dev, ctx); 86 + ctx->transport = transport; 87 + 88 + ctx->supplies[ctx->num_supplies++].supply = "vdd"; 89 + if (of_device_is_compatible(dev->of_node, 90 + "densitron,dmt028vghmcmi-1d") || 91 + of_device_is_compatible(dev->of_node, 92 + "ortustech,com35h3p70ulc")) { 93 + ctx->supplies[ctx->num_supplies++].supply = "vccio"; 94 + set_prepare_prev_first = true; 95 + } 96 + 97 + ret = devm_regulator_bulk_get(dev, ctx->num_supplies, ctx->supplies); 98 + if (ret) 99 + return dev_err_probe(dev, ret, "failed to get regulators\n"); 100 + 101 + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 102 + if (IS_ERR(ctx->reset_gpio)) 103 + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), 104 + "Failed to get reset-gpios\n"); 105 + 106 + drm_panel_init(&ctx->panel, dev, funcs, connector_type); 107 + 108 + ret = drm_panel_of_backlight(&ctx->panel); 109 + if (ret) 110 + return dev_err_probe(dev, ret, "Failed to get backlight\n"); 111 + 112 + if (set_prepare_prev_first) 113 + ctx->panel.prepare_prev_first = true; 114 + 115 + drm_panel_add(&ctx->panel); 116 + 117 + return 0; 118 + 119 + } 120 + EXPORT_SYMBOL_GPL(ili9806e_probe); 121 + 122 + void ili9806e_remove(struct device *dev) 123 + { 124 + struct ili9806e *ctx = dev_get_drvdata(dev); 125 + 126 + drm_panel_remove(&ctx->panel); 127 + } 128 + EXPORT_SYMBOL_GPL(ili9806e_remove); 129 + 130 + MODULE_AUTHOR("Dario Binacchi <dario.binacchi@amarulasolutions.com>"); 131 + MODULE_AUTHOR("Gunnar Dibbern <gunnar.dibbern@lht.dlh.de>"); 132 + MODULE_AUTHOR("Michael Walle <mwalle@kernel.org>"); 133 + MODULE_DESCRIPTION("Ilitek ILI9806E Controller Driver"); 134 + MODULE_LICENSE("GPL");
+15
drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + #ifndef _PANEL_ILITEK_ILI9806E_CORE_H 4 + #define _PANEL_ILITEK_ILI9806E_CORE_H 5 + 6 + void *ili9806e_get_transport(struct drm_panel *panel); 7 + int ili9806e_power_off(struct device *dev); 8 + int ili9806e_power_on(struct device *dev); 9 + 10 + int ili9806e_probe(struct device *dev, void *transport, 11 + const struct drm_panel_funcs *funcs, 12 + int connector_type); 13 + void ili9806e_remove(struct device *dev); 14 + 15 + #endif /* _PANEL_ILITEK_ILI9806E_CORE_H */
+323
drivers/gpu/drm/panel/panel-ilitek-ili9806e-spi.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * SPI interface to the Ilitek ILI9806E panel. 4 + * 5 + * Copyright (c) 2026 Amarula Solutions, Dario Binacchi <dario.binacchi@amarulasolutions.com> 6 + */ 7 + 8 + #include <linux/delay.h> 9 + #include <linux/device.h> 10 + #include <linux/media-bus-format.h> 11 + #include <linux/module.h> 12 + #include <linux/spi/spi.h> 13 + 14 + #include <drm/drm_mipi_dbi.h> 15 + #include <drm/drm_panel.h> 16 + #include <drm/drm_print.h> 17 + 18 + #include <video/mipi_display.h> 19 + 20 + #include "panel-ilitek-ili9806e-core.h" 21 + 22 + struct ili9806e_spi_panel { 23 + struct spi_device *spi; 24 + struct mipi_dbi dbi; 25 + const struct ili9806e_spi_panel_desc *desc; 26 + }; 27 + 28 + struct ili9806e_spi_panel_desc { 29 + const struct drm_display_mode *display_mode; 30 + u32 bus_format; 31 + u32 bus_flags; 32 + void (*init_sequence)(struct ili9806e_spi_panel *ctx); 33 + }; 34 + 35 + static int ili9806e_spi_off(struct ili9806e_spi_panel *ctx) 36 + { 37 + struct mipi_dbi *dbi = &ctx->dbi; 38 + 39 + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF, 0x00); 40 + mipi_dbi_command(dbi, MIPI_DCS_ENTER_SLEEP_MODE, 0x00); 41 + 42 + return 0; 43 + } 44 + 45 + static int ili9806e_spi_unprepare(struct drm_panel *panel) 46 + { 47 + struct ili9806e_spi_panel *ctx = ili9806e_get_transport(panel); 48 + struct device *dev = &ctx->spi->dev; 49 + int ret; 50 + 51 + ili9806e_spi_off(ctx); 52 + 53 + ret = ili9806e_power_off(dev); 54 + if (ret) 55 + dev_err(dev, "power off failed: %d\n", ret); 56 + 57 + return 0; 58 + } 59 + 60 + static int ili9806e_spi_prepare(struct drm_panel *panel) 61 + { 62 + struct ili9806e_spi_panel *ctx = ili9806e_get_transport(panel); 63 + struct device *dev = &ctx->spi->dev; 64 + int ret; 65 + 66 + ret = ili9806e_power_on(dev); 67 + if (ret) 68 + return ret; 69 + 70 + if (ctx->desc->init_sequence) 71 + ctx->desc->init_sequence(ctx); 72 + 73 + return 0; 74 + } 75 + 76 + static int ili9806e_spi_get_modes(struct drm_panel *panel, 77 + struct drm_connector *connector) 78 + { 79 + struct ili9806e_spi_panel *ctx = ili9806e_get_transport(panel); 80 + const struct ili9806e_spi_panel_desc *desc = ctx->desc; 81 + struct drm_display_mode *mode; 82 + 83 + mode = drm_mode_duplicate(connector->dev, desc->display_mode); 84 + if (!mode) 85 + return -ENOMEM; 86 + 87 + drm_mode_set_name(mode); 88 + 89 + connector->display_info.width_mm = mode->width_mm; 90 + connector->display_info.height_mm = mode->height_mm; 91 + connector->display_info.bus_flags = desc->bus_flags; 92 + drm_display_info_set_bus_formats(&connector->display_info, 93 + &desc->bus_format, 1); 94 + 95 + drm_mode_probed_add(connector, mode); 96 + 97 + return 1; 98 + } 99 + 100 + static const struct drm_panel_funcs ili9806e_spi_funcs = { 101 + .unprepare = ili9806e_spi_unprepare, 102 + .prepare = ili9806e_spi_prepare, 103 + .get_modes = ili9806e_spi_get_modes, 104 + }; 105 + 106 + static int ili9806e_spi_probe(struct spi_device *spi) 107 + { 108 + struct device *dev = &spi->dev; 109 + struct ili9806e_spi_panel *ctx; 110 + int err; 111 + 112 + ctx = devm_kzalloc(dev, sizeof(struct ili9806e_spi_panel), GFP_KERNEL); 113 + if (!ctx) 114 + return -ENOMEM; 115 + 116 + ctx->spi = spi; 117 + ctx->desc = device_get_match_data(dev); 118 + 119 + err = mipi_dbi_spi_init(spi, &ctx->dbi, NULL); 120 + if (err) 121 + return dev_err_probe(dev, err, "MIPI DBI init failed\n"); 122 + 123 + return ili9806e_probe(dev, ctx, &ili9806e_spi_funcs, 124 + DRM_MODE_CONNECTOR_DPI); 125 + } 126 + 127 + static void ili9806e_spi_remove(struct spi_device *spi) 128 + { 129 + ili9806e_remove(&spi->dev); 130 + } 131 + 132 + static void rk050hr345_ct106a_init(struct ili9806e_spi_panel *ctx) 133 + { 134 + struct mipi_dbi *dbi = &ctx->dbi; 135 + 136 + /* Switch to page 1 */ 137 + mipi_dbi_command(dbi, 0xff, 0xff, 0x98, 0x06, 0x04, 0x01); 138 + /* Interface Settings */ 139 + mipi_dbi_command(dbi, 0x08, 0x10); 140 + mipi_dbi_command(dbi, 0x21, 0x01); 141 + /* Panel Settings */ 142 + mipi_dbi_command(dbi, 0x30, 0x01); 143 + mipi_dbi_command(dbi, 0x31, 0x00); 144 + /* Power Control */ 145 + mipi_dbi_command(dbi, 0x40, 0x15); 146 + mipi_dbi_command(dbi, 0x41, 0x44); 147 + mipi_dbi_command(dbi, 0x42, 0x03); 148 + mipi_dbi_command(dbi, 0x43, 0x09); 149 + mipi_dbi_command(dbi, 0x44, 0x09); 150 + mipi_dbi_command(dbi, 0x50, 0x78); 151 + mipi_dbi_command(dbi, 0x51, 0x78); 152 + mipi_dbi_command(dbi, 0x52, 0x00); 153 + mipi_dbi_command(dbi, 0x53, 0x3a); 154 + mipi_dbi_command(dbi, 0x57, 0x50); 155 + /* Timing Control */ 156 + mipi_dbi_command(dbi, 0x60, 0x07); 157 + mipi_dbi_command(dbi, 0x61, 0x00); 158 + mipi_dbi_command(dbi, 0x62, 0x08); 159 + mipi_dbi_command(dbi, 0x63, 0x00); 160 + /* Gamma Settings */ 161 + mipi_dbi_command(dbi, 0xa0, 0x00); 162 + mipi_dbi_command(dbi, 0xa1, 0x03); 163 + mipi_dbi_command(dbi, 0xa2, 0x0b); 164 + mipi_dbi_command(dbi, 0xa3, 0x0f); 165 + mipi_dbi_command(dbi, 0xa4, 0x0b); 166 + mipi_dbi_command(dbi, 0xa5, 0x1b); 167 + mipi_dbi_command(dbi, 0xa6, 0x0a); 168 + mipi_dbi_command(dbi, 0xa7, 0x0a); 169 + mipi_dbi_command(dbi, 0xa8, 0x02); 170 + mipi_dbi_command(dbi, 0xa9, 0x07); 171 + mipi_dbi_command(dbi, 0xaa, 0x05); 172 + mipi_dbi_command(dbi, 0xab, 0x03); 173 + mipi_dbi_command(dbi, 0xac, 0x0e); 174 + mipi_dbi_command(dbi, 0xad, 0x32); 175 + mipi_dbi_command(dbi, 0xae, 0x2d); 176 + mipi_dbi_command(dbi, 0xaf, 0x00); 177 + mipi_dbi_command(dbi, 0xc0, 0x00); 178 + mipi_dbi_command(dbi, 0xc1, 0x03); 179 + mipi_dbi_command(dbi, 0xc2, 0x0e); 180 + mipi_dbi_command(dbi, 0xc3, 0x10); 181 + mipi_dbi_command(dbi, 0xc4, 0x09); 182 + mipi_dbi_command(dbi, 0xc5, 0x17); 183 + mipi_dbi_command(dbi, 0xc6, 0x09); 184 + mipi_dbi_command(dbi, 0xc7, 0x07); 185 + mipi_dbi_command(dbi, 0xc8, 0x04); 186 + mipi_dbi_command(dbi, 0xc9, 0x09); 187 + mipi_dbi_command(dbi, 0xca, 0x06); 188 + mipi_dbi_command(dbi, 0xcb, 0x06); 189 + mipi_dbi_command(dbi, 0xcc, 0x0c); 190 + mipi_dbi_command(dbi, 0xcd, 0x25); 191 + mipi_dbi_command(dbi, 0xce, 0x20); 192 + mipi_dbi_command(dbi, 0xcf, 0x00); 193 + 194 + /* Switch to page 6 */ 195 + mipi_dbi_command(dbi, 0xff, 0xff, 0x98, 0x06, 0x04, 0x06); 196 + /* GIP settings */ 197 + mipi_dbi_command(dbi, 0x00, 0x21); 198 + mipi_dbi_command(dbi, 0x01, 0x09); 199 + mipi_dbi_command(dbi, 0x02, 0x00); 200 + mipi_dbi_command(dbi, 0x03, 0x00); 201 + mipi_dbi_command(dbi, 0x04, 0x01); 202 + mipi_dbi_command(dbi, 0x05, 0x01); 203 + mipi_dbi_command(dbi, 0x06, 0x80); 204 + mipi_dbi_command(dbi, 0x07, 0x05); 205 + mipi_dbi_command(dbi, 0x08, 0x02); 206 + mipi_dbi_command(dbi, 0x09, 0x80); 207 + mipi_dbi_command(dbi, 0x0a, 0x00); 208 + mipi_dbi_command(dbi, 0x0b, 0x00); 209 + mipi_dbi_command(dbi, 0x0c, 0x0a); 210 + mipi_dbi_command(dbi, 0x0d, 0x0a); 211 + mipi_dbi_command(dbi, 0x0e, 0x00); 212 + mipi_dbi_command(dbi, 0x0f, 0x00); 213 + mipi_dbi_command(dbi, 0x10, 0xe0); 214 + mipi_dbi_command(dbi, 0x11, 0xe4); 215 + mipi_dbi_command(dbi, 0x12, 0x04); 216 + mipi_dbi_command(dbi, 0x13, 0x00); 217 + mipi_dbi_command(dbi, 0x14, 0x00); 218 + mipi_dbi_command(dbi, 0x15, 0xc0); 219 + mipi_dbi_command(dbi, 0x16, 0x08); 220 + mipi_dbi_command(dbi, 0x17, 0x00); 221 + mipi_dbi_command(dbi, 0x18, 0x00); 222 + mipi_dbi_command(dbi, 0x19, 0x00); 223 + mipi_dbi_command(dbi, 0x1a, 0x00); 224 + mipi_dbi_command(dbi, 0x1b, 0x00); 225 + mipi_dbi_command(dbi, 0x1c, 0x00); 226 + mipi_dbi_command(dbi, 0x1d, 0x00); 227 + mipi_dbi_command(dbi, 0x20, 0x01); 228 + mipi_dbi_command(dbi, 0x21, 0x23); 229 + mipi_dbi_command(dbi, 0x22, 0x45); 230 + mipi_dbi_command(dbi, 0x23, 0x67); 231 + mipi_dbi_command(dbi, 0x24, 0x01); 232 + mipi_dbi_command(dbi, 0x25, 0x23); 233 + mipi_dbi_command(dbi, 0x26, 0x45); 234 + mipi_dbi_command(dbi, 0x27, 0x67); 235 + mipi_dbi_command(dbi, 0x30, 0x01); 236 + mipi_dbi_command(dbi, 0x31, 0x11); 237 + mipi_dbi_command(dbi, 0x32, 0x00); 238 + mipi_dbi_command(dbi, 0x33, 0xee); 239 + mipi_dbi_command(dbi, 0x34, 0xff); 240 + mipi_dbi_command(dbi, 0x35, 0xbb); 241 + mipi_dbi_command(dbi, 0x36, 0xca); 242 + mipi_dbi_command(dbi, 0x37, 0xdd); 243 + mipi_dbi_command(dbi, 0x38, 0xac); 244 + mipi_dbi_command(dbi, 0x39, 0x76); 245 + mipi_dbi_command(dbi, 0x3a, 0x67); 246 + mipi_dbi_command(dbi, 0x3b, 0x22); 247 + mipi_dbi_command(dbi, 0x3c, 0x22); 248 + mipi_dbi_command(dbi, 0x3d, 0x22); 249 + mipi_dbi_command(dbi, 0x3e, 0x22); 250 + mipi_dbi_command(dbi, 0x3f, 0x22); 251 + mipi_dbi_command(dbi, 0x40, 0x22); 252 + mipi_dbi_command(dbi, 0x52, 0x10); 253 + mipi_dbi_command(dbi, 0x53, 0x10); 254 + 255 + /* Switch to page 7 */ 256 + mipi_dbi_command(dbi, 0xff, 0xff, 0x98, 0x06, 0x04, 0x07); 257 + mipi_dbi_command(dbi, 0x17, 0x22); 258 + mipi_dbi_command(dbi, 0x02, 0x77); 259 + mipi_dbi_command(dbi, 0xe1, 0x79); 260 + mipi_dbi_command(dbi, 0xb3, 0x10); 261 + 262 + /* Switch to page 0 */ 263 + mipi_dbi_command(dbi, 0xff, 0xff, 0x98, 0x06, 0x04, 0x00); 264 + mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, 0x00); // 0x36 265 + mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE); // 0x11 266 + 267 + msleep(120); 268 + 269 + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON); 270 + 271 + msleep(120); 272 + } 273 + 274 + static const struct drm_display_mode rk050hr345_ct106a_mode = { 275 + .width_mm = 62, 276 + .height_mm = 110, 277 + .clock = 27000, 278 + .hdisplay = 480, 279 + .hsync_start = 480 + 10, 280 + .hsync_end = 480 + 10 + 10, 281 + .htotal = 480 + 10 + 10 + 10, 282 + .vdisplay = 854, 283 + .vsync_start = 854 + 10, 284 + .vsync_end = 854 + 10 + 10, 285 + .vtotal = 854 + 10 + 10 + 10, 286 + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 287 + .type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER, 288 + }; 289 + 290 + static const struct ili9806e_spi_panel_desc rk050hr345_ct106a_desc = { 291 + .init_sequence = rk050hr345_ct106a_init, 292 + .display_mode = &rk050hr345_ct106a_mode, 293 + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, 294 + .bus_flags = DRM_BUS_FLAG_DE_HIGH | 295 + DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE, 296 + }; 297 + 298 + static const struct of_device_id ili9806e_spi_of_match[] = { 299 + { .compatible = "rocktech,rk050hr345-ct106a", .data = &rk050hr345_ct106a_desc }, 300 + { } 301 + }; 302 + MODULE_DEVICE_TABLE(of, ili9806e_spi_of_match); 303 + 304 + static const struct spi_device_id ili9806e_spi_ids[] = { 305 + { "rk050hr345-ct106a", }, 306 + { /* sentinel */ } 307 + }; 308 + MODULE_DEVICE_TABLE(spi, ili9806e_spi_ids); 309 + 310 + static struct spi_driver ili9806e_spi_driver = { 311 + .driver = { 312 + .name = "ili9806e-spi", 313 + .of_match_table = ili9806e_spi_of_match, 314 + }, 315 + .probe = ili9806e_spi_probe, 316 + .remove = ili9806e_spi_remove, 317 + .id_table = ili9806e_spi_ids, 318 + }; 319 + module_spi_driver(ili9806e_spi_driver); 320 + 321 + MODULE_AUTHOR("Dario Binacchi <dario.binacchi@amarulasolutions.com>"); 322 + MODULE_DESCRIPTION("Ilitek ILI9806E LCD SPI Driver"); 323 + MODULE_LICENSE("GPL");
+44 -109
drivers/gpu/drm/panel/panel-ilitek-ili9806e.c drivers/gpu/drm/panel/panel-ilitek-ili9806e-dsi.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 3 - #include <linux/delay.h> 4 3 #include <linux/device.h> 5 4 #include <linux/err.h> 6 5 #include <linux/errno.h> 7 - #include <linux/gpio/consumer.h> 8 6 #include <linux/kernel.h> 9 7 #include <linux/mod_devicetable.h> 10 8 #include <linux/module.h> 11 9 #include <linux/property.h> 12 - #include <linux/regulator/consumer.h> 13 10 14 11 #include <drm/drm_mipi_dsi.h> 15 12 #include <drm/drm_modes.h> ··· 15 18 16 19 #include <video/mipi_display.h> 17 20 18 - struct panel_desc { 21 + #include "panel-ilitek-ili9806e-core.h" 22 + 23 + struct ili9806e_dsi_panel_desc { 19 24 const struct drm_display_mode *display_mode; 20 25 unsigned long mode_flags; 21 26 enum mipi_dsi_pixel_format format; ··· 25 26 void (*init_sequence)(struct mipi_dsi_multi_context *ctx); 26 27 }; 27 28 28 - struct ili9806e_panel { 29 - struct drm_panel panel; 29 + struct ili9806e_dsi_panel { 30 30 struct mipi_dsi_device *dsi; 31 - struct gpio_desc *reset_gpio; 32 - struct regulator_bulk_data supplies[2]; 33 - const struct panel_desc *desc; 31 + const struct ili9806e_dsi_panel_desc *desc; 34 32 enum drm_panel_orientation orientation; 35 33 }; 36 34 37 - static const char * const regulator_names[] = { 38 - "vdd", 39 - "vccio", 40 - }; 41 - 42 - static inline struct ili9806e_panel *to_ili9806e_panel(struct drm_panel *panel) 43 - { 44 - return container_of(panel, struct ili9806e_panel, panel); 45 - } 46 - 47 - static int ili9806e_power_on(struct ili9806e_panel *ctx) 48 - { 49 - struct mipi_dsi_device *dsi = ctx->dsi; 50 - int ret; 51 - 52 - gpiod_set_value(ctx->reset_gpio, 1); 53 - 54 - ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 55 - if (ret < 0) { 56 - dev_err(&dsi->dev, "regulator bulk enable failed: %d\n", ret); 57 - return ret; 58 - } 59 - 60 - usleep_range(10000, 20000); 61 - gpiod_set_value(ctx->reset_gpio, 0); 62 - usleep_range(10000, 20000); 63 - 64 - return 0; 65 - } 66 - 67 - static int ili9806e_power_off(struct ili9806e_panel *ctx) 68 - { 69 - struct mipi_dsi_device *dsi = ctx->dsi; 70 - int ret; 71 - 72 - gpiod_set_value(ctx->reset_gpio, 1); 73 - 74 - ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 75 - if (ret) 76 - dev_err(&dsi->dev, "regulator bulk disable failed: %d\n", ret); 77 - 78 - return ret; 79 - } 80 - 81 - static int ili9806e_on(struct ili9806e_panel *ili9806e) 35 + static int ili9806e_dsi_on(struct ili9806e_dsi_panel *ili9806e) 82 36 { 83 37 struct mipi_dsi_multi_context ctx = { .dsi = ili9806e->dsi }; 84 38 ··· 45 93 return ctx.accum_err; 46 94 } 47 95 48 - static int ili9806e_off(struct ili9806e_panel *panel) 96 + static int ili9806e_dsi_off(struct ili9806e_dsi_panel *panel) 49 97 { 50 98 struct mipi_dsi_multi_context ctx = { .dsi = panel->dsi }; 51 99 ··· 56 104 return ctx.accum_err; 57 105 } 58 106 59 - static int ili9806e_prepare(struct drm_panel *panel) 107 + static int ili9806e_dsi_prepare(struct drm_panel *panel) 60 108 { 61 - struct ili9806e_panel *ctx = to_ili9806e_panel(panel); 109 + struct ili9806e_dsi_panel *ctx = ili9806e_get_transport(panel); 110 + struct device *dev = &ctx->dsi->dev; 62 111 int ret; 63 112 64 - ret = ili9806e_power_on(ctx); 113 + ret = ili9806e_power_on(dev); 65 114 if (ret < 0) 66 115 return ret; 67 116 68 - ret = ili9806e_on(ctx); 117 + ret = ili9806e_dsi_on(ctx); 69 118 if (ret < 0) { 70 - ili9806e_power_off(ctx); 119 + ili9806e_power_off(dev); 71 120 return ret; 72 121 } 73 122 74 123 return 0; 75 124 } 76 125 77 - static int ili9806e_unprepare(struct drm_panel *panel) 126 + static int ili9806e_dsi_unprepare(struct drm_panel *panel) 78 127 { 79 - struct ili9806e_panel *ctx = to_ili9806e_panel(panel); 80 - struct mipi_dsi_device *dsi = ctx->dsi; 128 + struct ili9806e_dsi_panel *ctx = ili9806e_get_transport(panel); 129 + struct device *dev = &ctx->dsi->dev; 81 130 int ret; 82 131 83 - ili9806e_off(ctx); 132 + ili9806e_dsi_off(ctx); 84 133 85 - ret = ili9806e_power_off(ctx); 134 + ret = ili9806e_power_off(dev); 86 135 if (ret < 0) 87 - dev_err(&dsi->dev, "power off failed: %d\n", ret); 136 + dev_err(dev, "power off failed: %d\n", ret); 88 137 89 138 return ret; 90 139 } 91 140 92 - static int ili9806e_get_modes(struct drm_panel *panel, 141 + static int ili9806e_dsi_get_modes(struct drm_panel *panel, 93 142 struct drm_connector *connector) 94 143 { 95 - struct ili9806e_panel *ctx = to_ili9806e_panel(panel); 144 + struct ili9806e_dsi_panel *ctx = ili9806e_get_transport(panel); 96 145 const struct drm_display_mode *mode = ctx->desc->display_mode; 97 146 98 147 return drm_connector_helper_get_modes_fixed(connector, mode); 99 148 } 100 149 101 - static enum drm_panel_orientation ili9806e_get_orientation(struct drm_panel *panel) 150 + static enum drm_panel_orientation ili9806e_dsi_get_orientation(struct drm_panel *panel) 102 151 { 103 - struct ili9806e_panel *ctx = to_ili9806e_panel(panel); 152 + struct ili9806e_dsi_panel *ctx = ili9806e_get_transport(panel); 104 153 105 154 return ctx->orientation; 106 155 } 107 156 108 - static const struct drm_panel_funcs ili9806e_funcs = { 109 - .prepare = ili9806e_prepare, 110 - .unprepare = ili9806e_unprepare, 111 - .get_modes = ili9806e_get_modes, 112 - .get_orientation = ili9806e_get_orientation, 157 + static const struct drm_panel_funcs ili9806e_dsi_funcs = { 158 + .prepare = ili9806e_dsi_prepare, 159 + .unprepare = ili9806e_dsi_unprepare, 160 + .get_modes = ili9806e_dsi_get_modes, 161 + .get_orientation = ili9806e_dsi_get_orientation, 113 162 }; 114 163 115 164 static int ili9806e_dsi_probe(struct mipi_dsi_device *dsi) 116 165 { 117 166 struct device *dev = &dsi->dev; 118 - struct ili9806e_panel *ctx; 119 - int i, ret; 167 + struct ili9806e_dsi_panel *ctx; 168 + int ret; 120 169 121 - ctx = devm_drm_panel_alloc(dev, struct ili9806e_panel, panel, &ili9806e_funcs, 122 - DRM_MODE_CONNECTOR_DSI); 123 - if (IS_ERR(ctx)) 124 - return PTR_ERR(ctx); 170 + ctx = devm_kzalloc(dev, sizeof(struct ili9806e_dsi_panel), GFP_KERNEL); 171 + if (!ctx) 172 + return -ENOMEM; 125 173 126 174 ctx->desc = device_get_match_data(dev); 127 - 128 - for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) 129 - ctx->supplies[i].supply = regulator_names[i]; 130 - 131 - ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), 132 - ctx->supplies); 133 - if (ret < 0) 134 - return ret; 135 - 136 - ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 137 - if (IS_ERR(ctx->reset_gpio)) 138 - return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), 139 - "Failed to get reset-gpios\n"); 140 175 141 176 mipi_dsi_set_drvdata(dsi, ctx); 142 177 ctx->dsi = dsi; ··· 136 197 if (ret) 137 198 return dev_err_probe(dev, ret, "Failed to get orientation\n"); 138 199 139 - ret = drm_panel_of_backlight(&ctx->panel); 200 + ret = ili9806e_probe(dev, ctx, &ili9806e_dsi_funcs, 201 + DRM_MODE_CONNECTOR_DSI); 140 202 if (ret) 141 - return dev_err_probe(dev, ret, "Failed to get backlight\n"); 142 - 143 - ctx->panel.prepare_prev_first = true; 144 - drm_panel_add(&ctx->panel); 203 + return ret; 145 204 146 205 ret = mipi_dsi_attach(dsi); 147 206 if (ret < 0) { 148 207 dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); 149 - drm_panel_remove(&ctx->panel); 208 + ili9806e_remove(dev); 150 209 return ret; 151 210 } 152 211 ··· 153 216 154 217 static void ili9806e_dsi_remove(struct mipi_dsi_device *dsi) 155 218 { 156 - struct ili9806e_panel *ctx = mipi_dsi_get_drvdata(dsi); 157 - 158 219 mipi_dsi_detach(dsi); 159 - drm_panel_remove(&ctx->panel); 220 + ili9806e_remove(&dsi->dev); 160 221 } 161 222 162 223 static void com35h3p70ulc_init(struct mipi_dsi_multi_context *ctx) ··· 304 369 .height_mm = 71, 305 370 }; 306 371 307 - static const struct panel_desc com35h3p70ulc_desc = { 372 + static const struct ili9806e_dsi_panel_desc com35h3p70ulc_desc = { 308 373 .init_sequence = com35h3p70ulc_init, 309 374 .display_mode = &com35h3p70ulc_default_mode, 310 375 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | ··· 468 533 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 469 534 }; 470 535 471 - static const struct panel_desc dmt028vghmcmi_1d_desc = { 536 + static const struct ili9806e_dsi_panel_desc dmt028vghmcmi_1d_desc = { 472 537 .init_sequence = dmt028vghmcmi_1d_init, 473 538 .display_mode = &dmt028vghmcmi_1d_default_mode, 474 539 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | ··· 477 542 .lanes = 2, 478 543 }; 479 544 480 - static const struct of_device_id ili9806e_of_match[] = { 545 + static const struct of_device_id ili9806e_dsi_of_match[] = { 481 546 { .compatible = "densitron,dmt028vghmcmi-1d", .data = &dmt028vghmcmi_1d_desc }, 482 547 { .compatible = "ortustech,com35h3p70ulc", .data = &com35h3p70ulc_desc }, 483 548 { } 484 549 }; 485 - MODULE_DEVICE_TABLE(of, ili9806e_of_match); 550 + MODULE_DEVICE_TABLE(of, ili9806e_dsi_of_match); 486 551 487 552 static struct mipi_dsi_driver ili9806e_dsi_driver = { 488 553 .driver = { 489 554 .name = "ili9806e-dsi", 490 - .of_match_table = ili9806e_of_match, 555 + .of_match_table = ili9806e_dsi_of_match, 491 556 }, 492 557 .probe = ili9806e_dsi_probe, 493 558 .remove = ili9806e_dsi_remove, ··· 496 561 497 562 MODULE_AUTHOR("Gunnar Dibbern <gunnar.dibbern@lht.dlh.de>"); 498 563 MODULE_AUTHOR("Michael Walle <mwalle@kernel.org>"); 499 - MODULE_DESCRIPTION("Ilitek ILI9806E Controller Driver"); 564 + MODULE_DESCRIPTION("Ilitek ILI9806E Controller DSI Driver"); 500 565 MODULE_LICENSE("GPL");
+301
drivers/gpu/drm/panel/panel-samsung-s6e8fc0-m1906f9.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // Copyright (c) Kamil Gołda <kamil.golda@protonmail.com> 3 + // Copyright (c) Yedaya Katsman <yedaya.ka@gmail.com> 4 + // Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree: 5 + // Copyright (c) The Linux Foundation. All rights reserved. 6 + 7 + #include <linux/backlight.h> 8 + #include <linux/delay.h> 9 + #include <linux/gpio/consumer.h> 10 + #include <linux/mod_devicetable.h> 11 + #include <linux/module.h> 12 + #include <linux/regulator/consumer.h> 13 + 14 + #include <video/mipi_display.h> 15 + 16 + #include <drm/drm_mipi_dsi.h> 17 + #include <drm/drm_modes.h> 18 + #include <drm/drm_panel.h> 19 + #include <drm/drm_probe_helper.h> 20 + 21 + struct s6e8fc0_ctx { 22 + struct drm_panel panel; 23 + struct mipi_dsi_device *dsi; 24 + struct regulator_bulk_data *supplies; 25 + struct gpio_desc *reset_gpio; 26 + }; 27 + 28 + static const struct regulator_bulk_data s6e8fc0_supplies[] = { 29 + { .supply = "vdd" }, 30 + { .supply = "vci" }, 31 + }; 32 + 33 + static inline 34 + struct s6e8fc0_ctx *to_s6e8fc0_ctx(struct drm_panel *panel) 35 + { 36 + return container_of_const(panel, struct s6e8fc0_ctx, panel); 37 + } 38 + 39 + static void s6e8fc0_m1906f9_reset(struct s6e8fc0_ctx *ctx) 40 + { 41 + gpiod_set_value_cansleep(ctx->reset_gpio, 0); 42 + usleep_range(12000, 13000); 43 + gpiod_set_value_cansleep(ctx->reset_gpio, 1); 44 + usleep_range(2000, 3000); 45 + gpiod_set_value_cansleep(ctx->reset_gpio, 0); 46 + usleep_range(10000, 11000); 47 + } 48 + 49 + #define s6e8fc0_test_key_on_lvl2(ctx) \ 50 + mipi_dsi_dcs_write_seq_multi(ctx, 0xf0, 0x5a, 0x5a) 51 + #define s6e8fc0_test_key_off_lvl2(ctx) \ 52 + mipi_dsi_dcs_write_seq_multi(ctx, 0xf0, 0xa5, 0xa5) 53 + #define s6e8fc0_test_key_on_lvl3(ctx) \ 54 + mipi_dsi_dcs_write_seq_multi(ctx, 0xfc, 0x5a, 0x5a) 55 + #define s6e8fc0_test_key_off_lvl3(ctx) \ 56 + mipi_dsi_dcs_write_seq_multi(ctx, 0xfc, 0xa5, 0xa5) 57 + 58 + static int s6e8fc0_m1906f9_on(struct s6e8fc0_ctx *ctx) 59 + { 60 + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; 61 + 62 + s6e8fc0_test_key_on_lvl3(&dsi_ctx); 63 + 64 + mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, 0x0000); 65 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 66 + 0x20); 67 + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); 68 + mipi_dsi_msleep(&dsi_ctx, 50); 69 + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); 70 + 71 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x04, 0xed); 72 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xed, 73 + 0xe4, 0x08, 0x96, 0xa4, 0x2a, 0x72, 0xe2, 74 + 0xca, 0x00); 75 + s6e8fc0_test_key_off_lvl3(&dsi_ctx); 76 + s6e8fc0_test_key_on_lvl2(&dsi_ctx); 77 + s6e8fc0_test_key_on_lvl3(&dsi_ctx); 78 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe1, 0x93); 79 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x05, 0xf4); 80 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf4, 0x03); 81 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xed, 0x01, 0x81, 0x04); 82 + s6e8fc0_test_key_off_lvl2(&dsi_ctx); 83 + s6e8fc0_test_key_off_lvl3(&dsi_ctx); 84 + 85 + return dsi_ctx.accum_err; 86 + } 87 + 88 + static int s6e8fc0_m1906f9_off(struct s6e8fc0_ctx *ctx) 89 + { 90 + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; 91 + 92 + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); 93 + mipi_dsi_msleep(&dsi_ctx, 20); 94 + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); 95 + mipi_dsi_msleep(&dsi_ctx, 120); 96 + 97 + return dsi_ctx.accum_err; 98 + } 99 + 100 + static int s6e8fc0_m1906f9_prepare(struct drm_panel *panel) 101 + { 102 + struct s6e8fc0_ctx *ctx = to_s6e8fc0_ctx(panel); 103 + struct device *dev = &ctx->dsi->dev; 104 + int ret; 105 + 106 + ret = regulator_bulk_enable(ARRAY_SIZE(s6e8fc0_supplies), ctx->supplies); 107 + if (ret < 0) { 108 + dev_err(dev, "Failed to enable regulators: %d\n", ret); 109 + return ret; 110 + } 111 + 112 + s6e8fc0_m1906f9_reset(ctx); 113 + 114 + ret = s6e8fc0_m1906f9_on(ctx); 115 + if (ret < 0) { 116 + dev_err(dev, "Failed to initialize panel: %d\n", ret); 117 + gpiod_set_value_cansleep(ctx->reset_gpio, 1); 118 + regulator_bulk_disable(ARRAY_SIZE(s6e8fc0_supplies), ctx->supplies); 119 + return ret; 120 + } 121 + 122 + return 0; 123 + } 124 + 125 + static int s6e8fc0_m1906f9_unprepare(struct drm_panel *panel) 126 + { 127 + struct s6e8fc0_ctx *ctx = to_s6e8fc0_ctx(panel); 128 + struct device *dev = &ctx->dsi->dev; 129 + int ret; 130 + 131 + ret = s6e8fc0_m1906f9_off(ctx); 132 + if (ret < 0) 133 + dev_err(dev, "Failed to un-initialize panel: %d\n", ret); 134 + 135 + gpiod_set_value_cansleep(ctx->reset_gpio, 1); 136 + regulator_bulk_disable(ARRAY_SIZE(s6e8fc0_supplies), ctx->supplies); 137 + 138 + return 0; 139 + } 140 + 141 + static const struct drm_display_mode s6e8fc0_m1906f9_samsungp_mode = { 142 + .clock = (720 + 350 + 40 + 294) * (1560 + 17 + 2 + 5) * 60 / 1000, 143 + .hdisplay = 720, 144 + .hsync_start = 720 + 350, 145 + .hsync_end = 720 + 350 + 40, 146 + .htotal = 720 + 350 + 40 + 294, 147 + .vdisplay = 1560, 148 + .vsync_start = 1560 + 17, 149 + .vsync_end = 1560 + 17 + 2, 150 + .vtotal = 1560 + 17 + 2 + 5, 151 + .width_mm = 65, 152 + .height_mm = 140, 153 + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 154 + }; 155 + 156 + static int s6e8fc0_m1906f9_get_modes(struct drm_panel *panel, 157 + struct drm_connector *connector) 158 + { 159 + return drm_connector_helper_get_modes_fixed(connector, &s6e8fc0_m1906f9_samsungp_mode); 160 + } 161 + 162 + static const struct drm_panel_funcs s6e8fc0_m1906f9_panel_funcs = { 163 + .prepare = s6e8fc0_m1906f9_prepare, 164 + .unprepare = s6e8fc0_m1906f9_unprepare, 165 + .get_modes = s6e8fc0_m1906f9_get_modes, 166 + }; 167 + 168 + static int s6e8fc0_bl_update_status(struct backlight_device *bl) 169 + { 170 + struct mipi_dsi_device *dsi = bl_get_data(bl); 171 + u16 brightness = backlight_get_brightness(bl); 172 + int ret; 173 + 174 + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 175 + 176 + ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness); 177 + if (ret < 0) 178 + return ret; 179 + 180 + dsi->mode_flags |= MIPI_DSI_MODE_LPM; 181 + 182 + return 0; 183 + } 184 + 185 + static int s6e8fc0_bl_get_brightness(struct backlight_device *bl) 186 + { 187 + struct mipi_dsi_device *dsi = bl_get_data(bl); 188 + u16 brightness; 189 + int ret; 190 + 191 + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 192 + 193 + ret = mipi_dsi_dcs_get_display_brightness_large(dsi, &brightness); 194 + if (ret < 0) 195 + return ret; 196 + 197 + dsi->mode_flags |= MIPI_DSI_MODE_LPM; 198 + 199 + return brightness; 200 + } 201 + 202 + static const struct backlight_ops s6e8fc0_bl_ops = { 203 + .update_status = s6e8fc0_bl_update_status, 204 + .get_brightness = s6e8fc0_bl_get_brightness, 205 + }; 206 + 207 + static struct backlight_device * 208 + s6e8fc0_m1906f9_create_backlight(struct mipi_dsi_device *dsi) 209 + { 210 + struct device *dev = &dsi->dev; 211 + const struct backlight_properties props = { 212 + .type = BACKLIGHT_RAW, 213 + .brightness = 512, 214 + .max_brightness = 1023, 215 + }; 216 + 217 + return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, 218 + &s6e8fc0_bl_ops, &props); 219 + } 220 + 221 + static int s6e8fc0_m1906f9_probe(struct mipi_dsi_device *dsi) 222 + { 223 + struct device *dev = &dsi->dev; 224 + struct s6e8fc0_ctx *ctx; 225 + int ret; 226 + 227 + ctx = devm_drm_panel_alloc(dev, struct s6e8fc0_ctx, panel, 228 + &s6e8fc0_m1906f9_panel_funcs, 229 + DRM_MODE_CONNECTOR_DSI); 230 + if (IS_ERR(ctx)) 231 + return PTR_ERR(ctx); 232 + 233 + ret = devm_regulator_bulk_get_const(dev, 234 + ARRAY_SIZE(s6e8fc0_supplies), 235 + s6e8fc0_supplies, 236 + &ctx->supplies); 237 + if (ret < 0) 238 + return ret; 239 + 240 + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 241 + if (IS_ERR(ctx->reset_gpio)) 242 + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), 243 + "Failed to get reset-gpios\n"); 244 + 245 + ctx->dsi = dsi; 246 + mipi_dsi_set_drvdata(dsi, ctx); 247 + 248 + dsi->lanes = 4; 249 + dsi->format = MIPI_DSI_FMT_RGB888; 250 + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | 251 + MIPI_DSI_CLOCK_NON_CONTINUOUS; 252 + 253 + ctx->panel.prepare_prev_first = true; 254 + 255 + ctx->panel.backlight = s6e8fc0_m1906f9_create_backlight(dsi); 256 + if (IS_ERR(ctx->panel.backlight)) 257 + return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight), 258 + "Failed to create backlight\n"); 259 + 260 + drm_panel_add(&ctx->panel); 261 + 262 + ret = mipi_dsi_attach(dsi); 263 + if (ret < 0) { 264 + drm_panel_remove(&ctx->panel); 265 + return dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); 266 + } 267 + 268 + return 0; 269 + } 270 + 271 + static void s6e8fc0_remove(struct mipi_dsi_device *dsi) 272 + { 273 + struct s6e8fc0_ctx *ctx = mipi_dsi_get_drvdata(dsi); 274 + int ret; 275 + 276 + ret = mipi_dsi_detach(dsi); 277 + if (ret < 0) 278 + dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); 279 + 280 + drm_panel_remove(&ctx->panel); 281 + } 282 + 283 + static const struct of_device_id samsung_s6e8fc0_of_match[] = { 284 + { .compatible = "samsung,s6e8fc0-m1906f9" }, 285 + { /* sentinel */ } 286 + }; 287 + MODULE_DEVICE_TABLE(of, samsung_s6e8fc0_of_match); 288 + 289 + static struct mipi_dsi_driver s6e8fc0_driver = { 290 + .probe = s6e8fc0_m1906f9_probe, 291 + .remove = s6e8fc0_remove, 292 + .driver = { 293 + .name = "panel-samsung-s6e8fc0-m1906f9", 294 + .of_match_table = samsung_s6e8fc0_of_match, 295 + }, 296 + }; 297 + module_mipi_dsi_driver(s6e8fc0_driver); 298 + 299 + MODULE_AUTHOR("Kamil Gołda <kamil.golda@protonmail.com>"); 300 + MODULE_DESCRIPTION("DRM driver for Samsung s6e8fc0 DSI controller"); 301 + MODULE_LICENSE("GPL");
+1
drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
··· 201 201 202 202 drm_panel_init(&sharp_nt->base, &sharp_nt->dsi->dev, 203 203 &sharp_nt_panel_funcs, DRM_MODE_CONNECTOR_DSI); 204 + sharp_nt->base.prepare_prev_first = true; 204 205 205 206 ret = drm_panel_of_backlight(&sharp_nt->base); 206 207 if (ret)
+36 -1
drivers/gpu/drm/panel/panel-simple.c
··· 1295 1295 .height = 301, 1296 1296 }, 1297 1297 .delay = { 1298 - .prepare = 50, 1298 + .prepare = 30, 1299 1299 .enable = 200, 1300 1300 .disable = 110, 1301 1301 .unprepare = 1000, ··· 2945 2945 .width = 154, 2946 2946 .height = 90, 2947 2947 }, 2948 + }; 2949 + 2950 + static const struct display_timing jutouch_jt070tm041_timing = { 2951 + .pixelclock = { 40800000, 51200000, 67200000 }, 2952 + .hactive = { 1024, 1024, 1024 }, 2953 + .hfront_porch = { 16, 160, 216 }, 2954 + .hback_porch = { 160, 160, 160 }, 2955 + .hsync_len = { 1, 1, 140 }, 2956 + .vactive = { 600, 600, 600 }, 2957 + .vfront_porch = { 1, 12, 127 }, 2958 + .vback_porch = { 23, 23, 23 }, 2959 + .vsync_len = { 1, 1, 20 }, 2960 + }; 2961 + 2962 + static const struct panel_desc jutouch_jt070tm041 = { 2963 + .timings = &jutouch_jt070tm041_timing, 2964 + .num_timings = 1, 2965 + .bpc = 8, 2966 + .size = { 2967 + .width = 154, 2968 + .height = 86, 2969 + }, 2970 + .delay = { 2971 + .enable = 50, 2972 + .disable = 50, 2973 + }, 2974 + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, 2975 + .bus_flags = DRM_BUS_FLAG_DE_HIGH, 2976 + .connector_type = DRM_MODE_CONNECTOR_LVDS, 2948 2977 }; 2949 2978 2950 2979 static const struct display_timing jutouch_jt101tm023_timing = { ··· 5443 5414 .compatible = "innolux,zj070na-01p", 5444 5415 .data = &innolux_zj070na_01p, 5445 5416 }, { 5417 + .compatible = "jutouch,jt070tm041", 5418 + .data = &jutouch_jt070tm041, 5419 + }, { 5446 5420 .compatible = "jutouch,jt101tm023", 5447 5421 .data = &jutouch_jt101tm023, 5448 5422 }, { ··· 5640 5608 }, { 5641 5609 .compatible = "tianma,p0700wxf1mbaa", 5642 5610 .data = &tianma_p0700wxf1mbaa, 5611 + }, { 5612 + .compatible = "tianma,tm050rdh03", 5613 + .data = &ontat_kd50g21_40nt_a1, 5643 5614 }, { 5644 5615 .compatible = "tianma,tm070jdhg30", 5645 5616 .data = &tianma_tm070jdhg30,
+128 -6
drivers/gpu/drm/panthor/panthor_drv.c
··· 13 13 #include <linux/pagemap.h> 14 14 #include <linux/platform_device.h> 15 15 #include <linux/pm_runtime.h> 16 + #include <linux/sched/clock.h> 16 17 #include <linux/time64.h> 18 + #include <linux/time_namespace.h> 17 19 18 20 #include <drm/drm_auth.h> 19 21 #include <drm/drm_debugfs.h> ··· 763 761 kvfree(ctx->jobs); 764 762 } 765 763 764 + #define VALID_TIMESTAMP_QUERY_FLAGS \ 765 + (DRM_PANTHOR_TIMESTAMP_GPU | \ 766 + DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK | \ 767 + DRM_PANTHOR_TIMESTAMP_GPU_OFFSET | \ 768 + DRM_PANTHOR_TIMESTAMP_GPU_CYCLE_COUNT | \ 769 + DRM_PANTHOR_TIMESTAMP_FREQ | \ 770 + DRM_PANTHOR_TIMESTAMP_DURATION) 771 + 766 772 static int panthor_query_timestamp_info(struct panthor_device *ptdev, 767 773 struct drm_panthor_timestamp_info *arg) 768 774 { 769 775 int ret; 776 + u32 flags; 777 + unsigned long irq_flags; 778 + struct timespec64 cpu_ts; 779 + u64 query_start_time; 780 + bool minimize_interruption; 781 + u32 timestamp_types = 0; 782 + 783 + if (arg->flags != 0) { 784 + flags = arg->flags; 785 + } else { 786 + /* 787 + * If flags are 0, then ask for the same things that we asked 788 + * for before flags were added. 789 + */ 790 + flags = DRM_PANTHOR_TIMESTAMP_GPU | 791 + DRM_PANTHOR_TIMESTAMP_GPU_OFFSET | 792 + DRM_PANTHOR_TIMESTAMP_FREQ; 793 + } 794 + 795 + switch (flags & DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK) { 796 + case DRM_PANTHOR_TIMESTAMP_CPU_NONE: 797 + break; 798 + case DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC: 799 + case DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC_RAW: 800 + timestamp_types++; 801 + break; 802 + default: 803 + return -EINVAL; 804 + } 805 + 806 + if (flags & ~VALID_TIMESTAMP_QUERY_FLAGS) 807 + return -EINVAL; 808 + 809 + if (flags & DRM_PANTHOR_TIMESTAMP_GPU) 810 + timestamp_types++; 811 + if (flags & DRM_PANTHOR_TIMESTAMP_GPU_CYCLE_COUNT) 812 + timestamp_types++; 813 + 814 + /* If user asked to obtain timestamps from more than one source, 815 + * then it very likely means they want them to be as close as possible. 816 + * If they asked for duration, then that likely means that they 817 + * want to know how long obtaining timestamp takes, without random 818 + * events, like process scheduling or interrupts. 819 + */ 820 + minimize_interruption = 821 + (flags & DRM_PANTHOR_TIMESTAMP_DURATION) || 822 + (timestamp_types >= 2); 770 823 771 824 ret = panthor_device_resume_and_get(ptdev); 772 825 if (ret) 773 826 return ret; 774 827 828 + if (flags & DRM_PANTHOR_TIMESTAMP_FREQ) { 775 829 #ifdef CONFIG_ARM_ARCH_TIMER 776 - arg->timestamp_frequency = arch_timer_get_cntfrq(); 830 + arg->timestamp_frequency = arch_timer_get_cntfrq(); 777 831 #else 778 - arg->timestamp_frequency = 0; 832 + arg->timestamp_frequency = 0; 779 833 #endif 780 - arg->current_timestamp = gpu_read64_counter(ptdev, GPU_TIMESTAMP); 781 - arg->timestamp_offset = gpu_read64(ptdev, GPU_TIMESTAMP_OFFSET); 834 + } else { 835 + arg->timestamp_frequency = 0; 836 + } 837 + 838 + if (flags & DRM_PANTHOR_TIMESTAMP_GPU_OFFSET) 839 + arg->timestamp_offset = gpu_read64(ptdev, GPU_TIMESTAMP_OFFSET); 840 + else 841 + arg->timestamp_offset = 0; 842 + 843 + if (minimize_interruption) { 844 + preempt_disable(); 845 + local_irq_save(irq_flags); 846 + } 847 + 848 + if (flags & DRM_PANTHOR_TIMESTAMP_DURATION) 849 + query_start_time = local_clock(); 850 + else 851 + query_start_time = 0; 852 + 853 + if (flags & DRM_PANTHOR_TIMESTAMP_GPU) 854 + arg->current_timestamp = gpu_read64_counter(ptdev, GPU_TIMESTAMP); 855 + else 856 + arg->current_timestamp = 0; 857 + 858 + switch (flags & DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK) { 859 + case DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC: 860 + ktime_get_ts64(&cpu_ts); 861 + break; 862 + case DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC_RAW: 863 + ktime_get_raw_ts64(&cpu_ts); 864 + break; 865 + default: 866 + break; 867 + } 868 + 869 + if (flags & DRM_PANTHOR_TIMESTAMP_GPU_CYCLE_COUNT) 870 + arg->cycle_count = gpu_read64_counter(ptdev, GPU_CYCLE_COUNT); 871 + else 872 + arg->cycle_count = 0; 873 + 874 + if (flags & DRM_PANTHOR_TIMESTAMP_DURATION) 875 + arg->duration_nsec = local_clock() - query_start_time; 876 + else 877 + arg->duration_nsec = 0; 878 + 879 + if (minimize_interruption) { 880 + local_irq_restore(irq_flags); 881 + preempt_enable(); 882 + } 883 + 884 + if (flags & DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK) { 885 + timens_add_monotonic(&cpu_ts); 886 + 887 + arg->cpu_timestamp_sec = cpu_ts.tv_sec; 888 + arg->cpu_timestamp_nsec = cpu_ts.tv_nsec; 889 + } else { 890 + arg->cpu_timestamp_sec = 0; 891 + arg->cpu_timestamp_nsec = 0; 892 + } 782 893 783 894 pm_runtime_put(ptdev->base.dev); 784 895 return 0; ··· 966 851 return PANTHOR_UOBJ_SET(args->pointer, args->size, ptdev->csif_info); 967 852 968 853 case DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO: 969 - ret = panthor_query_timestamp_info(ptdev, &timestamp_info); 854 + ret = copy_struct_from_user(&timestamp_info, 855 + sizeof(timestamp_info), 856 + u64_to_user_ptr(args->pointer), 857 + args->size); 858 + if (ret) 859 + return ret; 970 860 861 + ret = panthor_query_timestamp_info(ptdev, &timestamp_info); 971 862 if (ret) 972 863 return ret; 973 864 ··· 1801 1680 * - adds DRM_IOCTL_PANTHOR_BO_SYNC ioctl 1802 1681 * - adds DRM_IOCTL_PANTHOR_BO_QUERY_INFO ioctl 1803 1682 * - adds drm_panthor_gpu_info::selected_coherency 1683 + * - 1.8 - extends DEV_QUERY_TIMESTAMP_INFO with flags 1804 1684 */ 1805 1685 static const struct drm_driver panthor_drm_driver = { 1806 1686 .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ | ··· 1815 1693 .name = "panthor", 1816 1694 .desc = "Panthor DRM driver", 1817 1695 .major = 1, 1818 - .minor = 7, 1696 + .minor = 8, 1819 1697 1820 1698 .gem_create_object = panthor_gem_create_object, 1821 1699 .gem_prime_import_sg_table = drm_gem_shmem_prime_import_sg_table,
+2 -2
drivers/gpu/drm/panthor/panthor_fw.c
··· 581 581 582 582 if (hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_PROT) { 583 583 drm_warn(&ptdev->base, 584 - "Firmware protected mode entry not be supported, ignoring"); 584 + "Firmware protected mode entry is not supported, ignoring"); 585 585 return 0; 586 586 } 587 587 ··· 750 750 751 751 if ((iter->offset % sizeof(u32)) || 752 752 (CSF_FW_BINARY_ENTRY_SIZE(ehdr) % sizeof(u32))) { 753 - drm_err(&ptdev->base, "Firmware entry isn't 32 bit aligned, offset=0x%x size=0x%x\n", 753 + drm_err(&ptdev->base, "Firmware entry is not 32-bit aligned, offset=0x%x size=0x%x\n", 754 754 (u32)(iter->offset - sizeof(u32)), CSF_FW_BINARY_ENTRY_SIZE(ehdr)); 755 755 return -EINVAL; 756 756 }
+13 -13
drivers/gpu/drm/renesas/rcar-du/rcar_cmm.c
··· 59 59 60 60 /* 61 61 * rcar_cmm_setup() - Configure the CMM unit 62 - * @pdev: The platform device associated with the CMM instance 62 + * @dev: The device associated with the CMM instance 63 63 * @config: The CMM unit configuration 64 64 * 65 65 * Configure the CMM unit with the given configuration. Currently enabling, ··· 73 73 * TODO: Add support for LUT double buffer operations to avoid updating the 74 74 * LUT table entries while a frame is being displayed. 75 75 */ 76 - int rcar_cmm_setup(struct platform_device *pdev, 76 + int rcar_cmm_setup(struct device *dev, 77 77 const struct rcar_cmm_config *config) 78 78 { 79 - struct rcar_cmm *rcmm = platform_get_drvdata(pdev); 79 + struct rcar_cmm *rcmm = dev_get_drvdata(dev); 80 80 81 81 /* Disable LUT if no table is provided. */ 82 82 if (!config->lut.table) { ··· 102 102 103 103 /* 104 104 * rcar_cmm_enable() - Enable the CMM unit 105 - * @pdev: The platform device associated with the CMM instance 105 + * @dev: The device associated with the CMM instance 106 106 * 107 107 * When the output of the corresponding DU channel is routed to the CMM unit, 108 108 * the unit shall be enabled before the DU channel is started, and remain ··· 113 113 * It is an error to attempt to enable an already enabled CMM unit, or to 114 114 * attempt to disable a disabled unit. 115 115 */ 116 - int rcar_cmm_enable(struct platform_device *pdev) 116 + int rcar_cmm_enable(struct device *dev) 117 117 { 118 118 int ret; 119 119 120 - ret = pm_runtime_resume_and_get(&pdev->dev); 120 + ret = pm_runtime_resume_and_get(dev); 121 121 if (ret < 0) 122 122 return ret; 123 123 ··· 127 127 128 128 /* 129 129 * rcar_cmm_disable() - Disable the CMM unit 130 - * @pdev: The platform device associated with the CMM instance 130 + * @dev: The device associated with the CMM instance 131 131 * 132 132 * See rcar_cmm_enable() for usage information. 133 133 * ··· 135 135 * state shall thus be restored with rcar_cmm_setup() when re-enabling the CMM 136 136 * unit after the next rcar_cmm_enable() call. 137 137 */ 138 - void rcar_cmm_disable(struct platform_device *pdev) 138 + void rcar_cmm_disable(struct device *dev) 139 139 { 140 - struct rcar_cmm *rcmm = platform_get_drvdata(pdev); 140 + struct rcar_cmm *rcmm = dev_get_drvdata(dev); 141 141 142 142 rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0); 143 143 rcmm->lut.enabled = false; 144 144 145 - pm_runtime_put(&pdev->dev); 145 + pm_runtime_put(dev); 146 146 } 147 147 EXPORT_SYMBOL_GPL(rcar_cmm_disable); 148 148 149 149 /* 150 150 * rcar_cmm_init() - Initialize the CMM unit 151 - * @pdev: The platform device associated with the CMM instance 151 + * @dev: The device associated with the CMM instance 152 152 * 153 153 * Return: 0 on success, -EPROBE_DEFER if the CMM is not available yet, 154 154 * -ENODEV if the DRM_RCAR_CMM config option is disabled 155 155 */ 156 - int rcar_cmm_init(struct platform_device *pdev) 156 + int rcar_cmm_init(struct device *dev) 157 157 { 158 - struct rcar_cmm *rcmm = platform_get_drvdata(pdev); 158 + struct rcar_cmm *rcmm = dev_get_drvdata(dev); 159 159 160 160 if (!rcmm) 161 161 return -EPROBE_DEFER;
+9 -9
drivers/gpu/drm/renesas/rcar-du/rcar_cmm.h
··· 10 10 11 11 #define CM2_LUT_SIZE 256 12 12 13 + struct device; 13 14 struct drm_color_lut; 14 - struct platform_device; 15 15 16 16 /** 17 17 * struct rcar_cmm_config - CMM configuration ··· 26 26 }; 27 27 28 28 #if IS_ENABLED(CONFIG_DRM_RCAR_CMM) 29 - int rcar_cmm_init(struct platform_device *pdev); 29 + int rcar_cmm_init(struct device *dev); 30 30 31 - int rcar_cmm_enable(struct platform_device *pdev); 32 - void rcar_cmm_disable(struct platform_device *pdev); 31 + int rcar_cmm_enable(struct device *dev); 32 + void rcar_cmm_disable(struct device *dev); 33 33 34 - int rcar_cmm_setup(struct platform_device *pdev, 34 + int rcar_cmm_setup(struct device *dev, 35 35 const struct rcar_cmm_config *config); 36 36 #else 37 - static inline int rcar_cmm_init(struct platform_device *pdev) 37 + static inline int rcar_cmm_init(struct device *dev) 38 38 { 39 39 return -ENODEV; 40 40 } 41 41 42 - static inline int rcar_cmm_enable(struct platform_device *pdev) 42 + static inline int rcar_cmm_enable(struct device *dev) 43 43 { 44 44 return 0; 45 45 } 46 46 47 - static inline void rcar_cmm_disable(struct platform_device *pdev) 47 + static inline void rcar_cmm_disable(struct device *dev) 48 48 { 49 49 } 50 50 51 - static inline int rcar_cmm_setup(struct platform_device *pdev, 51 + static inline int rcar_cmm_setup(struct device *dev, 52 52 const struct rcar_cmm_config *config) 53 53 { 54 54 return 0;
+8 -8
drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c
··· 513 513 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); 514 514 struct rcar_cmm_config cmm_config = {}; 515 515 516 - if (!rcrtc->cmm) 516 + if (!rcrtc->cmm->dev) 517 517 return; 518 518 519 519 if (drm_lut) 520 520 cmm_config.lut.table = (struct drm_color_lut *)drm_lut->data; 521 521 522 - rcar_cmm_setup(rcrtc->cmm, &cmm_config); 522 + rcar_cmm_setup(rcrtc->cmm->dev, &cmm_config); 523 523 } 524 524 525 525 /* ----------------------------------------------------------------------------- ··· 667 667 if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) 668 668 rcar_du_vsp_disable(rcrtc); 669 669 670 - if (rcrtc->cmm) 671 - rcar_cmm_disable(rcrtc->cmm); 670 + if (rcrtc->cmm->dev) 671 + rcar_cmm_disable(rcrtc->cmm->dev); 672 672 673 673 /* 674 674 * Select switch sync mode. This stops display operation and configures ··· 726 726 struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(crtc->state); 727 727 struct rcar_du_device *rcdu = rcrtc->dev; 728 728 729 - if (rcrtc->cmm) 730 - rcar_cmm_enable(rcrtc->cmm); 729 + if (rcrtc->cmm->dev) 730 + rcar_cmm_enable(rcrtc->cmm->dev); 731 731 rcar_du_crtc_get(rcrtc); 732 732 733 733 /* ··· 1300 1300 return ret; 1301 1301 1302 1302 /* CMM might be disabled for this CRTC. */ 1303 - if (rcdu->cmms[swindex]) { 1304 - rcrtc->cmm = rcdu->cmms[swindex]; 1303 + if (rcdu->cmms[swindex].dev) { 1304 + rcrtc->cmm = &rcdu->cmms[swindex]; 1305 1305 rgrp->cmms_mask |= BIT(hwindex % 2); 1306 1306 1307 1307 drm_mode_crtc_set_gamma_size(crtc, CM2_LUT_SIZE);
+2 -1
drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h
··· 19 19 20 20 #include <media/vsp1.h> 21 21 22 + struct rcar_du_cmm; 22 23 struct rcar_du_group; 23 24 struct rcar_du_vsp; 24 25 ··· 66 65 unsigned int vblank_count; 67 66 68 67 struct rcar_du_group *group; 69 - struct platform_device *cmm; 68 + struct rcar_du_cmm *cmm; 70 69 struct rcar_du_vsp *vsp; 71 70 unsigned int vsp_pipe; 72 71
+7 -1
drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.h
··· 22 22 23 23 struct clk; 24 24 struct device; 25 + struct device_link; 25 26 struct drm_bridge; 26 27 struct drm_property; 27 28 struct rcar_du_device; ··· 89 88 unsigned int lvds_clk_mask; 90 89 }; 91 90 91 + struct rcar_du_cmm { 92 + struct device *dev; 93 + struct device_link *link; 94 + }; 95 + 92 96 #define RCAR_DU_MAX_CRTCS 4 93 97 #define RCAR_DU_MAX_GROUPS DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2) 94 98 #define RCAR_DU_MAX_VSPS 4 ··· 112 106 unsigned int num_crtcs; 113 107 114 108 struct rcar_du_group groups[RCAR_DU_MAX_GROUPS]; 115 - struct platform_device *cmms[RCAR_DU_MAX_CRTCS]; 109 + struct rcar_du_cmm cmms[RCAR_DU_MAX_CRTCS]; 116 110 struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS]; 117 111 struct drm_bridge *lvds[RCAR_DU_MAX_LVDS]; 118 112 struct drm_bridge *dsi[RCAR_DU_MAX_DSI];
+24 -28
drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c
··· 19 19 #include <drm/drm_probe_helper.h> 20 20 #include <drm/drm_vblank.h> 21 21 22 + #include <linux/cleanup.h> 22 23 #include <linux/device.h> 23 24 #include <linux/dma-buf.h> 24 25 #include <linux/of.h> ··· 574 573 enum rcar_du_output output, 575 574 struct of_endpoint *ep) 576 575 { 577 - struct device_node *entity; 576 + struct device_node *entity __free(device_node) = NULL; 578 577 int ret; 579 578 580 579 /* Locate the connected entity and initialize the encoder. */ ··· 589 588 dev_dbg(rcdu->dev, 590 589 "connected entity %pOF is disabled, skipping\n", 591 590 entity); 592 - of_node_put(entity); 593 591 return -ENODEV; 594 592 } 595 593 ··· 598 598 "failed to initialize encoder %pOF on output %s (%d), skipping\n", 599 599 entity, rcar_du_output_name(output), ret); 600 600 601 - of_node_put(entity); 602 - 603 601 return ret; 604 602 } 605 603 606 604 static int rcar_du_encoders_init(struct rcar_du_device *rcdu) 607 605 { 606 + struct device_node *ep_node __free(device_node) = NULL; 608 607 struct device_node *np = rcdu->dev->of_node; 609 - struct device_node *ep_node; 610 608 unsigned int num_encoders = 0; 611 609 612 610 /* ··· 618 620 int ret; 619 621 620 622 ret = of_graph_parse_endpoint(ep_node, &ep); 621 - if (ret < 0) { 622 - of_node_put(ep_node); 623 + if (ret < 0) 623 624 return ret; 624 - } 625 625 626 626 /* Find the output route corresponding to the port number. */ 627 627 for (i = 0; i < RCAR_DU_OUTPUT_MAX; ++i) { ··· 640 644 /* Process the output pipeline. */ 641 645 ret = rcar_du_encoders_init_one(rcdu, output, &ep); 642 646 if (ret < 0) { 643 - if (ret == -EPROBE_DEFER) { 644 - of_node_put(ep_node); 647 + if (ret == -EPROBE_DEFER) 645 648 return ret; 646 - } 647 649 648 650 continue; 649 651 } ··· 769 775 } 770 776 771 777 for (i = 0; i < cells; ++i) { 778 + struct device_node *cmm_node __free(device_node) = NULL; 779 + struct rcar_du_cmm *cmm = &rcdu->cmms[i]; 772 780 struct platform_device *pdev; 773 - struct device_link *link; 774 - struct device_node *cmm; 775 781 int ret; 776 782 777 - cmm = of_parse_phandle(np, "renesas,cmms", i); 778 - if (!cmm) { 783 + cmm_node = of_parse_phandle(np, "renesas,cmms", i); 784 + if (!cmm_node) { 779 785 dev_err(rcdu->dev, 780 786 "Failed to parse 'renesas,cmms' property\n"); 781 787 return -EINVAL; 782 788 } 783 789 784 - if (!of_device_is_available(cmm)) { 790 + if (!of_device_is_available(cmm_node)) 785 791 /* It's fine to have a phandle to a non-enabled CMM. */ 786 - of_node_put(cmm); 787 792 continue; 788 - } 789 793 790 - pdev = of_find_device_by_node(cmm); 794 + pdev = of_find_device_by_node(cmm_node); 791 795 if (!pdev) { 792 796 dev_err(rcdu->dev, "No device found for CMM%u\n", i); 793 - of_node_put(cmm); 794 797 return -EINVAL; 795 798 } 796 - 797 - of_node_put(cmm); 798 799 799 800 /* 800 801 * -ENODEV is used to report that the CMM config option is 801 802 * disabled: return 0 and let the DU continue probing. 802 803 */ 803 - ret = rcar_cmm_init(pdev); 804 + ret = rcar_cmm_init(&pdev->dev); 804 805 if (ret) { 805 806 platform_device_put(pdev); 806 807 return ret == -ENODEV ? 0 : ret; 807 808 } 808 809 809 - rcdu->cmms[i] = pdev; 810 + cmm->dev = &pdev->dev; 810 811 811 812 /* 812 813 * Enforce suspend/resume ordering by making the CMM a provider 813 814 * of the DU: CMM is suspended after and resumed before the DU. 814 815 */ 815 - link = device_link_add(rcdu->dev, &pdev->dev, DL_FLAG_STATELESS); 816 - if (!link) { 816 + cmm->link = device_link_add(rcdu->dev, cmm->dev, 817 + DL_FLAG_STATELESS); 818 + if (!cmm->link) { 817 819 dev_err(rcdu->dev, 818 820 "Failed to create device link to CMM%u\n", i); 819 821 return -EINVAL; ··· 824 834 struct rcar_du_device *rcdu = to_rcar_du_device(dev); 825 835 unsigned int i; 826 836 827 - for (i = 0; i < ARRAY_SIZE(rcdu->cmms); ++i) 828 - platform_device_put(rcdu->cmms[i]); 837 + for (i = 0; i < ARRAY_SIZE(rcdu->cmms); ++i) { 838 + struct rcar_du_cmm *cmm = &rcdu->cmms[i]; 839 + 840 + if (cmm->link) 841 + device_link_del(cmm->link); 842 + 843 + put_device(cmm->dev); 844 + } 829 845 } 830 846 831 847 int rcar_du_modeset_init(struct rcar_du_device *rcdu)
+16
drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.c
··· 20 20 #include <drm/drm_vblank.h> 21 21 22 22 #include <linux/bitops.h> 23 + #include <linux/device.h> 23 24 #include <linux/dma-mapping.h> 24 25 #include <linux/of_platform.h> 25 26 #include <linux/platform_device.h> ··· 459 458 460 459 kfree(vsp->planes); 461 460 461 + if (vsp->link) 462 + device_link_del(vsp->link); 463 + 462 464 put_device(vsp->vsp); 463 465 } 464 466 ··· 485 481 ret = drmm_add_action_or_reset(&rcdu->ddev, rcar_du_vsp_cleanup, vsp); 486 482 if (ret < 0) 487 483 return ret; 484 + 485 + /* 486 + * Enforce suspend/resume ordering between the DU (consumer) and the 487 + * VSP (supplier). The DU will be suspended before and resume after the 488 + * VSP. 489 + */ 490 + vsp->link = device_link_add(rcdu->dev, vsp->vsp, DL_FLAG_STATELESS); 491 + if (!vsp->link) { 492 + dev_err(rcdu->dev, "Failed to create device link to VSP %s\n", 493 + dev_name(vsp->vsp)); 494 + return -EINVAL; 495 + } 488 496 489 497 ret = vsp1_du_init(vsp->vsp); 490 498 if (ret < 0)
+2
drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.h
··· 12 12 13 13 #include <drm/drm_plane.h> 14 14 15 + struct device_link; 15 16 struct drm_framebuffer; 16 17 struct rcar_du_format_info; 17 18 struct rcar_du_vsp; ··· 27 26 struct rcar_du_vsp { 28 27 unsigned int index; 29 28 struct device *vsp; 29 + struct device_link *link; 30 30 struct rcar_du_device *dev; 31 31 struct rcar_du_vsp_plane *planes; 32 32 unsigned int num_planes;
+2 -2
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
··· 171 171 { 172 172 struct drm_display_info *di = &connector->display_info; 173 173 /* VOP couldn't output YUV video format for eDP rightly */ 174 - u32 mask = DRM_COLOR_FORMAT_YCBCR444 | DRM_COLOR_FORMAT_YCBCR422; 174 + u32 mask = BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) | BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422); 175 175 176 176 if ((di->color_formats & mask)) { 177 177 DRM_DEBUG_KMS("Swapping display color format from YUV to RGB\n"); 178 178 di->color_formats &= ~mask; 179 - di->color_formats |= DRM_COLOR_FORMAT_RGB444; 179 + di->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444); 180 180 di->bpc = 8; 181 181 } 182 182
+139 -46
drivers/gpu/drm/sitronix/st7586.c
··· 13 13 #include <video/mipi_display.h> 14 14 15 15 #include <drm/clients/drm_client_setup.h> 16 + #include <drm/drm_atomic.h> 16 17 #include <drm/drm_atomic_helper.h> 17 18 #include <drm/drm_damage_helper.h> 18 19 #include <drm/drm_drv.h> ··· 48 47 49 48 #define ST7586_DISP_CTRL_MX BIT(6) 50 49 #define ST7586_DISP_CTRL_MY BIT(7) 50 + 51 + struct st7586_device { 52 + struct mipi_dbi_dev dbidev; 53 + 54 + struct drm_plane plane; 55 + struct drm_crtc crtc; 56 + struct drm_encoder encoder; 57 + struct drm_connector connector; 58 + }; 59 + 60 + static struct st7586_device *to_st7586_device(struct drm_device *dev) 61 + { 62 + return container_of(drm_to_mipi_dbi_dev(dev), struct st7586_device, dbidev); 63 + } 51 64 52 65 /* 53 66 * The ST7586 controller has an unusual pixel format where 2bpp grayscale is ··· 162 147 dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret); 163 148 } 164 149 165 - static void st7586_pipe_update(struct drm_simple_display_pipe *pipe, 166 - struct drm_plane_state *old_state) 150 + static const u32 st7586_plane_formats[] = { 151 + DRM_FORMAT_XRGB8888, 152 + }; 153 + 154 + static const u64 st7586_plane_format_modifiers[] = { 155 + DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS, 156 + }; 157 + 158 + static void st7586_plane_helper_atomic_update(struct drm_plane *plane, 159 + struct drm_atomic_state *state) 167 160 { 168 - struct drm_plane_state *state = pipe->plane.state; 169 - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state); 170 - struct drm_framebuffer *fb = state->fb; 161 + struct drm_plane_state *plane_state = plane->state; 162 + struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 163 + struct drm_framebuffer *fb = plane_state->fb; 164 + struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); 171 165 struct drm_rect rect; 172 166 int idx; 173 167 174 - if (!pipe->crtc.state->active) 168 + if (!fb) 175 169 return; 176 170 177 - if (!drm_dev_enter(fb->dev, &idx)) 171 + if (!drm_dev_enter(plane->dev, &idx)) 178 172 return; 179 173 180 - if (drm_atomic_helper_damage_merged(old_state, state, &rect)) 174 + if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &rect)) 181 175 st7586_fb_dirty(&shadow_plane_state->data[0], fb, &rect, 182 176 &shadow_plane_state->fmtcnv_state); 183 177 184 178 drm_dev_exit(idx); 185 179 } 186 180 187 - static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, 188 - struct drm_crtc_state *crtc_state, 189 - struct drm_plane_state *plane_state) 181 + static const struct drm_plane_helper_funcs st7586_plane_helper_funcs = { 182 + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, 183 + .atomic_check = drm_mipi_dbi_plane_helper_atomic_check, 184 + .atomic_update = st7586_plane_helper_atomic_update 185 + }; 186 + 187 + static const struct drm_plane_funcs st7586_plane_funcs = { 188 + DRM_MIPI_DBI_PLANE_FUNCS, 189 + .destroy = drm_plane_cleanup, 190 + }; 191 + 192 + static void st7586_crtc_helper_atomic_enable(struct drm_crtc *crtc, 193 + struct drm_atomic_state *state) 190 194 { 191 - struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); 192 - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 193 - struct drm_framebuffer *fb = plane_state->fb; 195 + struct drm_device *drm = crtc->dev; 196 + struct st7586_device *st7586 = to_st7586_device(drm); 197 + struct mipi_dbi_dev *dbidev = &st7586->dbidev; 194 198 struct mipi_dbi *dbi = &dbidev->dbi; 195 - struct drm_rect rect = { 196 - .x1 = 0, 197 - .x2 = fb->width, 198 - .y1 = 0, 199 - .y2 = fb->height, 200 - }; 201 199 int idx, ret; 202 200 u8 addr_mode; 203 201 204 - if (!drm_dev_enter(pipe->crtc.dev, &idx)) 202 + if (!drm_dev_enter(drm, &idx)) 205 203 return; 206 204 207 205 DRM_DEBUG_KMS("\n"); ··· 270 242 271 243 msleep(100); 272 244 273 - st7586_fb_dirty(&shadow_plane_state->data[0], fb, &rect, 274 - &shadow_plane_state->fmtcnv_state); 275 - 276 245 mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON); 277 246 out_exit: 278 247 drm_dev_exit(idx); 279 248 } 280 249 281 - static void st7586_pipe_disable(struct drm_simple_display_pipe *pipe) 250 + static void st7586_crtc_helper_atomic_disable(struct drm_crtc *crtc, 251 + struct drm_atomic_state *state) 282 252 { 283 - struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); 253 + struct drm_device *drm = crtc->dev; 254 + struct st7586_device *st7586 = to_st7586_device(drm); 255 + struct mipi_dbi_dev *dbidev = &st7586->dbidev; 284 256 285 257 /* 286 258 * This callback is not protected by drm_dev_enter/exit since we want to ··· 294 266 mipi_dbi_command(&dbidev->dbi, MIPI_DCS_SET_DISPLAY_OFF); 295 267 } 296 268 297 - static const u32 st7586_formats[] = { 298 - DRM_FORMAT_XRGB8888, 269 + static const struct drm_crtc_helper_funcs st7586_crtc_helper_funcs = { 270 + .mode_valid = drm_mipi_dbi_crtc_helper_mode_valid, 271 + .atomic_check = drm_mipi_dbi_crtc_helper_atomic_check, 272 + .atomic_enable = st7586_crtc_helper_atomic_enable, 273 + .atomic_disable = st7586_crtc_helper_atomic_disable, 299 274 }; 300 275 301 - static const struct drm_simple_display_pipe_funcs st7586_pipe_funcs = { 302 - .mode_valid = mipi_dbi_pipe_mode_valid, 303 - .enable = st7586_pipe_enable, 304 - .disable = st7586_pipe_disable, 305 - .update = st7586_pipe_update, 306 - .begin_fb_access = mipi_dbi_pipe_begin_fb_access, 307 - .end_fb_access = mipi_dbi_pipe_end_fb_access, 308 - .reset_plane = mipi_dbi_pipe_reset_plane, 309 - .duplicate_plane_state = mipi_dbi_pipe_duplicate_plane_state, 310 - .destroy_plane_state = mipi_dbi_pipe_destroy_plane_state, 276 + static const struct drm_crtc_funcs st7586_crtc_funcs = { 277 + DRM_MIPI_DBI_CRTC_FUNCS, 278 + .destroy = drm_crtc_cleanup, 279 + }; 280 + 281 + static const struct drm_encoder_funcs st7586_encoder_funcs = { 282 + .destroy = drm_encoder_cleanup, 283 + }; 284 + 285 + static const struct drm_connector_helper_funcs st7586_connector_helper_funcs = { 286 + DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS, 287 + }; 288 + 289 + static const struct drm_connector_funcs st7586_connector_funcs = { 290 + DRM_MIPI_DBI_CONNECTOR_FUNCS, 291 + .destroy = drm_connector_cleanup, 292 + }; 293 + 294 + static const struct drm_mode_config_helper_funcs st7586_mode_config_helper_funcs = { 295 + DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS, 296 + }; 297 + 298 + static const struct drm_mode_config_funcs st7586_mode_config_funcs = { 299 + DRM_MIPI_DBI_MODE_CONFIG_FUNCS, 311 300 }; 312 301 313 302 static const struct drm_display_mode st7586_mode = { ··· 360 315 static int st7586_probe(struct spi_device *spi) 361 316 { 362 317 struct device *dev = &spi->dev; 318 + struct st7586_device *st7586; 363 319 struct mipi_dbi_dev *dbidev; 364 320 struct drm_device *drm; 365 321 struct mipi_dbi *dbi; 366 322 struct gpio_desc *a0; 323 + struct drm_plane *plane; 324 + struct drm_crtc *crtc; 325 + struct drm_encoder *encoder; 326 + struct drm_connector *connector; 367 327 u32 rotation = 0; 368 328 size_t bufsize; 369 329 int ret; 370 330 371 - dbidev = devm_drm_dev_alloc(dev, &st7586_driver, 372 - struct mipi_dbi_dev, drm); 373 - if (IS_ERR(dbidev)) 374 - return PTR_ERR(dbidev); 375 - 331 + st7586 = devm_drm_dev_alloc(dev, &st7586_driver, struct st7586_device, dbidev.drm); 332 + if (IS_ERR(st7586)) 333 + return PTR_ERR(st7586); 334 + dbidev = &st7586->dbidev; 376 335 dbi = &dbidev->dbi; 377 336 drm = &dbidev->drm; 378 337 ··· 405 356 /* Cannot read from this controller via SPI */ 406 357 dbi->read_commands = NULL; 407 358 408 - ret = mipi_dbi_dev_init_with_formats(dbidev, &st7586_pipe_funcs, 409 - st7586_formats, ARRAY_SIZE(st7586_formats), 410 - &st7586_mode, rotation, bufsize); 359 + ret = drm_mipi_dbi_dev_init(dbidev, &st7586_mode, st7586_plane_formats[0], 360 + rotation, bufsize); 361 + if (ret) 362 + return ret; 363 + 364 + ret = drmm_mode_config_init(drm); 365 + if (ret) 366 + return ret; 367 + 368 + drm->mode_config.min_width = dbidev->mode.hdisplay; 369 + drm->mode_config.max_width = dbidev->mode.hdisplay; 370 + drm->mode_config.min_height = dbidev->mode.vdisplay; 371 + drm->mode_config.max_height = dbidev->mode.vdisplay; 372 + drm->mode_config.funcs = &st7586_mode_config_funcs; 373 + drm->mode_config.preferred_depth = 24; 374 + drm->mode_config.helper_private = &st7586_mode_config_helper_funcs; 375 + 376 + plane = &st7586->plane; 377 + ret = drm_universal_plane_init(drm, plane, 0, &st7586_plane_funcs, 378 + st7586_plane_formats, ARRAY_SIZE(st7586_plane_formats), 379 + st7586_plane_format_modifiers, 380 + DRM_PLANE_TYPE_PRIMARY, NULL); 381 + if (ret) 382 + return ret; 383 + drm_plane_helper_add(plane, &st7586_plane_helper_funcs); 384 + drm_plane_enable_fb_damage_clips(plane); 385 + 386 + crtc = &st7586->crtc; 387 + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &st7586_crtc_funcs, NULL); 388 + if (ret) 389 + return ret; 390 + drm_crtc_helper_add(crtc, &st7586_crtc_helper_funcs); 391 + 392 + encoder = &st7586->encoder; 393 + ret = drm_encoder_init(drm, encoder, &st7586_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); 394 + if (ret) 395 + return ret; 396 + encoder->possible_crtcs = drm_crtc_mask(crtc); 397 + 398 + connector = &st7586->connector; 399 + ret = drm_connector_init(drm, connector, &st7586_connector_funcs, 400 + DRM_MODE_CONNECTOR_SPI); 401 + if (ret) 402 + return ret; 403 + drm_connector_helper_add(connector, &st7586_connector_helper_funcs); 404 + 405 + ret = drm_connector_attach_encoder(connector, encoder); 411 406 if (ret) 412 407 return ret; 413 408
+121 -21
drivers/gpu/drm/sitronix/st7735r.c
··· 52 52 unsigned int rgb:1; /* RGB (vs. BGR) */ 53 53 }; 54 54 55 - struct st7735r_priv { 55 + struct st7735r_device { 56 56 struct mipi_dbi_dev dbidev; /* Must be first for .release() */ 57 57 const struct st7735r_cfg *cfg; 58 + 59 + struct drm_plane plane; 60 + struct drm_crtc crtc; 61 + struct drm_encoder encoder; 62 + struct drm_connector connector; 58 63 }; 59 64 60 - static void st7735r_pipe_enable(struct drm_simple_display_pipe *pipe, 61 - struct drm_crtc_state *crtc_state, 62 - struct drm_plane_state *plane_state) 65 + static struct st7735r_device *to_st7735r_device(struct drm_device *drm) 63 66 { 64 - struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); 65 - struct st7735r_priv *priv = container_of(dbidev, struct st7735r_priv, 66 - dbidev); 67 + return container_of(drm_to_mipi_dbi_dev(drm), struct st7735r_device, dbidev); 68 + } 69 + 70 + static const u32 st7735r_plane_formats[] = { 71 + DRM_MIPI_DBI_PLANE_FORMATS, 72 + }; 73 + 74 + static const u64 st7735r_plane_format_modifiers[] = { 75 + DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS, 76 + }; 77 + 78 + static const struct drm_plane_helper_funcs st7735r_plane_helper_funcs = { 79 + DRM_MIPI_DBI_PLANE_HELPER_FUNCS, 80 + }; 81 + 82 + static const struct drm_plane_funcs st7735r_plane_funcs = { 83 + DRM_MIPI_DBI_PLANE_FUNCS, 84 + .destroy = drm_plane_cleanup, 85 + }; 86 + 87 + static void st7735r_crtc_helper_atomic_enable(struct drm_crtc *crtc, 88 + struct drm_atomic_state *state) 89 + { 90 + struct drm_device *drm = crtc->dev; 91 + struct st7735r_device *st7735r = to_st7735r_device(drm); 92 + struct mipi_dbi_dev *dbidev = &st7735r->dbidev; 67 93 struct mipi_dbi *dbi = &dbidev->dbi; 68 94 int ret, idx; 69 95 u8 addr_mode; 70 96 71 - if (!drm_dev_enter(pipe->crtc.dev, &idx)) 97 + if (!drm_dev_enter(drm, &idx)) 72 98 return; 73 99 74 100 DRM_DEBUG_KMS("\n"); ··· 135 109 break; 136 110 } 137 111 138 - if (priv->cfg->rgb) 112 + if (st7735r->cfg->rgb) 139 113 addr_mode |= ST7735R_RGB; 140 114 141 115 mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); ··· 155 129 156 130 msleep(20); 157 131 158 - mipi_dbi_enable_flush(dbidev, crtc_state, plane_state); 132 + backlight_enable(dbidev->backlight); 159 133 out_exit: 160 134 drm_dev_exit(idx); 161 135 } 162 136 163 - static const struct drm_simple_display_pipe_funcs st7735r_pipe_funcs = { 164 - DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(st7735r_pipe_enable), 137 + static const struct drm_crtc_helper_funcs st7735r_crtc_helper_funcs = { 138 + DRM_MIPI_DBI_CRTC_HELPER_FUNCS, 139 + .atomic_enable = st7735r_crtc_helper_atomic_enable, 140 + }; 141 + 142 + static const struct drm_crtc_funcs st7735r_crtc_funcs = { 143 + DRM_MIPI_DBI_CRTC_FUNCS, 144 + .destroy = drm_crtc_cleanup, 145 + }; 146 + 147 + static const struct drm_encoder_funcs st7735r_encoder_funcs = { 148 + .destroy = drm_encoder_cleanup, 149 + }; 150 + 151 + static const struct drm_connector_helper_funcs st7735r_connector_helper_funcs = { 152 + DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS, 153 + }; 154 + 155 + static const struct drm_connector_funcs st7735r_connector_funcs = { 156 + DRM_MIPI_DBI_CONNECTOR_FUNCS, 157 + .destroy = drm_connector_cleanup, 158 + }; 159 + 160 + static const struct drm_mode_config_helper_funcs st7735r_mode_config_helper_funcs = { 161 + DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS, 162 + }; 163 + 164 + static const struct drm_mode_config_funcs st7735r_mode_config_funcs = { 165 + DRM_MIPI_DBI_MODE_CONFIG_FUNCS, 165 166 }; 166 167 167 168 static const struct st7735r_cfg jd_t18003_t01_cfg = { ··· 237 184 struct device *dev = &spi->dev; 238 185 const struct st7735r_cfg *cfg; 239 186 struct mipi_dbi_dev *dbidev; 240 - struct st7735r_priv *priv; 187 + struct st7735r_device *st7735r; 241 188 struct drm_device *drm; 242 189 struct mipi_dbi *dbi; 243 190 struct gpio_desc *dc; 191 + struct drm_plane *plane; 192 + struct drm_crtc *crtc; 193 + struct drm_encoder *encoder; 194 + struct drm_connector *connector; 244 195 u32 rotation = 0; 245 196 int ret; 246 197 ··· 252 195 if (!cfg) 253 196 cfg = (void *)spi_get_device_id(spi)->driver_data; 254 197 255 - priv = devm_drm_dev_alloc(dev, &st7735r_driver, 256 - struct st7735r_priv, dbidev.drm); 257 - if (IS_ERR(priv)) 258 - return PTR_ERR(priv); 198 + st7735r = devm_drm_dev_alloc(dev, &st7735r_driver, struct st7735r_device, dbidev.drm); 199 + if (IS_ERR(st7735r)) 200 + return PTR_ERR(st7735r); 259 201 260 - dbidev = &priv->dbidev; 261 - priv->cfg = cfg; 202 + dbidev = &st7735r->dbidev; 203 + st7735r->cfg = cfg; 262 204 263 205 dbi = &dbidev->dbi; 264 206 drm = &dbidev->drm; ··· 286 230 dbidev->left_offset = cfg->left_offset; 287 231 dbidev->top_offset = cfg->top_offset; 288 232 289 - ret = mipi_dbi_dev_init(dbidev, &st7735r_pipe_funcs, &cfg->mode, 290 - rotation); 233 + ret = drm_mipi_dbi_dev_init(dbidev, &cfg->mode, st7735r_plane_formats[0], rotation, 0); 234 + if (ret) 235 + return ret; 236 + 237 + ret = drmm_mode_config_init(drm); 238 + if (ret) 239 + return ret; 240 + 241 + drm->mode_config.min_width = dbidev->mode.hdisplay; 242 + drm->mode_config.max_width = dbidev->mode.hdisplay; 243 + drm->mode_config.min_height = dbidev->mode.vdisplay; 244 + drm->mode_config.max_height = dbidev->mode.vdisplay; 245 + drm->mode_config.funcs = &st7735r_mode_config_funcs; 246 + drm->mode_config.preferred_depth = 16; 247 + drm->mode_config.helper_private = &st7735r_mode_config_helper_funcs; 248 + 249 + plane = &st7735r->plane; 250 + ret = drm_universal_plane_init(drm, plane, 0, &st7735r_plane_funcs, 251 + st7735r_plane_formats, ARRAY_SIZE(st7735r_plane_formats), 252 + st7735r_plane_format_modifiers, 253 + DRM_PLANE_TYPE_PRIMARY, NULL); 254 + if (ret) 255 + return ret; 256 + drm_plane_helper_add(plane, &st7735r_plane_helper_funcs); 257 + drm_plane_enable_fb_damage_clips(plane); 258 + 259 + crtc = &st7735r->crtc; 260 + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &st7735r_crtc_funcs, NULL); 261 + if (ret) 262 + return ret; 263 + drm_crtc_helper_add(crtc, &st7735r_crtc_helper_funcs); 264 + 265 + encoder = &st7735r->encoder; 266 + ret = drm_encoder_init(drm, encoder, &st7735r_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); 267 + if (ret) 268 + return ret; 269 + encoder->possible_crtcs = drm_crtc_mask(crtc); 270 + 271 + connector = &st7735r->connector; 272 + ret = drm_connector_init(drm, connector, &st7735r_connector_funcs, 273 + DRM_MODE_CONNECTOR_SPI); 274 + if (ret) 275 + return ret; 276 + drm_connector_helper_add(connector, &st7735r_connector_helper_funcs); 277 + 278 + ret = drm_connector_attach_encoder(connector, encoder); 291 279 if (ret) 292 280 return ret; 293 281
+15 -12
drivers/gpu/drm/sun4i/sun4i_backend.c
··· 798 798 dev_set_drvdata(dev, backend); 799 799 spin_lock_init(&backend->frontend_lock); 800 800 801 - if (of_property_present(dev->of_node, "interconnects")) { 802 - /* 803 - * This assume we have the same DMA constraints for all our the 804 - * devices in our pipeline (all the backends, but also the 805 - * frontends). This sounds bad, but it has always been the case 806 - * for us, and DRM doesn't do per-device allocation either, so 807 - * we would need to fix DRM first... 808 - */ 809 - ret = of_dma_configure(drm->dev, dev->of_node, true); 810 - if (ret) 811 - return ret; 812 - } 801 + /* 802 + * This assume we have the same DMA constraints for all our the 803 + * devices in our pipeline (all the backends, but also the 804 + * frontends). This sounds bad, but it has always been the case 805 + * for us, and DRM doesn't do per-device allocation either, so 806 + * we would need to fix DRM first... 807 + * 808 + * Always use the first bound backend as the DMA device. While 809 + * our device trees always have all backends enabled, some in 810 + * the wild may actually have the first one disabled. If both 811 + * are enabled, the order in which they are bound is guaranteed 812 + * since the driver adds components in order. 813 + */ 814 + if (drm_dev_dma_dev(drm) == drm->dev) 815 + drm_dev_set_dma_dev(drm, dev); 813 816 814 817 backend->engine.node = dev->of_node; 815 818 backend->engine.ops = &sun4i_backend_engine_ops;
+1 -1
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
··· 661 661 &sun4i_hdmi_hdmi_connector_funcs, 662 662 DRM_MODE_CONNECTOR_HDMIA, 663 663 hdmi->ddc_i2c, 664 - BIT(HDMI_COLORSPACE_RGB), 664 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 665 665 8); 666 666 if (ret) { 667 667 dev_err(dev,
+15 -12
drivers/gpu/drm/sun4i/sun8i_mixer.c
··· 536 536 mixer->engine.ops = &sun8i_engine_ops; 537 537 mixer->engine.node = dev->of_node; 538 538 539 - if (of_property_present(dev->of_node, "iommus")) { 540 - /* 541 - * This assume we have the same DMA constraints for 542 - * all our the mixers in our pipeline. This sounds 543 - * bad, but it has always been the case for us, and 544 - * DRM doesn't do per-device allocation either, so we 545 - * would need to fix DRM first... 546 - */ 547 - ret = of_dma_configure(drm->dev, dev->of_node, true); 548 - if (ret) 549 - return ret; 550 - } 539 + /* 540 + * This assume we have the same DMA constraints for all our the 541 + * devices in our pipeline (all the backends, but also the 542 + * frontends). This sounds bad, but it has always been the case 543 + * for us, and DRM doesn't do per-device allocation either, so 544 + * we would need to fix DRM first... 545 + * 546 + * Always use the first bound backend as the DMA device. While 547 + * our device trees always have all backends enabled, some in 548 + * the wild may actually have the first one disabled. If both 549 + * are enabled, the order in which they are bound is guaranteed 550 + * since the driver adds components in order. 551 + */ 552 + if (drm_dev_dma_dev(drm) == drm->dev) 553 + drm_dev_set_dma_dev(drm, dev); 551 554 552 555 /* 553 556 * While this function can fail, we shouldn't do anything
+16 -6
drivers/gpu/drm/tegra/hub.c
··· 825 825 kfree(hub_state); 826 826 } 827 827 828 + static struct drm_private_state * 829 + tegra_display_hub_create_state(struct drm_private_obj *obj) 830 + { 831 + struct tegra_display_hub_state *hub_state; 832 + 833 + hub_state = kzalloc_obj(*hub_state); 834 + if (!hub_state) 835 + return ERR_PTR(-ENOMEM); 836 + 837 + __drm_atomic_helper_private_obj_create_state(obj, &hub_state->base); 838 + 839 + return &hub_state->base; 840 + } 841 + 828 842 static const struct drm_private_state_funcs tegra_display_hub_state_funcs = { 843 + .atomic_create_state = tegra_display_hub_create_state, 829 844 .atomic_duplicate_state = tegra_display_hub_duplicate_state, 830 845 .atomic_destroy_state = tegra_display_hub_destroy_state, 831 846 }; ··· 956 941 struct tegra_display_hub *hub = to_tegra_display_hub(client); 957 942 struct drm_device *drm = dev_get_drvdata(client->host); 958 943 struct tegra_drm *tegra = drm->dev_private; 959 - struct tegra_display_hub_state *state; 960 944 961 - state = kzalloc_obj(*state); 962 - if (!state) 963 - return -ENOMEM; 964 - 965 - drm_atomic_private_obj_init(drm, &hub->base, &state->base, 945 + drm_atomic_private_obj_init(drm, &hub->base, 966 946 &tegra_display_hub_state_funcs); 967 947 968 948 tegra->hub = hub;
+40 -40
drivers/gpu/drm/tests/drm_connector_test.c
··· 675 675 &dummy_hdmi_funcs, 676 676 DRM_MODE_CONNECTOR_HDMIA, 677 677 &priv->ddc, 678 - BIT(HDMI_COLORSPACE_RGB), 678 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 679 679 8); 680 680 KUNIT_EXPECT_EQ(test, ret, 0); 681 681 } ··· 695 695 &dummy_hdmi_funcs, 696 696 DRM_MODE_CONNECTOR_HDMIA, 697 697 NULL, 698 - BIT(HDMI_COLORSPACE_RGB), 698 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 699 699 8); 700 700 KUNIT_EXPECT_EQ(test, ret, 0); 701 701 } ··· 715 715 &dummy_hdmi_funcs, 716 716 DRM_MODE_CONNECTOR_HDMIA, 717 717 &priv->ddc, 718 - BIT(HDMI_COLORSPACE_RGB), 718 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 719 719 8); 720 720 KUNIT_EXPECT_LT(test, ret, 0); 721 721 } ··· 735 735 &dummy_hdmi_funcs, 736 736 DRM_MODE_CONNECTOR_HDMIA, 737 737 &priv->ddc, 738 - BIT(HDMI_COLORSPACE_RGB), 738 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 739 739 8); 740 740 KUNIT_EXPECT_LT(test, ret, 0); 741 741 } ··· 761 761 &dummy_hdmi_funcs, 762 762 DRM_MODE_CONNECTOR_HDMIA, 763 763 &priv->ddc, 764 - BIT(HDMI_COLORSPACE_RGB), 764 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 765 765 8); 766 766 KUNIT_EXPECT_EQ(test, ret, 0); 767 767 KUNIT_EXPECT_MEMEQ(test, ··· 794 794 &dummy_hdmi_funcs, 795 795 DRM_MODE_CONNECTOR_HDMIA, 796 796 &priv->ddc, 797 - BIT(HDMI_COLORSPACE_RGB), 797 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 798 798 8); 799 799 KUNIT_EXPECT_EQ(test, ret, 0); 800 800 KUNIT_EXPECT_MEMEQ(test, ··· 821 821 &dummy_hdmi_funcs, 822 822 DRM_MODE_CONNECTOR_HDMIA, 823 823 &priv->ddc, 824 - BIT(HDMI_COLORSPACE_RGB), 824 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 825 825 8); 826 826 KUNIT_EXPECT_LT(test, ret, 0); 827 827 } ··· 847 847 &dummy_hdmi_funcs, 848 848 DRM_MODE_CONNECTOR_HDMIA, 849 849 &priv->ddc, 850 - BIT(HDMI_COLORSPACE_RGB), 850 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 851 851 8); 852 852 KUNIT_EXPECT_EQ(test, ret, 0); 853 853 KUNIT_EXPECT_MEMEQ(test, ··· 879 879 &dummy_hdmi_funcs, 880 880 DRM_MODE_CONNECTOR_HDMIA, 881 881 &priv->ddc, 882 - BIT(HDMI_COLORSPACE_RGB), 882 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 883 883 8); 884 884 KUNIT_EXPECT_EQ(test, ret, 0); 885 885 KUNIT_EXPECT_MEMEQ(test, ··· 906 906 &dummy_hdmi_funcs, 907 907 DRM_MODE_CONNECTOR_HDMIA, 908 908 &priv->ddc, 909 - BIT(HDMI_COLORSPACE_RGB), 909 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 910 910 8); 911 911 KUNIT_EXPECT_LT(test, ret, 0); 912 912 } ··· 926 926 &dummy_hdmi_funcs, 927 927 DRM_MODE_CONNECTOR_HDMIA, 928 928 &priv->ddc, 929 - BIT(HDMI_COLORSPACE_RGB), 929 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 930 930 9); 931 931 KUNIT_EXPECT_LT(test, ret, 0); 932 932 } ··· 946 946 &dummy_hdmi_funcs, 947 947 DRM_MODE_CONNECTOR_HDMIA, 948 948 &priv->ddc, 949 - BIT(HDMI_COLORSPACE_RGB), 949 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 950 950 0); 951 951 KUNIT_EXPECT_LT(test, ret, 0); 952 952 } ··· 971 971 &dummy_hdmi_funcs, 972 972 DRM_MODE_CONNECTOR_HDMIA, 973 973 &priv->ddc, 974 - BIT(HDMI_COLORSPACE_RGB), 974 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 975 975 8); 976 976 KUNIT_EXPECT_EQ(test, ret, 0); 977 977 ··· 1012 1012 &dummy_hdmi_funcs, 1013 1013 DRM_MODE_CONNECTOR_HDMIA, 1014 1014 &priv->ddc, 1015 - BIT(HDMI_COLORSPACE_RGB), 1015 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 1016 1016 10); 1017 1017 KUNIT_EXPECT_EQ(test, ret, 0); 1018 1018 ··· 1053 1053 &dummy_hdmi_funcs, 1054 1054 DRM_MODE_CONNECTOR_HDMIA, 1055 1055 &priv->ddc, 1056 - BIT(HDMI_COLORSPACE_RGB), 1056 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 1057 1057 12); 1058 1058 KUNIT_EXPECT_EQ(test, ret, 0); 1059 1059 ··· 1109 1109 &dummy_hdmi_funcs, 1110 1110 DRM_MODE_CONNECTOR_HDMIA, 1111 1111 &priv->ddc, 1112 - BIT(HDMI_COLORSPACE_YUV422), 1112 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422), 1113 1113 8); 1114 1114 KUNIT_EXPECT_LT(test, ret, 0); 1115 1115 } ··· 1122 1122 1123 1123 #define YUV420_ALLOWED_TEST(_formats, _allowed, _result) \ 1124 1124 { \ 1125 - .supported_formats = BIT(HDMI_COLORSPACE_RGB) | (_formats), \ 1125 + .supported_formats = BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | (_formats), \ 1126 1126 .yuv420_allowed = _allowed, \ 1127 1127 .expected_result = _result, \ 1128 1128 } 1129 1129 1130 1130 static const struct drm_connector_hdmi_init_formats_yuv420_allowed_test 1131 1131 drm_connector_hdmi_init_formats_yuv420_allowed_tests[] = { 1132 - YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV420), true, 0), 1133 - YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV420), false, -EINVAL), 1134 - YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV422), true, -EINVAL), 1135 - YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV422), false, 0), 1132 + YUV420_ALLOWED_TEST(BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420), true, 0), 1133 + YUV420_ALLOWED_TEST(BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420), false, -EINVAL), 1134 + YUV420_ALLOWED_TEST(BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422), true, -EINVAL), 1135 + YUV420_ALLOWED_TEST(BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422), false, 0), 1136 1136 }; 1137 1137 1138 1138 static void ··· 1188 1188 &dummy_hdmi_funcs, 1189 1189 connector_type, 1190 1190 &priv->ddc, 1191 - BIT(HDMI_COLORSPACE_RGB), 1191 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 1192 1192 8); 1193 1193 KUNIT_EXPECT_EQ(test, ret, 0); 1194 1194 } ··· 1223 1223 &dummy_hdmi_funcs, 1224 1224 connector_type, 1225 1225 &priv->ddc, 1226 - BIT(HDMI_COLORSPACE_RGB), 1226 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 1227 1227 8); 1228 1228 KUNIT_EXPECT_LT(test, ret, 0); 1229 1229 } ··· 1432 1432 static const 1433 1433 struct drm_hdmi_connector_get_output_format_name_test 1434 1434 drm_hdmi_connector_get_output_format_name_valid_tests[] = { 1435 - OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_RGB, "RGB"), 1436 - OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV420, "YUV 4:2:0"), 1437 - OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV422, "YUV 4:2:2"), 1438 - OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV444, "YUV 4:4:4"), 1435 + OUTPUT_FORMAT_TEST(DRM_OUTPUT_COLOR_FORMAT_RGB444, "RGB"), 1436 + OUTPUT_FORMAT_TEST(DRM_OUTPUT_COLOR_FORMAT_YCBCR420, "YUV 4:2:0"), 1437 + OUTPUT_FORMAT_TEST(DRM_OUTPUT_COLOR_FORMAT_YCBCR422, "YUV 4:2:2"), 1438 + OUTPUT_FORMAT_TEST(DRM_OUTPUT_COLOR_FORMAT_YCBCR444, "YUV 4:4:4"), 1439 1439 }; 1440 1440 1441 1441 static void ··· 1500 1500 &dummy_hdmi_funcs, 1501 1501 DRM_MODE_CONNECTOR_HDMIA, 1502 1502 &priv->ddc, 1503 - BIT(HDMI_COLORSPACE_RGB), 1503 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 1504 1504 8); 1505 1505 KUNIT_EXPECT_EQ(test, ret, 0); 1506 1506 ··· 1540 1540 1541 1541 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 1542 1542 1543 - rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB); 1543 + rate = drm_hdmi_compute_mode_clock(mode, 8, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1544 1544 KUNIT_ASSERT_GT(test, rate, 0); 1545 1545 KUNIT_EXPECT_EQ(test, mode->clock * 1000ULL, rate); 1546 1546 } ··· 1561 1561 1562 1562 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 1563 1563 1564 - rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB); 1564 + rate = drm_hdmi_compute_mode_clock(mode, 10, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1565 1565 KUNIT_ASSERT_GT(test, rate, 0); 1566 1566 KUNIT_EXPECT_EQ(test, mode->clock * 1250, rate); 1567 1567 } ··· 1580 1580 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); 1581 1581 KUNIT_ASSERT_NOT_NULL(test, mode); 1582 1582 1583 - rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB); 1583 + rate = drm_hdmi_compute_mode_clock(mode, 10, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1584 1584 KUNIT_EXPECT_EQ(test, rate, 0); 1585 1585 } 1586 1586 ··· 1600 1600 1601 1601 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 1602 1602 1603 - rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB); 1603 + rate = drm_hdmi_compute_mode_clock(mode, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1604 1604 KUNIT_ASSERT_GT(test, rate, 0); 1605 1605 KUNIT_EXPECT_EQ(test, mode->clock * 1500, rate); 1606 1606 } ··· 1619 1619 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); 1620 1620 KUNIT_ASSERT_NOT_NULL(test, mode); 1621 1621 1622 - rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB); 1622 + rate = drm_hdmi_compute_mode_clock(mode, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1623 1623 KUNIT_EXPECT_EQ(test, rate, 0); 1624 1624 } 1625 1625 ··· 1639 1639 1640 1640 KUNIT_ASSERT_TRUE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 1641 1641 1642 - rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB); 1642 + rate = drm_hdmi_compute_mode_clock(mode, 8, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1643 1643 KUNIT_ASSERT_GT(test, rate, 0); 1644 1644 KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) * 2, rate); 1645 1645 } ··· 1662 1662 1663 1663 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 1664 1664 1665 - rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV420); 1665 + rate = drm_hdmi_compute_mode_clock(mode, 8, DRM_OUTPUT_COLOR_FORMAT_YCBCR420); 1666 1666 KUNIT_ASSERT_GT(test, rate, 0); 1667 1667 KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) / 2, rate); 1668 1668 } ··· 1699 1699 1700 1700 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 1701 1701 1702 - rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV420); 1702 + rate = drm_hdmi_compute_mode_clock(mode, 10, DRM_OUTPUT_COLOR_FORMAT_YCBCR420); 1703 1703 KUNIT_ASSERT_GT(test, rate, 0); 1704 1704 1705 1705 KUNIT_EXPECT_EQ(test, mode->clock * 625, rate); ··· 1724 1724 1725 1725 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 1726 1726 1727 - rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV420); 1727 + rate = drm_hdmi_compute_mode_clock(mode, 12, DRM_OUTPUT_COLOR_FORMAT_YCBCR420); 1728 1728 KUNIT_ASSERT_GT(test, rate, 0); 1729 1729 1730 1730 KUNIT_EXPECT_EQ(test, mode->clock * 750, rate); ··· 1747 1747 1748 1748 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 1749 1749 1750 - rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV422); 1750 + rate = drm_hdmi_compute_mode_clock(mode, 8, DRM_OUTPUT_COLOR_FORMAT_YCBCR422); 1751 1751 KUNIT_ASSERT_GT(test, rate, 0); 1752 1752 KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate); 1753 1753 } ··· 1769 1769 1770 1770 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 1771 1771 1772 - rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV422); 1772 + rate = drm_hdmi_compute_mode_clock(mode, 10, DRM_OUTPUT_COLOR_FORMAT_YCBCR422); 1773 1773 KUNIT_ASSERT_GT(test, rate, 0); 1774 1774 KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate); 1775 1775 } ··· 1791 1791 1792 1792 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 1793 1793 1794 - rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV422); 1794 + rate = drm_hdmi_compute_mode_clock(mode, 12, DRM_OUTPUT_COLOR_FORMAT_YCBCR422); 1795 1795 KUNIT_ASSERT_GT(test, rate, 0); 1796 1796 KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate); 1797 1797 }
+91 -91
drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
··· 239 239 enc->possible_crtcs = drm_crtc_mask(priv->crtc); 240 240 241 241 conn = &priv->connector; 242 - conn->ycbcr_420_allowed = !!(formats & BIT(HDMI_COLORSPACE_YUV420)); 242 + conn->ycbcr_420_allowed = !!(formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420)); 243 243 244 244 ret = drmm_connector_hdmi_init(drm, conn, 245 245 "Vendor", "Product", ··· 300 300 int ret; 301 301 302 302 priv = drm_kunit_helper_connector_hdmi_init(test, 303 - BIT(HDMI_COLORSPACE_RGB), 303 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 304 304 8); 305 305 KUNIT_ASSERT_NOT_NULL(test, priv); 306 306 ··· 375 375 int ret; 376 376 377 377 priv = drm_kunit_helper_connector_hdmi_init(test, 378 - BIT(HDMI_COLORSPACE_RGB), 378 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 379 379 8); 380 380 KUNIT_ASSERT_NOT_NULL(test, priv); 381 381 ··· 450 450 int ret; 451 451 452 452 priv = drm_kunit_helper_connector_hdmi_init(test, 453 - BIT(HDMI_COLORSPACE_RGB), 453 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 454 454 8); 455 455 KUNIT_ASSERT_NOT_NULL(test, priv); 456 456 ··· 517 517 int ret; 518 518 519 519 priv = drm_kunit_helper_connector_hdmi_init(test, 520 - BIT(HDMI_COLORSPACE_RGB), 520 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 521 521 8); 522 522 KUNIT_ASSERT_NOT_NULL(test, priv); 523 523 ··· 584 584 int ret; 585 585 586 586 priv = drm_kunit_helper_connector_hdmi_init(test, 587 - BIT(HDMI_COLORSPACE_RGB), 587 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 588 588 8); 589 589 KUNIT_ASSERT_NOT_NULL(test, priv); 590 590 ··· 653 653 int ret; 654 654 655 655 priv = drm_kunit_helper_connector_hdmi_init(test, 656 - BIT(HDMI_COLORSPACE_RGB), 656 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 657 657 8); 658 658 KUNIT_ASSERT_NOT_NULL(test, priv); 659 659 ··· 722 722 int ret; 723 723 724 724 priv = drm_kunit_helper_connector_hdmi_init(test, 725 - BIT(HDMI_COLORSPACE_RGB), 725 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 726 726 8); 727 727 KUNIT_ASSERT_NOT_NULL(test, priv); 728 728 ··· 791 791 int ret; 792 792 793 793 priv = drm_kunit_helper_connector_hdmi_init(test, 794 - BIT(HDMI_COLORSPACE_RGB), 794 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 795 795 8); 796 796 KUNIT_ASSERT_NOT_NULL(test, priv); 797 797 ··· 863 863 broadcast_rgb = *(enum drm_hdmi_broadcast_rgb *)test->param_value; 864 864 865 865 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 866 - BIT(HDMI_COLORSPACE_RGB) | 867 - BIT(HDMI_COLORSPACE_YUV420), 866 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | 867 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420), 868 868 8, 869 869 &dummy_connector_hdmi_funcs, 870 870 test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz); ··· 918 918 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 919 919 920 920 KUNIT_ASSERT_EQ(test, conn_state->hdmi.broadcast_rgb, broadcast_rgb); 921 - KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_YUV420); 921 + KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_YCBCR420); 922 922 923 923 KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range); 924 924 ··· 963 963 int ret; 964 964 965 965 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 966 - BIT(HDMI_COLORSPACE_RGB), 966 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 967 967 10, 968 968 &dummy_connector_hdmi_funcs, 969 969 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); ··· 1045 1045 int ret; 1046 1046 1047 1047 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1048 - BIT(HDMI_COLORSPACE_RGB), 1048 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 1049 1049 10, 1050 1050 &dummy_connector_hdmi_funcs, 1051 1051 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); ··· 1122 1122 int ret; 1123 1123 1124 1124 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1125 - BIT(HDMI_COLORSPACE_RGB) | 1126 - BIT(HDMI_COLORSPACE_YUV422) | 1127 - BIT(HDMI_COLORSPACE_YUV444), 1125 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | 1126 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) | 1127 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444), 1128 1128 12, 1129 1129 &dummy_connector_hdmi_funcs, 1130 1130 test_edid_dvi_1080p); ··· 1157 1157 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1158 1158 1159 1159 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 1160 - KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1160 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1161 1161 1162 1162 drm_modeset_drop_locks(&ctx); 1163 1163 drm_modeset_acquire_fini(&ctx); ··· 1179 1179 int ret; 1180 1180 1181 1181 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1182 - BIT(HDMI_COLORSPACE_RGB), 1182 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 1183 1183 8, 1184 1184 &dummy_connector_hdmi_funcs, 1185 1185 test_edid_hdmi_1080p_rgb_max_200mhz); ··· 1210 1210 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1211 1211 1212 1212 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 8); 1213 - KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1213 + KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1214 1214 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1000); 1215 1215 1216 1216 drm_modeset_drop_locks(&ctx); ··· 1234 1234 int ret; 1235 1235 1236 1236 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1237 - BIT(HDMI_COLORSPACE_RGB), 1237 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 1238 1238 10, 1239 1239 &dummy_connector_hdmi_funcs, 1240 1240 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz); ··· 1265 1265 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1266 1266 1267 1267 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 10); 1268 - KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1268 + KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1269 1269 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250); 1270 1270 1271 1271 drm_modeset_drop_locks(&ctx); ··· 1289 1289 int ret; 1290 1290 1291 1291 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1292 - BIT(HDMI_COLORSPACE_RGB), 1292 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 1293 1293 12, 1294 1294 &dummy_connector_hdmi_funcs, 1295 1295 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz); ··· 1320 1320 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1321 1321 1322 1322 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 12); 1323 - KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1323 + KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1324 1324 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1500); 1325 1325 1326 1326 drm_modeset_drop_locks(&ctx); ··· 1348 1348 int ret; 1349 1349 1350 1350 priv = drm_kunit_helper_connector_hdmi_init(test, 1351 - BIT(HDMI_COLORSPACE_RGB), 1351 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 1352 1352 8); 1353 1353 KUNIT_ASSERT_NOT_NULL(test, priv); 1354 1354 ··· 1416 1416 int ret; 1417 1417 1418 1418 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1419 - BIT(HDMI_COLORSPACE_RGB), 1419 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 1420 1420 12, 1421 1421 &dummy_connector_hdmi_funcs, 1422 1422 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); ··· 1433 1433 KUNIT_ASSERT_NOT_NULL(test, preferred); 1434 1434 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1435 1435 1436 - rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 1436 + rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1437 1437 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1438 1438 1439 - rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); 1439 + rate = drm_hdmi_compute_mode_clock(preferred, 10, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1440 1440 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1441 1441 1442 1442 drm_modeset_acquire_init(&ctx, 0); ··· 1457 1457 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1458 1458 1459 1459 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); 1460 - KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1460 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1461 1461 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250); 1462 1462 1463 1463 drm_modeset_drop_locks(&ctx); ··· 1490 1490 int ret; 1491 1491 1492 1492 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1493 - BIT(HDMI_COLORSPACE_RGB) | 1494 - BIT(HDMI_COLORSPACE_YUV420), 1493 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | 1494 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420), 1495 1495 12, 1496 1496 &dummy_connector_hdmi_funcs, 1497 1497 test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz); ··· 1509 1509 KUNIT_ASSERT_NOT_NULL(test, yuv420_only_mode); 1510 1510 KUNIT_ASSERT_TRUE(test, drm_mode_is_420_only(info, yuv420_only_mode)); 1511 1511 1512 - rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 12, HDMI_COLORSPACE_YUV420); 1512 + rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 12, DRM_OUTPUT_COLOR_FORMAT_YCBCR420); 1513 1513 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1514 1514 1515 - rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 10, HDMI_COLORSPACE_YUV420); 1515 + rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 10, DRM_OUTPUT_COLOR_FORMAT_YCBCR420); 1516 1516 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1517 1517 1518 1518 drm_modeset_acquire_init(&ctx, 0); ··· 1531 1531 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1532 1532 1533 1533 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); 1534 - KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_YUV420); 1534 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_YCBCR420); 1535 1535 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, yuv420_only_mode->clock * 625); 1536 1536 1537 1537 drm_modeset_drop_locks(&ctx); ··· 1565 1565 int ret; 1566 1566 1567 1567 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1568 - BIT(HDMI_COLORSPACE_RGB) | 1569 - BIT(HDMI_COLORSPACE_YUV422) | 1570 - BIT(HDMI_COLORSPACE_YUV444), 1568 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | 1569 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) | 1570 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444), 1571 1571 12, 1572 1572 &dummy_connector_hdmi_funcs, 1573 1573 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); ··· 1584 1584 KUNIT_ASSERT_NOT_NULL(test, preferred); 1585 1585 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1586 1586 1587 - rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); 1587 + rate = drm_hdmi_compute_mode_clock(preferred, 10, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1588 1588 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1589 1589 1590 - rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 1590 + rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1591 1591 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1592 1592 1593 - rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); 1593 + rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_YCBCR422); 1594 1594 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1595 1595 1596 1596 drm_modeset_acquire_init(&ctx, 0); ··· 1611 1611 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1612 1612 1613 1613 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); 1614 - KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1614 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1615 1615 1616 1616 drm_modeset_drop_locks(&ctx); 1617 1617 drm_modeset_acquire_fini(&ctx); ··· 1644 1644 int ret; 1645 1645 1646 1646 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1647 - BIT(HDMI_COLORSPACE_RGB) | 1648 - BIT(HDMI_COLORSPACE_YUV420), 1647 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | 1648 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420), 1649 1649 12, 1650 1650 &dummy_connector_hdmi_funcs, 1651 1651 test_edid_hdmi_4k_rgb_yuv420_dc_max_340mhz); ··· 1664 1664 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1665 1665 KUNIT_ASSERT_TRUE(test, drm_mode_is_420_also(info, preferred)); 1666 1666 1667 - rate = drm_hdmi_compute_mode_clock(preferred, 8, HDMI_COLORSPACE_RGB); 1667 + rate = drm_hdmi_compute_mode_clock(preferred, 8, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1668 1668 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1669 1669 1670 - rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); 1670 + rate = drm_hdmi_compute_mode_clock(preferred, 10, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1671 1671 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1672 1672 1673 - rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV420); 1673 + rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_YCBCR420); 1674 1674 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1675 1675 1676 1676 drm_modeset_acquire_init(&ctx, 0); ··· 1689 1689 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1690 1690 1691 1691 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 1692 - KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1692 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1693 1693 1694 1694 drm_modeset_drop_locks(&ctx); 1695 1695 drm_modeset_acquire_fini(&ctx); ··· 1715 1715 int ret; 1716 1716 1717 1717 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1718 - BIT(HDMI_COLORSPACE_RGB), 1718 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 1719 1719 12, 1720 1720 &dummy_connector_hdmi_funcs, 1721 1721 test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz); ··· 1750 1750 1751 1751 conn_state = conn->state; 1752 1752 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1753 - KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1753 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1754 1754 1755 1755 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 1756 1756 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); ··· 1800 1800 int ret; 1801 1801 1802 1802 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1803 - BIT(HDMI_COLORSPACE_RGB) | 1804 - BIT(HDMI_COLORSPACE_YUV422) | 1805 - BIT(HDMI_COLORSPACE_YUV444), 1803 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | 1804 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) | 1805 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444), 1806 1806 12, 1807 1807 &dummy_connector_hdmi_funcs, 1808 1808 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); ··· 1847 1847 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1848 1848 1849 1849 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 1850 - KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1850 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1851 1851 1852 1852 drm_modeset_drop_locks(&ctx); 1853 1853 drm_modeset_acquire_fini(&ctx); ··· 1871 1871 int ret; 1872 1872 1873 1873 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1874 - BIT(HDMI_COLORSPACE_RGB), 1874 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 1875 1875 12, 1876 1876 &dummy_connector_hdmi_funcs, 1877 1877 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); ··· 1896 1896 * But since the driver only supports RGB, we should fallback to 1897 1897 * a lower bpc with RGB. 1898 1898 */ 1899 - rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 1899 + rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1900 1900 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1901 1901 1902 - rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); 1902 + rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_YCBCR422); 1903 1903 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1904 1904 1905 1905 drm_modeset_acquire_init(&ctx, 0); ··· 1920 1920 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1921 1921 1922 1922 KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12); 1923 - KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1923 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1924 1924 1925 1925 drm_modeset_drop_locks(&ctx); 1926 1926 drm_modeset_acquire_fini(&ctx); ··· 1944 1944 int ret; 1945 1945 1946 1946 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1947 - BIT(HDMI_COLORSPACE_RGB) | 1948 - BIT(HDMI_COLORSPACE_YUV422) | 1949 - BIT(HDMI_COLORSPACE_YUV444), 1947 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | 1948 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) | 1949 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444), 1950 1950 12, 1951 1951 &dummy_connector_hdmi_funcs, 1952 1952 test_edid_hdmi_1080p_rgb_max_200mhz); ··· 1971 1971 * But since the display only supports RGB, we should fallback to 1972 1972 * a lower bpc with RGB. 1973 1973 */ 1974 - rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 1974 + rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1975 1975 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1976 1976 1977 - rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); 1977 + rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_YCBCR422); 1978 1978 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1979 1979 1980 1980 drm_modeset_acquire_init(&ctx, 0); ··· 1995 1995 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1996 1996 1997 1997 KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12); 1998 - KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1998 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444); 1999 1999 2000 2000 drm_modeset_drop_locks(&ctx); 2001 2001 drm_modeset_acquire_fini(&ctx); ··· 2020 2020 int ret; 2021 2021 2022 2022 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2023 - BIT(HDMI_COLORSPACE_RGB), 2023 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 2024 2024 8, 2025 2025 &dummy_connector_hdmi_funcs, 2026 2026 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz); ··· 2040 2040 * We're making sure that we have headroom on the TMDS character 2041 2041 * clock to actually use 12bpc. 2042 2042 */ 2043 - rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 2043 + rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444); 2044 2044 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 2045 2045 2046 2046 drm_modeset_acquire_init(&ctx, 0); ··· 2061 2061 KUNIT_ASSERT_NOT_NULL(test, conn_state); 2062 2062 2063 2063 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 2064 - KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 2064 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444); 2065 2065 2066 2066 drm_modeset_drop_locks(&ctx); 2067 2067 drm_modeset_acquire_fini(&ctx); ··· 2086 2086 int ret; 2087 2087 2088 2088 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2089 - BIT(HDMI_COLORSPACE_RGB) | 2090 - BIT(HDMI_COLORSPACE_YUV422) | 2091 - BIT(HDMI_COLORSPACE_YUV444), 2089 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | 2090 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) | 2091 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444), 2092 2092 12, 2093 2093 &dummy_connector_hdmi_funcs, 2094 2094 test_edid_hdmi_1080p_rgb_max_340mhz); ··· 2108 2108 * We're making sure that we have headroom on the TMDS character 2109 2109 * clock to actually use 12bpc. 2110 2110 */ 2111 - rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 2111 + rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444); 2112 2112 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 2113 2113 2114 2114 drm_modeset_acquire_init(&ctx, 0); ··· 2129 2129 KUNIT_ASSERT_NOT_NULL(test, conn_state); 2130 2130 2131 2131 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 2132 - KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 2132 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444); 2133 2133 2134 2134 drm_modeset_drop_locks(&ctx); 2135 2135 drm_modeset_acquire_fini(&ctx); ··· 2150 2150 int ret; 2151 2151 2152 2152 priv = drm_kunit_helper_connector_hdmi_init(test, 2153 - BIT(HDMI_COLORSPACE_RGB), 2153 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 2154 2154 8); 2155 2155 KUNIT_ASSERT_NOT_NULL(test, priv); 2156 2156 ··· 2255 2255 struct drm_connector *conn; 2256 2256 2257 2257 priv = drm_kunit_helper_connector_hdmi_init(test, 2258 - BIT(HDMI_COLORSPACE_RGB), 2258 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 2259 2259 8); 2260 2260 KUNIT_ASSERT_NOT_NULL(test, priv); 2261 2261 ··· 2277 2277 struct drm_connector *conn; 2278 2278 2279 2279 priv = drm_kunit_helper_connector_hdmi_init(test, 2280 - BIT(HDMI_COLORSPACE_RGB), 2280 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 2281 2281 8); 2282 2282 KUNIT_ASSERT_NOT_NULL(test, priv); 2283 2283 ··· 2301 2301 struct drm_connector *conn; 2302 2302 2303 2303 priv = drm_kunit_helper_connector_hdmi_init(test, 2304 - BIT(HDMI_COLORSPACE_RGB), 2304 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 2305 2305 10); 2306 2306 KUNIT_ASSERT_NOT_NULL(test, priv); 2307 2307 ··· 2325 2325 struct drm_connector *conn; 2326 2326 2327 2327 priv = drm_kunit_helper_connector_hdmi_init(test, 2328 - BIT(HDMI_COLORSPACE_RGB), 2328 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 2329 2329 12); 2330 2330 KUNIT_ASSERT_NOT_NULL(test, priv); 2331 2331 ··· 2347 2347 struct drm_connector *conn; 2348 2348 2349 2349 priv = drm_kunit_helper_connector_hdmi_init(test, 2350 - BIT(HDMI_COLORSPACE_RGB) | 2351 - BIT(HDMI_COLORSPACE_YUV422) | 2352 - BIT(HDMI_COLORSPACE_YUV444), 2350 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | 2351 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) | 2352 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444), 2353 2353 8); 2354 2354 KUNIT_ASSERT_NOT_NULL(test, priv); 2355 2355 ··· 2369 2369 struct drm_connector *conn; 2370 2370 2371 2371 priv = drm_kunit_helper_connector_hdmi_init(test, 2372 - BIT(HDMI_COLORSPACE_RGB) | 2373 - BIT(HDMI_COLORSPACE_YUV422) | 2374 - BIT(HDMI_COLORSPACE_YUV444), 2372 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | 2373 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) | 2374 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444), 2375 2375 12); 2376 2376 KUNIT_ASSERT_NOT_NULL(test, priv); 2377 2377 ··· 2407 2407 struct drm_display_mode *preferred; 2408 2408 2409 2409 priv = drm_kunit_helper_connector_hdmi_init(test, 2410 - BIT(HDMI_COLORSPACE_RGB), 2410 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 2411 2411 8); 2412 2412 KUNIT_ASSERT_NOT_NULL(test, priv); 2413 2413 ··· 2431 2431 struct drm_display_mode *preferred; 2432 2432 2433 2433 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2434 - BIT(HDMI_COLORSPACE_RGB), 2434 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 2435 2435 8, 2436 2436 &reject_100mhz_connector_hdmi_funcs, 2437 2437 test_edid_hdmi_1080p_rgb_max_200mhz); ··· 2463 2463 int ret; 2464 2464 2465 2465 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2466 - BIT(HDMI_COLORSPACE_RGB), 2466 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 2467 2467 8, 2468 2468 &reject_connector_hdmi_funcs, 2469 2469 no_edid); ··· 2493 2493 struct drm_display_mode *preferred; 2494 2494 2495 2495 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2496 - BIT(HDMI_COLORSPACE_RGB), 2496 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 2497 2497 8, 2498 2498 &dummy_connector_hdmi_funcs, 2499 2499 test_edid_hdmi_1080p_rgb_max_100mhz); ··· 2540 2540 int ret; 2541 2541 2542 2542 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2543 - BIT(HDMI_COLORSPACE_RGB), 2543 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 2544 2544 8, 2545 2545 &dummy_connector_hdmi_funcs, 2546 2546 test_edid_hdmi_1080p_rgb_max_200mhz); ··· 2643 2643 int ret; 2644 2644 2645 2645 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2646 - BIT(HDMI_COLORSPACE_RGB), 2646 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 2647 2647 8, 2648 2648 &reject_avi_infoframe_hdmi_funcs, 2649 2649 test_edid_hdmi_1080p_rgb_max_200mhz); ··· 2747 2747 int ret; 2748 2748 2749 2749 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2750 - BIT(HDMI_COLORSPACE_RGB), 2750 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 2751 2751 8, 2752 2752 &reject_hdr_infoframe_hdmi_funcs, 2753 2753 test_edid_hdmi_1080p_rgb_max_200mhz_hdr); ··· 2861 2861 int ret; 2862 2862 2863 2863 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2864 - BIT(HDMI_COLORSPACE_RGB), 2864 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 2865 2865 10, 2866 2866 &reject_hdr_infoframe_hdmi_funcs, 2867 2867 test_edid_hdmi_1080p_rgb_max_200mhz_hdr); ··· 2996 2996 int ret; 2997 2997 2998 2998 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2999 - BIT(HDMI_COLORSPACE_RGB), 2999 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), 3000 3000 8, 3001 3001 &reject_audio_infoframe_hdmi_funcs, 3002 3002 test_edid_hdmi_1080p_rgb_max_200mhz);
+124 -14
drivers/gpu/drm/tiny/hx8357d.c
··· 46 46 #define HX8357D_MADCTL_BGR 0x08 47 47 #define HX8357D_MADCTL_MH 0x04 48 48 49 - static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, 50 - struct drm_crtc_state *crtc_state, 51 - struct drm_plane_state *plane_state) 49 + struct hx8357d_device { 50 + struct mipi_dbi_dev dbidev; 51 + 52 + struct drm_plane plane; 53 + struct drm_crtc crtc; 54 + struct drm_encoder encoder; 55 + struct drm_connector connector; 56 + }; 57 + 58 + static struct hx8357d_device *to_hx8357d_device(struct drm_device *dev) 52 59 { 53 - struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); 60 + return container_of(drm_to_mipi_dbi_dev(dev), struct hx8357d_device, dbidev); 61 + } 62 + 63 + static const u32 hx8357d_plane_formats[] = { 64 + DRM_MIPI_DBI_PLANE_FORMATS, 65 + }; 66 + 67 + static const u64 hx8357d_plane_format_modifiers[] = { 68 + DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS, 69 + }; 70 + 71 + static const struct drm_plane_helper_funcs hx8357d_plane_helper_funcs = { 72 + DRM_MIPI_DBI_PLANE_HELPER_FUNCS, 73 + }; 74 + 75 + static const struct drm_plane_funcs hx8357d_plane_funcs = { 76 + DRM_MIPI_DBI_PLANE_FUNCS, 77 + .destroy = drm_plane_cleanup, 78 + }; 79 + 80 + static void hx8357d_crtc_helper_atomic_enable(struct drm_crtc *crtc, 81 + struct drm_atomic_state *state) 82 + { 83 + struct drm_device *drm = crtc->dev; 84 + struct hx8357d_device *hx8357d = to_hx8357d_device(drm); 85 + struct mipi_dbi_dev *dbidev = &hx8357d->dbidev; 54 86 struct mipi_dbi *dbi = &dbidev->dbi; 55 87 u8 addr_mode; 56 88 int ret, idx; 57 89 58 - if (!drm_dev_enter(pipe->crtc.dev, &idx)) 90 + if (!drm_dev_enter(drm, &idx)) 59 91 return; 60 92 61 93 DRM_DEBUG_KMS("\n"); ··· 209 177 break; 210 178 } 211 179 mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); 212 - mipi_dbi_enable_flush(dbidev, crtc_state, plane_state); 180 + 181 + backlight_enable(dbidev->backlight); 213 182 out_exit: 214 183 drm_dev_exit(idx); 215 184 } 216 185 217 - static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = { 218 - DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(yx240qv29_enable), 186 + static const struct drm_crtc_helper_funcs hx8357d_crtc_helper_funcs = { 187 + DRM_MIPI_DBI_CRTC_HELPER_FUNCS, 188 + .atomic_enable = hx8357d_crtc_helper_atomic_enable, 189 + }; 190 + 191 + static const struct drm_crtc_funcs hx8357d_crtc_funcs = { 192 + DRM_MIPI_DBI_CRTC_FUNCS, 193 + .destroy = drm_crtc_cleanup, 194 + }; 195 + 196 + static const struct drm_encoder_funcs hx8357d_encoder_funcs = { 197 + .destroy = drm_encoder_cleanup, 198 + }; 199 + 200 + static const struct drm_connector_helper_funcs hx8357d_connector_helper_funcs = { 201 + DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS, 202 + }; 203 + 204 + static const struct drm_connector_funcs hx8357d_connector_funcs = { 205 + DRM_MIPI_DBI_CONNECTOR_FUNCS, 206 + .destroy = drm_connector_cleanup, 207 + }; 208 + 209 + static const struct drm_mode_config_helper_funcs hx8357d_mode_config_helper_funcs = { 210 + DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS, 211 + }; 212 + 213 + static const struct drm_mode_config_funcs hx8357d_mode_config_funcs = { 214 + DRM_MIPI_DBI_MODE_CONFIG_FUNCS, 219 215 }; 220 216 221 217 static const struct drm_display_mode yx350hv15_mode = { ··· 279 219 static int hx8357d_probe(struct spi_device *spi) 280 220 { 281 221 struct device *dev = &spi->dev; 222 + struct hx8357d_device *hx8357d; 282 223 struct mipi_dbi_dev *dbidev; 283 224 struct drm_device *drm; 284 225 struct gpio_desc *dc; 226 + struct drm_plane *plane; 227 + struct drm_crtc *crtc; 228 + struct drm_encoder *encoder; 229 + struct drm_connector *connector; 285 230 u32 rotation = 0; 286 231 int ret; 287 232 288 - dbidev = devm_drm_dev_alloc(dev, &hx8357d_driver, 289 - struct mipi_dbi_dev, drm); 290 - if (IS_ERR(dbidev)) 291 - return PTR_ERR(dbidev); 292 - 233 + hx8357d = devm_drm_dev_alloc(dev, &hx8357d_driver, struct hx8357d_device, dbidev.drm); 234 + if (IS_ERR(hx8357d)) 235 + return PTR_ERR(hx8357d); 236 + dbidev = &hx8357d->dbidev; 293 237 drm = &dbidev->drm; 294 238 295 239 dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW); ··· 310 246 if (ret) 311 247 return ret; 312 248 313 - ret = mipi_dbi_dev_init(dbidev, &hx8357d_pipe_funcs, &yx350hv15_mode, rotation); 249 + ret = drm_mipi_dbi_dev_init(dbidev, &yx350hv15_mode, hx8357d_plane_formats[0], 250 + rotation, 0); 251 + if (ret) 252 + return ret; 253 + 254 + ret = drmm_mode_config_init(drm); 255 + if (ret) 256 + return ret; 257 + 258 + drm->mode_config.min_width = dbidev->mode.hdisplay; 259 + drm->mode_config.max_width = dbidev->mode.hdisplay; 260 + drm->mode_config.min_height = dbidev->mode.vdisplay; 261 + drm->mode_config.max_height = dbidev->mode.vdisplay; 262 + drm->mode_config.funcs = &hx8357d_mode_config_funcs; 263 + drm->mode_config.preferred_depth = 16; 264 + drm->mode_config.helper_private = &hx8357d_mode_config_helper_funcs; 265 + 266 + plane = &hx8357d->plane; 267 + ret = drm_universal_plane_init(drm, plane, 0, &hx8357d_plane_funcs, 268 + hx8357d_plane_formats, ARRAY_SIZE(hx8357d_plane_formats), 269 + hx8357d_plane_format_modifiers, 270 + DRM_PLANE_TYPE_PRIMARY, NULL); 271 + if (ret) 272 + return ret; 273 + drm_plane_helper_add(plane, &hx8357d_plane_helper_funcs); 274 + drm_plane_enable_fb_damage_clips(plane); 275 + 276 + crtc = &hx8357d->crtc; 277 + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &hx8357d_crtc_funcs, NULL); 278 + if (ret) 279 + return ret; 280 + drm_crtc_helper_add(crtc, &hx8357d_crtc_helper_funcs); 281 + 282 + encoder = &hx8357d->encoder; 283 + ret = drm_encoder_init(drm, encoder, &hx8357d_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); 284 + if (ret) 285 + return ret; 286 + encoder->possible_crtcs = drm_crtc_mask(crtc); 287 + 288 + connector = &hx8357d->connector; 289 + ret = drm_connector_init(drm, connector, &hx8357d_connector_funcs, 290 + DRM_MODE_CONNECTOR_SPI); 291 + if (ret) 292 + return ret; 293 + drm_connector_helper_add(connector, &hx8357d_connector_helper_funcs); 294 + 295 + ret = drm_connector_attach_encoder(connector, encoder); 314 296 if (ret) 315 297 return ret; 316 298
+124 -14
drivers/gpu/drm/tiny/ili9163.c
··· 35 35 #define ILI9163_MADCTL_MX BIT(6) 36 36 #define ILI9163_MADCTL_MY BIT(7) 37 37 38 - static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, 39 - struct drm_crtc_state *crtc_state, 40 - struct drm_plane_state *plane_state) 38 + struct ili9163_device { 39 + struct mipi_dbi_dev dbidev; 40 + 41 + struct drm_plane plane; 42 + struct drm_crtc crtc; 43 + struct drm_encoder encoder; 44 + struct drm_connector connector; 45 + }; 46 + 47 + static struct ili9163_device *to_ili9163_device(struct drm_device *dev) 41 48 { 42 - struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); 49 + return container_of(drm_to_mipi_dbi_dev(dev), struct ili9163_device, dbidev); 50 + } 51 + 52 + static const u32 ili9163_plane_formats[] = { 53 + DRM_MIPI_DBI_PLANE_FORMATS, 54 + }; 55 + 56 + static const u64 ili9163_plane_format_modifiers[] = { 57 + DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS, 58 + }; 59 + 60 + static const struct drm_plane_helper_funcs ili9163_plane_helper_funcs = { 61 + DRM_MIPI_DBI_PLANE_HELPER_FUNCS, 62 + }; 63 + 64 + static const struct drm_plane_funcs ili9163_plane_funcs = { 65 + DRM_MIPI_DBI_PLANE_FUNCS, 66 + .destroy = drm_plane_cleanup, 67 + }; 68 + 69 + static void ili9163_crtc_helper_atomic_enable(struct drm_crtc *crtc, 70 + struct drm_atomic_state *state) 71 + { 72 + struct drm_device *drm = crtc->dev; 73 + struct ili9163_device *ili9163 = to_ili9163_device(drm); 74 + struct mipi_dbi_dev *dbidev = &ili9163->dbidev; 43 75 struct mipi_dbi *dbi = &dbidev->dbi; 44 76 u8 addr_mode; 45 77 int ret, idx; 46 78 47 - if (!drm_dev_enter(pipe->crtc.dev, &idx)) 79 + if (!drm_dev_enter(drm, &idx)) 48 80 return; 49 81 50 82 DRM_DEBUG_KMS("\n"); ··· 128 96 } 129 97 addr_mode |= ILI9163_MADCTL_BGR; 130 98 mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); 131 - mipi_dbi_enable_flush(dbidev, crtc_state, plane_state); 99 + 100 + backlight_enable(dbidev->backlight); 132 101 out_exit: 133 102 drm_dev_exit(idx); 134 103 } 135 104 136 - static const struct drm_simple_display_pipe_funcs ili9163_pipe_funcs = { 137 - DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(yx240qv29_enable), 105 + static const struct drm_crtc_helper_funcs ili9163_crtc_helper_funcs = { 106 + DRM_MIPI_DBI_CRTC_HELPER_FUNCS, 107 + .atomic_enable = ili9163_crtc_helper_atomic_enable, 108 + }; 109 + 110 + static const struct drm_crtc_funcs ili9163_crtc_funcs = { 111 + DRM_MIPI_DBI_CRTC_FUNCS, 112 + .destroy = drm_crtc_cleanup, 113 + }; 114 + 115 + static const struct drm_encoder_funcs ili9163_encoder_funcs = { 116 + .destroy = drm_encoder_cleanup, 117 + }; 118 + 119 + static const struct drm_connector_helper_funcs ili9163_connector_helper_funcs = { 120 + DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS, 121 + }; 122 + 123 + static const struct drm_connector_funcs ili9163_connector_funcs = { 124 + DRM_MIPI_DBI_CONNECTOR_FUNCS, 125 + .destroy = drm_connector_cleanup, 126 + }; 127 + 128 + static const struct drm_mode_config_helper_funcs ili9163_mode_config_helper_funcs = { 129 + DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS, 130 + }; 131 + 132 + static const struct drm_mode_config_funcs ili9163_mode_config_funcs = { 133 + DRM_MIPI_DBI_MODE_CONFIG_FUNCS, 138 134 }; 139 135 140 136 static const struct drm_display_mode yx240qv29_mode = { ··· 198 138 static int ili9163_probe(struct spi_device *spi) 199 139 { 200 140 struct device *dev = &spi->dev; 141 + struct ili9163_device *ili9163; 201 142 struct mipi_dbi_dev *dbidev; 202 143 struct drm_device *drm; 203 144 struct mipi_dbi *dbi; 204 145 struct gpio_desc *dc; 146 + struct drm_plane *plane; 147 + struct drm_crtc *crtc; 148 + struct drm_encoder *encoder; 149 + struct drm_connector *connector; 205 150 u32 rotation = 0; 206 151 int ret; 207 152 208 - dbidev = devm_drm_dev_alloc(dev, &ili9163_driver, 209 - struct mipi_dbi_dev, drm); 210 - if (IS_ERR(dbidev)) 211 - return PTR_ERR(dbidev); 212 - 153 + ili9163 = devm_drm_dev_alloc(dev, &ili9163_driver, struct ili9163_device, dbidev.drm); 154 + if (IS_ERR(ili9163)) 155 + return PTR_ERR(ili9163); 156 + dbidev = &ili9163->dbidev; 213 157 dbi = &dbidev->dbi; 214 158 drm = &dbidev->drm; 215 159 ··· 241 177 if (ret) 242 178 return ret; 243 179 244 - ret = mipi_dbi_dev_init(dbidev, &ili9163_pipe_funcs, &yx240qv29_mode, rotation); 180 + ret = drm_mipi_dbi_dev_init(dbidev, &yx240qv29_mode, ili9163_plane_formats[0], 181 + rotation, 0); 182 + if (ret) 183 + return ret; 184 + 185 + ret = drmm_mode_config_init(drm); 186 + if (ret) 187 + return ret; 188 + 189 + drm->mode_config.min_width = dbidev->mode.hdisplay; 190 + drm->mode_config.max_width = dbidev->mode.hdisplay; 191 + drm->mode_config.min_height = dbidev->mode.vdisplay; 192 + drm->mode_config.max_height = dbidev->mode.vdisplay; 193 + drm->mode_config.funcs = &ili9163_mode_config_funcs; 194 + drm->mode_config.preferred_depth = 16; 195 + drm->mode_config.helper_private = &ili9163_mode_config_helper_funcs; 196 + 197 + plane = &ili9163->plane; 198 + ret = drm_universal_plane_init(drm, plane, 0, &ili9163_plane_funcs, 199 + ili9163_plane_formats, ARRAY_SIZE(ili9163_plane_formats), 200 + ili9163_plane_format_modifiers, 201 + DRM_PLANE_TYPE_PRIMARY, NULL); 202 + if (ret) 203 + return ret; 204 + drm_plane_helper_add(plane, &ili9163_plane_helper_funcs); 205 + drm_plane_enable_fb_damage_clips(plane); 206 + 207 + crtc = &ili9163->crtc; 208 + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &ili9163_crtc_funcs, NULL); 209 + if (ret) 210 + return ret; 211 + drm_crtc_helper_add(crtc, &ili9163_crtc_helper_funcs); 212 + 213 + encoder = &ili9163->encoder; 214 + ret = drm_encoder_init(drm, encoder, &ili9163_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); 215 + if (ret) 216 + return ret; 217 + encoder->possible_crtcs = drm_crtc_mask(crtc); 218 + 219 + connector = &ili9163->connector; 220 + ret = drm_connector_init(drm, connector, &ili9163_connector_funcs, 221 + DRM_MODE_CONNECTOR_SPI); 222 + if (ret) 223 + return ret; 224 + drm_connector_helper_add(connector, &ili9163_connector_helper_funcs); 225 + 226 + ret = drm_connector_attach_encoder(connector, encoder); 245 227 if (ret) 246 228 return ret; 247 229
+145 -47
drivers/gpu/drm/tiny/ili9225.c
··· 17 17 #include <video/mipi_display.h> 18 18 19 19 #include <drm/clients/drm_client_setup.h> 20 + #include <drm/drm_atomic.h> 20 21 #include <drm/drm_atomic_helper.h> 21 22 #include <drm/drm_damage_helper.h> 22 23 #include <drm/drm_drv.h> ··· 25 24 #include <drm/drm_fbdev_dma.h> 26 25 #include <drm/drm_fourcc.h> 27 26 #include <drm/drm_framebuffer.h> 28 - #include <drm/drm_gem_atomic_helper.h> 29 27 #include <drm/drm_gem_dma_helper.h> 30 - #include <drm/drm_gem_framebuffer_helper.h> 31 28 #include <drm/drm_managed.h> 32 29 #include <drm/drm_mipi_dbi.h> 33 30 #include <drm/drm_print.h> ··· 70 71 #define ILI9225_GAMMA_CONTROL_8 0x57 71 72 #define ILI9225_GAMMA_CONTROL_9 0x58 72 73 #define ILI9225_GAMMA_CONTROL_10 0x59 74 + 75 + struct ili9225_device { 76 + struct mipi_dbi_dev dbidev; 77 + 78 + struct drm_plane plane; 79 + struct drm_crtc crtc; 80 + struct drm_encoder encoder; 81 + struct drm_connector connector; 82 + }; 83 + 84 + static struct ili9225_device *to_ili9225_device(struct drm_device *dev) 85 + { 86 + return container_of(drm_to_mipi_dbi_dev(dev), struct ili9225_device, dbidev); 87 + } 73 88 74 89 static inline int ili9225_command(struct mipi_dbi *dbi, u8 cmd, u16 data) 75 90 { ··· 170 157 dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret); 171 158 } 172 159 173 - static void ili9225_pipe_update(struct drm_simple_display_pipe *pipe, 174 - struct drm_plane_state *old_state) 160 + static const u32 ili9225_plane_formats[] = { 161 + DRM_MIPI_DBI_PLANE_FORMATS, 162 + }; 163 + 164 + static const u64 ili9225_plane_format_modifiers[] = { 165 + DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS, 166 + }; 167 + 168 + static void ili9225_plane_helper_atomic_update(struct drm_plane *plane, 169 + struct drm_atomic_state *state) 175 170 { 176 - struct drm_plane_state *state = pipe->plane.state; 177 - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state); 178 - struct drm_framebuffer *fb = state->fb; 171 + struct drm_device *drm = plane->dev; 172 + struct drm_plane_state *plane_state = plane->state; 173 + struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 174 + struct drm_framebuffer *fb = plane_state->fb; 175 + struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); 179 176 struct drm_rect rect; 180 177 int idx; 181 178 182 - if (!pipe->crtc.state->active) 179 + if (!plane_state->fb) 183 180 return; 184 181 185 - if (!drm_dev_enter(fb->dev, &idx)) 182 + if (!drm_dev_enter(drm, &idx)) 186 183 return; 187 184 188 - if (drm_atomic_helper_damage_merged(old_state, state, &rect)) 185 + if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &rect)) 189 186 ili9225_fb_dirty(&shadow_plane_state->data[0], fb, &rect, 190 187 &shadow_plane_state->fmtcnv_state); 191 188 192 189 drm_dev_exit(idx); 193 190 } 194 191 195 - static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, 196 - struct drm_crtc_state *crtc_state, 197 - struct drm_plane_state *plane_state) 192 + static const struct drm_plane_helper_funcs ili9225_plane_helper_funcs = { 193 + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, 194 + .atomic_check = drm_mipi_dbi_plane_helper_atomic_check, 195 + .atomic_update = ili9225_plane_helper_atomic_update, 196 + }; 197 + 198 + static const struct drm_plane_funcs ili9225_plane_funcs = { 199 + DRM_MIPI_DBI_PLANE_FUNCS, 200 + .destroy = drm_plane_cleanup, 201 + }; 202 + 203 + static void ili9225_crtc_helper_atomic_enable(struct drm_crtc *crtc, 204 + struct drm_atomic_state *state) 198 205 { 199 - struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); 200 - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 201 - struct drm_framebuffer *fb = plane_state->fb; 202 - struct device *dev = pipe->crtc.dev->dev; 206 + struct drm_device *drm = crtc->dev; 207 + struct ili9225_device *ili9225 = to_ili9225_device(drm); 208 + struct mipi_dbi_dev *dbidev = &ili9225->dbidev; 209 + struct device *dev = drm->dev; 203 210 struct mipi_dbi *dbi = &dbidev->dbi; 204 - struct drm_rect rect = { 205 - .x1 = 0, 206 - .x2 = fb->width, 207 - .y1 = 0, 208 - .y2 = fb->height, 209 - }; 210 211 int ret, idx; 211 212 u8 am_id; 212 213 213 - if (!drm_dev_enter(pipe->crtc.dev, &idx)) 214 + if (!drm_dev_enter(drm, &idx)) 214 215 return; 215 216 216 217 DRM_DEBUG_KMS("\n"); ··· 311 284 312 285 ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x1017); 313 286 314 - ili9225_fb_dirty(&shadow_plane_state->data[0], fb, &rect, 315 - &shadow_plane_state->fmtcnv_state); 316 - 317 287 out_exit: 318 288 drm_dev_exit(idx); 319 289 } 320 290 321 - static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe) 291 + static void ili9225_crtc_helper_atomic_disable(struct drm_crtc *crtc, 292 + struct drm_atomic_state *state) 322 293 { 323 - struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); 294 + struct drm_device *drm = crtc->dev; 295 + struct ili9225_device *ili9225 = to_ili9225_device(drm); 296 + struct mipi_dbi_dev *dbidev = &ili9225->dbidev; 324 297 struct mipi_dbi *dbi = &dbidev->dbi; 325 298 326 299 DRM_DEBUG_KMS("\n"); ··· 338 311 msleep(50); 339 312 ili9225_command(dbi, ILI9225_POWER_CONTROL_1, 0x0a02); 340 313 } 314 + 315 + static const struct drm_crtc_helper_funcs ili9225_crtc_helper_funcs = { 316 + .mode_valid = drm_mipi_dbi_crtc_helper_mode_valid, 317 + .atomic_check = drm_mipi_dbi_crtc_helper_atomic_check, 318 + .atomic_enable = ili9225_crtc_helper_atomic_enable, 319 + .atomic_disable = ili9225_crtc_helper_atomic_disable, 320 + }; 321 + 322 + static const struct drm_crtc_funcs ili9225_crtc_funcs = { 323 + DRM_MIPI_DBI_CRTC_FUNCS, 324 + .destroy = drm_crtc_cleanup, 325 + }; 326 + 327 + static const struct drm_encoder_funcs ili9225_encoder_funcs = { 328 + .destroy = drm_encoder_cleanup, 329 + }; 330 + 331 + static const struct drm_connector_helper_funcs ili9225_connector_helper_funcs = { 332 + DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS, 333 + }; 334 + 335 + static const struct drm_connector_funcs ili9225_connector_funcs = { 336 + DRM_MIPI_DBI_CONNECTOR_FUNCS, 337 + .destroy = drm_connector_cleanup, 338 + }; 339 + 340 + static const struct drm_mode_config_helper_funcs ili9225_mode_config_helper_funcs = { 341 + DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS, 342 + }; 343 + 344 + static const struct drm_mode_config_funcs ili9225_mode_config_funcs = { 345 + DRM_MIPI_DBI_MODE_CONFIG_FUNCS, 346 + }; 341 347 342 348 static int ili9225_dbi_command(struct mipi_dbi *dbi, u8 *cmd, u8 *par, 343 349 size_t num) ··· 399 339 400 340 return ret; 401 341 } 402 - 403 - static const struct drm_simple_display_pipe_funcs ili9225_pipe_funcs = { 404 - .mode_valid = mipi_dbi_pipe_mode_valid, 405 - .enable = ili9225_pipe_enable, 406 - .disable = ili9225_pipe_disable, 407 - .update = ili9225_pipe_update, 408 - .begin_fb_access = mipi_dbi_pipe_begin_fb_access, 409 - .end_fb_access = mipi_dbi_pipe_end_fb_access, 410 - .reset_plane = mipi_dbi_pipe_reset_plane, 411 - .duplicate_plane_state = mipi_dbi_pipe_duplicate_plane_state, 412 - .destroy_plane_state = mipi_dbi_pipe_destroy_plane_state, 413 - }; 414 342 415 343 static const struct drm_display_mode ili9225_mode = { 416 344 DRM_SIMPLE_MODE(176, 220, 35, 44), ··· 432 384 static int ili9225_probe(struct spi_device *spi) 433 385 { 434 386 struct device *dev = &spi->dev; 387 + struct ili9225_device *ili9225; 435 388 struct mipi_dbi_dev *dbidev; 436 389 struct drm_device *drm; 437 390 struct mipi_dbi *dbi; 438 391 struct gpio_desc *rs; 392 + struct drm_plane *plane; 393 + struct drm_crtc *crtc; 394 + struct drm_encoder *encoder; 395 + struct drm_connector *connector; 439 396 u32 rotation = 0; 440 397 int ret; 441 398 442 - dbidev = devm_drm_dev_alloc(dev, &ili9225_driver, 443 - struct mipi_dbi_dev, drm); 444 - if (IS_ERR(dbidev)) 445 - return PTR_ERR(dbidev); 446 - 399 + ili9225 = devm_drm_dev_alloc(dev, &ili9225_driver, struct ili9225_device, dbidev.drm); 400 + if (IS_ERR(ili9225)) 401 + return PTR_ERR(ili9225); 402 + dbidev = &ili9225->dbidev; 447 403 dbi = &dbidev->dbi; 448 404 drm = &dbidev->drm; 449 405 ··· 468 416 /* override the command function set in mipi_dbi_spi_init() */ 469 417 dbi->command = ili9225_dbi_command; 470 418 471 - ret = mipi_dbi_dev_init(dbidev, &ili9225_pipe_funcs, &ili9225_mode, rotation); 419 + ret = drm_mipi_dbi_dev_init(dbidev, &ili9225_mode, ili9225_plane_formats[0], 420 + rotation, 0); 421 + if (ret) 422 + return ret; 423 + 424 + ret = drmm_mode_config_init(drm); 425 + if (ret) 426 + return ret; 427 + 428 + drm->mode_config.min_width = dbidev->mode.hdisplay; 429 + drm->mode_config.max_width = dbidev->mode.hdisplay; 430 + drm->mode_config.min_height = dbidev->mode.vdisplay; 431 + drm->mode_config.max_height = dbidev->mode.vdisplay; 432 + drm->mode_config.funcs = &ili9225_mode_config_funcs; 433 + drm->mode_config.preferred_depth = 16; 434 + drm->mode_config.helper_private = &ili9225_mode_config_helper_funcs; 435 + 436 + plane = &ili9225->plane; 437 + ret = drm_universal_plane_init(drm, plane, 0, &ili9225_plane_funcs, 438 + ili9225_plane_formats, ARRAY_SIZE(ili9225_plane_formats), 439 + ili9225_plane_format_modifiers, 440 + DRM_PLANE_TYPE_PRIMARY, NULL); 441 + if (ret) 442 + return ret; 443 + drm_plane_helper_add(plane, &ili9225_plane_helper_funcs); 444 + drm_plane_enable_fb_damage_clips(plane); 445 + 446 + crtc = &ili9225->crtc; 447 + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &ili9225_crtc_funcs, NULL); 448 + if (ret) 449 + return ret; 450 + drm_crtc_helper_add(crtc, &ili9225_crtc_helper_funcs); 451 + 452 + encoder = &ili9225->encoder; 453 + ret = drm_encoder_init(drm, encoder, &ili9225_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); 454 + if (ret) 455 + return ret; 456 + encoder->possible_crtcs = drm_crtc_mask(crtc); 457 + 458 + connector = &ili9225->connector; 459 + ret = drm_connector_init(drm, connector, &ili9225_connector_funcs, 460 + DRM_MODE_CONNECTOR_SPI); 461 + if (ret) 462 + return ret; 463 + drm_connector_helper_add(connector, &ili9225_connector_helper_funcs); 464 + 465 + ret = drm_connector_attach_encoder(connector, encoder); 472 466 if (ret) 473 467 return ret; 474 468
+124 -14
drivers/gpu/drm/tiny/ili9341.c
··· 52 52 #define ILI9341_MADCTL_MX BIT(6) 53 53 #define ILI9341_MADCTL_MY BIT(7) 54 54 55 - static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, 56 - struct drm_crtc_state *crtc_state, 57 - struct drm_plane_state *plane_state) 55 + struct ili9341_device { 56 + struct mipi_dbi_dev dbidev; 57 + 58 + struct drm_plane plane; 59 + struct drm_crtc crtc; 60 + struct drm_encoder encoder; 61 + struct drm_connector connector; 62 + }; 63 + 64 + static struct ili9341_device *to_ili9341_device(struct drm_device *dev) 58 65 { 59 - struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); 66 + return container_of(drm_to_mipi_dbi_dev(dev), struct ili9341_device, dbidev); 67 + } 68 + 69 + static const u32 ili9341_plane_formats[] = { 70 + DRM_MIPI_DBI_PLANE_FORMATS, 71 + }; 72 + 73 + static const u64 ili9341_plane_format_modifiers[] = { 74 + DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS, 75 + }; 76 + 77 + static const struct drm_plane_helper_funcs ili9341_plane_helper_funcs = { 78 + DRM_MIPI_DBI_PLANE_HELPER_FUNCS, 79 + }; 80 + 81 + static const struct drm_plane_funcs ili9341_plane_funcs = { 82 + DRM_MIPI_DBI_PLANE_FUNCS, 83 + .destroy = drm_plane_cleanup, 84 + }; 85 + 86 + static void ili9341_crtc_helper_atomic_enable(struct drm_crtc *crtc, 87 + struct drm_atomic_state *state) 88 + { 89 + struct drm_device *drm = crtc->dev; 90 + struct ili9341_device *ili9341 = to_ili9341_device(drm); 91 + struct mipi_dbi_dev *dbidev = &ili9341->dbidev; 60 92 struct mipi_dbi *dbi = &dbidev->dbi; 61 93 u8 addr_mode; 62 94 int ret, idx; 63 95 64 - if (!drm_dev_enter(pipe->crtc.dev, &idx)) 96 + if (!drm_dev_enter(drm, &idx)) 65 97 return; 66 98 67 99 DRM_DEBUG_KMS("\n"); ··· 165 133 } 166 134 addr_mode |= ILI9341_MADCTL_BGR; 167 135 mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); 168 - mipi_dbi_enable_flush(dbidev, crtc_state, plane_state); 136 + 137 + backlight_enable(dbidev->backlight); 169 138 out_exit: 170 139 drm_dev_exit(idx); 171 140 } 172 141 173 - static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = { 174 - DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(yx240qv29_enable), 142 + static const struct drm_crtc_helper_funcs ili9341_crtc_helper_funcs = { 143 + DRM_MIPI_DBI_CRTC_HELPER_FUNCS, 144 + .atomic_enable = ili9341_crtc_helper_atomic_enable, 145 + }; 146 + 147 + static const struct drm_crtc_funcs ili9341_crtc_funcs = { 148 + DRM_MIPI_DBI_CRTC_FUNCS, 149 + .destroy = drm_crtc_cleanup, 150 + }; 151 + 152 + static const struct drm_encoder_funcs ili9341_encoder_funcs = { 153 + .destroy = drm_encoder_cleanup, 154 + }; 155 + 156 + static const struct drm_connector_helper_funcs ili9341_connector_helper_funcs = { 157 + DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS, 158 + }; 159 + 160 + static const struct drm_connector_funcs ili9341_connector_funcs = { 161 + DRM_MIPI_DBI_CONNECTOR_FUNCS, 162 + .destroy = drm_connector_cleanup, 163 + }; 164 + 165 + static const struct drm_mode_config_helper_funcs ili9341_mode_config_helper_funcs = { 166 + DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS, 167 + }; 168 + 169 + static const struct drm_mode_config_funcs ili9341_mode_config_funcs = { 170 + DRM_MIPI_DBI_MODE_CONFIG_FUNCS, 175 171 }; 176 172 177 173 static const struct drm_display_mode yx240qv29_mode = { ··· 235 175 static int ili9341_probe(struct spi_device *spi) 236 176 { 237 177 struct device *dev = &spi->dev; 178 + struct ili9341_device *ili9341; 238 179 struct mipi_dbi_dev *dbidev; 239 180 struct drm_device *drm; 240 181 struct mipi_dbi *dbi; 241 182 struct gpio_desc *dc; 183 + struct drm_plane *plane; 184 + struct drm_crtc *crtc; 185 + struct drm_encoder *encoder; 186 + struct drm_connector *connector; 242 187 u32 rotation = 0; 243 188 int ret; 244 189 245 - dbidev = devm_drm_dev_alloc(dev, &ili9341_driver, 246 - struct mipi_dbi_dev, drm); 247 - if (IS_ERR(dbidev)) 248 - return PTR_ERR(dbidev); 249 - 190 + ili9341 = devm_drm_dev_alloc(dev, &ili9341_driver, struct ili9341_device, dbidev.drm); 191 + if (IS_ERR(ili9341)) 192 + return PTR_ERR(ili9341); 193 + dbidev = &ili9341->dbidev; 250 194 dbi = &dbidev->dbi; 251 195 drm = &dbidev->drm; 252 196 ··· 272 208 if (ret) 273 209 return ret; 274 210 275 - ret = mipi_dbi_dev_init(dbidev, &ili9341_pipe_funcs, &yx240qv29_mode, rotation); 211 + ret = drm_mipi_dbi_dev_init(dbidev, &yx240qv29_mode, ili9341_plane_formats[0], 212 + rotation, 0); 213 + if (ret) 214 + return ret; 215 + 216 + ret = drmm_mode_config_init(drm); 217 + if (ret) 218 + return ret; 219 + 220 + drm->mode_config.min_width = dbidev->mode.hdisplay; 221 + drm->mode_config.max_width = dbidev->mode.hdisplay; 222 + drm->mode_config.min_height = dbidev->mode.vdisplay; 223 + drm->mode_config.max_height = dbidev->mode.vdisplay; 224 + drm->mode_config.funcs = &ili9341_mode_config_funcs; 225 + drm->mode_config.preferred_depth = 16; 226 + drm->mode_config.helper_private = &ili9341_mode_config_helper_funcs; 227 + 228 + plane = &ili9341->plane; 229 + ret = drm_universal_plane_init(drm, plane, 0, &ili9341_plane_funcs, 230 + ili9341_plane_formats, ARRAY_SIZE(ili9341_plane_formats), 231 + ili9341_plane_format_modifiers, 232 + DRM_PLANE_TYPE_PRIMARY, NULL); 233 + if (ret) 234 + return ret; 235 + drm_plane_helper_add(plane, &ili9341_plane_helper_funcs); 236 + drm_plane_enable_fb_damage_clips(plane); 237 + 238 + crtc = &ili9341->crtc; 239 + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &ili9341_crtc_funcs, NULL); 240 + if (ret) 241 + return ret; 242 + drm_crtc_helper_add(crtc, &ili9341_crtc_helper_funcs); 243 + 244 + encoder = &ili9341->encoder; 245 + ret = drm_encoder_init(drm, encoder, &ili9341_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); 246 + if (ret) 247 + return ret; 248 + encoder->possible_crtcs = drm_crtc_mask(crtc); 249 + 250 + connector = &ili9341->connector; 251 + ret = drm_connector_init(drm, connector, &ili9341_connector_funcs, 252 + DRM_MODE_CONNECTOR_SPI); 253 + if (ret) 254 + return ret; 255 + drm_connector_helper_add(connector, &ili9341_connector_helper_funcs); 256 + 257 + ret = drm_connector_attach_encoder(connector, encoder); 276 258 if (ret) 277 259 return ret; 278 260
+124 -15
drivers/gpu/drm/tiny/ili9486.c
··· 36 36 #define ILI9486_MADCTL_MX BIT(6) 37 37 #define ILI9486_MADCTL_MY BIT(7) 38 38 39 + struct ili9486_device { 40 + struct mipi_dbi_dev dbidev; 41 + 42 + struct drm_plane plane; 43 + struct drm_crtc crtc; 44 + struct drm_encoder encoder; 45 + struct drm_connector connector; 46 + }; 47 + 48 + static struct ili9486_device *to_ili9486_device(struct drm_device *dev) 49 + { 50 + return container_of(drm_to_mipi_dbi_dev(dev), struct ili9486_device, dbidev); 51 + } 52 + 39 53 /* 40 54 * The PiScreen/waveshare rpi-lcd-35 has a SPI to 16-bit parallel bus converter 41 55 * in front of the display controller. This means that 8-bit values have to be ··· 108 94 return ret; 109 95 } 110 96 111 - static void waveshare_enable(struct drm_simple_display_pipe *pipe, 112 - struct drm_crtc_state *crtc_state, 113 - struct drm_plane_state *plane_state) 97 + static const u32 ili9486_plane_formats[] = { 98 + DRM_MIPI_DBI_PLANE_FORMATS, 99 + }; 100 + 101 + static const u64 ili9486_plane_format_modifiers[] = { 102 + DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS, 103 + }; 104 + 105 + static const struct drm_plane_helper_funcs ili9486_plane_helper_funcs = { 106 + DRM_MIPI_DBI_PLANE_HELPER_FUNCS, 107 + }; 108 + 109 + static const struct drm_plane_funcs ili9486_plane_funcs = { 110 + DRM_MIPI_DBI_PLANE_FUNCS, 111 + .destroy = drm_plane_cleanup, 112 + }; 113 + 114 + static void ili9486_crtc_helper_atomic_enable(struct drm_crtc *crtc, 115 + struct drm_atomic_state *state) 114 116 { 115 - struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); 117 + struct drm_device *drm = crtc->dev; 118 + struct ili9486_device *ili9486 = to_ili9486_device(drm); 119 + struct mipi_dbi_dev *dbidev = &ili9486->dbidev; 116 120 struct mipi_dbi *dbi = &dbidev->dbi; 117 121 u8 addr_mode; 118 122 int ret, idx; 119 123 120 - if (!drm_dev_enter(pipe->crtc.dev, &idx)) 124 + if (!drm_dev_enter(drm, &idx)) 121 125 return; 122 126 123 127 DRM_DEBUG_KMS("\n"); ··· 187 155 } 188 156 addr_mode |= ILI9486_MADCTL_BGR; 189 157 mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); 190 - mipi_dbi_enable_flush(dbidev, crtc_state, plane_state); 158 + 159 + backlight_enable(dbidev->backlight); 191 160 out_exit: 192 161 drm_dev_exit(idx); 193 162 } 194 163 195 - static const struct drm_simple_display_pipe_funcs waveshare_pipe_funcs = { 196 - DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(waveshare_enable), 164 + static const struct drm_crtc_helper_funcs ili9486_crtc_helper_funcs = { 165 + DRM_MIPI_DBI_CRTC_HELPER_FUNCS, 166 + .atomic_enable = ili9486_crtc_helper_atomic_enable, 167 + }; 168 + 169 + static const struct drm_crtc_funcs ili9486_crtc_funcs = { 170 + DRM_MIPI_DBI_CRTC_FUNCS, 171 + .destroy = drm_crtc_cleanup, 172 + }; 173 + 174 + static const struct drm_encoder_funcs ili9486_encoder_funcs = { 175 + .destroy = drm_encoder_cleanup, 176 + }; 177 + 178 + static const struct drm_connector_helper_funcs ili9486_connector_helper_funcs = { 179 + DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS, 180 + }; 181 + 182 + static const struct drm_connector_funcs ili9486_connector_funcs = { 183 + DRM_MIPI_DBI_CONNECTOR_FUNCS, 184 + .destroy = drm_connector_cleanup, 185 + }; 186 + 187 + static const struct drm_mode_config_helper_funcs ili9486_mode_config_helper_funcs = { 188 + DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS, 189 + }; 190 + 191 + static const struct drm_mode_config_funcs ili9486_mode_config_funcs = { 192 + DRM_MIPI_DBI_MODE_CONFIG_FUNCS, 197 193 }; 198 194 199 195 static const struct drm_display_mode waveshare_mode = { ··· 260 200 static int ili9486_probe(struct spi_device *spi) 261 201 { 262 202 struct device *dev = &spi->dev; 203 + struct ili9486_device *ili9486; 263 204 struct mipi_dbi_dev *dbidev; 264 205 struct drm_device *drm; 265 206 struct mipi_dbi *dbi; 266 207 struct gpio_desc *dc; 208 + struct drm_plane *plane; 209 + struct drm_crtc *crtc; 210 + struct drm_encoder *encoder; 211 + struct drm_connector *connector; 267 212 u32 rotation = 0; 268 213 int ret; 269 214 270 - dbidev = devm_drm_dev_alloc(dev, &ili9486_driver, 271 - struct mipi_dbi_dev, drm); 272 - if (IS_ERR(dbidev)) 273 - return PTR_ERR(dbidev); 274 - 215 + ili9486 = devm_drm_dev_alloc(dev, &ili9486_driver, struct ili9486_device, dbidev.drm); 216 + if (IS_ERR(ili9486)) 217 + return PTR_ERR(ili9486); 218 + dbidev = &ili9486->dbidev; 275 219 dbi = &dbidev->dbi; 276 220 drm = &dbidev->drm; 277 221 ··· 300 236 dbi->command = waveshare_command; 301 237 dbi->read_commands = NULL; 302 238 303 - ret = mipi_dbi_dev_init(dbidev, &waveshare_pipe_funcs, 304 - &waveshare_mode, rotation); 239 + ret = drm_mipi_dbi_dev_init(dbidev, &waveshare_mode, ili9486_plane_formats[0], 240 + rotation, 0); 241 + if (ret) 242 + return ret; 243 + 244 + ret = drmm_mode_config_init(drm); 245 + if (ret) 246 + return ret; 247 + 248 + drm->mode_config.min_width = dbidev->mode.hdisplay; 249 + drm->mode_config.max_width = dbidev->mode.hdisplay; 250 + drm->mode_config.min_height = dbidev->mode.vdisplay; 251 + drm->mode_config.max_height = dbidev->mode.vdisplay; 252 + drm->mode_config.funcs = &ili9486_mode_config_funcs; 253 + drm->mode_config.preferred_depth = 16; 254 + drm->mode_config.helper_private = &ili9486_mode_config_helper_funcs; 255 + 256 + plane = &ili9486->plane; 257 + ret = drm_universal_plane_init(drm, plane, 0, &ili9486_plane_funcs, 258 + ili9486_plane_formats, ARRAY_SIZE(ili9486_plane_formats), 259 + ili9486_plane_format_modifiers, 260 + DRM_PLANE_TYPE_PRIMARY, NULL); 261 + if (ret) 262 + return ret; 263 + drm_plane_helper_add(plane, &ili9486_plane_helper_funcs); 264 + drm_plane_enable_fb_damage_clips(plane); 265 + 266 + crtc = &ili9486->crtc; 267 + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &ili9486_crtc_funcs, NULL); 268 + if (ret) 269 + return ret; 270 + drm_crtc_helper_add(crtc, &ili9486_crtc_helper_funcs); 271 + 272 + encoder = &ili9486->encoder; 273 + ret = drm_encoder_init(drm, encoder, &ili9486_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); 274 + if (ret) 275 + return ret; 276 + encoder->possible_crtcs = drm_crtc_mask(crtc); 277 + 278 + connector = &ili9486->connector; 279 + ret = drm_connector_init(drm, connector, &ili9486_connector_funcs, 280 + DRM_MODE_CONNECTOR_SPI); 281 + if (ret) 282 + return ret; 283 + drm_connector_helper_add(connector, &ili9486_connector_helper_funcs); 284 + 285 + ret = drm_connector_attach_encoder(connector, encoder); 305 286 if (ret) 306 287 return ret; 307 288
+124 -14
drivers/gpu/drm/tiny/mi0283qt.c
··· 50 50 #define ILI9341_MADCTL_MX BIT(6) 51 51 #define ILI9341_MADCTL_MY BIT(7) 52 52 53 - static void mi0283qt_enable(struct drm_simple_display_pipe *pipe, 54 - struct drm_crtc_state *crtc_state, 55 - struct drm_plane_state *plane_state) 53 + struct mi0283qt_device { 54 + struct mipi_dbi_dev dbidev; 55 + 56 + struct drm_plane plane; 57 + struct drm_crtc crtc; 58 + struct drm_encoder encoder; 59 + struct drm_connector connector; 60 + }; 61 + 62 + static struct mi0283qt_device *to_mi0283qt_device(struct drm_device *dev) 56 63 { 57 - struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); 64 + return container_of(drm_to_mipi_dbi_dev(dev), struct mi0283qt_device, dbidev); 65 + } 66 + 67 + static const u32 mi0283qt_plane_formats[] = { 68 + DRM_MIPI_DBI_PLANE_FORMATS, 69 + }; 70 + 71 + static const u64 mi0283qt_plane_format_modifiers[] = { 72 + DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS, 73 + }; 74 + 75 + static const struct drm_plane_helper_funcs mi0283qt_plane_helper_funcs = { 76 + DRM_MIPI_DBI_PLANE_HELPER_FUNCS, 77 + }; 78 + 79 + static const struct drm_plane_funcs mi0283qt_plane_funcs = { 80 + DRM_MIPI_DBI_PLANE_FUNCS, 81 + .destroy = drm_plane_cleanup, 82 + }; 83 + 84 + static void mi0283qt_crtc_helper_atomic_enable(struct drm_crtc *crtc, 85 + struct drm_atomic_state *state) 86 + { 87 + struct drm_device *drm = crtc->dev; 88 + struct mi0283qt_device *mi0283qt = to_mi0283qt_device(drm); 89 + struct mipi_dbi_dev *dbidev = &mi0283qt->dbidev; 58 90 struct mipi_dbi *dbi = &dbidev->dbi; 59 91 u8 addr_mode; 60 92 int ret, idx; 61 93 62 - if (!drm_dev_enter(pipe->crtc.dev, &idx)) 94 + if (!drm_dev_enter(drm, &idx)) 63 95 return; 64 96 65 97 DRM_DEBUG_KMS("\n"); ··· 169 137 } 170 138 addr_mode |= ILI9341_MADCTL_BGR; 171 139 mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); 172 - mipi_dbi_enable_flush(dbidev, crtc_state, plane_state); 140 + 141 + backlight_enable(dbidev->backlight); 173 142 out_exit: 174 143 drm_dev_exit(idx); 175 144 } 176 145 177 - static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = { 178 - DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(mi0283qt_enable), 146 + static const struct drm_crtc_helper_funcs mi0283qt_crtc_helper_funcs = { 147 + DRM_MIPI_DBI_CRTC_HELPER_FUNCS, 148 + .atomic_enable = mi0283qt_crtc_helper_atomic_enable, 149 + }; 150 + 151 + static const struct drm_crtc_funcs mi0283qt_crtc_funcs = { 152 + DRM_MIPI_DBI_CRTC_FUNCS, 153 + .destroy = drm_crtc_cleanup, 154 + }; 155 + 156 + static const struct drm_encoder_funcs mi0283qt_encoder_funcs = { 157 + .destroy = drm_encoder_cleanup, 158 + }; 159 + 160 + static const struct drm_connector_helper_funcs mi0283qt_connector_helper_funcs = { 161 + DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS, 162 + }; 163 + 164 + static const struct drm_connector_funcs mi0283qt_connector_funcs = { 165 + DRM_MIPI_DBI_CONNECTOR_FUNCS, 166 + .destroy = drm_connector_cleanup, 167 + }; 168 + 169 + static const struct drm_mode_config_helper_funcs mi0283qt_mode_config_helper_funcs = { 170 + DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS, 171 + }; 172 + 173 + static const struct drm_mode_config_funcs mi0283qt_mode_config_funcs = { 174 + DRM_MIPI_DBI_MODE_CONFIG_FUNCS, 179 175 }; 180 176 181 177 static const struct drm_display_mode mi0283qt_mode = { ··· 239 179 static int mi0283qt_probe(struct spi_device *spi) 240 180 { 241 181 struct device *dev = &spi->dev; 182 + struct mi0283qt_device *mi0283qt; 242 183 struct mipi_dbi_dev *dbidev; 243 184 struct drm_device *drm; 244 185 struct mipi_dbi *dbi; 245 186 struct gpio_desc *dc; 187 + struct drm_plane *plane; 188 + struct drm_crtc *crtc; 189 + struct drm_encoder *encoder; 190 + struct drm_connector *connector; 246 191 u32 rotation = 0; 247 192 int ret; 248 193 249 - dbidev = devm_drm_dev_alloc(dev, &mi0283qt_driver, 250 - struct mipi_dbi_dev, drm); 251 - if (IS_ERR(dbidev)) 252 - return PTR_ERR(dbidev); 253 - 194 + mi0283qt = devm_drm_dev_alloc(dev, &mi0283qt_driver, struct mi0283qt_device, dbidev.drm); 195 + if (IS_ERR(mi0283qt)) 196 + return PTR_ERR(mi0283qt); 197 + dbidev = &mi0283qt->dbidev; 254 198 dbi = &dbidev->dbi; 255 199 drm = &dbidev->drm; 256 200 ··· 280 216 if (ret) 281 217 return ret; 282 218 283 - ret = mipi_dbi_dev_init(dbidev, &mi0283qt_pipe_funcs, &mi0283qt_mode, rotation); 219 + ret = drm_mipi_dbi_dev_init(dbidev, &mi0283qt_mode, mi0283qt_plane_formats[0], 220 + rotation, 0); 221 + if (ret) 222 + return ret; 223 + 224 + ret = drmm_mode_config_init(drm); 225 + if (ret) 226 + return ret; 227 + 228 + drm->mode_config.min_width = dbidev->mode.hdisplay; 229 + drm->mode_config.max_width = dbidev->mode.hdisplay; 230 + drm->mode_config.min_height = dbidev->mode.vdisplay; 231 + drm->mode_config.max_height = dbidev->mode.vdisplay; 232 + drm->mode_config.funcs = &mi0283qt_mode_config_funcs; 233 + drm->mode_config.preferred_depth = 16; 234 + drm->mode_config.helper_private = &mi0283qt_mode_config_helper_funcs; 235 + 236 + plane = &mi0283qt->plane; 237 + ret = drm_universal_plane_init(drm, plane, 0, &mi0283qt_plane_funcs, 238 + mi0283qt_plane_formats, ARRAY_SIZE(mi0283qt_plane_formats), 239 + mi0283qt_plane_format_modifiers, 240 + DRM_PLANE_TYPE_PRIMARY, NULL); 241 + if (ret) 242 + return ret; 243 + drm_plane_helper_add(plane, &mi0283qt_plane_helper_funcs); 244 + drm_plane_enable_fb_damage_clips(plane); 245 + 246 + crtc = &mi0283qt->crtc; 247 + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &mi0283qt_crtc_funcs, NULL); 248 + if (ret) 249 + return ret; 250 + drm_crtc_helper_add(crtc, &mi0283qt_crtc_helper_funcs); 251 + 252 + encoder = &mi0283qt->encoder; 253 + ret = drm_encoder_init(drm, encoder, &mi0283qt_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); 254 + if (ret) 255 + return ret; 256 + encoder->possible_crtcs = drm_crtc_mask(crtc); 257 + 258 + connector = &mi0283qt->connector; 259 + ret = drm_connector_init(drm, connector, &mi0283qt_connector_funcs, 260 + DRM_MODE_CONNECTOR_SPI); 261 + if (ret) 262 + return ret; 263 + drm_connector_helper_add(connector, &mi0283qt_connector_helper_funcs); 264 + 265 + ret = drm_connector_attach_encoder(connector, encoder); 284 266 if (ret) 285 267 return ret; 286 268
+124 -17
drivers/gpu/drm/tiny/panel-mipi-dbi.c
··· 233 233 } 234 234 } 235 235 236 - static void panel_mipi_dbi_enable(struct drm_simple_display_pipe *pipe, 237 - struct drm_crtc_state *crtc_state, 238 - struct drm_plane_state *plane_state) 236 + struct panel_mipi_dbi_device { 237 + struct mipi_dbi_dev dbidev; 238 + 239 + struct drm_plane plane; 240 + struct drm_crtc crtc; 241 + struct drm_encoder encoder; 242 + struct drm_connector connector; 243 + }; 244 + 245 + static struct panel_mipi_dbi_device *to_panel_mipi_dbi_device(struct drm_device *dev) 239 246 { 240 - struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); 247 + return container_of(drm_to_mipi_dbi_dev(dev), struct panel_mipi_dbi_device, dbidev); 248 + } 249 + 250 + static const u64 panel_mipi_dbi_plane_format_modifiers[] = { 251 + DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS, 252 + }; 253 + 254 + static const struct drm_plane_helper_funcs panel_mipi_dbi_plane_helper_funcs = { 255 + DRM_MIPI_DBI_PLANE_HELPER_FUNCS, 256 + }; 257 + 258 + static const struct drm_plane_funcs panel_mipi_dbi_plane_funcs = { 259 + DRM_MIPI_DBI_PLANE_FUNCS, 260 + .destroy = drm_plane_cleanup, 261 + }; 262 + 263 + static void panel_mipi_dbi_crtc_helper_atomic_enable(struct drm_crtc *crtc, 264 + struct drm_atomic_state *state) 265 + { 266 + struct drm_device *drm = crtc->dev; 267 + struct panel_mipi_dbi_device *panel_mipi_dbi = to_panel_mipi_dbi_device(drm); 268 + struct mipi_dbi_dev *dbidev = &panel_mipi_dbi->dbidev; 241 269 struct mipi_dbi *dbi = &dbidev->dbi; 242 270 int ret, idx; 243 271 244 - if (!drm_dev_enter(pipe->crtc.dev, &idx)) 272 + if (!drm_dev_enter(drm, &idx)) 245 273 return; 246 274 247 - drm_dbg(pipe->crtc.dev, "\n"); 275 + drm_dbg(drm, "\n"); 248 276 249 277 ret = mipi_dbi_poweron_conditional_reset(dbidev); 250 278 if (ret < 0) ··· 280 252 if (!ret) 281 253 panel_mipi_dbi_commands_execute(dbi, dbidev->driver_private); 282 254 283 - mipi_dbi_enable_flush(dbidev, crtc_state, plane_state); 255 + backlight_enable(dbidev->backlight); 284 256 out_exit: 285 257 drm_dev_exit(idx); 286 258 } 287 259 288 - static const struct drm_simple_display_pipe_funcs panel_mipi_dbi_pipe_funcs = { 289 - DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(panel_mipi_dbi_enable), 260 + static const struct drm_crtc_helper_funcs panel_mipi_dbi_crtc_helper_funcs = { 261 + DRM_MIPI_DBI_CRTC_HELPER_FUNCS, 262 + .atomic_enable = panel_mipi_dbi_crtc_helper_atomic_enable, 263 + }; 264 + 265 + static const struct drm_crtc_funcs panel_mipi_dbi_crtc_funcs = { 266 + DRM_MIPI_DBI_CRTC_FUNCS, 267 + .destroy = drm_crtc_cleanup, 268 + }; 269 + 270 + static const struct drm_encoder_funcs panel_mipi_dbi_encoder_funcs = { 271 + .destroy = drm_encoder_cleanup, 272 + }; 273 + 274 + static const struct drm_connector_helper_funcs panel_mipi_dbi_connector_helper_funcs = { 275 + DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS, 276 + }; 277 + 278 + static const struct drm_connector_funcs panel_mipi_dbi_connector_funcs = { 279 + DRM_MIPI_DBI_CONNECTOR_FUNCS, 280 + .destroy = drm_connector_cleanup, 281 + }; 282 + 283 + static const struct drm_mode_config_helper_funcs panel_mipi_dbi_mode_config_helper_funcs = { 284 + DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS, 285 + }; 286 + 287 + static const struct drm_mode_config_funcs panel_mipi_dbi_mode_config_funcs = { 288 + DRM_MIPI_DBI_MODE_CONFIG_FUNCS, 290 289 }; 291 290 292 291 DEFINE_DRM_GEM_DMA_FOPS(panel_mipi_dbi_fops); ··· 372 317 static int panel_mipi_dbi_spi_probe(struct spi_device *spi) 373 318 { 374 319 struct device *dev = &spi->dev; 375 - struct drm_display_mode mode; 320 + struct panel_mipi_dbi_device *panel_mipi_dbi; 376 321 struct mipi_dbi_dev *dbidev; 377 322 struct drm_device *drm; 323 + struct drm_display_mode mode; 378 324 struct mipi_dbi *dbi; 379 325 struct gpio_desc *dc; 380 326 unsigned int bpp; 381 327 size_t buf_size; 382 328 u32 formats[2]; 329 + struct drm_plane *plane; 330 + struct drm_crtc *crtc; 331 + struct drm_encoder *encoder; 332 + struct drm_connector *connector; 383 333 int ret; 384 334 385 - dbidev = devm_drm_dev_alloc(dev, &panel_mipi_dbi_driver, struct mipi_dbi_dev, drm); 386 - if (IS_ERR(dbidev)) 387 - return PTR_ERR(dbidev); 388 - 335 + panel_mipi_dbi = devm_drm_dev_alloc(dev, &panel_mipi_dbi_driver, 336 + struct panel_mipi_dbi_device, 337 + dbidev.drm); 338 + if (IS_ERR(panel_mipi_dbi)) 339 + return PTR_ERR(panel_mipi_dbi); 340 + dbidev = &panel_mipi_dbi->dbidev; 389 341 dbi = &dbidev->dbi; 390 342 drm = &dbidev->drm; 391 343 ··· 439 377 return ret; 440 378 441 379 buf_size = DIV_ROUND_UP(mode.hdisplay * mode.vdisplay * bpp, 8); 442 - ret = mipi_dbi_dev_init_with_formats(dbidev, &panel_mipi_dbi_pipe_funcs, 443 - formats, ARRAY_SIZE(formats), 444 - &mode, 0, buf_size); 380 + ret = drm_mipi_dbi_dev_init(dbidev, &mode, formats[0], 0, buf_size); 381 + if (ret) 382 + return ret; 383 + 384 + ret = drmm_mode_config_init(drm); 385 + if (ret) 386 + return ret; 387 + 388 + drm->mode_config.min_width = dbidev->mode.hdisplay; 389 + drm->mode_config.max_width = dbidev->mode.hdisplay; 390 + drm->mode_config.min_height = dbidev->mode.vdisplay; 391 + drm->mode_config.max_height = dbidev->mode.vdisplay; 392 + drm->mode_config.funcs = &panel_mipi_dbi_mode_config_funcs; 393 + drm->mode_config.preferred_depth = bpp; 394 + drm->mode_config.helper_private = &panel_mipi_dbi_mode_config_helper_funcs; 395 + 396 + plane = &panel_mipi_dbi->plane; 397 + ret = drm_universal_plane_init(drm, plane, 0, &panel_mipi_dbi_plane_funcs, 398 + formats, ARRAY_SIZE(formats), 399 + panel_mipi_dbi_plane_format_modifiers, 400 + DRM_PLANE_TYPE_PRIMARY, NULL); 401 + if (ret) 402 + return ret; 403 + drm_plane_helper_add(plane, &panel_mipi_dbi_plane_helper_funcs); 404 + drm_plane_enable_fb_damage_clips(plane); 405 + 406 + crtc = &panel_mipi_dbi->crtc; 407 + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &panel_mipi_dbi_crtc_funcs, 408 + NULL); 409 + if (ret) 410 + return ret; 411 + drm_crtc_helper_add(crtc, &panel_mipi_dbi_crtc_helper_funcs); 412 + 413 + encoder = &panel_mipi_dbi->encoder; 414 + ret = drm_encoder_init(drm, encoder, &panel_mipi_dbi_encoder_funcs, 415 + DRM_MODE_ENCODER_NONE, NULL); 416 + if (ret) 417 + return ret; 418 + encoder->possible_crtcs = drm_crtc_mask(crtc); 419 + 420 + connector = &panel_mipi_dbi->connector; 421 + ret = drm_connector_init(drm, connector, &panel_mipi_dbi_connector_funcs, 422 + DRM_MODE_CONNECTOR_SPI); 423 + if (ret) 424 + return ret; 425 + drm_connector_helper_add(connector, &panel_mipi_dbi_connector_helper_funcs); 426 + 427 + ret = drm_connector_attach_encoder(connector, encoder); 445 428 if (ret) 446 429 return ret; 447 430
+4 -2
drivers/gpu/drm/ttm/ttm_backup.c
··· 44 44 * @dst: The struct page to copy into. 45 45 * @handle: The handle returned when the page was backed up. 46 46 * @intr: Try to perform waits interruptible or at least killable. 47 + * @additional_gfp: GFP mask to add to the default GFP mask if any. 47 48 * 48 49 * Return: 0 on success, Negative error code on failure, notably 49 50 * -EINTR if @intr was set to true and a signal is pending. 50 51 */ 51 52 int ttm_backup_copy_page(struct file *backup, struct page *dst, 52 - pgoff_t handle, bool intr) 53 + pgoff_t handle, bool intr, gfp_t additional_gfp) 53 54 { 54 55 struct address_space *mapping = backup->f_mapping; 55 56 struct folio *from_folio; 56 57 pgoff_t idx = ttm_backup_handle_to_shmem_idx(handle); 57 58 58 - from_folio = shmem_read_folio(mapping, idx); 59 + from_folio = shmem_read_folio_gfp(mapping, idx, mapping_gfp_mask(mapping) 60 + | additional_gfp); 59 61 if (IS_ERR(from_folio)) 60 62 return PTR_ERR(from_folio); 61 63
+5 -2
drivers/gpu/drm/ttm/ttm_pool.c
··· 530 530 p = first_page[i]; 531 531 if (ttm_backup_page_ptr_is_handle(p)) { 532 532 unsigned long handle = ttm_backup_page_ptr_to_handle(p); 533 + gfp_t additional_gfp = ctx->gfp_retry_mayfail ? 534 + __GFP_RETRY_MAYFAIL | __GFP_NOWARN : 0; 533 535 534 536 if (IS_ENABLED(CONFIG_FAULT_INJECTION) && ctx->interruptible && 535 537 should_fail(&backup_fault_inject, 1)) { ··· 545 543 } 546 544 547 545 ret = ttm_backup_copy_page(backup, restore->alloced_page + i, 548 - handle, ctx->interruptible); 546 + handle, ctx->interruptible, 547 + additional_gfp); 549 548 if (ret) 550 549 break; 551 550 ··· 729 726 gfp_flags |= __GFP_ZERO; 730 727 731 728 if (ctx->gfp_retry_mayfail) 732 - gfp_flags |= __GFP_RETRY_MAYFAIL; 729 + gfp_flags |= __GFP_RETRY_MAYFAIL | __GFP_NOWARN; 733 730 734 731 if (ttm_pool_uses_dma32(pool)) 735 732 gfp_flags |= GFP_DMA32;
+9 -9
drivers/gpu/drm/vc4/vc4_hdmi.c
··· 133 133 134 134 static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode, 135 135 unsigned int bpc, 136 - enum hdmi_colorspace fmt) 136 + enum drm_output_color_format fmt) 137 137 { 138 138 unsigned long long clock = drm_hdmi_compute_mode_clock(mode, bpc, fmt); 139 139 ··· 444 444 const struct drm_display_mode *mode; 445 445 446 446 list_for_each_entry(mode, &connector->probed_modes, head) { 447 - if (vc4_hdmi_mode_needs_scrambling(mode, 8, HDMI_COLORSPACE_RGB)) { 447 + if (vc4_hdmi_mode_needs_scrambling(mode, 8, DRM_OUTPUT_COLOR_FORMAT_RGB444)) { 448 448 drm_warn_once(drm, "The core clock cannot reach frequencies high enough to support 4k @ 60Hz."); 449 449 drm_warn_once(drm, "Please change your config.txt file to add hdmi_enable_4kp60."); 450 450 } ··· 547 547 &vc4_hdmi_hdmi_connector_funcs, 548 548 DRM_MODE_CONNECTOR_HDMIA, 549 549 vc4_hdmi->ddc, 550 - BIT(HDMI_COLORSPACE_RGB) | 551 - BIT(HDMI_COLORSPACE_YUV422) | 552 - BIT(HDMI_COLORSPACE_YUV444), 550 + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | 551 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) | 552 + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444), 553 553 max_bpc); 554 554 if (ret) 555 555 return ret; ··· 1214 1214 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); 1215 1215 1216 1216 switch (state->hdmi.output_format) { 1217 - case HDMI_COLORSPACE_YUV444: 1217 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR444: 1218 1218 csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range); 1219 1219 1220 1220 vc5_hdmi_set_csc_coeffs_swap(vc4_hdmi, csc); 1221 1221 break; 1222 1222 1223 - case HDMI_COLORSPACE_YUV422: 1223 + case DRM_OUTPUT_COLOR_FORMAT_YCBCR422: 1224 1224 csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range); 1225 1225 1226 1226 csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD, ··· 1237 1237 vc5_hdmi_set_csc_coeffs(vc4_hdmi, csc); 1238 1238 break; 1239 1239 1240 - case HDMI_COLORSPACE_RGB: 1240 + case DRM_OUTPUT_COLOR_FORMAT_RGB444: 1241 1241 if_xbar = 0x354021; 1242 1242 1243 1243 vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_rgb[lim_range]); ··· 1394 1394 * YCC422 is always 36-bit and not considered deep colour so 1395 1395 * doesn't signal in GCP. 1396 1396 */ 1397 - if (state->hdmi.output_format == HDMI_COLORSPACE_YUV422) { 1397 + if (state->hdmi.output_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR422) { 1398 1398 gcp = 0; 1399 1399 } 1400 1400
+1 -1
drivers/gpu/drm/vc4/vc4_hdmi.h
··· 210 210 * @drm_connector_state.hdmi.output_format for use outside of 211 211 * KMS hooks. Protected by @mutex. 212 212 */ 213 - enum hdmi_colorspace output_format; 213 + enum drm_output_color_format output_format; 214 214 215 215 /** 216 216 * @hdmi_jack: Represents the connection state of the HDMI plug, for
+1 -3
drivers/gpu/drm/vc4/vc4_kms.c
··· 116 116 { 117 117 drm_modeset_lock_init(&vc4->ctm_state_lock); 118 118 119 - drm_atomic_private_obj_init(&vc4->base, &vc4->ctm_manager, NULL, 119 + drm_atomic_private_obj_init(&vc4->base, &vc4->ctm_manager, 120 120 &vc4_ctm_state_funcs); 121 121 122 122 return drmm_add_action_or_reset(&vc4->base, vc4_ctm_obj_fini, NULL); ··· 757 757 static int vc4_load_tracker_obj_init(struct vc4_dev *vc4) 758 758 { 759 759 drm_atomic_private_obj_init(&vc4->base, &vc4->load_tracker, 760 - NULL, 761 760 &vc4_load_tracker_state_funcs); 762 761 763 762 return drmm_add_action_or_reset(&vc4->base, vc4_load_tracker_obj_fini, NULL); ··· 848 849 static int vc4_hvs_channels_obj_init(struct vc4_dev *vc4) 849 850 { 850 851 drm_atomic_private_obj_init(&vc4->base, &vc4->hvs_channels, 851 - NULL, 852 852 &vc4_hvs_state_funcs); 853 853 854 854 return drmm_add_action_or_reset(&vc4->base, vc4_hvs_channels_obj_fini, NULL);
+1 -1
drivers/gpu/drm/verisilicon/vs_dc.c
··· 190 190 vs_drm_shutdown_handler(dc); 191 191 } 192 192 193 - struct platform_driver vs_dc_platform_driver = { 193 + static struct platform_driver vs_dc_platform_driver = { 194 194 .probe = vs_dc_probe, 195 195 .remove = vs_dc_remove, 196 196 .shutdown = vs_dc_shutdown,
+8 -1
drivers/gpu/drm/xe/xe_device.c
··· 1348 1348 xe_gt_declare_wedged(gt); 1349 1349 1350 1350 if (xe_device_wedged(xe)) { 1351 + /* 1352 + * XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET is intended for debugging 1353 + * hangs, so wedge the device with 'none' recovery method and have 1354 + * it available to the user for debugging. 1355 + */ 1356 + if (xe->wedged.mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET) 1357 + xe_device_set_wedged_method(xe, DRM_WEDGE_RECOVERY_NONE); 1351 1358 /* If no wedge recovery method is set, use default */ 1352 - if (!xe->wedged.method) 1359 + else if (!xe->wedged.method) 1353 1360 xe_device_set_wedged_method(xe, DRM_WEDGE_RECOVERY_REBIND | 1354 1361 DRM_WEDGE_RECOVERY_BUS_RESET); 1355 1362
+1 -1
include/drm/bridge/dw_hdmi_qp.h
··· 25 25 int main_irq; 26 26 int cec_irq; 27 27 unsigned long ref_clk_rate; 28 - /* Supported output formats: bitmask of @hdmi_colorspace */ 28 + /* Supported output formats: bitmask of @drm_output_color_format */ 29 29 unsigned int supported_formats; 30 30 /* Maximum bits per color channel: 8, 10 or 12 */ 31 31 unsigned int max_bpc;
+2 -1
include/drm/display/drm_hdmi_helper.h
··· 8 8 struct drm_connector; 9 9 struct drm_connector_state; 10 10 struct drm_display_mode; 11 + enum drm_output_color_format; 11 12 12 13 void 13 14 drm_hdmi_avi_infoframe_colorimetry(struct hdmi_avi_infoframe *frame, ··· 27 26 28 27 unsigned long long 29 28 drm_hdmi_compute_mode_clock(const struct drm_display_mode *mode, 30 - unsigned int bpc, enum hdmi_colorspace fmt); 29 + unsigned int bpc, enum drm_output_color_format fmt); 31 30 32 31 void 33 32 drm_hdmi_acr_get_n_cts(unsigned long long tmds_char_rate,
-1
include/drm/drm_atomic.h
··· 738 738 739 739 int drm_atomic_private_obj_init(struct drm_device *dev, 740 740 struct drm_private_obj *obj, 741 - struct drm_private_state *state, 742 741 const struct drm_private_state_funcs *funcs); 743 742 void drm_atomic_private_obj_fini(struct drm_private_obj *obj); 744 743
+4 -2
include/drm/drm_bridge.h
··· 1188 1188 const char *product; 1189 1189 1190 1190 /** 1191 - * @supported_formats: Bitmask of @hdmi_colorspace listing supported 1192 - * output formats. This is only relevant if @DRM_BRIDGE_OP_HDMI is set. 1191 + * @supported_formats: Bitmask of @drm_output_color_format listing 1192 + * supported output formats. This is only relevant if 1193 + * @DRM_BRIDGE_OP_HDMI is set. 1193 1194 */ 1194 1195 unsigned int supported_formats; 1195 1196 ··· 1291 1290 1292 1291 struct drm_bridge *drm_bridge_get(struct drm_bridge *bridge); 1293 1292 void drm_bridge_put(struct drm_bridge *bridge); 1293 + void drm_bridge_clear_and_put(struct drm_bridge **bridge_pp); 1294 1294 1295 1295 /* Cleanup action for use with __free() */ 1296 1296 DEFINE_FREE(drm_bridge_put, struct drm_bridge *, if (_T) drm_bridge_put(_T))
+35 -13
include/drm/drm_connector.h
··· 402 402 403 403 const char * 404 404 drm_hdmi_connector_get_broadcast_rgb_name(enum drm_hdmi_broadcast_rgb broadcast_rgb); 405 - const char * 406 - drm_hdmi_connector_get_output_format_name(enum hdmi_colorspace fmt); 407 405 408 406 /** 409 407 * struct drm_monitor_range_info - Panel's Monitor range in EDID for ··· 555 557 }; 556 558 557 559 /** 560 + * enum drm_output_color_format - Output Color Format 561 + * 562 + * This enum is a consolidated color format list supported by 563 + * connectors. It's only ever really been used for HDMI and DP so far, 564 + * so it's not exhaustive and can be extended to represent other formats 565 + * in the future. 566 + * 567 + * 568 + * @DRM_OUTPUT_COLOR_FORMAT_RGB444: 569 + * RGB output format 570 + * @DRM_OUTPUT_COLOR_FORMAT_YCBCR444: 571 + * YCbCr 4:4:4 output format (ie. not subsampled) 572 + * @DRM_OUTPUT_COLOR_FORMAT_YCBCR422: 573 + * YCbCr 4:2:2 output format (ie. with horizontal subsampling) 574 + * @DRM_OUTPUT_COLOR_FORMAT_YCBCR420: 575 + * YCbCr 4:2:0 output format (ie. with horizontal and vertical subsampling) 576 + */ 577 + enum drm_output_color_format { 578 + DRM_OUTPUT_COLOR_FORMAT_RGB444 = 0, 579 + DRM_OUTPUT_COLOR_FORMAT_YCBCR444, 580 + DRM_OUTPUT_COLOR_FORMAT_YCBCR422, 581 + DRM_OUTPUT_COLOR_FORMAT_YCBCR420, 582 + }; 583 + 584 + const char * 585 + drm_hdmi_connector_get_output_format_name(enum drm_output_color_format fmt); 586 + 587 + /** 558 588 * enum drm_bus_flags - bus_flags info for &drm_display_info 559 589 * 560 590 * This enum defines signal polarities and clock edge information for signals on ··· 725 699 */ 726 700 enum subpixel_order subpixel_order; 727 701 728 - #define DRM_COLOR_FORMAT_RGB444 (1<<0) 729 - #define DRM_COLOR_FORMAT_YCBCR444 (1<<1) 730 - #define DRM_COLOR_FORMAT_YCBCR422 (1<<2) 731 - #define DRM_COLOR_FORMAT_YCBCR420 (1<<3) 732 - 733 702 /** 734 703 * @panel_orientation: Read only connector property for built-in panels, 735 704 * indicating the orientation of the panel vs the device's casing. ··· 735 714 int panel_orientation; 736 715 737 716 /** 738 - * @color_formats: HDMI Color formats, selects between RGB and YCrCb 739 - * modes. Used DRM_COLOR_FORMAT\_ defines, which are _not_ the same ones 740 - * as used to describe the pixel format in framebuffers, and also don't 741 - * match the formats in @bus_formats which are shared with v4l. 717 + * @color_formats: HDMI Color formats, selects between RGB and 718 + * YCbCr modes. Uses a bitmask of DRM_OUTPUT_COLOR_FORMAT\_ 719 + * defines, which are _not_ the same ones as used to describe 720 + * the pixel format in framebuffers, and also don't match the 721 + * formats in @bus_formats which are shared with v4l. 742 722 */ 743 723 u32 color_formats; 744 724 ··· 1013 991 /** 1014 992 * @output_format: Pixel format to output in. 1015 993 */ 1016 - enum hdmi_colorspace output_format; 994 + enum drm_output_color_format output_format; 1017 995 1018 996 /** 1019 997 * @tmds_char_rate: TMDS Character Rate, in Hz. ··· 1901 1879 unsigned char product[DRM_CONNECTOR_HDMI_PRODUCT_LEN] __nonstring; 1902 1880 1903 1881 /** 1904 - * @supported_formats: Bitmask of @hdmi_colorspace 1882 + * @supported_formats: Bitmask of @drm_output_color_format 1905 1883 * supported by the controller. 1906 1884 */ 1907 1885 unsigned long supported_formats;
+89 -56
include/drm/drm_mipi_dbi.h
··· 9 9 #define __LINUX_MIPI_DBI_H 10 10 11 11 #include <linux/mutex.h> 12 + 13 + #include <drm/drm_atomic_state_helper.h> 12 14 #include <drm/drm_device.h> 13 - #include <drm/drm_simple_kms_helper.h> 15 + #include <drm/drm_gem_atomic_helper.h> 16 + #include <drm/drm_gem_framebuffer_helper.h> 17 + #include <drm/drm_probe_helper.h> 14 18 15 19 struct drm_format_conv_state; 16 20 struct drm_rect; ··· 91 87 struct drm_device drm; 92 88 93 89 /** 94 - * @pipe: Display pipe structure 95 - */ 96 - struct drm_simple_display_pipe pipe; 97 - 98 - /** 99 - * @connector: Connector 100 - */ 101 - struct drm_connector connector; 102 - 103 - /** 104 90 * @mode: Fixed display mode 105 91 */ 106 92 struct drm_display_mode mode; ··· 158 164 159 165 int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi, 160 166 struct gpio_desc *dc); 161 - int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev, 162 - const struct drm_simple_display_pipe_funcs *funcs, 163 - const uint32_t *formats, unsigned int format_count, 164 - const struct drm_display_mode *mode, 165 - unsigned int rotation, size_t tx_buf_size); 166 - int mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev, 167 - const struct drm_simple_display_pipe_funcs *funcs, 168 - const struct drm_display_mode *mode, unsigned int rotation); 169 - enum drm_mode_status mipi_dbi_pipe_mode_valid(struct drm_simple_display_pipe *pipe, 170 - const struct drm_display_mode *mode); 171 - void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe, 172 - struct drm_plane_state *old_state); 173 - void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev, 174 - struct drm_crtc_state *crtc_state, 175 - struct drm_plane_state *plan_state); 176 - void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe); 177 - int mipi_dbi_pipe_begin_fb_access(struct drm_simple_display_pipe *pipe, 178 - struct drm_plane_state *plane_state); 179 - void mipi_dbi_pipe_end_fb_access(struct drm_simple_display_pipe *pipe, 180 - struct drm_plane_state *plane_state); 181 - void mipi_dbi_pipe_reset_plane(struct drm_simple_display_pipe *pipe); 182 - struct drm_plane_state *mipi_dbi_pipe_duplicate_plane_state(struct drm_simple_display_pipe *pipe); 183 - void mipi_dbi_pipe_destroy_plane_state(struct drm_simple_display_pipe *pipe, 184 - struct drm_plane_state *plane_state); 167 + 168 + int drm_mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev, const struct drm_display_mode *mode, 169 + u32 format, unsigned int rotation, size_t tx_buf_size); 185 170 186 171 void mipi_dbi_hw_reset(struct mipi_dbi *dbi); 187 172 bool mipi_dbi_display_is_on(struct mipi_dbi *dbi); ··· 202 229 ret; \ 203 230 }) 204 231 232 + /* 233 + * Plane 234 + */ 235 + 236 + #define DRM_MIPI_DBI_PLANE_FORMATS \ 237 + DRM_FORMAT_RGB565, \ 238 + DRM_FORMAT_XRGB8888 239 + 240 + #define DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS \ 241 + DRM_FORMAT_MOD_LINEAR, \ 242 + DRM_FORMAT_MOD_INVALID 243 + 244 + #define DRM_MIPI_DBI_PLANE_FUNCS \ 245 + DRM_GEM_SHADOW_PLANE_FUNCS, \ 246 + .update_plane = drm_atomic_helper_update_plane, \ 247 + .disable_plane = drm_atomic_helper_disable_plane 248 + 249 + int drm_mipi_dbi_plane_helper_atomic_check(struct drm_plane *plane, 250 + struct drm_atomic_state *state); 251 + void drm_mipi_dbi_plane_helper_atomic_update(struct drm_plane *plane, 252 + struct drm_atomic_state *state); 253 + 254 + #define DRM_MIPI_DBI_PLANE_HELPER_FUNCS \ 255 + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, \ 256 + .atomic_check = drm_mipi_dbi_plane_helper_atomic_check, \ 257 + .atomic_update = drm_mipi_dbi_plane_helper_atomic_update 258 + 259 + /* 260 + * CRTC 261 + */ 262 + 263 + #define DRM_MIPI_DBI_CRTC_FUNCS \ 264 + .reset = drm_atomic_helper_crtc_reset, \ 265 + .set_config = drm_atomic_helper_set_config, \ 266 + .page_flip = drm_atomic_helper_page_flip, \ 267 + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, \ 268 + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state 269 + 270 + enum drm_mode_status drm_mipi_dbi_crtc_helper_mode_valid(struct drm_crtc *crtc, 271 + const struct drm_display_mode *mode); 272 + int drm_mipi_dbi_crtc_helper_atomic_check(struct drm_crtc *crtc, 273 + struct drm_atomic_state *state); 274 + void drm_mipi_dbi_crtc_helper_atomic_disable(struct drm_crtc *crtc, 275 + struct drm_atomic_state *state); 276 + 277 + #define DRM_MIPI_DBI_CRTC_HELPER_FUNCS \ 278 + .mode_valid = drm_mipi_dbi_crtc_helper_mode_valid, \ 279 + .atomic_check = drm_mipi_dbi_crtc_helper_atomic_check, \ 280 + .atomic_disable = drm_mipi_dbi_crtc_helper_atomic_disable 281 + 282 + /* 283 + * Connector 284 + */ 285 + 286 + #define DRM_MIPI_DBI_CONNECTOR_FUNCS \ 287 + .reset = drm_atomic_helper_connector_reset, \ 288 + .fill_modes = drm_helper_probe_single_connector_modes, \ 289 + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, \ 290 + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state 291 + 292 + int drm_mipi_dbi_connector_helper_get_modes(struct drm_connector *connector); 293 + 294 + #define DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS \ 295 + .get_modes = drm_mipi_dbi_connector_helper_get_modes 296 + 297 + /* 298 + * Mode config 299 + */ 300 + 301 + #define DRM_MIPI_DBI_MODE_CONFIG_FUNCS \ 302 + .fb_create = drm_gem_fb_create_with_dirty, \ 303 + .atomic_check = drm_atomic_helper_check, \ 304 + .atomic_commit = drm_atomic_helper_commit 305 + 306 + #define DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS \ 307 + .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm 308 + 309 + /* 310 + * Debug FS 311 + */ 312 + 205 313 #ifdef CONFIG_DEBUG_FS 206 314 void mipi_dbi_debugfs_init(struct drm_minor *minor); 207 315 #else 208 316 static inline void mipi_dbi_debugfs_init(struct drm_minor *minor) {} 209 317 #endif 210 - 211 - /** 212 - * DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS - Initializes struct drm_simple_display_pipe_funcs 213 - * for MIPI-DBI devices 214 - * @enable_: Enable-callback implementation 215 - * 216 - * This macro initializes struct drm_simple_display_pipe_funcs with default 217 - * values for MIPI-DBI-based devices. The only callback that depends on the 218 - * hardware is @enable, for which the driver has to provide an implementation. 219 - * MIPI-based drivers are encouraged to use this macro for initialization. 220 - */ 221 - #define DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(enable_) \ 222 - .mode_valid = mipi_dbi_pipe_mode_valid, \ 223 - .enable = (enable_), \ 224 - .disable = mipi_dbi_pipe_disable, \ 225 - .update = mipi_dbi_pipe_update, \ 226 - .begin_fb_access = mipi_dbi_pipe_begin_fb_access, \ 227 - .end_fb_access = mipi_dbi_pipe_end_fb_access, \ 228 - .reset_plane = mipi_dbi_pipe_reset_plane, \ 229 - .duplicate_plane_state = mipi_dbi_pipe_duplicate_plane_state, \ 230 - .destroy_plane_state = mipi_dbi_pipe_destroy_plane_state 231 318 232 319 #endif /* __LINUX_MIPI_DBI_H */
+5 -211
include/drm/drm_simple_kms_helper.h
··· 3 3 * Copyright (C) 2016 Noralf Trønnes 4 4 */ 5 5 6 + /* 7 + * Simple KMS helpers are deprected in favor of regular atomic helpers. Do not 8 + * use the min new code. 9 + */ 10 + 6 11 #ifndef __LINUX_DRM_SIMPLE_KMS_HELPER_H 7 12 #define __LINUX_DRM_SIMPLE_KMS_HELPER_H 8 13 ··· 17 12 18 13 struct drm_simple_display_pipe; 19 14 20 - /** 21 - * struct drm_simple_display_pipe_funcs - helper operations for a simple 22 - * display pipeline 23 - */ 24 15 struct drm_simple_display_pipe_funcs { 25 - /** 26 - * @mode_valid: 27 - * 28 - * This callback is used to check if a specific mode is valid in the 29 - * crtc used in this simple display pipe. This should be implemented 30 - * if the display pipe has some sort of restriction in the modes 31 - * it can display. For example, a given display pipe may be responsible 32 - * to set a clock value. If the clock can not produce all the values 33 - * for the available modes then this callback can be used to restrict 34 - * the number of modes to only the ones that can be displayed. Another 35 - * reason can be bandwidth mitigation: the memory port on the display 36 - * controller can have bandwidth limitations not allowing pixel data 37 - * to be fetched at any rate. 38 - * 39 - * This hook is used by the probe helpers to filter the mode list in 40 - * drm_helper_probe_single_connector_modes(), and it is used by the 41 - * atomic helpers to validate modes supplied by userspace in 42 - * drm_atomic_helper_check_modeset(). 43 - * 44 - * This function is optional. 45 - * 46 - * NOTE: 47 - * 48 - * Since this function is both called from the check phase of an atomic 49 - * commit, and the mode validation in the probe paths it is not allowed 50 - * to look at anything else but the passed-in mode, and validate it 51 - * against configuration-invariant hardware constraints. 52 - * 53 - * RETURNS: 54 - * 55 - * drm_mode_status Enum 56 - */ 57 16 enum drm_mode_status (*mode_valid)(struct drm_simple_display_pipe *pipe, 58 17 const struct drm_display_mode *mode); 59 - 60 - /** 61 - * @enable: 62 - * 63 - * This function should be used to enable the pipeline. 64 - * It is called when the underlying crtc is enabled. 65 - * This hook is optional. 66 - */ 67 18 void (*enable)(struct drm_simple_display_pipe *pipe, 68 19 struct drm_crtc_state *crtc_state, 69 20 struct drm_plane_state *plane_state); 70 - /** 71 - * @disable: 72 - * 73 - * This function should be used to disable the pipeline. 74 - * It is called when the underlying crtc is disabled. 75 - * This hook is optional. 76 - */ 77 21 void (*disable)(struct drm_simple_display_pipe *pipe); 78 - 79 - /** 80 - * @check: 81 - * 82 - * This function is called in the check phase of an atomic update, 83 - * specifically when the underlying plane is checked. 84 - * The simple display pipeline helpers already check that the plane is 85 - * not scaled, fills the entire visible area and is always enabled 86 - * when the crtc is also enabled. 87 - * This hook is optional. 88 - * 89 - * RETURNS: 90 - * 91 - * 0 on success, -EINVAL if the state or the transition can't be 92 - * supported, -ENOMEM on memory allocation failure and -EDEADLK if an 93 - * attempt to obtain another state object ran into a &drm_modeset_lock 94 - * deadlock. 95 - */ 96 22 int (*check)(struct drm_simple_display_pipe *pipe, 97 23 struct drm_plane_state *plane_state, 98 24 struct drm_crtc_state *crtc_state); 99 - /** 100 - * @update: 101 - * 102 - * This function is called when the underlying plane state is updated. 103 - * This hook is optional. 104 - * 105 - * This is the function drivers should submit the 106 - * &drm_pending_vblank_event from. Using either 107 - * drm_crtc_arm_vblank_event(), when the driver supports vblank 108 - * interrupt handling, or drm_crtc_send_vblank_event() for more 109 - * complex case. In case the hardware lacks vblank support entirely, 110 - * drivers can set &struct drm_crtc_state.no_vblank in 111 - * &struct drm_simple_display_pipe_funcs.check and let DRM's 112 - * atomic helper fake a vblank event. 113 - */ 114 25 void (*update)(struct drm_simple_display_pipe *pipe, 115 26 struct drm_plane_state *old_plane_state); 116 - 117 - /** 118 - * @prepare_fb: 119 - * 120 - * Optional, called by &drm_plane_helper_funcs.prepare_fb. Please read 121 - * the documentation for the &drm_plane_helper_funcs.prepare_fb hook for 122 - * more details. 123 - * 124 - * For GEM drivers who neither have a @prepare_fb nor @cleanup_fb hook 125 - * set, drm_gem_plane_helper_prepare_fb() is called automatically 126 - * to implement this. Other drivers which need additional plane 127 - * processing can call drm_gem_plane_helper_prepare_fb() from 128 - * their @prepare_fb hook. 129 - */ 130 27 int (*prepare_fb)(struct drm_simple_display_pipe *pipe, 131 28 struct drm_plane_state *plane_state); 132 - 133 - /** 134 - * @cleanup_fb: 135 - * 136 - * Optional, called by &drm_plane_helper_funcs.cleanup_fb. Please read 137 - * the documentation for the &drm_plane_helper_funcs.cleanup_fb hook for 138 - * more details. 139 - */ 140 29 void (*cleanup_fb)(struct drm_simple_display_pipe *pipe, 141 30 struct drm_plane_state *plane_state); 142 - 143 - /** 144 - * @begin_fb_access: 145 - * 146 - * Optional, called by &drm_plane_helper_funcs.begin_fb_access. Please read 147 - * the documentation for the &drm_plane_helper_funcs.begin_fb_access hook for 148 - * more details. 149 - */ 150 31 int (*begin_fb_access)(struct drm_simple_display_pipe *pipe, 151 32 struct drm_plane_state *new_plane_state); 152 - 153 - /** 154 - * @end_fb_access: 155 - * 156 - * Optional, called by &drm_plane_helper_funcs.end_fb_access. Please read 157 - * the documentation for the &drm_plane_helper_funcs.end_fb_access hook for 158 - * more details. 159 - */ 160 33 void (*end_fb_access)(struct drm_simple_display_pipe *pipe, 161 34 struct drm_plane_state *plane_state); 162 - 163 - /** 164 - * @enable_vblank: 165 - * 166 - * Optional, called by &drm_crtc_funcs.enable_vblank. Please read 167 - * the documentation for the &drm_crtc_funcs.enable_vblank hook for 168 - * more details. 169 - */ 170 35 int (*enable_vblank)(struct drm_simple_display_pipe *pipe); 171 - 172 - /** 173 - * @disable_vblank: 174 - * 175 - * Optional, called by &drm_crtc_funcs.disable_vblank. Please read 176 - * the documentation for the &drm_crtc_funcs.disable_vblank hook for 177 - * more details. 178 - */ 179 36 void (*disable_vblank)(struct drm_simple_display_pipe *pipe); 180 - 181 - /** 182 - * @reset_crtc: 183 - * 184 - * Optional, called by &drm_crtc_funcs.reset. Please read the 185 - * documentation for the &drm_crtc_funcs.reset hook for more details. 186 - */ 187 37 void (*reset_crtc)(struct drm_simple_display_pipe *pipe); 188 - 189 - /** 190 - * @duplicate_crtc_state: 191 - * 192 - * Optional, called by &drm_crtc_funcs.atomic_duplicate_state. Please 193 - * read the documentation for the &drm_crtc_funcs.atomic_duplicate_state 194 - * hook for more details. 195 - */ 196 38 struct drm_crtc_state * (*duplicate_crtc_state)(struct drm_simple_display_pipe *pipe); 197 - 198 - /** 199 - * @destroy_crtc_state: 200 - * 201 - * Optional, called by &drm_crtc_funcs.atomic_destroy_state. Please 202 - * read the documentation for the &drm_crtc_funcs.atomic_destroy_state 203 - * hook for more details. 204 - */ 205 39 void (*destroy_crtc_state)(struct drm_simple_display_pipe *pipe, 206 40 struct drm_crtc_state *crtc_state); 207 - 208 - /** 209 - * @reset_plane: 210 - * 211 - * Optional, called by &drm_plane_funcs.reset. Please read the 212 - * documentation for the &drm_plane_funcs.reset hook for more details. 213 - */ 214 41 void (*reset_plane)(struct drm_simple_display_pipe *pipe); 215 - 216 - /** 217 - * @duplicate_plane_state: 218 - * 219 - * Optional, called by &drm_plane_funcs.atomic_duplicate_state. Please 220 - * read the documentation for the &drm_plane_funcs.atomic_duplicate_state 221 - * hook for more details. 222 - */ 223 42 struct drm_plane_state * (*duplicate_plane_state)(struct drm_simple_display_pipe *pipe); 224 - 225 - /** 226 - * @destroy_plane_state: 227 - * 228 - * Optional, called by &drm_plane_funcs.atomic_destroy_state. Please 229 - * read the documentation for the &drm_plane_funcs.atomic_destroy_state 230 - * hook for more details. 231 - */ 232 43 void (*destroy_plane_state)(struct drm_simple_display_pipe *pipe, 233 44 struct drm_plane_state *plane_state); 234 45 }; 235 46 236 - /** 237 - * struct drm_simple_display_pipe - simple display pipeline 238 - * @crtc: CRTC control structure 239 - * @plane: Plane control structure 240 - * @encoder: Encoder control structure 241 - * @connector: Connector control structure 242 - * @funcs: Pipeline control functions (optional) 243 - * 244 - * Simple display pipeline with plane, crtc and encoder collapsed into one 245 - * entity. It should be initialized by calling drm_simple_display_pipe_init(). 246 - */ 247 47 struct drm_simple_display_pipe { 248 48 struct drm_crtc crtc; 249 49 struct drm_plane plane; ··· 75 265 void *__drmm_simple_encoder_alloc(struct drm_device *dev, size_t size, 76 266 size_t offset, int encoder_type); 77 267 78 - /** 79 - * drmm_simple_encoder_alloc - Allocate and initialize an encoder with basic 80 - * functionality. 81 - * @dev: drm device 82 - * @type: the type of the struct which contains struct &drm_encoder 83 - * @member: the name of the &drm_encoder within @type. 84 - * @encoder_type: user visible type of the encoder 85 - * 86 - * Allocates and initializes an encoder that has no further functionality. 87 - * Settings for possible CRTC and clones are left to their initial values. 88 - * Cleanup is automatically handled through registering drm_encoder_cleanup() 89 - * with drmm_add_action(). 90 - * 91 - * Returns: 92 - * Pointer to new encoder, or ERR_PTR on failure. 93 - */ 94 268 #define drmm_simple_encoder_alloc(dev, type, member, encoder_type) \ 95 269 ((type *)__drmm_simple_encoder_alloc(dev, sizeof(type), \ 96 270 offsetof(type, member), \
+1 -1
include/drm/ttm/ttm_backup.h
··· 56 56 void ttm_backup_drop(struct file *backup, pgoff_t handle); 57 57 58 58 int ttm_backup_copy_page(struct file *backup, struct page *dst, 59 - pgoff_t handle, bool intr); 59 + pgoff_t handle, bool intr, gfp_t additional_gfp); 60 60 61 61 s64 62 62 ttm_backup_backup_page(struct file *backup, struct page *page,
+19 -9
include/drm/ttm/ttm_bo.h
··· 167 167 /** 168 168 * struct ttm_operation_ctx 169 169 * 170 - * @interruptible: Sleep interruptible if sleeping. 171 - * @no_wait_gpu: Return immediately if the GPU is busy. 172 - * @gfp_retry_mayfail: Set the __GFP_RETRY_MAYFAIL when allocation pages. 173 - * @allow_res_evict: Allow eviction of reserved BOs. Can be used when multiple 174 - * BOs share the same reservation object. 175 - * faults. Should only be used by TTM internally. 176 - * @resv: Reservation object to allow reserved evictions with. 177 - * @bytes_moved: Statistics on how many bytes have been moved. 178 - * 179 170 * Context for TTM operations like changing buffer placement or general memory 180 171 * allocation. 181 172 */ 182 173 struct ttm_operation_ctx { 174 + /** @interruptible: Sleep interruptible if sleeping. */ 183 175 bool interruptible; 176 + /** @no_wait_gpu: Return immediately if the GPU is busy. */ 184 177 bool no_wait_gpu; 178 + /** 179 + * @gfp_retry_mayfail: Use __GFP_RETRY_MAYFAIL | __GFP_NOWARN 180 + * when allocation pages. This is to avoid invoking the OOM 181 + * killer when populating a buffer object, in order to 182 + * forward the error for it to be dealt with. 183 + */ 185 184 bool gfp_retry_mayfail; 185 + /** 186 + * @allow_res_evict: Allow eviction of reserved BOs. Can be used 187 + * when multiple BOs share the same reservation object @resv. 188 + */ 186 189 bool allow_res_evict; 190 + /** 191 + * @resv: Reservation object to be used together with 192 + * @allow_res_evict. 193 + */ 187 194 struct dma_resv *resv; 195 + /** 196 + * @bytes_moved: Statistics on how many bytes have been moved. 197 + */ 188 198 uint64_t bytes_moved; 189 199 }; 190 200
+40 -4
include/uapi/drm/amdxdna_accel.h
··· 156 156 157 157 enum amdxdna_bo_type { 158 158 AMDXDNA_BO_INVALID = 0, 159 - AMDXDNA_BO_SHMEM, 160 - AMDXDNA_BO_DEV_HEAP, 161 - AMDXDNA_BO_DEV, 162 - AMDXDNA_BO_CMD, 159 + AMDXDNA_BO_SHMEM = 1, /* Be compatible with legacy application code. */ 160 + AMDXDNA_BO_SHARE = 1, 161 + AMDXDNA_BO_DEV_HEAP = 2, 162 + AMDXDNA_BO_DEV = 3, 163 + AMDXDNA_BO_CMD = 4, 163 164 }; 164 165 165 166 /** ··· 591 590 __u64 ex_err_code; 592 591 }; 593 592 593 + /** 594 + * struct amdxdna_drm_bo_usage - all types of BO usage 595 + * BOs managed by XRT/SHIM/driver is counted as internal. 596 + * Others are counted as external which are managed by applications. 597 + * 598 + * Among all types of BOs: 599 + * AMDXDNA_BO_DEV_HEAP - is counted for internal. 600 + * AMDXDNA_BO_SHARE - is counted for external. 601 + * AMDXDNA_BO_CMD - is counted for internal. 602 + * AMDXDNA_BO_DEV - is counted by heap_usage only, not internal 603 + * or external. It does not add to the total memory 604 + * footprint since its mem comes from heap which is 605 + * already counted as internal. 606 + */ 607 + struct amdxdna_drm_bo_usage { 608 + /** @pid: The ID of the process to query from. */ 609 + __s64 pid; 610 + /** @total_usage: Total BO size used by process. */ 611 + __u64 total_usage; 612 + /** @internal_usage: Total internal BO size used by process. */ 613 + __u64 internal_usage; 614 + /** @heap_usage: Total device BO size used by process. */ 615 + __u64 heap_usage; 616 + }; 617 + 618 + /* 619 + * Supported params in struct amdxdna_drm_get_array 620 + */ 594 621 #define DRM_AMDXDNA_HW_CONTEXT_ALL 0 595 622 #define DRM_AMDXDNA_HW_LAST_ASYNC_ERR 2 623 + #define DRM_AMDXDNA_BO_USAGE 6 596 624 597 625 /** 598 626 * struct amdxdna_drm_get_array - Get information array. ··· 634 604 * 635 605 * %DRM_AMDXDNA_HW_CONTEXT_ALL: 636 606 * Returns all created hardware contexts. 607 + * 608 + * %DRM_AMDXDNA_HW_LAST_ASYNC_ERR: 609 + * Returns last async error. 610 + * 611 + * %DRM_AMDXDNA_BO_USAGE: 612 + * Returns usage of heap/internal/external BOs. 637 613 */ 638 614 __u32 param; 639 615 /**
+61 -2
include/uapi/drm/panthor_drm.h
··· 410 410 }; 411 411 412 412 /** 413 + * enum drm_panthor_timestamp_info_flags - drm_panthor_timestamp_info.flags 414 + */ 415 + enum drm_panthor_timestamp_info_flags { 416 + /** @DRM_PANTHOR_TIMESTAMP_GPU: Query GPU time. */ 417 + DRM_PANTHOR_TIMESTAMP_GPU = 1 << 0, 418 + 419 + /** @DRM_PANTHOR_TIMESTAMP_CPU_NONE: Don't query CPU time. */ 420 + DRM_PANTHOR_TIMESTAMP_CPU_NONE = 0 << 1, 421 + 422 + /** @DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC: Query CPU time using CLOCK_MONOTONIC. */ 423 + DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC = 1 << 1, 424 + 425 + /** @DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC_RAW: Query CPU time using CLOCK_MONOTONIC_RAW. */ 426 + DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC_RAW = 2 << 1, 427 + 428 + /** @DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK: Space reserved for CPU clock type. */ 429 + DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK = 7 << 1, 430 + 431 + /** @DRM_PANTHOR_TIMESTAMP_GPU_OFFSET: Query GPU offset. */ 432 + DRM_PANTHOR_TIMESTAMP_GPU_OFFSET = 1 << 4, 433 + 434 + /** @DRM_PANTHOR_TIMESTAMP_GPU_CYCLE_COUNT: Query GPU cycle count. */ 435 + DRM_PANTHOR_TIMESTAMP_GPU_CYCLE_COUNT = 1 << 5, 436 + 437 + /** @DRM_PANTHOR_TIMESTAMP_FREQ: Query timestamp frequency. */ 438 + DRM_PANTHOR_TIMESTAMP_FREQ = 1 << 6, 439 + 440 + /** @DRM_PANTHOR_TIMESTAMP_DURATION: Return duration of time query. */ 441 + DRM_PANTHOR_TIMESTAMP_DURATION = 1 << 7, 442 + }; 443 + 444 + /** 413 445 * struct drm_panthor_timestamp_info - Timestamp information 414 446 * 415 447 * Structure grouping all queryable information relating to the GPU timestamp. ··· 453 421 */ 454 422 __u64 timestamp_frequency; 455 423 456 - /** @current_timestamp: The current timestamp. */ 424 + /** @current_timestamp: The current GPU timestamp. */ 457 425 __u64 current_timestamp; 458 426 459 - /** @timestamp_offset: The offset of the timestamp timer. */ 427 + /** @timestamp_offset: The offset of the GPU timestamp timer. */ 460 428 __u64 timestamp_offset; 429 + 430 + /** 431 + * @flags: Bitmask of drm_panthor_timestamp_info_flags. 432 + * 433 + * If set to 0, then it is interpreted as: 434 + * DRM_PANTHOR_TIMESTAMP_GPU | 435 + * DRM_PANTHOR_TIMESTAMP_GPU_OFFSET | 436 + * DRM_PANTHOR_TIMESTAMP_FREQ 437 + * 438 + * Note: these flags are exclusive to each other (only one can be used): 439 + * - DRM_PANTHOR_TIMESTAMP_CPU_NONE 440 + * - DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC 441 + * - DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC_RAW 442 + */ 443 + __u32 flags; 444 + 445 + /** @duration_nsec: Duration of time query. */ 446 + __u32 duration_nsec; 447 + 448 + /** @cycle_count: Value of GPU_CYCLE_COUNT. */ 449 + __u64 cycle_count; 450 + 451 + /** @cpu_timestamp_sec: Seconds part of CPU timestamp. */ 452 + __u64 cpu_timestamp_sec; 453 + 454 + /** @cpu_timestamp_nsec: Nanseconds part of CPU timestamp. */ 455 + __u64 cpu_timestamp_nsec; 461 456 }; 462 457 463 458 /**