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

Merge tag 'drm-misc-next-2024-04-25' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next

drm-misc-next for v6.10-rc1:

UAPI Changes:

Cross-subsystem Changes:
- Devicetree updates for rockchip (#sound-dai-cells)
- Add dt bindings for new panels.
- Change bridge/tc358775 dt bindings.

Core Changes:
- Fix SIZE_HINTS cursor property doc.
- Parse topology blocks for all DispID < 2.0.
- Implement support for tracking cleared free memory, use it in amdgpu.
- Drop seq_file.h from drm_print.h, and include debugfs.h explicitly
where needed (drivers).

Driver Changes:
- Small fixes to rockchip, panthor, v3d, bridge chaining, xlx.
- Add Khadas TS050 V2, EDO RM69380 OLED, CSOT MNB601LS1-1 panels,
- Add SAM9X7 SoC's LVDS controller.
- More driver conversions to struct drm_edid.
- Support tc358765 in tc358775 bridge.

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1ab99848-8fb8-41a6-8967-c4ce6f3634fd@linux.intel.com

+2651 -1042
+55
Documentation/devicetree/bindings/display/bridge/microchip,sam9x75-lvds.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/bridge/microchip,sam9x75-lvds.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Microchip SAM9X75 LVDS Controller 8 + 9 + maintainers: 10 + - Dharma Balasubiramani <dharma.b@microchip.com> 11 + 12 + description: 13 + The Low Voltage Differential Signaling Controller (LVDSC) manages data 14 + format conversion from the LCD Controller internal DPI bus to OpenLDI 15 + LVDS output signals. LVDSC functions include bit mapping, balanced mode 16 + management, and serializer. 17 + 18 + properties: 19 + compatible: 20 + const: microchip,sam9x75-lvds 21 + 22 + reg: 23 + maxItems: 1 24 + 25 + interrupts: 26 + maxItems: 1 27 + 28 + clocks: 29 + items: 30 + - description: Peripheral Bus Clock 31 + 32 + clock-names: 33 + items: 34 + - const: pclk 35 + 36 + required: 37 + - compatible 38 + - reg 39 + - interrupts 40 + - clocks 41 + - clock-names 42 + 43 + additionalProperties: false 44 + 45 + examples: 46 + - | 47 + #include <dt-bindings/interrupt-controller/irq.h> 48 + #include <dt-bindings/clock/at91.h> 49 + lvds-controller@f8060000 { 50 + compatible = "microchip,sam9x75-lvds"; 51 + reg = <0xf8060000 0x100>; 52 + interrupts = <56 IRQ_TYPE_LEVEL_HIGH 0>; 53 + clocks = <&pmc PMC_TYPE_PERIPHERAL 56>; 54 + clock-names = "pclk"; 55 + };
+33 -6
Documentation/devicetree/bindings/display/bridge/toshiba,tc358775.yaml
··· 10 10 - Vinay Simha BN <simhavcs@gmail.com> 11 11 12 12 description: | 13 - This binding supports DSI to LVDS bridge TC358775 13 + This binding supports DSI to LVDS bridges TC358765 and TC358775 14 14 15 15 MIPI DSI-RX Data 4-lane, CLK 1-lane with data rates up to 800 Mbps/lane. 16 16 Video frame size: ··· 21 21 22 22 properties: 23 23 compatible: 24 - const: toshiba,tc358775 24 + enum: 25 + - toshiba,tc358765 26 + - toshiba,tc358775 25 27 26 28 reg: 27 29 maxItems: 1 ··· 48 46 49 47 properties: 50 48 port@0: 51 - $ref: /schemas/graph.yaml#/properties/port 49 + $ref: /schemas/graph.yaml#/$defs/port-base 50 + unevaluatedProperties: false 52 51 description: | 53 52 DSI Input. The remote endpoint phandle should be a 54 53 reference to a valid mipi_dsi_host device node. 54 + 55 + properties: 56 + endpoint: 57 + $ref: /schemas/media/video-interfaces.yaml# 58 + unevaluatedProperties: false 59 + 60 + properties: 61 + data-lanes: 62 + description: array of physical DSI data lane indexes. 63 + minItems: 1 64 + items: 65 + - const: 1 66 + - const: 2 67 + - const: 3 68 + - const: 4 55 69 56 70 port@1: 57 71 $ref: /schemas/graph.yaml#/properties/port ··· 88 70 - reg 89 71 - vdd-supply 90 72 - vddio-supply 91 - - stby-gpios 92 73 - reset-gpios 93 74 - ports 75 + 76 + allOf: 77 + - if: 78 + properties: 79 + compatible: 80 + contains: 81 + const: toshiba,tc358765 82 + then: 83 + properties: 84 + stby-gpios: false 94 85 95 86 additionalProperties: false 96 87 ··· 135 108 reg = <0>; 136 109 d2l_in_test: endpoint { 137 110 remote-endpoint = <&dsi0_out>; 111 + data-lanes = <1 2 3 4>; 138 112 }; 139 113 }; 140 114 ··· 160 132 reg = <1>; 161 133 dsi0_out: endpoint { 162 134 remote-endpoint = <&d2l_in_test>; 163 - data-lanes = <0 1 2 3>; 164 135 }; 165 136 }; 166 137 }; ··· 194 167 reg = <0>; 195 168 d2l_in_dual: endpoint { 196 169 remote-endpoint = <&dsi0_out_dual>; 170 + data-lanes = <1 2 3 4>; 197 171 }; 198 172 }; 199 173 ··· 226 198 reg = <1>; 227 199 dsi0_out_dual: endpoint { 228 200 remote-endpoint = <&d2l_in_dual>; 229 - data-lanes = <0 1 2 3>; 230 201 }; 231 202 }; 232 203 };
+2
Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
··· 36 36 - jdi,fhd-r63452 37 37 # Khadas TS050 5" 1080x1920 LCD panel 38 38 - khadas,ts050 39 + # Khadas TS050 V2 5" 1080x1920 LCD panel 40 + - khadas,ts050v2 39 41 # Kingdisplay KD097D04 9.7" 1536x2048 TFT LCD panel 40 42 - kingdisplay,kd097d04 41 43 # LG ACX467AKM-7 4.95" 1080×1920 LCD Panel
+89
Documentation/devicetree/bindings/display/panel/raydium,rm69380.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/raydium,rm69380.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Raydium RM69380-based DSI display panels 8 + 9 + maintainers: 10 + - David Wronek <david@mainlining.org> 11 + 12 + description: 13 + The Raydium RM69380 is a generic DSI panel IC used to control 14 + OLED panels. 15 + 16 + allOf: 17 + - $ref: panel-common-dual.yaml# 18 + 19 + properties: 20 + compatible: 21 + items: 22 + - enum: 23 + - lenovo,j716f-edo-rm69380 24 + - const: raydium,rm69380 25 + description: This indicates the panel manufacturer of the panel 26 + that is in turn using the RM69380 panel driver. The compatible 27 + string determines how the RM69380 panel driver shall be configured 28 + to work with the indicated panel. The raydium,rm69380 compatible shall 29 + always be provided as a fallback. 30 + 31 + avdd-supply: 32 + description: Analog voltage rail 33 + 34 + vddio-supply: 35 + description: I/O voltage rail 36 + 37 + reset-gpios: 38 + maxItems: 1 39 + description: phandle of gpio for reset line - This should be active low 40 + 41 + reg: true 42 + 43 + required: 44 + - compatible 45 + - reg 46 + - avdd-supply 47 + - vddio-supply 48 + - reset-gpios 49 + 50 + unevaluatedProperties: false 51 + 52 + examples: 53 + - | 54 + #include <dt-bindings/gpio/gpio.h> 55 + 56 + dsi { 57 + #address-cells = <1>; 58 + #size-cells = <0>; 59 + 60 + panel@0 { 61 + compatible = "lenovo,j716f-edo-rm69380", "raydium,rm69380"; 62 + reg = <0>; 63 + 64 + avdd-supply = <&panel_avdd_regulator>; 65 + vddio-supply = <&vreg_l14a>; 66 + reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>; 67 + 68 + ports { 69 + #address-cells = <1>; 70 + #size-cells = <0>; 71 + 72 + port@0 { 73 + reg = <0>; 74 + panel_in_0: endpoint { 75 + remote-endpoint = <&mdss_dsi0_out>; 76 + }; 77 + }; 78 + 79 + port@1 { 80 + reg = <1>; 81 + panel_in_1: endpoint { 82 + remote-endpoint = <&mdss_dsi1_out>; 83 + }; 84 + }; 85 + }; 86 + }; 87 + }; 88 + 89 + ...
+5
Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
··· 15 15 16 16 allOf: 17 17 - $ref: ../bridge/synopsys,dw-hdmi.yaml# 18 + - $ref: /schemas/sound/dai-common.yaml# 18 19 19 20 properties: 20 21 compatible: ··· 125 124 description: 126 125 phandle to the GRF to mux vopl/vopb. 127 126 127 + "#sound-dai-cells": 128 + const: 0 129 + 128 130 required: 129 131 - compatible 130 132 - reg ··· 157 153 ddc-i2c-bus = <&i2c5>; 158 154 power-domains = <&power RK3288_PD_VIO>; 159 155 rockchip,grf = <&grf>; 156 + #sound-dai-cells = <0>; 160 157 161 158 ports { 162 159 #address-cells = <1>;
+5
Documentation/devicetree/bindings/display/rockchip/rockchip,inno-hdmi.yaml
··· 37 37 power-domains: 38 38 maxItems: 1 39 39 40 + "#sound-dai-cells": 41 + const: 0 42 + 40 43 ports: 41 44 $ref: /schemas/graph.yaml#/properties/ports 42 45 ··· 69 66 - ports 70 67 71 68 allOf: 69 + - $ref: /schemas/sound/dai-common.yaml# 72 70 - if: 73 71 properties: 74 72 compatible: ··· 110 106 clock-names = "pclk"; 111 107 pinctrl-names = "default"; 112 108 pinctrl-0 = <&hdmi_ctl>; 109 + #sound-dai-cells = <0>; 113 110 114 111 ports { 115 112 #address-cells = <1>;
+7
Documentation/devicetree/bindings/display/rockchip/rockchip,rk3066-hdmi.yaml
··· 10 10 - Sandy Huang <hjc@rock-chips.com> 11 11 - Heiko Stuebner <heiko@sntech.de> 12 12 13 + allOf: 14 + - $ref: /schemas/sound/dai-common.yaml# 15 + 13 16 properties: 14 17 compatible: 15 18 const: rockchip,rk3066-hdmi ··· 36 33 $ref: /schemas/types.yaml#/definitions/phandle 37 34 description: 38 35 This soc uses GRF regs to switch the HDMI TX input between vop0 and vop1. 36 + 37 + "#sound-dai-cells": 38 + const: 0 39 39 40 40 ports: 41 41 $ref: /schemas/graph.yaml#/properties/ports ··· 89 83 pinctrl-names = "default"; 90 84 power-domains = <&power RK3066_PD_VIO>; 91 85 rockchip,grf = <&grf>; 86 + #sound-dai-cells = <0>; 92 87 93 88 ports { 94 89 #address-cells = <1>;
+8
MAINTAINERS
··· 14582 14582 F: Documentation/devicetree/bindings/pwm/atmel,at91sam-pwm.yaml 14583 14583 F: drivers/pwm/pwm-atmel.c 14584 14584 14585 + MICROCHIP SAM9x7-COMPATIBLE LVDS CONTROLLER 14586 + M: Manikandan Muralidharan <manikandan.m@microchip.com> 14587 + M: Dharma Balasubiramani <dharma.b@microchip.com> 14588 + L: dri-devel@lists.freedesktop.org 14589 + S: Supported 14590 + F: Documentation/devicetree/bindings/display/bridge/microchip,sam9x75-lvds.yaml 14591 + F: drivers/gpu/drm/bridge/microchip-lvds.c 14592 + 14585 14593 MICROCHIP SAMA5D2-COMPATIBLE ADC DRIVER 14586 14594 M: Eugen Hristev <eugen.hristev@microchip.com> 14587 14595 L: linux-iio@vger.kernel.org
+2
drivers/accel/ivpu/ivpu_debugfs.c
··· 3 3 * Copyright (C) 2020-2023 Intel Corporation 4 4 */ 5 5 6 + #include <linux/debugfs.h> 7 + 6 8 #include <drm/drm_debugfs.h> 7 9 #include <drm/drm_file.h> 8 10 #include <drm/drm_print.h>
+5 -4
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
··· 39 39 #include "amdgpu.h" 40 40 #include "amdgpu_trace.h" 41 41 #include "amdgpu_amdkfd.h" 42 + #include "amdgpu_vram_mgr.h" 42 43 43 44 /** 44 45 * DOC: amdgpu_object ··· 602 601 if (!amdgpu_bo_support_uswc(bo->flags)) 603 602 bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC; 604 603 605 - if (adev->ras_enabled) 606 - bo->flags |= AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE; 604 + bo->flags |= AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE; 607 605 608 606 bo->tbo.bdev = &adev->mman.bdev; 609 607 if (bp->domain & (AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA | ··· 633 633 bo->tbo.resource->mem_type == TTM_PL_VRAM) { 634 634 struct dma_fence *fence; 635 635 636 - r = amdgpu_fill_buffer(bo, 0, bo->tbo.base.resv, &fence, true); 636 + r = amdgpu_ttm_clear_buffer(bo, bo->tbo.base.resv, &fence); 637 637 if (unlikely(r)) 638 638 goto fail_unreserve; 639 639 ··· 1366 1366 if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv))) 1367 1367 return; 1368 1368 1369 - r = amdgpu_fill_buffer(abo, AMDGPU_POISON, bo->base.resv, &fence, true); 1369 + r = amdgpu_fill_buffer(abo, 0, bo->base.resv, &fence, true); 1370 1370 if (!WARN_ON(r)) { 1371 + amdgpu_vram_mgr_set_cleared(bo->resource); 1371 1372 amdgpu_bo_fence(abo, fence, false); 1372 1373 dma_fence_put(fence); 1373 1374 }
+25
drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
··· 164 164 } 165 165 } 166 166 167 + /** 168 + * amdgpu_res_cleared - check if blocks are cleared 169 + * 170 + * @cur: the cursor to extract the block 171 + * 172 + * Check if the @cur block is cleared 173 + */ 174 + static inline bool amdgpu_res_cleared(struct amdgpu_res_cursor *cur) 175 + { 176 + struct drm_buddy_block *block; 177 + 178 + switch (cur->mem_type) { 179 + case TTM_PL_VRAM: 180 + block = cur->node; 181 + 182 + if (!amdgpu_vram_mgr_is_cleared(block)) 183 + return false; 184 + break; 185 + default: 186 + return false; 187 + } 188 + 189 + return true; 190 + } 191 + 167 192 #endif
+68 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
··· 378 378 (abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE)) { 379 379 struct dma_fence *wipe_fence = NULL; 380 380 381 - r = amdgpu_fill_buffer(abo, AMDGPU_POISON, NULL, &wipe_fence, 382 - false); 381 + r = amdgpu_fill_buffer(abo, 0, NULL, &wipe_fence, 382 + false); 383 383 if (r) { 384 384 goto error; 385 385 } else if (wipe_fence) { 386 + amdgpu_vram_mgr_set_cleared(bo->resource); 386 387 dma_fence_put(fence); 387 388 fence = wipe_fence; 388 389 } ··· 2225 2224 WARN_ON(job->ibs[0].length_dw > num_dw); 2226 2225 *fence = amdgpu_job_submit(job); 2227 2226 return 0; 2227 + } 2228 + 2229 + /** 2230 + * amdgpu_ttm_clear_buffer - clear memory buffers 2231 + * @bo: amdgpu buffer object 2232 + * @resv: reservation object 2233 + * @fence: dma_fence associated with the operation 2234 + * 2235 + * Clear the memory buffer resource. 2236 + * 2237 + * Returns: 2238 + * 0 for success or a negative error code on failure. 2239 + */ 2240 + int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo, 2241 + struct dma_resv *resv, 2242 + struct dma_fence **fence) 2243 + { 2244 + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); 2245 + struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; 2246 + struct amdgpu_res_cursor cursor; 2247 + u64 addr; 2248 + int r; 2249 + 2250 + if (!adev->mman.buffer_funcs_enabled) 2251 + return -EINVAL; 2252 + 2253 + if (!fence) 2254 + return -EINVAL; 2255 + 2256 + *fence = dma_fence_get_stub(); 2257 + 2258 + amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor); 2259 + 2260 + mutex_lock(&adev->mman.gtt_window_lock); 2261 + while (cursor.remaining) { 2262 + struct dma_fence *next = NULL; 2263 + u64 size; 2264 + 2265 + if (amdgpu_res_cleared(&cursor)) { 2266 + amdgpu_res_next(&cursor, cursor.size); 2267 + continue; 2268 + } 2269 + 2270 + /* Never clear more than 256MiB at once to avoid timeouts */ 2271 + size = min(cursor.size, 256ULL << 20); 2272 + 2273 + r = amdgpu_ttm_map_buffer(&bo->tbo, bo->tbo.resource, &cursor, 2274 + 1, ring, false, &size, &addr); 2275 + if (r) 2276 + goto err; 2277 + 2278 + r = amdgpu_ttm_fill_mem(ring, 0, addr, size, resv, 2279 + &next, true, true); 2280 + if (r) 2281 + goto err; 2282 + 2283 + dma_fence_put(*fence); 2284 + *fence = next; 2285 + 2286 + amdgpu_res_next(&cursor, size); 2287 + } 2288 + err: 2289 + mutex_unlock(&adev->mman.gtt_window_lock); 2290 + 2291 + return r; 2228 2292 } 2229 2293 2230 2294 int amdgpu_fill_buffer(struct amdgpu_bo *bo,
+3 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
··· 38 38 #define AMDGPU_GTT_MAX_TRANSFER_SIZE 512 39 39 #define AMDGPU_GTT_NUM_TRANSFER_WINDOWS 2 40 40 41 - #define AMDGPU_POISON 0xd0bed0be 42 - 43 41 extern const struct attribute_group amdgpu_vram_mgr_attr_group; 44 42 extern const struct attribute_group amdgpu_gtt_mgr_attr_group; 45 43 ··· 156 158 uint64_t size, bool tmz, 157 159 struct dma_resv *resv, 158 160 struct dma_fence **f); 161 + int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo, 162 + struct dma_resv *resv, 163 + struct dma_fence **fence); 159 164 int amdgpu_fill_buffer(struct amdgpu_bo *bo, 160 165 uint32_t src_data, 161 166 struct dma_resv *resv,
+7 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
··· 450 450 { 451 451 struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); 452 452 struct amdgpu_device *adev = to_amdgpu_device(mgr); 453 + struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo); 453 454 u64 vis_usage = 0, max_bytes, min_block_size; 454 455 struct amdgpu_vram_mgr_resource *vres; 455 456 u64 size, remaining_size, lpfn, fpfn; ··· 501 500 502 501 if (place->flags & TTM_PL_FLAG_CONTIGUOUS) 503 502 vres->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION; 503 + 504 + if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CLEARED) 505 + vres->flags |= DRM_BUDDY_CLEAR_ALLOCATION; 504 506 505 507 if (fpfn || lpfn != mgr->mm.size) 506 508 /* Allocate blocks in desired range */ ··· 575 571 return 0; 576 572 577 573 error_free_blocks: 578 - drm_buddy_free_list(mm, &vres->blocks); 574 + drm_buddy_free_list(mm, &vres->blocks, 0); 579 575 mutex_unlock(&mgr->lock); 580 576 error_fini: 581 577 ttm_resource_fini(man, &vres->base); ··· 608 604 609 605 amdgpu_vram_mgr_do_reserve(man); 610 606 611 - drm_buddy_free_list(mm, &vres->blocks); 607 + drm_buddy_free_list(mm, &vres->blocks, vres->flags); 612 608 mutex_unlock(&mgr->lock); 613 609 614 610 atomic64_sub(vis_usage, &mgr->vis_usage); ··· 916 912 kfree(rsv); 917 913 918 914 list_for_each_entry_safe(rsv, temp, &mgr->reserved_pages, blocks) { 919 - drm_buddy_free_list(&mgr->mm, &rsv->allocated); 915 + drm_buddy_free_list(&mgr->mm, &rsv->allocated, 0); 920 916 kfree(rsv); 921 917 } 922 918 if (!adev->gmc.is_app_apu)
+10
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
··· 53 53 return (u64)PAGE_SIZE << drm_buddy_block_order(block); 54 54 } 55 55 56 + static inline bool amdgpu_vram_mgr_is_cleared(struct drm_buddy_block *block) 57 + { 58 + return drm_buddy_block_is_clear(block); 59 + } 60 + 56 61 static inline struct amdgpu_vram_mgr_resource * 57 62 to_amdgpu_vram_mgr_resource(struct ttm_resource *res) 58 63 { 59 64 return container_of(res, struct amdgpu_vram_mgr_resource, base); 65 + } 66 + 67 + static inline void amdgpu_vram_mgr_set_cleared(struct ttm_resource *res) 68 + { 69 + to_amdgpu_vram_mgr_resource(res)->flags |= DRM_BUDDY_CLEARED; 60 70 } 61 71 62 72 #endif
+1
drivers/gpu/drm/armada/armada_debugfs.c
··· 5 5 */ 6 6 7 7 #include <linux/ctype.h> 8 + #include <linux/debugfs.h> 8 9 #include <linux/module.h> 9 10 #include <linux/seq_file.h> 10 11 #include <linux/uaccess.h>
+7
drivers/gpu/drm/bridge/Kconfig
··· 189 189 to DP++. This is used with the i.MX6 imx-ldb 190 190 driver. You are likely to say N here. 191 191 192 + config DRM_MICROCHIP_LVDS_SERIALIZER 193 + tristate "Microchip LVDS serializer support" 194 + depends on OF 195 + depends on DRM_ATMEL_HLCDC 196 + help 197 + Support for Microchip's LVDS serializer. 198 + 192 199 config DRM_NWL_MIPI_DSI 193 200 tristate "Northwest Logic MIPI DSI Host controller" 194 201 depends on DRM
+1
drivers/gpu/drm/bridge/Makefile
··· 13 13 obj-$(CONFIG_DRM_LONTIUM_LT9611UXC) += lontium-lt9611uxc.o 14 14 obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o 15 15 obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o 16 + obj-$(CONFIG_DRM_MICROCHIP_LVDS_SERIALIZER) += microchip-lvds.o 16 17 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o 17 18 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o 18 19 obj-$(CONFIG_DRM_PARADE_PS8640) += parade-ps8640.o
+1
drivers/gpu/drm/bridge/adv7511/adv7511.h
··· 356 356 enum drm_connector_status status; 357 357 bool powered; 358 358 359 + struct drm_bridge *next_bridge; 359 360 struct drm_display_mode curr_mode; 360 361 361 362 unsigned int f_tmds;
+12
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
··· 17 17 #include <drm/drm_atomic.h> 18 18 #include <drm/drm_atomic_helper.h> 19 19 #include <drm/drm_edid.h> 20 + #include <drm/drm_of.h> 20 21 #include <drm/drm_print.h> 21 22 #include <drm/drm_probe_helper.h> 22 23 ··· 952 951 struct adv7511 *adv = bridge_to_adv7511(bridge); 953 952 int ret = 0; 954 953 954 + if (adv->next_bridge) { 955 + ret = drm_bridge_attach(bridge->encoder, adv->next_bridge, bridge, flags); 956 + if (ret) 957 + return ret; 958 + } 959 + 955 960 if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { 956 961 ret = adv7511_connector_init(adv); 957 962 if (ret < 0) ··· 1227 1220 adv7511->info = i2c_get_match_data(i2c); 1228 1221 1229 1222 memset(&link_config, 0, sizeof(link_config)); 1223 + 1224 + ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1, NULL, 1225 + &adv7511->next_bridge); 1226 + if (ret && ret != -ENODEV) 1227 + return ret; 1230 1228 1231 1229 if (adv7511->info->link_config) 1232 1230 ret = adv7511_parse_dt(dev->of_node, &link_config);
-1
drivers/gpu/drm/bridge/chipone-icn6211.c
··· 781 781 .remove = chipone_dsi_remove, 782 782 .driver = { 783 783 .name = "chipone-icn6211", 784 - .owner = THIS_MODULE, 785 784 .of_match_table = chipone_of_match, 786 785 }, 787 786 };
+2 -2
drivers/gpu/drm/bridge/imx/Kconfig
··· 8 8 depends on COMMON_CLK 9 9 depends on DRM_DW_HDMI 10 10 depends on OF 11 - select DRM_IMX8MP_HDMI_PVI 12 - select PHY_FSL_SAMSUNG_HDMI_PHY 11 + imply DRM_IMX8MP_HDMI_PVI 12 + imply PHY_FSL_SAMSUNG_HDMI_PHY 13 13 help 14 14 Choose this to enable support for the internal HDMI encoder found 15 15 on the i.MX8MP SoC.
+1
drivers/gpu/drm/bridge/ite-it6505.c
··· 3 3 * Copyright (c) 2020, The Linux Foundation. All rights reserved. 4 4 */ 5 5 #include <linux/bits.h> 6 + #include <linux/debugfs.h> 6 7 #include <linux/delay.h> 7 8 #include <linux/device.h> 8 9 #include <linux/err.h>
+229
drivers/gpu/drm/bridge/microchip-lvds.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2023 Microchip Technology Inc. and its subsidiaries 4 + * 5 + * Author: Manikandan Muralidharan <manikandan.m@microchip.com> 6 + * Author: Dharma Balasubiramani <dharma.b@microchip.com> 7 + * 8 + */ 9 + 10 + #include <linux/clk.h> 11 + #include <linux/component.h> 12 + #include <linux/delay.h> 13 + #include <linux/jiffies.h> 14 + #include <linux/mfd/syscon.h> 15 + #include <linux/of_graph.h> 16 + #include <linux/pinctrl/devinfo.h> 17 + #include <linux/phy/phy.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/pm_runtime.h> 20 + #include <linux/regmap.h> 21 + #include <linux/reset.h> 22 + 23 + #include <drm/drm_atomic_helper.h> 24 + #include <drm/drm_bridge.h> 25 + #include <drm/drm_of.h> 26 + #include <drm/drm_panel.h> 27 + #include <drm/drm_print.h> 28 + #include <drm/drm_probe_helper.h> 29 + #include <drm/drm_simple_kms_helper.h> 30 + 31 + #define LVDS_POLL_TIMEOUT_MS 1000 32 + 33 + /* LVDSC register offsets */ 34 + #define LVDSC_CR 0x00 35 + #define LVDSC_CFGR 0x04 36 + #define LVDSC_SR 0x0C 37 + #define LVDSC_WPMR 0xE4 38 + 39 + /* Bitfields in LVDSC_CR (Control Register) */ 40 + #define LVDSC_CR_SER_EN BIT(0) 41 + 42 + /* Bitfields in LVDSC_CFGR (Configuration Register) */ 43 + #define LVDSC_CFGR_PIXSIZE_24BITS 0 44 + #define LVDSC_CFGR_DEN_POL_HIGH 0 45 + #define LVDSC_CFGR_DC_UNBALANCED 0 46 + #define LVDSC_CFGR_MAPPING_JEIDA BIT(6) 47 + 48 + /*Bitfields in LVDSC_SR */ 49 + #define LVDSC_SR_CS BIT(0) 50 + 51 + /* Bitfields in LVDSC_WPMR (Write Protection Mode Register) */ 52 + #define LVDSC_WPMR_WPKEY_MASK GENMASK(31, 8) 53 + #define LVDSC_WPMR_WPKEY_PSSWD 0x4C5644 54 + 55 + struct mchp_lvds { 56 + struct device *dev; 57 + void __iomem *regs; 58 + struct clk *pclk; 59 + struct drm_panel *panel; 60 + struct drm_bridge bridge; 61 + struct drm_bridge *panel_bridge; 62 + }; 63 + 64 + static inline struct mchp_lvds *bridge_to_lvds(struct drm_bridge *bridge) 65 + { 66 + return container_of(bridge, struct mchp_lvds, bridge); 67 + } 68 + 69 + static inline u32 lvds_readl(struct mchp_lvds *lvds, u32 offset) 70 + { 71 + return readl_relaxed(lvds->regs + offset); 72 + } 73 + 74 + static inline void lvds_writel(struct mchp_lvds *lvds, u32 offset, u32 val) 75 + { 76 + writel_relaxed(val, lvds->regs + offset); 77 + } 78 + 79 + static void lvds_serialiser_on(struct mchp_lvds *lvds) 80 + { 81 + unsigned long timeout = jiffies + msecs_to_jiffies(LVDS_POLL_TIMEOUT_MS); 82 + 83 + /* The LVDSC registers can only be written if WPEN is cleared */ 84 + lvds_writel(lvds, LVDSC_WPMR, (LVDSC_WPMR_WPKEY_PSSWD & 85 + LVDSC_WPMR_WPKEY_MASK)); 86 + 87 + /* Wait for the status of configuration registers to be changed */ 88 + while (lvds_readl(lvds, LVDSC_SR) & LVDSC_SR_CS) { 89 + if (time_after(jiffies, timeout)) { 90 + dev_err(lvds->dev, "%s: timeout error\n", __func__); 91 + return; 92 + } 93 + usleep_range(1000, 2000); 94 + } 95 + 96 + /* Configure the LVDSC */ 97 + lvds_writel(lvds, LVDSC_CFGR, (LVDSC_CFGR_MAPPING_JEIDA | 98 + LVDSC_CFGR_DC_UNBALANCED | 99 + LVDSC_CFGR_DEN_POL_HIGH | 100 + LVDSC_CFGR_PIXSIZE_24BITS)); 101 + 102 + /* Enable the LVDS serializer */ 103 + lvds_writel(lvds, LVDSC_CR, LVDSC_CR_SER_EN); 104 + } 105 + 106 + static int mchp_lvds_attach(struct drm_bridge *bridge, 107 + enum drm_bridge_attach_flags flags) 108 + { 109 + struct mchp_lvds *lvds = bridge_to_lvds(bridge); 110 + 111 + return drm_bridge_attach(bridge->encoder, lvds->panel_bridge, 112 + bridge, flags); 113 + } 114 + 115 + static void mchp_lvds_enable(struct drm_bridge *bridge) 116 + { 117 + struct mchp_lvds *lvds = bridge_to_lvds(bridge); 118 + int ret; 119 + 120 + ret = clk_prepare_enable(lvds->pclk); 121 + if (ret < 0) { 122 + dev_err(lvds->dev, "failed to enable lvds pclk %d\n", ret); 123 + return; 124 + } 125 + 126 + ret = pm_runtime_get_sync(lvds->dev); 127 + if (ret < 0) { 128 + dev_err(lvds->dev, "failed to get pm runtime: %d\n", ret); 129 + return; 130 + } 131 + 132 + lvds_serialiser_on(lvds); 133 + } 134 + 135 + static void mchp_lvds_disable(struct drm_bridge *bridge) 136 + { 137 + struct mchp_lvds *lvds = bridge_to_lvds(bridge); 138 + 139 + pm_runtime_put(lvds->dev); 140 + clk_disable_unprepare(lvds->pclk); 141 + } 142 + 143 + static const struct drm_bridge_funcs mchp_lvds_bridge_funcs = { 144 + .attach = mchp_lvds_attach, 145 + .enable = mchp_lvds_enable, 146 + .disable = mchp_lvds_disable, 147 + }; 148 + 149 + static int mchp_lvds_probe(struct platform_device *pdev) 150 + { 151 + struct device *dev = &pdev->dev; 152 + struct mchp_lvds *lvds; 153 + struct device_node *port; 154 + int ret; 155 + 156 + if (!dev->of_node) 157 + return -ENODEV; 158 + 159 + lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL); 160 + if (!lvds) 161 + return -ENOMEM; 162 + 163 + lvds->dev = dev; 164 + 165 + lvds->regs = devm_ioremap_resource(lvds->dev, 166 + platform_get_resource(pdev, IORESOURCE_MEM, 0)); 167 + if (IS_ERR(lvds->regs)) 168 + return PTR_ERR(lvds->regs); 169 + 170 + lvds->pclk = devm_clk_get(lvds->dev, "pclk"); 171 + if (IS_ERR(lvds->pclk)) 172 + return dev_err_probe(lvds->dev, PTR_ERR(lvds->pclk), 173 + "could not get pclk_lvds\n"); 174 + 175 + port = of_graph_get_remote_node(dev->of_node, 1, 0); 176 + if (!port) { 177 + dev_err(dev, 178 + "can't find port point, please init lvds panel port!\n"); 179 + return -ENODEV; 180 + } 181 + 182 + lvds->panel = of_drm_find_panel(port); 183 + of_node_put(port); 184 + 185 + if (IS_ERR(lvds->panel)) 186 + return -EPROBE_DEFER; 187 + 188 + lvds->panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); 189 + 190 + if (IS_ERR(lvds->panel_bridge)) 191 + return PTR_ERR(lvds->panel_bridge); 192 + 193 + lvds->bridge.of_node = dev->of_node; 194 + lvds->bridge.type = DRM_MODE_CONNECTOR_LVDS; 195 + lvds->bridge.funcs = &mchp_lvds_bridge_funcs; 196 + 197 + dev_set_drvdata(dev, lvds); 198 + ret = devm_pm_runtime_enable(dev); 199 + if (ret < 0) { 200 + dev_err(lvds->dev, "failed to enable pm runtime: %d\n", ret); 201 + return ret; 202 + } 203 + 204 + drm_bridge_add(&lvds->bridge); 205 + 206 + return 0; 207 + } 208 + 209 + static const struct of_device_id mchp_lvds_dt_ids[] = { 210 + { 211 + .compatible = "microchip,sam9x75-lvds", 212 + }, 213 + {}, 214 + }; 215 + MODULE_DEVICE_TABLE(of, mchp_lvds_dt_ids); 216 + 217 + static struct platform_driver mchp_lvds_driver = { 218 + .probe = mchp_lvds_probe, 219 + .driver = { 220 + .name = "microchip-lvds", 221 + .of_match_table = mchp_lvds_dt_ids, 222 + }, 223 + }; 224 + module_platform_driver(mchp_lvds_driver); 225 + 226 + MODULE_AUTHOR("Manikandan Muralidharan <manikandan.m@microchip.com>"); 227 + MODULE_AUTHOR("Dharma Balasubiramani <dharma.b@microchip.com>"); 228 + MODULE_DESCRIPTION("Low Voltage Differential Signaling Controller Driver"); 229 + MODULE_LICENSE("GPL");
+2
drivers/gpu/drm/bridge/panel.c
··· 4 4 * Copyright (C) 2017 Broadcom 5 5 */ 6 6 7 + #include <linux/debugfs.h> 8 + 7 9 #include <drm/drm_atomic_helper.h> 8 10 #include <drm/drm_bridge.h> 9 11 #include <drm/drm_connector.h>
-1
drivers/gpu/drm/bridge/tc358764.c
··· 401 401 .remove = tc358764_remove, 402 402 .driver = { 403 403 .name = "tc358764", 404 - .owner = THIS_MODULE, 405 404 .of_match_table = tc358764_of_match, 406 405 }, 407 406 };
+61 -37
drivers/gpu/drm/bridge/tc358775.c
··· 15 15 #include <linux/kernel.h> 16 16 #include <linux/media-bus-format.h> 17 17 #include <linux/module.h> 18 + #include <linux/of_device.h> 18 19 #include <linux/regulator/consumer.h> 19 20 #include <linux/slab.h> 20 21 ··· 108 107 #define RDPKTLN 0x0404 /* Command Read Packet Length */ 109 108 110 109 #define VPCTRL 0x0450 /* Video Path Control */ 110 + #define EVTMODE BIT(5) /* Video event mode enable, tc35876x only */ 111 111 #define HTIM1 0x0454 /* Horizontal Timing Control 1 */ 112 112 #define HTIM2 0x0458 /* Horizontal Timing Control 2 */ 113 113 #define VTIM1 0x045C /* Vertical Timing Control 1 */ ··· 256 254 TC358775_LVDS_OUT1, 257 255 }; 258 256 257 + enum tc3587x5_type { 258 + TC358765 = 0x65, 259 + TC358775 = 0x75, 260 + }; 261 + 259 262 struct tc_data { 260 263 struct i2c_client *i2c; 261 264 struct device *dev; ··· 278 271 struct gpio_desc *stby_gpio; 279 272 u8 lvds_link; /* single-link or dual-link */ 280 273 u8 bpc; 274 + 275 + enum tc3587x5_type type; 281 276 }; 282 277 283 278 static inline struct tc_data *bridge_to_tc(struct drm_bridge *b) ··· 433 424 d2l_write(tc->i2c, PPI_STARTPPI, PPI_START_FUNCTION); 434 425 d2l_write(tc->i2c, DSI_STARTDSI, DSI_RX_START); 435 426 427 + /* Video event mode vs pulse mode bit, does not exist for tc358775 */ 428 + if (tc->type == TC358765) 429 + val = EVTMODE; 430 + else 431 + val = 0; 432 + 436 433 if (tc->bpc == 8) 437 - val = TC358775_VPCTRL_OPXLFMT(1); 434 + val |= TC358775_VPCTRL_OPXLFMT(1); 438 435 else /* bpc = 6; */ 439 - val = TC358775_VPCTRL_MSF(1); 436 + val |= TC358775_VPCTRL_MSF(1); 440 437 441 438 dsiclk = mode->crtc_clock * 3 * tc->bpc / tc->num_dsi_lanes / 1000; 442 439 clkdiv = dsiclk / (tc->lvds_link == DUAL_LINK ? DIVIDE_BY_6 : DIVIDE_BY_3); ··· 469 454 dev_dbg(tc->dev, "bus_formats %04x bpc %d\n", 470 455 connector->display_info.bus_formats[0], 471 456 tc->bpc); 472 - /* 473 - * Default hardware register settings of tc358775 configured 474 - * with MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA jeida-24 format 475 - */ 476 457 if (connector->display_info.bus_formats[0] == 477 458 MEDIA_BUS_FMT_RGB888_1X7X4_SPWG) { 478 459 /* VESA-24 */ ··· 479 468 d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_B6, LVI_B7, LVI_B1, LVI_B2)); 480 469 d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0)); 481 470 d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R6)); 482 - } else { /* MEDIA_BUS_FMT_RGB666_1X7X3_SPWG - JEIDA-18 */ 483 - d2l_write(tc->i2c, LV_MX0003, LV_MX(LVI_R0, LVI_R1, LVI_R2, LVI_R3)); 484 - d2l_write(tc->i2c, LV_MX0407, LV_MX(LVI_R4, LVI_L0, LVI_R5, LVI_G0)); 485 - d2l_write(tc->i2c, LV_MX0811, LV_MX(LVI_G1, LVI_G2, LVI_L0, LVI_L0)); 486 - d2l_write(tc->i2c, LV_MX1215, LV_MX(LVI_G3, LVI_G4, LVI_G5, LVI_B0)); 487 - d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_L0, LVI_L0, LVI_B1, LVI_B2)); 488 - d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0)); 489 - d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_L0)); 471 + } else { 472 + /* JEIDA-18 and JEIDA-24 */ 473 + d2l_write(tc->i2c, LV_MX0003, LV_MX(LVI_R2, LVI_R3, LVI_R4, LVI_R5)); 474 + d2l_write(tc->i2c, LV_MX0407, LV_MX(LVI_R6, LVI_R1, LVI_R7, LVI_G2)); 475 + d2l_write(tc->i2c, LV_MX0811, LV_MX(LVI_G3, LVI_G4, LVI_G0, LVI_G1)); 476 + d2l_write(tc->i2c, LV_MX1215, LV_MX(LVI_G5, LVI_G6, LVI_G7, LVI_B2)); 477 + d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_B0, LVI_B1, LVI_B3, LVI_B4)); 478 + d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B5, LVI_B6, LVI_B7, LVI_L0)); 479 + d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R0)); 490 480 } 491 481 492 482 d2l_write(tc->i2c, VFUEN, VFUEN_EN); ··· 540 528 static int tc358775_parse_dt(struct device_node *np, struct tc_data *tc) 541 529 { 542 530 struct device_node *endpoint; 543 - struct device_node *parent; 544 531 struct device_node *remote; 545 532 int dsi_lanes = -1; 546 533 547 - /* 548 - * To get the data-lanes of dsi, we need to access the dsi0_out of port1 549 - * of dsi0 endpoint from bridge port0 of d2l_in 550 - */ 551 534 endpoint = of_graph_get_endpoint_by_regs(tc->dev->of_node, 552 535 TC358775_DSI_IN, -1); 553 - if (endpoint) { 554 - /* dsi0_out node */ 555 - parent = of_graph_get_remote_port_parent(endpoint); 556 - of_node_put(endpoint); 557 - if (parent) { 558 - /* dsi0 port 1 */ 559 - dsi_lanes = drm_of_get_data_lanes_count_ep(parent, 1, -1, 1, 4); 560 - of_node_put(parent); 561 - } 536 + dsi_lanes = drm_of_get_data_lanes_count(endpoint, 1, 4); 537 + 538 + /* Quirk old dtb: Use data lanes from the DSI host side instead of bridge */ 539 + if (dsi_lanes == -EINVAL || dsi_lanes == -ENODEV) { 540 + remote = of_graph_get_remote_endpoint(endpoint); 541 + dsi_lanes = drm_of_get_data_lanes_count(remote, 1, 4); 542 + of_node_put(remote); 543 + if (dsi_lanes >= 1) 544 + dev_warn(tc->dev, "no dsi-lanes for the bridge, using host lanes\n"); 562 545 } 546 + 547 + of_node_put(endpoint); 563 548 564 549 if (dsi_lanes < 0) 565 550 return dsi_lanes; ··· 632 623 633 624 dsi->lanes = tc->num_dsi_lanes; 634 625 dsi->format = MIPI_DSI_FMT_RGB888; 635 - dsi->mode_flags = MIPI_DSI_MODE_VIDEO; 626 + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | 627 + MIPI_DSI_MODE_LPM; 628 + 629 + /* 630 + * The hs_rate and lp_rate are data rate values. The HS mode is 631 + * differential, while the LP mode is single ended. As the HS mode 632 + * uses DDR, the DSI clock frequency is half the hs_rate. The 10 Mbs 633 + * data rate for LP mode is not specified in the bridge data sheet, 634 + * but seems to be part of the MIPI DSI spec. 635 + */ 636 + if (tc->type == TC358765) 637 + dsi->hs_rate = 800000000; 638 + else 639 + dsi->hs_rate = 1000000000; 640 + dsi->lp_rate = 10000000; 636 641 637 642 ret = devm_mipi_dsi_attach(dev, dsi); 638 643 if (ret < 0) { ··· 669 646 670 647 tc->dev = dev; 671 648 tc->i2c = client; 649 + tc->type = (enum tc3587x5_type)(unsigned long)of_device_get_match_data(dev); 672 650 673 651 tc->panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 674 652 TC358775_LVDS_OUT0, 0); ··· 694 670 return ret; 695 671 } 696 672 697 - tc->stby_gpio = devm_gpiod_get(dev, "stby", GPIOD_OUT_HIGH); 698 - if (IS_ERR(tc->stby_gpio)) { 699 - ret = PTR_ERR(tc->stby_gpio); 700 - dev_err(dev, "cannot get stby-gpio %d\n", ret); 701 - return ret; 702 - } 673 + tc->stby_gpio = devm_gpiod_get_optional(dev, "stby", GPIOD_OUT_HIGH); 674 + if (IS_ERR(tc->stby_gpio)) 675 + return PTR_ERR(tc->stby_gpio); 703 676 704 677 tc->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 705 678 if (IS_ERR(tc->reset_gpio)) { ··· 707 686 708 687 tc->bridge.funcs = &tc_bridge_funcs; 709 688 tc->bridge.of_node = dev->of_node; 689 + tc->bridge.pre_enable_prev_first = true; 710 690 drm_bridge_add(&tc->bridge); 711 691 712 692 i2c_set_clientdata(client, tc); ··· 731 709 } 732 710 733 711 static const struct i2c_device_id tc358775_i2c_ids[] = { 734 - { "tc358775", 0 }, 712 + { "tc358765", TC358765, }, 713 + { "tc358775", TC358775, }, 735 714 { } 736 715 }; 737 716 MODULE_DEVICE_TABLE(i2c, tc358775_i2c_ids); 738 717 739 718 static const struct of_device_id tc358775_of_ids[] = { 740 - { .compatible = "toshiba,tc358775", }, 719 + { .compatible = "toshiba,tc358765", .data = (void *)TC358765, }, 720 + { .compatible = "toshiba,tc358775", .data = (void *)TC358775, }, 741 721 { } 742 722 }; 743 723 MODULE_DEVICE_TABLE(of, tc358775_of_ids);
+329 -102
drivers/gpu/drm/drm_buddy.c
··· 57 57 __list_add(&block->link, node->link.prev, &node->link); 58 58 } 59 59 60 + static void clear_reset(struct drm_buddy_block *block) 61 + { 62 + block->header &= ~DRM_BUDDY_HEADER_CLEAR; 63 + } 64 + 65 + static void mark_cleared(struct drm_buddy_block *block) 66 + { 67 + block->header |= DRM_BUDDY_HEADER_CLEAR; 68 + } 69 + 60 70 static void mark_allocated(struct drm_buddy_block *block) 61 71 { 62 72 block->header &= ~DRM_BUDDY_HEADER_STATE; ··· 90 80 block->header |= DRM_BUDDY_SPLIT; 91 81 92 82 list_del(&block->link); 83 + } 84 + 85 + static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2) 86 + { 87 + return s1 <= e2 && e1 >= s2; 88 + } 89 + 90 + static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2) 91 + { 92 + return s1 <= s2 && e1 >= e2; 93 + } 94 + 95 + static struct drm_buddy_block * 96 + __get_buddy(struct drm_buddy_block *block) 97 + { 98 + struct drm_buddy_block *parent; 99 + 100 + parent = block->parent; 101 + if (!parent) 102 + return NULL; 103 + 104 + if (parent->left == block) 105 + return parent->right; 106 + 107 + return parent->left; 108 + } 109 + 110 + static unsigned int __drm_buddy_free(struct drm_buddy *mm, 111 + struct drm_buddy_block *block, 112 + bool force_merge) 113 + { 114 + struct drm_buddy_block *parent; 115 + unsigned int order; 116 + 117 + while ((parent = block->parent)) { 118 + struct drm_buddy_block *buddy; 119 + 120 + buddy = __get_buddy(block); 121 + 122 + if (!drm_buddy_block_is_free(buddy)) 123 + break; 124 + 125 + if (!force_merge) { 126 + /* 127 + * Check the block and its buddy clear state and exit 128 + * the loop if they both have the dissimilar state. 129 + */ 130 + if (drm_buddy_block_is_clear(block) != 131 + drm_buddy_block_is_clear(buddy)) 132 + break; 133 + 134 + if (drm_buddy_block_is_clear(block)) 135 + mark_cleared(parent); 136 + } 137 + 138 + list_del(&buddy->link); 139 + if (force_merge && drm_buddy_block_is_clear(buddy)) 140 + mm->clear_avail -= drm_buddy_block_size(mm, buddy); 141 + 142 + drm_block_free(mm, block); 143 + drm_block_free(mm, buddy); 144 + 145 + block = parent; 146 + } 147 + 148 + order = drm_buddy_block_order(block); 149 + mark_free(mm, block); 150 + 151 + return order; 152 + } 153 + 154 + static int __force_merge(struct drm_buddy *mm, 155 + u64 start, 156 + u64 end, 157 + unsigned int min_order) 158 + { 159 + unsigned int order; 160 + int i; 161 + 162 + if (!min_order) 163 + return -ENOMEM; 164 + 165 + if (min_order > mm->max_order) 166 + return -EINVAL; 167 + 168 + for (i = min_order - 1; i >= 0; i--) { 169 + struct drm_buddy_block *block, *prev; 170 + 171 + list_for_each_entry_safe_reverse(block, prev, &mm->free_list[i], link) { 172 + struct drm_buddy_block *buddy; 173 + u64 block_start, block_end; 174 + 175 + if (!block->parent) 176 + continue; 177 + 178 + block_start = drm_buddy_block_offset(block); 179 + block_end = block_start + drm_buddy_block_size(mm, block) - 1; 180 + 181 + if (!contains(start, end, block_start, block_end)) 182 + continue; 183 + 184 + buddy = __get_buddy(block); 185 + if (!drm_buddy_block_is_free(buddy)) 186 + continue; 187 + 188 + WARN_ON(drm_buddy_block_is_clear(block) == 189 + drm_buddy_block_is_clear(buddy)); 190 + 191 + /* 192 + * If the prev block is same as buddy, don't access the 193 + * block in the next iteration as we would free the 194 + * buddy block as part of the free function. 195 + */ 196 + if (prev == buddy) 197 + prev = list_prev_entry(prev, link); 198 + 199 + list_del(&block->link); 200 + if (drm_buddy_block_is_clear(block)) 201 + mm->clear_avail -= drm_buddy_block_size(mm, block); 202 + 203 + order = __drm_buddy_free(mm, block, true); 204 + if (order >= min_order) 205 + return 0; 206 + } 207 + } 208 + 209 + return -ENOMEM; 93 210 } 94 211 95 212 /** ··· 323 186 */ 324 187 void drm_buddy_fini(struct drm_buddy *mm) 325 188 { 189 + u64 root_size, size; 190 + unsigned int order; 326 191 int i; 327 192 193 + size = mm->size; 194 + 328 195 for (i = 0; i < mm->n_roots; ++i) { 196 + order = ilog2(size) - ilog2(mm->chunk_size); 197 + __force_merge(mm, 0, size, order); 198 + 329 199 WARN_ON(!drm_buddy_block_is_free(mm->roots[i])); 330 200 drm_block_free(mm, mm->roots[i]); 201 + 202 + root_size = mm->chunk_size << order; 203 + size -= root_size; 331 204 } 332 205 333 206 WARN_ON(mm->avail != mm->size); ··· 370 223 mark_free(mm, block->left); 371 224 mark_free(mm, block->right); 372 225 226 + if (drm_buddy_block_is_clear(block)) { 227 + mark_cleared(block->left); 228 + mark_cleared(block->right); 229 + clear_reset(block); 230 + } 231 + 373 232 mark_split(block); 374 233 375 234 return 0; 376 - } 377 - 378 - static struct drm_buddy_block * 379 - __get_buddy(struct drm_buddy_block *block) 380 - { 381 - struct drm_buddy_block *parent; 382 - 383 - parent = block->parent; 384 - if (!parent) 385 - return NULL; 386 - 387 - if (parent->left == block) 388 - return parent->right; 389 - 390 - return parent->left; 391 235 } 392 236 393 237 /** ··· 398 260 } 399 261 EXPORT_SYMBOL(drm_get_buddy); 400 262 401 - static void __drm_buddy_free(struct drm_buddy *mm, 402 - struct drm_buddy_block *block) 403 - { 404 - struct drm_buddy_block *parent; 405 - 406 - while ((parent = block->parent)) { 407 - struct drm_buddy_block *buddy; 408 - 409 - buddy = __get_buddy(block); 410 - 411 - if (!drm_buddy_block_is_free(buddy)) 412 - break; 413 - 414 - list_del(&buddy->link); 415 - 416 - drm_block_free(mm, block); 417 - drm_block_free(mm, buddy); 418 - 419 - block = parent; 420 - } 421 - 422 - mark_free(mm, block); 423 - } 424 - 425 263 /** 426 264 * drm_buddy_free_block - free a block 427 265 * ··· 409 295 { 410 296 BUG_ON(!drm_buddy_block_is_allocated(block)); 411 297 mm->avail += drm_buddy_block_size(mm, block); 412 - __drm_buddy_free(mm, block); 298 + if (drm_buddy_block_is_clear(block)) 299 + mm->clear_avail += drm_buddy_block_size(mm, block); 300 + 301 + __drm_buddy_free(mm, block, false); 413 302 } 414 303 EXPORT_SYMBOL(drm_buddy_free_block); 304 + 305 + static void __drm_buddy_free_list(struct drm_buddy *mm, 306 + struct list_head *objects, 307 + bool mark_clear, 308 + bool mark_dirty) 309 + { 310 + struct drm_buddy_block *block, *on; 311 + 312 + WARN_ON(mark_dirty && mark_clear); 313 + 314 + list_for_each_entry_safe(block, on, objects, link) { 315 + if (mark_clear) 316 + mark_cleared(block); 317 + else if (mark_dirty) 318 + clear_reset(block); 319 + drm_buddy_free_block(mm, block); 320 + cond_resched(); 321 + } 322 + INIT_LIST_HEAD(objects); 323 + } 324 + 325 + static void drm_buddy_free_list_internal(struct drm_buddy *mm, 326 + struct list_head *objects) 327 + { 328 + /* 329 + * Don't touch the clear/dirty bit, since allocation is still internal 330 + * at this point. For example we might have just failed part of the 331 + * allocation. 332 + */ 333 + __drm_buddy_free_list(mm, objects, false, false); 334 + } 415 335 416 336 /** 417 337 * drm_buddy_free_list - free blocks 418 338 * 419 339 * @mm: DRM buddy manager 420 340 * @objects: input list head to free blocks 341 + * @flags: optional flags like DRM_BUDDY_CLEARED 421 342 */ 422 - void drm_buddy_free_list(struct drm_buddy *mm, struct list_head *objects) 343 + void drm_buddy_free_list(struct drm_buddy *mm, 344 + struct list_head *objects, 345 + unsigned int flags) 423 346 { 424 - struct drm_buddy_block *block, *on; 347 + bool mark_clear = flags & DRM_BUDDY_CLEARED; 425 348 426 - list_for_each_entry_safe(block, on, objects, link) { 427 - drm_buddy_free_block(mm, block); 428 - cond_resched(); 429 - } 430 - INIT_LIST_HEAD(objects); 349 + __drm_buddy_free_list(mm, objects, mark_clear, !mark_clear); 431 350 } 432 351 EXPORT_SYMBOL(drm_buddy_free_list); 433 352 434 - static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2) 353 + static bool block_incompatible(struct drm_buddy_block *block, unsigned int flags) 435 354 { 436 - return s1 <= e2 && e1 >= s2; 437 - } 355 + bool needs_clear = flags & DRM_BUDDY_CLEAR_ALLOCATION; 438 356 439 - static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2) 440 - { 441 - return s1 <= s2 && e1 >= e2; 357 + return needs_clear != drm_buddy_block_is_clear(block); 442 358 } 443 359 444 360 static struct drm_buddy_block * 445 - alloc_range_bias(struct drm_buddy *mm, 446 - u64 start, u64 end, 447 - unsigned int order) 361 + __alloc_range_bias(struct drm_buddy *mm, 362 + u64 start, u64 end, 363 + unsigned int order, 364 + unsigned long flags, 365 + bool fallback) 448 366 { 449 367 u64 req_size = mm->chunk_size << order; 450 368 struct drm_buddy_block *block; ··· 525 379 526 380 if (contains(start, end, block_start, block_end) && 527 381 order == drm_buddy_block_order(block)) { 382 + if (!fallback && block_incompatible(block, flags)) 383 + continue; 384 + 528 385 /* 529 386 * Find the free block within the range. 530 387 */ ··· 559 410 if (buddy && 560 411 (drm_buddy_block_is_free(block) && 561 412 drm_buddy_block_is_free(buddy))) 562 - __drm_buddy_free(mm, block); 413 + __drm_buddy_free(mm, block, false); 563 414 return ERR_PTR(err); 564 415 } 565 416 566 417 static struct drm_buddy_block * 567 - get_maxblock(struct drm_buddy *mm, unsigned int order) 418 + __drm_buddy_alloc_range_bias(struct drm_buddy *mm, 419 + u64 start, u64 end, 420 + unsigned int order, 421 + unsigned long flags) 568 422 { 569 - struct drm_buddy_block *max_block = NULL, *node; 423 + struct drm_buddy_block *block; 424 + bool fallback = false; 425 + 426 + block = __alloc_range_bias(mm, start, end, order, 427 + flags, fallback); 428 + if (IS_ERR(block) && mm->clear_avail) 429 + return __alloc_range_bias(mm, start, end, order, 430 + flags, !fallback); 431 + 432 + return block; 433 + } 434 + 435 + static struct drm_buddy_block * 436 + get_maxblock(struct drm_buddy *mm, unsigned int order, 437 + unsigned long flags) 438 + { 439 + struct drm_buddy_block *max_block = NULL, *block = NULL; 570 440 unsigned int i; 571 441 572 442 for (i = order; i <= mm->max_order; ++i) { 573 - if (!list_empty(&mm->free_list[i])) { 574 - node = list_last_entry(&mm->free_list[i], 575 - struct drm_buddy_block, 576 - link); 577 - if (!max_block) { 578 - max_block = node; 579 - continue; 580 - } 443 + struct drm_buddy_block *tmp_block; 581 444 582 - if (drm_buddy_block_offset(node) > 583 - drm_buddy_block_offset(max_block)) { 584 - max_block = node; 585 - } 445 + list_for_each_entry_reverse(tmp_block, &mm->free_list[i], link) { 446 + if (block_incompatible(tmp_block, flags)) 447 + continue; 448 + 449 + block = tmp_block; 450 + break; 451 + } 452 + 453 + if (!block) 454 + continue; 455 + 456 + if (!max_block) { 457 + max_block = block; 458 + continue; 459 + } 460 + 461 + if (drm_buddy_block_offset(block) > 462 + drm_buddy_block_offset(max_block)) { 463 + max_block = block; 586 464 } 587 465 } 588 466 ··· 626 450 int err; 627 451 628 452 if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) { 629 - block = get_maxblock(mm, order); 453 + block = get_maxblock(mm, order, flags); 630 454 if (block) 631 455 /* Store the obtained block order */ 632 456 tmp = drm_buddy_block_order(block); 633 457 } else { 458 + for (tmp = order; tmp <= mm->max_order; ++tmp) { 459 + struct drm_buddy_block *tmp_block; 460 + 461 + list_for_each_entry_reverse(tmp_block, &mm->free_list[tmp], link) { 462 + if (block_incompatible(tmp_block, flags)) 463 + continue; 464 + 465 + block = tmp_block; 466 + break; 467 + } 468 + 469 + if (block) 470 + break; 471 + } 472 + } 473 + 474 + if (!block) { 475 + /* Fallback method */ 634 476 for (tmp = order; tmp <= mm->max_order; ++tmp) { 635 477 if (!list_empty(&mm->free_list[tmp])) { 636 478 block = list_last_entry(&mm->free_list[tmp], ··· 658 464 break; 659 465 } 660 466 } 661 - } 662 467 663 - if (!block) 664 - return ERR_PTR(-ENOSPC); 468 + if (!block) 469 + return ERR_PTR(-ENOSPC); 470 + } 665 471 666 472 BUG_ON(!drm_buddy_block_is_free(block)); 667 473 ··· 677 483 678 484 err_undo: 679 485 if (tmp != order) 680 - __drm_buddy_free(mm, block); 486 + __drm_buddy_free(mm, block, false); 681 487 return ERR_PTR(err); 682 488 } 683 489 ··· 720 526 } 721 527 722 528 if (contains(start, end, block_start, block_end)) { 723 - if (!drm_buddy_block_is_free(block)) { 529 + if (drm_buddy_block_is_free(block)) { 530 + mark_allocated(block); 531 + total_allocated += drm_buddy_block_size(mm, block); 532 + mm->avail -= drm_buddy_block_size(mm, block); 533 + if (drm_buddy_block_is_clear(block)) 534 + mm->clear_avail -= drm_buddy_block_size(mm, block); 535 + list_add_tail(&block->link, &allocated); 536 + continue; 537 + } else if (!mm->clear_avail) { 724 538 err = -ENOSPC; 725 539 goto err_free; 726 540 } 727 - 728 - mark_allocated(block); 729 - total_allocated += drm_buddy_block_size(mm, block); 730 - mm->avail -= drm_buddy_block_size(mm, block); 731 - list_add_tail(&block->link, &allocated); 732 - continue; 733 541 } 734 542 735 543 if (!drm_buddy_block_is_split(block)) { ··· 763 567 if (buddy && 764 568 (drm_buddy_block_is_free(block) && 765 569 drm_buddy_block_is_free(buddy))) 766 - __drm_buddy_free(mm, block); 570 + __drm_buddy_free(mm, block, false); 767 571 768 572 err_free: 769 573 if (err == -ENOSPC && total_allocated_on_err) { 770 574 list_splice_tail(&allocated, blocks); 771 575 *total_allocated_on_err = total_allocated; 772 576 } else { 773 - drm_buddy_free_list(mm, &allocated); 577 + drm_buddy_free_list_internal(mm, &allocated); 774 578 } 775 579 776 580 return err; ··· 836 640 list_splice(&blocks_lhs, blocks); 837 641 return 0; 838 642 } else if (err != -ENOSPC) { 839 - drm_buddy_free_list(mm, blocks); 643 + drm_buddy_free_list_internal(mm, blocks); 840 644 return err; 841 645 } 842 646 /* Free blocks for the next iteration */ 843 - drm_buddy_free_list(mm, blocks); 647 + drm_buddy_free_list_internal(mm, blocks); 844 648 } 845 649 846 650 return -ENOSPC; ··· 896 700 list_del(&block->link); 897 701 mark_free(mm, block); 898 702 mm->avail += drm_buddy_block_size(mm, block); 703 + if (drm_buddy_block_is_clear(block)) 704 + mm->clear_avail += drm_buddy_block_size(mm, block); 899 705 900 706 /* Prevent recursively freeing this node */ 901 707 parent = block->parent; ··· 909 711 if (err) { 910 712 mark_allocated(block); 911 713 mm->avail -= drm_buddy_block_size(mm, block); 714 + if (drm_buddy_block_is_clear(block)) 715 + mm->clear_avail -= drm_buddy_block_size(mm, block); 912 716 list_add(&block->link, blocks); 913 717 } 914 718 ··· 919 719 } 920 720 EXPORT_SYMBOL(drm_buddy_block_trim); 921 721 722 + static struct drm_buddy_block * 723 + __drm_buddy_alloc_blocks(struct drm_buddy *mm, 724 + u64 start, u64 end, 725 + unsigned int order, 726 + unsigned long flags) 727 + { 728 + if (flags & DRM_BUDDY_RANGE_ALLOCATION) 729 + /* Allocate traversing within the range */ 730 + return __drm_buddy_alloc_range_bias(mm, start, end, 731 + order, flags); 732 + else 733 + /* Allocate from freelist */ 734 + return alloc_from_freelist(mm, order, flags); 735 + } 736 + 922 737 /** 923 738 * drm_buddy_alloc_blocks - allocate power-of-two blocks 924 739 * 925 740 * @mm: DRM buddy manager to allocate from 926 741 * @start: start of the allowed range for this block 927 742 * @end: end of the allowed range for this block 928 - * @size: size of the allocation 743 + * @size: size of the allocation in bytes 929 744 * @min_block_size: alignment of the allocation 930 745 * @blocks: output list head to add allocated blocks 931 746 * @flags: DRM_BUDDY_*_ALLOCATION flags ··· 1015 800 BUG_ON(order < min_order); 1016 801 1017 802 do { 1018 - if (flags & DRM_BUDDY_RANGE_ALLOCATION) 1019 - /* Allocate traversing within the range */ 1020 - block = alloc_range_bias(mm, start, end, order); 1021 - else 1022 - /* Allocate from freelist */ 1023 - block = alloc_from_freelist(mm, order, flags); 1024 - 803 + block = __drm_buddy_alloc_blocks(mm, start, 804 + end, 805 + order, 806 + flags); 1025 807 if (!IS_ERR(block)) 1026 808 break; 1027 809 1028 810 if (order-- == min_order) { 811 + /* Try allocation through force merge method */ 812 + if (mm->clear_avail && 813 + !__force_merge(mm, start, end, min_order)) { 814 + block = __drm_buddy_alloc_blocks(mm, start, 815 + end, 816 + min_order, 817 + flags); 818 + if (!IS_ERR(block)) { 819 + order = min_order; 820 + break; 821 + } 822 + } 823 + 824 + /* 825 + * Try contiguous block allocation through 826 + * try harder method. 827 + */ 1029 828 if (flags & DRM_BUDDY_CONTIGUOUS_ALLOCATION && 1030 829 !(flags & DRM_BUDDY_RANGE_ALLOCATION)) 1031 - /* 1032 - * Try contiguous block allocation through 1033 - * try harder method 1034 - */ 1035 830 return __alloc_contig_try_harder(mm, 1036 831 original_size, 1037 832 original_min_size, ··· 1053 828 1054 829 mark_allocated(block); 1055 830 mm->avail -= drm_buddy_block_size(mm, block); 831 + if (drm_buddy_block_is_clear(block)) 832 + mm->clear_avail -= drm_buddy_block_size(mm, block); 1056 833 kmemleak_update_trace(block); 1057 834 list_add_tail(&block->link, &allocated); 1058 835 ··· 1093 866 return 0; 1094 867 1095 868 err_free: 1096 - drm_buddy_free_list(mm, &allocated); 869 + drm_buddy_free_list_internal(mm, &allocated); 1097 870 return err; 1098 871 } 1099 872 EXPORT_SYMBOL(drm_buddy_alloc_blocks); ··· 1126 899 { 1127 900 int order; 1128 901 1129 - drm_printf(p, "chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB\n", 1130 - mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20); 902 + drm_printf(p, "chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB, clear_free: %lluMiB\n", 903 + mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avail >> 20); 1131 904 1132 905 for (order = mm->max_order; order >= 0; order--) { 1133 906 struct drm_buddy_block *block;
-1
drivers/gpu/drm/drm_displayid_internal.h
··· 31 31 #define VESA_IEEE_OUI 0x3a0292 32 32 33 33 /* DisplayID Structure versions */ 34 - #define DISPLAY_ID_STRUCTURE_VER_12 0x12 35 34 #define DISPLAY_ID_STRUCTURE_VER_20 0x20 36 35 37 36 /* DisplayID Structure v1r2 Data Blocks */
+1 -1
drivers/gpu/drm/drm_edid.c
··· 7462 7462 static bool displayid_is_tiled_block(const struct displayid_iter *iter, 7463 7463 const struct displayid_block *block) 7464 7464 { 7465 - return (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_12 && 7465 + return (displayid_version(iter) < DISPLAY_ID_STRUCTURE_VER_20 && 7466 7466 block->tag == DATA_BLOCK_TILED_DISPLAY) || 7467 7467 (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_20 && 7468 7468 block->tag == DATA_BLOCK_2_TILED_DISPLAY_TOPOLOGY);
+1 -1
drivers/gpu/drm/drm_plane.c
··· 1750 1750 EXPORT_SYMBOL(drm_plane_create_scaling_filter_property); 1751 1751 1752 1752 /** 1753 - * drm_plane_add_size_hint_property - create a size hint property 1753 + * drm_plane_add_size_hints_property - create a size hints property 1754 1754 * 1755 1755 * @plane: drm plane 1756 1756 * @hints: size hints
+3 -3
drivers/gpu/drm/drm_print.c
··· 23 23 * Rob Clark <robdclark@gmail.com> 24 24 */ 25 25 26 - #include <linux/stdarg.h> 27 - 26 + #include <linux/debugfs.h> 27 + #include <linux/dynamic_debug.h> 28 28 #include <linux/io.h> 29 29 #include <linux/moduleparam.h> 30 30 #include <linux/seq_file.h> 31 31 #include <linux/slab.h> 32 - #include <linux/dynamic_debug.h> 32 + #include <linux/stdarg.h> 33 33 34 34 #include <drm/drm.h> 35 35 #include <drm/drm_drv.h>
+6 -6
drivers/gpu/drm/gud/gud_connector.c
··· 221 221 struct gud_display_mode_req *reqmodes = NULL; 222 222 struct gud_connector_get_edid_ctx edid_ctx; 223 223 unsigned int i, num_modes = 0; 224 - struct edid *edid = NULL; 224 + const struct drm_edid *drm_edid = NULL; 225 225 int idx, ret; 226 226 227 227 if (!drm_dev_enter(connector->dev, &idx)) ··· 238 238 gud_conn_err(connector, "Invalid EDID size", ret); 239 239 } else if (ret > 0) { 240 240 edid_ctx.len = ret; 241 - edid = drm_do_get_edid(connector, gud_connector_get_edid_block, &edid_ctx); 241 + drm_edid = drm_edid_read_custom(connector, gud_connector_get_edid_block, &edid_ctx); 242 242 } 243 243 244 244 kfree(edid_ctx.buf); 245 - drm_connector_update_edid_property(connector, edid); 245 + drm_edid_connector_update(connector, drm_edid); 246 246 247 - if (edid && edid_ctx.edid_override) 247 + if (drm_edid && edid_ctx.edid_override) 248 248 goto out; 249 249 250 250 reqmodes = kmalloc_array(GUD_CONNECTOR_MAX_NUM_MODES, sizeof(*reqmodes), GFP_KERNEL); ··· 276 276 } 277 277 out: 278 278 if (!num_modes) 279 - num_modes = drm_add_edid_modes(connector, edid); 279 + num_modes = drm_edid_connector_add_modes(connector); 280 280 281 281 kfree(reqmodes); 282 - kfree(edid); 282 + drm_edid_free(drm_edid); 283 283 drm_dev_exit(idx); 284 284 285 285 return num_modes;
+1
drivers/gpu/drm/i915/display/intel_dmc.c
··· 22 22 * 23 23 */ 24 24 25 + #include <linux/debugfs.h> 25 26 #include <linux/firmware.h> 26 27 27 28 #include "i915_drv.h"
+3 -3
drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
··· 126 126 return 0; 127 127 128 128 err_free_blocks: 129 - drm_buddy_free_list(mm, &bman_res->blocks); 129 + drm_buddy_free_list(mm, &bman_res->blocks, 0); 130 130 mutex_unlock(&bman->lock); 131 131 err_free_res: 132 132 ttm_resource_fini(man, &bman_res->base); ··· 141 141 struct i915_ttm_buddy_manager *bman = to_buddy_manager(man); 142 142 143 143 mutex_lock(&bman->lock); 144 - drm_buddy_free_list(&bman->mm, &bman_res->blocks); 144 + drm_buddy_free_list(&bman->mm, &bman_res->blocks, 0); 145 145 bman->visible_avail += bman_res->used_visible_size; 146 146 mutex_unlock(&bman->lock); 147 147 ··· 345 345 ttm_set_driver_manager(bdev, type, NULL); 346 346 347 347 mutex_lock(&bman->lock); 348 - drm_buddy_free_list(mm, &bman->reserved); 348 + drm_buddy_free_list(mm, &bman->reserved, 0); 349 349 drm_buddy_fini(mm); 350 350 bman->visible_avail += bman->visible_reserved; 351 351 WARN_ON_ONCE(bman->visible_avail != bman->visible_size);
+1
drivers/gpu/drm/imagination/pvr_fw_trace.c
··· 12 12 13 13 #include <linux/build_bug.h> 14 14 #include <linux/dcache.h> 15 + #include <linux/debugfs.h> 15 16 #include <linux/sysfs.h> 16 17 #include <linux/types.h> 17 18
+7
drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
··· 95 95 return ret; 96 96 } 97 97 98 + clk_disable_unprepare(mipi_dsi->px_clk); 98 99 ret = clk_set_rate(mipi_dsi->px_clk, mipi_dsi->mode->clock * 1000); 99 100 100 101 if (ret) { 101 102 dev_err(mipi_dsi->dev, "Failed to set DSI Pixel clock rate %u (%d)\n", 102 103 mipi_dsi->mode->clock * 1000, ret); 104 + return ret; 105 + } 106 + 107 + ret = clk_prepare_enable(mipi_dsi->px_clk); 108 + if (ret) { 109 + dev_err(mipi_dsi->dev, "Failed to enable DSI Pixel clock (ret %d)\n", ret); 103 110 return ret; 104 111 } 105 112
+2
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
··· 2 2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. 3 3 */ 4 4 5 + #include <linux/debugfs.h> 6 + 5 7 #include "dpu_hwio.h" 6 8 #include "dpu_hw_catalog.h" 7 9 #include "dpu_hw_lm.h"
+2
drivers/gpu/drm/nouveau/dispnv50/crc.c
··· 1 1 // SPDX-License-Identifier: MIT 2 + #include <linux/debugfs.h> 2 3 #include <linux/string.h> 4 + 3 5 #include <drm/drm_crtc.h> 4 6 #include <drm/drm_atomic_helper.h> 5 7 #include <drm/drm_vblank.h>
+12
drivers/gpu/drm/panel/Kconfig
··· 553 553 Say Y here if you want to enable support for Raydium RM692E5-based 554 554 display panels, such as the one found in the Fairphone 5 smartphone. 555 555 556 + config DRM_PANEL_RAYDIUM_RM69380 557 + tristate "Raydium RM69380-based DSI panel" 558 + depends on OF && GPIOLIB 559 + depends on DRM_MIPI_DSI 560 + depends on BACKLIGHT_CLASS_DEVICE 561 + help 562 + Say Y here if you want to enable support for Raydium RM69380-based 563 + display panels. 564 + 565 + This panel controller can be found in the Lenovo Xiaoxin Pad Pro 2021 566 + in combination with an EDO OLED panel. 567 + 556 568 config DRM_PANEL_RONBO_RB070D30 557 569 tristate "Ronbo Electronics RB070D30 panel" 558 570 depends on OF
+1
drivers/gpu/drm/panel/Makefile
··· 56 56 obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM67191) += panel-raydium-rm67191.o 57 57 obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o 58 58 obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM692E5) += panel-raydium-rm692e5.o 59 + obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM69380) += panel-raydium-rm69380.o 59 60 obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o 60 61 obj-$(CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20) += panel-samsung-atna33xc20.o 61 62 obj-$(CONFIG_DRM_PANEL_SAMSUNG_DB7430) += panel-samsung-db7430.o
+12 -7
drivers/gpu/drm/panel/panel-edp.c
··· 242 242 243 243 const struct edp_panel_entry *detected_panel; 244 244 245 - struct edid *edid; 245 + const struct drm_edid *drm_edid; 246 246 247 247 struct drm_display_mode override_mode; 248 248 ··· 617 617 if (p->ddc) { 618 618 pm_runtime_get_sync(panel->dev); 619 619 620 - if (!p->edid) 621 - p->edid = drm_get_edid(connector, p->ddc); 620 + if (!p->drm_edid) 621 + p->drm_edid = drm_edid_read_ddc(connector, p->ddc); 622 + 623 + drm_edid_connector_update(connector, p->drm_edid); 624 + 622 625 /* 623 626 * If both edid and hard-coded modes exists, skip edid modes to 624 627 * avoid multiple preferred modes. 625 628 */ 626 - if (p->edid && !has_hard_coded_modes) { 629 + if (p->drm_edid && !has_hard_coded_modes) { 627 630 if (has_override_edid_mode) { 628 631 /* 629 632 * override_edid_mode is specified. Use ··· 635 632 num += panel_edp_override_edid_mode(p, connector, 636 633 p->detected_panel->override_edid_mode); 637 634 } else { 638 - num += drm_add_edid_modes(connector, p->edid); 635 + num += drm_edid_connector_add_modes(connector); 639 636 } 640 637 } 641 638 ··· 984 981 if (panel->ddc && (!panel->aux || panel->ddc != &panel->aux->ddc)) 985 982 put_device(&panel->ddc->dev); 986 983 987 - kfree(panel->edid); 988 - panel->edid = NULL; 984 + drm_edid_free(panel->drm_edid); 985 + panel->drm_edid = NULL; 989 986 } 990 987 991 988 static void panel_edp_shutdown(struct device *dev) ··· 2077 2074 EDP_PANEL_ENTRY('C', 'M', 'N', 0x14e5, &delay_200_500_e80_d50, "N140HGA-EA1"), 2078 2075 2079 2076 EDP_PANEL_ENTRY('C', 'S', 'O', 0x1200, &delay_200_500_e50_p2e200, "MNC207QS1-1"), 2077 + 2078 + EDP_PANEL_ENTRY('C', 'S', 'W', 0x1100, &delay_200_500_e80_d50, "MNB601LS1-1"), 2080 2079 2081 2080 EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d51, &delay_200_500_e200, "Unknown"), 2082 2081 EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d5b, &delay_200_500_e200, "Unknown"),
+1
drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c
··· 247 247 248 248 drm_panel_init(&ctx->panel, dev, &jdi_fhd_r63452_panel_funcs, 249 249 DRM_MODE_CONNECTOR_DSI); 250 + ctx->panel.prepare_prev_first = true; 250 251 251 252 ret = drm_panel_of_backlight(&ctx->panel); 252 253 if (ret)
+590 -522
drivers/gpu/drm/panel/panel-khadas-ts050.c
··· 25 25 struct regulator *supply; 26 26 struct gpio_desc *reset_gpio; 27 27 struct gpio_desc *enable_gpio; 28 + struct khadas_ts050_panel_data *panel_data; 28 29 29 30 bool prepared; 30 31 bool enabled; ··· 33 32 34 33 struct khadas_ts050_panel_cmd { 35 34 u8 cmd; 36 - u8 data; 35 + u8 data[55]; 36 + u8 size; 37 + }; 38 + 39 + struct khadas_ts050_panel_data { 40 + struct khadas_ts050_panel_cmd *init_code; 41 + int len; 42 + }; 43 + 44 + static const struct khadas_ts050_panel_cmd ts050v2_init_code[] = { 45 + {0xB9, {0xFF, 0x83, 0x99}, 0x03}, 46 + {0xBA, {0x63, 0x23, 0x68, 0xCF}, 0x04}, 47 + {0xD2, {0x55}, 0x01}, 48 + {0xB1, {0x02, 0x04, 0x70, 0x90, 0x01, 0x32, 0x33, 49 + 0x11, 0x11, 0x4D, 0x57, 0x56, 0x73, 0x02, 0x02}, 0x0f}, 50 + {0xB2, {0x00, 0x80, 0x80, 0xAE, 0x0A, 0x0E, 0x75, 0x11, 0x00, 0x00, 0x00}, 0x0b}, 51 + {0xB4, {0x00, 0xFF, 0x04, 0xA4, 0x02, 0xA0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 52 + 0x00, 0x24, 0x02, 0x04, 0x0A, 0x21, 0x03, 0x00, 0x00, 0x08, 0xA6, 0x88, 53 + 0x04, 0xA4, 0x02, 0xA0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x24, 54 + 0x02, 0x04, 0x0A, 0x00, 0x00, 0x08, 0xA6, 0x00, 0x08, 0x11}, 0x2e}, 55 + {0xD3, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 56 + 0x18, 0x32, 0x10, 0x09, 0x00, 0x09, 0x32, 57 + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 58 + 0x00, 0x00, 0x11, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00, 0x0A, 59 + 0x40}, 0x21}, 60 + {0xD5, {0x18, 0x18, 0x18, 0x18, 0x21, 0x20, 0x18, 0x18, 0x19, 0x19, 0x19, 61 + 0x19, 0x18, 0x18, 0x18, 0x18, 0x03, 0x02, 0x01, 0x00, 0x2F, 0x2F, 62 + 0x30, 0x30, 0x31, 0x31, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, 0x20}, 63 + {0xD6, {0x18, 0x18, 0x18, 0x18, 0x20, 0x21, 0x19, 0x19, 0x18, 0x18, 0x19, 64 + 0x19, 0x18, 0x18, 0x18, 0x18, 0x00, 0x01, 0x02, 0x03, 0x2F, 0x2F, 65 + 0x30, 0x30, 0x31, 0x31, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, 0x20}, 66 + {0xD8, {0x0A, 0xBE, 0xFA, 0xA0, 0x0A, 0xBE, 0xFA, 0xA0}, 0x08}, 67 + {0xBD, {0x01}, 0x01}, 68 + {0xD8, {0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0}, 0x08}, 69 + {0xBD, {0x02}, 0x01}, 70 + {0xD8, {0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0}, 0x08}, 71 + {0xBD, {0x00}, 0x01}, 72 + {0xE0, {0x01, 0x35, 0x41, 0x3B, 0x79, 0x81, 0x8C, 0x85, 0x8E, 73 + 0x95, 0x9B, 0xA0, 0xA4, 0xAB, 0xB1, 0xB3, 0xB7, 0xC5, 0xBD, 0xC5, 74 + 0xB6, 0xC2, 0xC2, 0x62, 0x5D, 0x66, 0x73, 0x01, 0x35, 0x41, 0x3B, 75 + 0x79, 0x81, 0x8C, 0x85, 0x8E, 0x95, 0x9B, 0xA0, 0xA4, 0xAB, 0xB1, 76 + 0xB3, 0xB7, 0xB5, 0xBD, 0xC5, 0xB6, 0xC2, 0xC2, 0x62, 0x5D, 0x66, 77 + 0x73}, 0x36}, 78 + {0xB6, {0x97, 0x97}, 0x02}, 79 + {0xCC, {0xC8}, 0x02}, 80 + {0xBF, {0x40, 0x41, 0x50, 0x19}, 0x04}, 81 + {0xC6, {0xFF, 0xF9}, 0x02}, 82 + {0xC0, {0x25, 0x5A}, 0x02}, 37 83 }; 38 84 39 85 /* Only the CMD1 User Command set is documented */ 40 - static const struct khadas_ts050_panel_cmd init_code[] = { 86 + static const struct khadas_ts050_panel_cmd ts050_init_code[] = { 41 87 /* Select Unknown CMD Page (Undocumented) */ 42 - {0xff, 0xee}, 88 + {0xff, {0xee}, 0x01}, 43 89 /* Reload CMD1: Don't reload default value to register */ 44 - {0xfb, 0x01}, 45 - {0x1f, 0x45}, 46 - {0x24, 0x4f}, 47 - {0x38, 0xc8}, 48 - {0x39, 0x27}, 49 - {0x1e, 0x77}, 50 - {0x1d, 0x0f}, 51 - {0x7e, 0x71}, 52 - {0x7c, 0x03}, 53 - {0xff, 0x00}, 54 - {0xfb, 0x01}, 55 - {0x35, 0x01}, 90 + {0xfb, {0x01}, 0x01}, 91 + {0x1f, {0x45}, 0x01}, 92 + {0x24, {0x4f}, 0x01}, 93 + {0x38, {0xc8}, 0x01}, 94 + {0x39, {0x27}, 0x01}, 95 + {0x1e, {0x77}, 0x01}, 96 + {0x1d, {0x0f}, 0x01}, 97 + {0x7e, {0x71}, 0x01}, 98 + {0x7c, {0x03}, 0x01}, 99 + {0xff, {0x00}, 0x01}, 100 + {0xfb, {0x01}, 0x01}, 101 + {0x35, {0x01}, 0x01}, 56 102 /* Select CMD2 Page0 (Undocumented) */ 57 - {0xff, 0x01}, 103 + {0xff, {0x01}, 0x01}, 58 104 /* Reload CMD1: Don't reload default value to register */ 59 - {0xfb, 0x01}, 60 - {0x00, 0x01}, 61 - {0x01, 0x55}, 62 - {0x02, 0x40}, 63 - {0x05, 0x40}, 64 - {0x06, 0x4a}, 65 - {0x07, 0x24}, 66 - {0x08, 0x0c}, 67 - {0x0b, 0x7d}, 68 - {0x0c, 0x7d}, 69 - {0x0e, 0xb0}, 70 - {0x0f, 0xae}, 71 - {0x11, 0x10}, 72 - {0x12, 0x10}, 73 - {0x13, 0x03}, 74 - {0x14, 0x4a}, 75 - {0x15, 0x12}, 76 - {0x16, 0x12}, 77 - {0x18, 0x00}, 78 - {0x19, 0x77}, 79 - {0x1a, 0x55}, 80 - {0x1b, 0x13}, 81 - {0x1c, 0x00}, 82 - {0x1d, 0x00}, 83 - {0x1e, 0x13}, 84 - {0x1f, 0x00}, 85 - {0x23, 0x00}, 86 - {0x24, 0x00}, 87 - {0x25, 0x00}, 88 - {0x26, 0x00}, 89 - {0x27, 0x00}, 90 - {0x28, 0x00}, 91 - {0x35, 0x00}, 92 - {0x66, 0x00}, 93 - {0x58, 0x82}, 94 - {0x59, 0x02}, 95 - {0x5a, 0x02}, 96 - {0x5b, 0x02}, 97 - {0x5c, 0x82}, 98 - {0x5d, 0x82}, 99 - {0x5e, 0x02}, 100 - {0x5f, 0x02}, 101 - {0x72, 0x31}, 105 + {0xfb, {0x01}, 0x01}, 106 + {0x00, {0x01}, 0x01}, 107 + {0x01, {0x55}, 0x01}, 108 + {0x02, {0x40}, 0x01}, 109 + {0x05, {0x40}, 0x01}, 110 + {0x06, {0x4a}, 0x01}, 111 + {0x07, {0x24}, 0x01}, 112 + {0x08, {0x0c}, 0x01}, 113 + {0x0b, {0x7d}, 0x01}, 114 + {0x0c, {0x7d}, 0x01}, 115 + {0x0e, {0xb0}, 0x01}, 116 + {0x0f, {0xae}, 0x01}, 117 + {0x11, {0x10}, 0x01}, 118 + {0x12, {0x10}, 0x01}, 119 + {0x13, {0x03}, 0x01}, 120 + {0x14, {0x4a}, 0x01}, 121 + {0x15, {0x12}, 0x01}, 122 + {0x16, {0x12}, 0x01}, 123 + {0x18, {0x00}, 0x01}, 124 + {0x19, {0x77}, 0x01}, 125 + {0x1a, {0x55}, 0x01}, 126 + {0x1b, {0x13}, 0x01}, 127 + {0x1c, {0x00}, 0x01}, 128 + {0x1d, {0x00}, 0x01}, 129 + {0x1e, {0x13}, 0x01}, 130 + {0x1f, {0x00}, 0x01}, 131 + {0x23, {0x00}, 0x01}, 132 + {0x24, {0x00}, 0x01}, 133 + {0x25, {0x00}, 0x01}, 134 + {0x26, {0x00}, 0x01}, 135 + {0x27, {0x00}, 0x01}, 136 + {0x28, {0x00}, 0x01}, 137 + {0x35, {0x00}, 0x01}, 138 + {0x66, {0x00}, 0x01}, 139 + {0x58, {0x82}, 0x01}, 140 + {0x59, {0x02}, 0x01}, 141 + {0x5a, {0x02}, 0x01}, 142 + {0x5b, {0x02}, 0x01}, 143 + {0x5c, {0x82}, 0x01}, 144 + {0x5d, {0x82}, 0x01}, 145 + {0x5e, {0x02}, 0x01}, 146 + {0x5f, {0x02}, 0x01}, 147 + {0x72, {0x31}, 0x01}, 102 148 /* Select CMD2 Page4 (Undocumented) */ 103 - {0xff, 0x05}, 149 + {0xff, {0x05}, 0x01}, 104 150 /* Reload CMD1: Don't reload default value to register */ 105 - {0xfb, 0x01}, 106 - {0x00, 0x01}, 107 - {0x01, 0x0b}, 108 - {0x02, 0x0c}, 109 - {0x03, 0x09}, 110 - {0x04, 0x0a}, 111 - {0x05, 0x00}, 112 - {0x06, 0x0f}, 113 - {0x07, 0x10}, 114 - {0x08, 0x00}, 115 - {0x09, 0x00}, 116 - {0x0a, 0x00}, 117 - {0x0b, 0x00}, 118 - {0x0c, 0x00}, 119 - {0x0d, 0x13}, 120 - {0x0e, 0x15}, 121 - {0x0f, 0x17}, 122 - {0x10, 0x01}, 123 - {0x11, 0x0b}, 124 - {0x12, 0x0c}, 125 - {0x13, 0x09}, 126 - {0x14, 0x0a}, 127 - {0x15, 0x00}, 128 - {0x16, 0x0f}, 129 - {0x17, 0x10}, 130 - {0x18, 0x00}, 131 - {0x19, 0x00}, 132 - {0x1a, 0x00}, 133 - {0x1b, 0x00}, 134 - {0x1c, 0x00}, 135 - {0x1d, 0x13}, 136 - {0x1e, 0x15}, 137 - {0x1f, 0x17}, 138 - {0x20, 0x00}, 139 - {0x21, 0x03}, 140 - {0x22, 0x01}, 141 - {0x23, 0x40}, 142 - {0x24, 0x40}, 143 - {0x25, 0xed}, 144 - {0x29, 0x58}, 145 - {0x2a, 0x12}, 146 - {0x2b, 0x01}, 147 - {0x4b, 0x06}, 148 - {0x4c, 0x11}, 149 - {0x4d, 0x20}, 150 - {0x4e, 0x02}, 151 - {0x4f, 0x02}, 152 - {0x50, 0x20}, 153 - {0x51, 0x61}, 154 - {0x52, 0x01}, 155 - {0x53, 0x63}, 156 - {0x54, 0x77}, 157 - {0x55, 0xed}, 158 - {0x5b, 0x00}, 159 - {0x5c, 0x00}, 160 - {0x5d, 0x00}, 161 - {0x5e, 0x00}, 162 - {0x5f, 0x15}, 163 - {0x60, 0x75}, 164 - {0x61, 0x00}, 165 - {0x62, 0x00}, 166 - {0x63, 0x00}, 167 - {0x64, 0x00}, 168 - {0x65, 0x00}, 169 - {0x66, 0x00}, 170 - {0x67, 0x00}, 171 - {0x68, 0x04}, 172 - {0x69, 0x00}, 173 - {0x6a, 0x00}, 174 - {0x6c, 0x40}, 175 - {0x75, 0x01}, 176 - {0x76, 0x01}, 177 - {0x7a, 0x80}, 178 - {0x7b, 0xa3}, 179 - {0x7c, 0xd8}, 180 - {0x7d, 0x60}, 181 - {0x7f, 0x15}, 182 - {0x80, 0x81}, 183 - {0x83, 0x05}, 184 - {0x93, 0x08}, 185 - {0x94, 0x10}, 186 - {0x8a, 0x00}, 187 - {0x9b, 0x0f}, 188 - {0xea, 0xff}, 189 - {0xec, 0x00}, 151 + {0xfb, {0x01}, 0x01}, 152 + {0x00, {0x01}, 0x01}, 153 + {0x01, {0x0b}, 0x01}, 154 + {0x02, {0x0c}, 0x01}, 155 + {0x03, {0x09}, 0x01}, 156 + {0x04, {0x0a}, 0x01}, 157 + {0x05, {0x00}, 0x01}, 158 + {0x06, {0x0f}, 0x01}, 159 + {0x07, {0x10}, 0x01}, 160 + {0x08, {0x00}, 0x01}, 161 + {0x09, {0x00}, 0x01}, 162 + {0x0a, {0x00}, 0x01}, 163 + {0x0b, {0x00}, 0x01}, 164 + {0x0c, {0x00}, 0x01}, 165 + {0x0d, {0x13}, 0x01}, 166 + {0x0e, {0x15}, 0x01}, 167 + {0x0f, {0x17}, 0x01}, 168 + {0x10, {0x01}, 0x01}, 169 + {0x11, {0x0b}, 0x01}, 170 + {0x12, {0x0c}, 0x01}, 171 + {0x13, {0x09}, 0x01}, 172 + {0x14, {0x0a}, 0x01}, 173 + {0x15, {0x00}, 0x01}, 174 + {0x16, {0x0f}, 0x01}, 175 + {0x17, {0x10}, 0x01}, 176 + {0x18, {0x00}, 0x01}, 177 + {0x19, {0x00}, 0x01}, 178 + {0x1a, {0x00}, 0x01}, 179 + {0x1b, {0x00}, 0x01}, 180 + {0x1c, {0x00}, 0x01}, 181 + {0x1d, {0x13}, 0x01}, 182 + {0x1e, {0x15}, 0x01}, 183 + {0x1f, {0x17}, 0x01}, 184 + {0x20, {0x00}, 0x01}, 185 + {0x21, {0x03}, 0x01}, 186 + {0x22, {0x01}, 0x01}, 187 + {0x23, {0x40}, 0x01}, 188 + {0x24, {0x40}, 0x01}, 189 + {0x25, {0xed}, 0x01}, 190 + {0x29, {0x58}, 0x01}, 191 + {0x2a, {0x12}, 0x01}, 192 + {0x2b, {0x01}, 0x01}, 193 + {0x4b, {0x06}, 0x01}, 194 + {0x4c, {0x11}, 0x01}, 195 + {0x4d, {0x20}, 0x01}, 196 + {0x4e, {0x02}, 0x01}, 197 + {0x4f, {0x02}, 0x01}, 198 + {0x50, {0x20}, 0x01}, 199 + {0x51, {0x61}, 0x01}, 200 + {0x52, {0x01}, 0x01}, 201 + {0x53, {0x63}, 0x01}, 202 + {0x54, {0x77}, 0x01}, 203 + {0x55, {0xed}, 0x01}, 204 + {0x5b, {0x00}, 0x01}, 205 + {0x5c, {0x00}, 0x01}, 206 + {0x5d, {0x00}, 0x01}, 207 + {0x5e, {0x00}, 0x01}, 208 + {0x5f, {0x15}, 0x01}, 209 + {0x60, {0x75}, 0x01}, 210 + {0x61, {0x00}, 0x01}, 211 + {0x62, {0x00}, 0x01}, 212 + {0x63, {0x00}, 0x01}, 213 + {0x64, {0x00}, 0x01}, 214 + {0x65, {0x00}, 0x01}, 215 + {0x66, {0x00}, 0x01}, 216 + {0x67, {0x00}, 0x01}, 217 + {0x68, {0x04}, 0x01}, 218 + {0x69, {0x00}, 0x01}, 219 + {0x6a, {0x00}, 0x01}, 220 + {0x6c, {0x40}, 0x01}, 221 + {0x75, {0x01}, 0x01}, 222 + {0x76, {0x01}, 0x01}, 223 + {0x7a, {0x80}, 0x01}, 224 + {0x7b, {0xa3}, 0x01}, 225 + {0x7c, {0xd8}, 0x01}, 226 + {0x7d, {0x60}, 0x01}, 227 + {0x7f, {0x15}, 0x01}, 228 + {0x80, {0x81}, 0x01}, 229 + {0x83, {0x05}, 0x01}, 230 + {0x93, {0x08}, 0x01}, 231 + {0x94, {0x10}, 0x01}, 232 + {0x8a, {0x00}, 0x01}, 233 + {0x9b, {0x0f}, 0x01}, 234 + {0xea, {0xff}, 0x01}, 235 + {0xec, {0x00}, 0x01}, 190 236 /* Select CMD2 Page0 (Undocumented) */ 191 - {0xff, 0x01}, 237 + {0xff, {0x01}, 0x01}, 192 238 /* Reload CMD1: Don't reload default value to register */ 193 - {0xfb, 0x01}, 194 - {0x75, 0x00}, 195 - {0x76, 0xdf}, 196 - {0x77, 0x00}, 197 - {0x78, 0xe4}, 198 - {0x79, 0x00}, 199 - {0x7a, 0xed}, 200 - {0x7b, 0x00}, 201 - {0x7c, 0xf6}, 202 - {0x7d, 0x00}, 203 - {0x7e, 0xff}, 204 - {0x7f, 0x01}, 205 - {0x80, 0x07}, 206 - {0x81, 0x01}, 207 - {0x82, 0x10}, 208 - {0x83, 0x01}, 209 - {0x84, 0x18}, 210 - {0x85, 0x01}, 211 - {0x86, 0x20}, 212 - {0x87, 0x01}, 213 - {0x88, 0x3d}, 214 - {0x89, 0x01}, 215 - {0x8a, 0x56}, 216 - {0x8b, 0x01}, 217 - {0x8c, 0x84}, 218 - {0x8d, 0x01}, 219 - {0x8e, 0xab}, 220 - {0x8f, 0x01}, 221 - {0x90, 0xec}, 222 - {0x91, 0x02}, 223 - {0x92, 0x22}, 224 - {0x93, 0x02}, 225 - {0x94, 0x23}, 226 - {0x95, 0x02}, 227 - {0x96, 0x55}, 228 - {0x97, 0x02}, 229 - {0x98, 0x8b}, 230 - {0x99, 0x02}, 231 - {0x9a, 0xaf}, 232 - {0x9b, 0x02}, 233 - {0x9c, 0xdf}, 234 - {0x9d, 0x03}, 235 - {0x9e, 0x01}, 236 - {0x9f, 0x03}, 237 - {0xa0, 0x2c}, 238 - {0xa2, 0x03}, 239 - {0xa3, 0x39}, 240 - {0xa4, 0x03}, 241 - {0xa5, 0x47}, 242 - {0xa6, 0x03}, 243 - {0xa7, 0x56}, 244 - {0xa9, 0x03}, 245 - {0xaa, 0x66}, 246 - {0xab, 0x03}, 247 - {0xac, 0x76}, 248 - {0xad, 0x03}, 249 - {0xae, 0x85}, 250 - {0xaf, 0x03}, 251 - {0xb0, 0x90}, 252 - {0xb1, 0x03}, 253 - {0xb2, 0xcb}, 254 - {0xb3, 0x00}, 255 - {0xb4, 0xdf}, 256 - {0xb5, 0x00}, 257 - {0xb6, 0xe4}, 258 - {0xb7, 0x00}, 259 - {0xb8, 0xed}, 260 - {0xb9, 0x00}, 261 - {0xba, 0xf6}, 262 - {0xbb, 0x00}, 263 - {0xbc, 0xff}, 264 - {0xbd, 0x01}, 265 - {0xbe, 0x07}, 266 - {0xbf, 0x01}, 267 - {0xc0, 0x10}, 268 - {0xc1, 0x01}, 269 - {0xc2, 0x18}, 270 - {0xc3, 0x01}, 271 - {0xc4, 0x20}, 272 - {0xc5, 0x01}, 273 - {0xc6, 0x3d}, 274 - {0xc7, 0x01}, 275 - {0xc8, 0x56}, 276 - {0xc9, 0x01}, 277 - {0xca, 0x84}, 278 - {0xcb, 0x01}, 279 - {0xcc, 0xab}, 280 - {0xcd, 0x01}, 281 - {0xce, 0xec}, 282 - {0xcf, 0x02}, 283 - {0xd0, 0x22}, 284 - {0xd1, 0x02}, 285 - {0xd2, 0x23}, 286 - {0xd3, 0x02}, 287 - {0xd4, 0x55}, 288 - {0xd5, 0x02}, 289 - {0xd6, 0x8b}, 290 - {0xd7, 0x02}, 291 - {0xd8, 0xaf}, 292 - {0xd9, 0x02}, 293 - {0xda, 0xdf}, 294 - {0xdb, 0x03}, 295 - {0xdc, 0x01}, 296 - {0xdd, 0x03}, 297 - {0xde, 0x2c}, 298 - {0xdf, 0x03}, 299 - {0xe0, 0x39}, 300 - {0xe1, 0x03}, 301 - {0xe2, 0x47}, 302 - {0xe3, 0x03}, 303 - {0xe4, 0x56}, 304 - {0xe5, 0x03}, 305 - {0xe6, 0x66}, 306 - {0xe7, 0x03}, 307 - {0xe8, 0x76}, 308 - {0xe9, 0x03}, 309 - {0xea, 0x85}, 310 - {0xeb, 0x03}, 311 - {0xec, 0x90}, 312 - {0xed, 0x03}, 313 - {0xee, 0xcb}, 314 - {0xef, 0x00}, 315 - {0xf0, 0xbb}, 316 - {0xf1, 0x00}, 317 - {0xf2, 0xc0}, 318 - {0xf3, 0x00}, 319 - {0xf4, 0xcc}, 320 - {0xf5, 0x00}, 321 - {0xf6, 0xd6}, 322 - {0xf7, 0x00}, 323 - {0xf8, 0xe1}, 324 - {0xf9, 0x00}, 325 - {0xfa, 0xea}, 239 + {0xfb, {0x01}, 0x01}, 240 + {0x75, {0x00}, 0x01}, 241 + {0x76, {0xdf}, 0x01}, 242 + {0x77, {0x00}, 0x01}, 243 + {0x78, {0xe4}, 0x01}, 244 + {0x79, {0x00}, 0x01}, 245 + {0x7a, {0xed}, 0x01}, 246 + {0x7b, {0x00}, 0x01}, 247 + {0x7c, {0xf6}, 0x01}, 248 + {0x7d, {0x00}, 0x01}, 249 + {0x7e, {0xff}, 0x01}, 250 + {0x7f, {0x01}, 0x01}, 251 + {0x80, {0x07}, 0x01}, 252 + {0x81, {0x01}, 0x01}, 253 + {0x82, {0x10}, 0x01}, 254 + {0x83, {0x01}, 0x01}, 255 + {0x84, {0x18}, 0x01}, 256 + {0x85, {0x01}, 0x01}, 257 + {0x86, {0x20}, 0x01}, 258 + {0x87, {0x01}, 0x01}, 259 + {0x88, {0x3d}, 0x01}, 260 + {0x89, {0x01}, 0x01}, 261 + {0x8a, {0x56}, 0x01}, 262 + {0x8b, {0x01}, 0x01}, 263 + {0x8c, {0x84}, 0x01}, 264 + {0x8d, {0x01}, 0x01}, 265 + {0x8e, {0xab}, 0x01}, 266 + {0x8f, {0x01}, 0x01}, 267 + {0x90, {0xec}, 0x01}, 268 + {0x91, {0x02}, 0x01}, 269 + {0x92, {0x22}, 0x01}, 270 + {0x93, {0x02}, 0x01}, 271 + {0x94, {0x23}, 0x01}, 272 + {0x95, {0x02}, 0x01}, 273 + {0x96, {0x55}, 0x01}, 274 + {0x97, {0x02}, 0x01}, 275 + {0x98, {0x8b}, 0x01}, 276 + {0x99, {0x02}, 0x01}, 277 + {0x9a, {0xaf}, 0x01}, 278 + {0x9b, {0x02}, 0x01}, 279 + {0x9c, {0xdf}, 0x01}, 280 + {0x9d, {0x03}, 0x01}, 281 + {0x9e, {0x01}, 0x01}, 282 + {0x9f, {0x03}, 0x01}, 283 + {0xa0, {0x2c}, 0x01}, 284 + {0xa2, {0x03}, 0x01}, 285 + {0xa3, {0x39}, 0x01}, 286 + {0xa4, {0x03}, 0x01}, 287 + {0xa5, {0x47}, 0x01}, 288 + {0xa6, {0x03}, 0x01}, 289 + {0xa7, {0x56}, 0x01}, 290 + {0xa9, {0x03}, 0x01}, 291 + {0xaa, {0x66}, 0x01}, 292 + {0xab, {0x03}, 0x01}, 293 + {0xac, {0x76}, 0x01}, 294 + {0xad, {0x03}, 0x01}, 295 + {0xae, {0x85}, 0x01}, 296 + {0xaf, {0x03}, 0x01}, 297 + {0xb0, {0x90}, 0x01}, 298 + {0xb1, {0x03}, 0x01}, 299 + {0xb2, {0xcb}, 0x01}, 300 + {0xb3, {0x00}, 0x01}, 301 + {0xb4, {0xdf}, 0x01}, 302 + {0xb5, {0x00}, 0x01}, 303 + {0xb6, {0xe4}, 0x01}, 304 + {0xb7, {0x00}, 0x01}, 305 + {0xb8, {0xed}, 0x01}, 306 + {0xb9, {0x00}, 0x01}, 307 + {0xba, {0xf6}, 0x01}, 308 + {0xbb, {0x00}, 0x01}, 309 + {0xbc, {0xff}, 0x01}, 310 + {0xbd, {0x01}, 0x01}, 311 + {0xbe, {0x07}, 0x01}, 312 + {0xbf, {0x01}, 0x01}, 313 + {0xc0, {0x10}, 0x01}, 314 + {0xc1, {0x01}, 0x01}, 315 + {0xc2, {0x18}, 0x01}, 316 + {0xc3, {0x01}, 0x01}, 317 + {0xc4, {0x20}, 0x01}, 318 + {0xc5, {0x01}, 0x01}, 319 + {0xc6, {0x3d}, 0x01}, 320 + {0xc7, {0x01}, 0x01}, 321 + {0xc8, {0x56}, 0x01}, 322 + {0xc9, {0x01}, 0x01}, 323 + {0xca, {0x84}, 0x01}, 324 + {0xcb, {0x01}, 0x01}, 325 + {0xcc, {0xab}, 0x01}, 326 + {0xcd, {0x01}, 0x01}, 327 + {0xce, {0xec}, 0x01}, 328 + {0xcf, {0x02}, 0x01}, 329 + {0xd0, {0x22}, 0x01}, 330 + {0xd1, {0x02}, 0x01}, 331 + {0xd2, {0x23}, 0x01}, 332 + {0xd3, {0x02}, 0x01}, 333 + {0xd4, {0x55}, 0x01}, 334 + {0xd5, {0x02}, 0x01}, 335 + {0xd6, {0x8b}, 0x01}, 336 + {0xd7, {0x02}, 0x01}, 337 + {0xd8, {0xaf}, 0x01}, 338 + {0xd9, {0x02}, 0x01}, 339 + {0xda, {0xdf}, 0x01}, 340 + {0xdb, {0x03}, 0x01}, 341 + {0xdc, {0x01}, 0x01}, 342 + {0xdd, {0x03}, 0x01}, 343 + {0xde, {0x2c}, 0x01}, 344 + {0xdf, {0x03}, 0x01}, 345 + {0xe0, {0x39}, 0x01}, 346 + {0xe1, {0x03}, 0x01}, 347 + {0xe2, {0x47}, 0x01}, 348 + {0xe3, {0x03}, 0x01}, 349 + {0xe4, {0x56}, 0x01}, 350 + {0xe5, {0x03}, 0x01}, 351 + {0xe6, {0x66}, 0x01}, 352 + {0xe7, {0x03}, 0x01}, 353 + {0xe8, {0x76}, 0x01}, 354 + {0xe9, {0x03}, 0x01}, 355 + {0xea, {0x85}, 0x01}, 356 + {0xeb, {0x03}, 0x01}, 357 + {0xec, {0x90}, 0x01}, 358 + {0xed, {0x03}, 0x01}, 359 + {0xee, {0xcb}, 0x01}, 360 + {0xef, {0x00}, 0x01}, 361 + {0xf0, {0xbb}, 0x01}, 362 + {0xf1, {0x00}, 0x01}, 363 + {0xf2, {0xc0}, 0x01}, 364 + {0xf3, {0x00}, 0x01}, 365 + {0xf4, {0xcc}, 0x01}, 366 + {0xf5, {0x00}, 0x01}, 367 + {0xf6, {0xd6}, 0x01}, 368 + {0xf7, {0x00}, 0x01}, 369 + {0xf8, {0xe1}, 0x01}, 370 + {0xf9, {0x00}, 0x01}, 371 + {0xfa, {0xea}, 0x01}, 326 372 /* Select CMD2 Page2 (Undocumented) */ 327 - {0xff, 0x02}, 373 + {0xff, {0x02}, 0x01}, 328 374 /* Reload CMD1: Don't reload default value to register */ 329 - {0xfb, 0x01}, 330 - {0x00, 0x00}, 331 - {0x01, 0xf4}, 332 - {0x02, 0x00}, 333 - {0x03, 0xef}, 334 - {0x04, 0x01}, 335 - {0x05, 0x07}, 336 - {0x06, 0x01}, 337 - {0x07, 0x28}, 338 - {0x08, 0x01}, 339 - {0x09, 0x44}, 340 - {0x0a, 0x01}, 341 - {0x0b, 0x76}, 342 - {0x0c, 0x01}, 343 - {0x0d, 0xa0}, 344 - {0x0e, 0x01}, 345 - {0x0f, 0xe7}, 346 - {0x10, 0x02}, 347 - {0x11, 0x1f}, 348 - {0x12, 0x02}, 349 - {0x13, 0x22}, 350 - {0x14, 0x02}, 351 - {0x15, 0x54}, 352 - {0x16, 0x02}, 353 - {0x17, 0x8b}, 354 - {0x18, 0x02}, 355 - {0x19, 0xaf}, 356 - {0x1a, 0x02}, 357 - {0x1b, 0xe0}, 358 - {0x1c, 0x03}, 359 - {0x1d, 0x01}, 360 - {0x1e, 0x03}, 361 - {0x1f, 0x2d}, 362 - {0x20, 0x03}, 363 - {0x21, 0x39}, 364 - {0x22, 0x03}, 365 - {0x23, 0x47}, 366 - {0x24, 0x03}, 367 - {0x25, 0x57}, 368 - {0x26, 0x03}, 369 - {0x27, 0x65}, 370 - {0x28, 0x03}, 371 - {0x29, 0x77}, 372 - {0x2a, 0x03}, 373 - {0x2b, 0x85}, 374 - {0x2d, 0x03}, 375 - {0x2f, 0x8f}, 376 - {0x30, 0x03}, 377 - {0x31, 0xcb}, 378 - {0x32, 0x00}, 379 - {0x33, 0xbb}, 380 - {0x34, 0x00}, 381 - {0x35, 0xc0}, 382 - {0x36, 0x00}, 383 - {0x37, 0xcc}, 384 - {0x38, 0x00}, 385 - {0x39, 0xd6}, 386 - {0x3a, 0x00}, 387 - {0x3b, 0xe1}, 388 - {0x3d, 0x00}, 389 - {0x3f, 0xea}, 390 - {0x40, 0x00}, 391 - {0x41, 0xf4}, 392 - {0x42, 0x00}, 393 - {0x43, 0xfe}, 394 - {0x44, 0x01}, 395 - {0x45, 0x07}, 396 - {0x46, 0x01}, 397 - {0x47, 0x28}, 398 - {0x48, 0x01}, 399 - {0x49, 0x44}, 400 - {0x4a, 0x01}, 401 - {0x4b, 0x76}, 402 - {0x4c, 0x01}, 403 - {0x4d, 0xa0}, 404 - {0x4e, 0x01}, 405 - {0x4f, 0xe7}, 406 - {0x50, 0x02}, 407 - {0x51, 0x1f}, 408 - {0x52, 0x02}, 409 - {0x53, 0x22}, 410 - {0x54, 0x02}, 411 - {0x55, 0x54}, 412 - {0x56, 0x02}, 413 - {0x58, 0x8b}, 414 - {0x59, 0x02}, 415 - {0x5a, 0xaf}, 416 - {0x5b, 0x02}, 417 - {0x5c, 0xe0}, 418 - {0x5d, 0x03}, 419 - {0x5e, 0x01}, 420 - {0x5f, 0x03}, 421 - {0x60, 0x2d}, 422 - {0x61, 0x03}, 423 - {0x62, 0x39}, 424 - {0x63, 0x03}, 425 - {0x64, 0x47}, 426 - {0x65, 0x03}, 427 - {0x66, 0x57}, 428 - {0x67, 0x03}, 429 - {0x68, 0x65}, 430 - {0x69, 0x03}, 431 - {0x6a, 0x77}, 432 - {0x6b, 0x03}, 433 - {0x6c, 0x85}, 434 - {0x6d, 0x03}, 435 - {0x6e, 0x8f}, 436 - {0x6f, 0x03}, 437 - {0x70, 0xcb}, 438 - {0x71, 0x00}, 439 - {0x72, 0x00}, 440 - {0x73, 0x00}, 441 - {0x74, 0x21}, 442 - {0x75, 0x00}, 443 - {0x76, 0x4c}, 444 - {0x77, 0x00}, 445 - {0x78, 0x6b}, 446 - {0x79, 0x00}, 447 - {0x7a, 0x85}, 448 - {0x7b, 0x00}, 449 - {0x7c, 0x9a}, 450 - {0x7d, 0x00}, 451 - {0x7e, 0xad}, 452 - {0x7f, 0x00}, 453 - {0x80, 0xbe}, 454 - {0x81, 0x00}, 455 - {0x82, 0xcd}, 456 - {0x83, 0x01}, 457 - {0x84, 0x01}, 458 - {0x85, 0x01}, 459 - {0x86, 0x29}, 460 - {0x87, 0x01}, 461 - {0x88, 0x68}, 462 - {0x89, 0x01}, 463 - {0x8a, 0x98}, 464 - {0x8b, 0x01}, 465 - {0x8c, 0xe5}, 466 - {0x8d, 0x02}, 467 - {0x8e, 0x1e}, 468 - {0x8f, 0x02}, 469 - {0x90, 0x30}, 470 - {0x91, 0x02}, 471 - {0x92, 0x52}, 472 - {0x93, 0x02}, 473 - {0x94, 0x88}, 474 - {0x95, 0x02}, 475 - {0x96, 0xaa}, 476 - {0x97, 0x02}, 477 - {0x98, 0xd7}, 478 - {0x99, 0x02}, 479 - {0x9a, 0xf7}, 480 - {0x9b, 0x03}, 481 - {0x9c, 0x21}, 482 - {0x9d, 0x03}, 483 - {0x9e, 0x2e}, 484 - {0x9f, 0x03}, 485 - {0xa0, 0x3d}, 486 - {0xa2, 0x03}, 487 - {0xa3, 0x4c}, 488 - {0xa4, 0x03}, 489 - {0xa5, 0x5e}, 490 - {0xa6, 0x03}, 491 - {0xa7, 0x71}, 492 - {0xa9, 0x03}, 493 - {0xaa, 0x86}, 494 - {0xab, 0x03}, 495 - {0xac, 0x94}, 496 - {0xad, 0x03}, 497 - {0xae, 0xfa}, 498 - {0xaf, 0x00}, 499 - {0xb0, 0x00}, 500 - {0xb1, 0x00}, 501 - {0xb2, 0x21}, 502 - {0xb3, 0x00}, 503 - {0xb4, 0x4c}, 504 - {0xb5, 0x00}, 505 - {0xb6, 0x6b}, 506 - {0xb7, 0x00}, 507 - {0xb8, 0x85}, 508 - {0xb9, 0x00}, 509 - {0xba, 0x9a}, 510 - {0xbb, 0x00}, 511 - {0xbc, 0xad}, 512 - {0xbd, 0x00}, 513 - {0xbe, 0xbe}, 514 - {0xbf, 0x00}, 515 - {0xc0, 0xcd}, 516 - {0xc1, 0x01}, 517 - {0xc2, 0x01}, 518 - {0xc3, 0x01}, 519 - {0xc4, 0x29}, 520 - {0xc5, 0x01}, 521 - {0xc6, 0x68}, 522 - {0xc7, 0x01}, 523 - {0xc8, 0x98}, 524 - {0xc9, 0x01}, 525 - {0xca, 0xe5}, 526 - {0xcb, 0x02}, 527 - {0xcc, 0x1e}, 528 - {0xcd, 0x02}, 529 - {0xce, 0x20}, 530 - {0xcf, 0x02}, 531 - {0xd0, 0x52}, 532 - {0xd1, 0x02}, 533 - {0xd2, 0x88}, 534 - {0xd3, 0x02}, 535 - {0xd4, 0xaa}, 536 - {0xd5, 0x02}, 537 - {0xd6, 0xd7}, 538 - {0xd7, 0x02}, 539 - {0xd8, 0xf7}, 540 - {0xd9, 0x03}, 541 - {0xda, 0x21}, 542 - {0xdb, 0x03}, 543 - {0xdc, 0x2e}, 544 - {0xdd, 0x03}, 545 - {0xde, 0x3d}, 546 - {0xdf, 0x03}, 547 - {0xe0, 0x4c}, 548 - {0xe1, 0x03}, 549 - {0xe2, 0x5e}, 550 - {0xe3, 0x03}, 551 - {0xe4, 0x71}, 552 - {0xe5, 0x03}, 553 - {0xe6, 0x86}, 554 - {0xe7, 0x03}, 555 - {0xe8, 0x94}, 556 - {0xe9, 0x03}, 557 - {0xea, 0xfa}, 375 + {0xfb, {0x01}, 0x01}, 376 + {0x00, {0x00}, 0x01}, 377 + {0x01, {0xf4}, 0x01}, 378 + {0x02, {0x00}, 0x01}, 379 + {0x03, {0xef}, 0x01}, 380 + {0x04, {0x01}, 0x01}, 381 + {0x05, {0x07}, 0x01}, 382 + {0x06, {0x01}, 0x01}, 383 + {0x07, {0x28}, 0x01}, 384 + {0x08, {0x01}, 0x01}, 385 + {0x09, {0x44}, 0x01}, 386 + {0x0a, {0x01}, 0x01}, 387 + {0x0b, {0x76}, 0x01}, 388 + {0x0c, {0x01}, 0x01}, 389 + {0x0d, {0xa0}, 0x01}, 390 + {0x0e, {0x01}, 0x01}, 391 + {0x0f, {0xe7}, 0x01}, 392 + {0x10, {0x02}, 0x01}, 393 + {0x11, {0x1f}, 0x01}, 394 + {0x12, {0x02}, 0x01}, 395 + {0x13, {0x22}, 0x01}, 396 + {0x14, {0x02}, 0x01}, 397 + {0x15, {0x54}, 0x01}, 398 + {0x16, {0x02}, 0x01}, 399 + {0x17, {0x8b}, 0x01}, 400 + {0x18, {0x02}, 0x01}, 401 + {0x19, {0xaf}, 0x01}, 402 + {0x1a, {0x02}, 0x01}, 403 + {0x1b, {0xe0}, 0x01}, 404 + {0x1c, {0x03}, 0x01}, 405 + {0x1d, {0x01}, 0x01}, 406 + {0x1e, {0x03}, 0x01}, 407 + {0x1f, {0x2d}, 0x01}, 408 + {0x20, {0x03}, 0x01}, 409 + {0x21, {0x39}, 0x01}, 410 + {0x22, {0x03}, 0x01}, 411 + {0x23, {0x47}, 0x01}, 412 + {0x24, {0x03}, 0x01}, 413 + {0x25, {0x57}, 0x01}, 414 + {0x26, {0x03}, 0x01}, 415 + {0x27, {0x65}, 0x01}, 416 + {0x28, {0x03}, 0x01}, 417 + {0x29, {0x77}, 0x01}, 418 + {0x2a, {0x03}, 0x01}, 419 + {0x2b, {0x85}, 0x01}, 420 + {0x2d, {0x03}, 0x01}, 421 + {0x2f, {0x8f}, 0x01}, 422 + {0x30, {0x03}, 0x01}, 423 + {0x31, {0xcb}, 0x01}, 424 + {0x32, {0x00}, 0x01}, 425 + {0x33, {0xbb}, 0x01}, 426 + {0x34, {0x00}, 0x01}, 427 + {0x35, {0xc0}, 0x01}, 428 + {0x36, {0x00}, 0x01}, 429 + {0x37, {0xcc}, 0x01}, 430 + {0x38, {0x00}, 0x01}, 431 + {0x39, {0xd6}, 0x01}, 432 + {0x3a, {0x00}, 0x01}, 433 + {0x3b, {0xe1}, 0x01}, 434 + {0x3d, {0x00}, 0x01}, 435 + {0x3f, {0xea}, 0x01}, 436 + {0x40, {0x00}, 0x01}, 437 + {0x41, {0xf4}, 0x01}, 438 + {0x42, {0x00}, 0x01}, 439 + {0x43, {0xfe}, 0x01}, 440 + {0x44, {0x01}, 0x01}, 441 + {0x45, {0x07}, 0x01}, 442 + {0x46, {0x01}, 0x01}, 443 + {0x47, {0x28}, 0x01}, 444 + {0x48, {0x01}, 0x01}, 445 + {0x49, {0x44}, 0x01}, 446 + {0x4a, {0x01}, 0x01}, 447 + {0x4b, {0x76}, 0x01}, 448 + {0x4c, {0x01}, 0x01}, 449 + {0x4d, {0xa0}, 0x01}, 450 + {0x4e, {0x01}, 0x01}, 451 + {0x4f, {0xe7}, 0x01}, 452 + {0x50, {0x02}, 0x01}, 453 + {0x51, {0x1f}, 0x01}, 454 + {0x52, {0x02}, 0x01}, 455 + {0x53, {0x22}, 0x01}, 456 + {0x54, {0x02}, 0x01}, 457 + {0x55, {0x54}, 0x01}, 458 + {0x56, {0x02}, 0x01}, 459 + {0x58, {0x8b}, 0x01}, 460 + {0x59, {0x02}, 0x01}, 461 + {0x5a, {0xaf}, 0x01}, 462 + {0x5b, {0x02}, 0x01}, 463 + {0x5c, {0xe0}, 0x01}, 464 + {0x5d, {0x03}, 0x01}, 465 + {0x5e, {0x01}, 0x01}, 466 + {0x5f, {0x03}, 0x01}, 467 + {0x60, {0x2d}, 0x01}, 468 + {0x61, {0x03}, 0x01}, 469 + {0x62, {0x39}, 0x01}, 470 + {0x63, {0x03}, 0x01}, 471 + {0x64, {0x47}, 0x01}, 472 + {0x65, {0x03}, 0x01}, 473 + {0x66, {0x57}, 0x01}, 474 + {0x67, {0x03}, 0x01}, 475 + {0x68, {0x65}, 0x01}, 476 + {0x69, {0x03}, 0x01}, 477 + {0x6a, {0x77}, 0x01}, 478 + {0x6b, {0x03}, 0x01}, 479 + {0x6c, {0x85}, 0x01}, 480 + {0x6d, {0x03}, 0x01}, 481 + {0x6e, {0x8f}, 0x01}, 482 + {0x6f, {0x03}, 0x01}, 483 + {0x70, {0xcb}, 0x01}, 484 + {0x71, {0x00}, 0x01}, 485 + {0x72, {0x00}, 0x01}, 486 + {0x73, {0x00}, 0x01}, 487 + {0x74, {0x21}, 0x01}, 488 + {0x75, {0x00}, 0x01}, 489 + {0x76, {0x4c}, 0x01}, 490 + {0x77, {0x00}, 0x01}, 491 + {0x78, {0x6b}, 0x01}, 492 + {0x79, {0x00}, 0x01}, 493 + {0x7a, {0x85}, 0x01}, 494 + {0x7b, {0x00}, 0x01}, 495 + {0x7c, {0x9a}, 0x01}, 496 + {0x7d, {0x00}, 0x01}, 497 + {0x7e, {0xad}, 0x01}, 498 + {0x7f, {0x00}, 0x01}, 499 + {0x80, {0xbe}, 0x01}, 500 + {0x81, {0x00}, 0x01}, 501 + {0x82, {0xcd}, 0x01}, 502 + {0x83, {0x01}, 0x01}, 503 + {0x84, {0x01}, 0x01}, 504 + {0x85, {0x01}, 0x01}, 505 + {0x86, {0x29}, 0x01}, 506 + {0x87, {0x01}, 0x01}, 507 + {0x88, {0x68}, 0x01}, 508 + {0x89, {0x01}, 0x01}, 509 + {0x8a, {0x98}, 0x01}, 510 + {0x8b, {0x01}, 0x01}, 511 + {0x8c, {0xe5}, 0x01}, 512 + {0x8d, {0x02}, 0x01}, 513 + {0x8e, {0x1e}, 0x01}, 514 + {0x8f, {0x02}, 0x01}, 515 + {0x90, {0x30}, 0x01}, 516 + {0x91, {0x02}, 0x01}, 517 + {0x92, {0x52}, 0x01}, 518 + {0x93, {0x02}, 0x01}, 519 + {0x94, {0x88}, 0x01}, 520 + {0x95, {0x02}, 0x01}, 521 + {0x96, {0xaa}, 0x01}, 522 + {0x97, {0x02}, 0x01}, 523 + {0x98, {0xd7}, 0x01}, 524 + {0x99, {0x02}, 0x01}, 525 + {0x9a, {0xf7}, 0x01}, 526 + {0x9b, {0x03}, 0x01}, 527 + {0x9c, {0x21}, 0x01}, 528 + {0x9d, {0x03}, 0x01}, 529 + {0x9e, {0x2e}, 0x01}, 530 + {0x9f, {0x03}, 0x01}, 531 + {0xa0, {0x3d}, 0x01}, 532 + {0xa2, {0x03}, 0x01}, 533 + {0xa3, {0x4c}, 0x01}, 534 + {0xa4, {0x03}, 0x01}, 535 + {0xa5, {0x5e}, 0x01}, 536 + {0xa6, {0x03}, 0x01}, 537 + {0xa7, {0x71}, 0x01}, 538 + {0xa9, {0x03}, 0x01}, 539 + {0xaa, {0x86}, 0x01}, 540 + {0xab, {0x03}, 0x01}, 541 + {0xac, {0x94}, 0x01}, 542 + {0xad, {0x03}, 0x01}, 543 + {0xae, {0xfa}, 0x01}, 544 + {0xaf, {0x00}, 0x01}, 545 + {0xb0, {0x00}, 0x01}, 546 + {0xb1, {0x00}, 0x01}, 547 + {0xb2, {0x21}, 0x01}, 548 + {0xb3, {0x00}, 0x01}, 549 + {0xb4, {0x4c}, 0x01}, 550 + {0xb5, {0x00}, 0x01}, 551 + {0xb6, {0x6b}, 0x01}, 552 + {0xb7, {0x00}, 0x01}, 553 + {0xb8, {0x85}, 0x01}, 554 + {0xb9, {0x00}, 0x01}, 555 + {0xba, {0x9a}, 0x01}, 556 + {0xbb, {0x00}, 0x01}, 557 + {0xbc, {0xad}, 0x01}, 558 + {0xbd, {0x00}, 0x01}, 559 + {0xbe, {0xbe}, 0x01}, 560 + {0xbf, {0x00}, 0x01}, 561 + {0xc0, {0xcd}, 0x01}, 562 + {0xc1, {0x01}, 0x01}, 563 + {0xc2, {0x01}, 0x01}, 564 + {0xc3, {0x01}, 0x01}, 565 + {0xc4, {0x29}, 0x01}, 566 + {0xc5, {0x01}, 0x01}, 567 + {0xc6, {0x68}, 0x01}, 568 + {0xc7, {0x01}, 0x01}, 569 + {0xc8, {0x98}, 0x01}, 570 + {0xc9, {0x01}, 0x01}, 571 + {0xca, {0xe5}, 0x01}, 572 + {0xcb, {0x02}, 0x01}, 573 + {0xcc, {0x1e}, 0x01}, 574 + {0xcd, {0x02}, 0x01}, 575 + {0xce, {0x20}, 0x01}, 576 + {0xcf, {0x02}, 0x01}, 577 + {0xd0, {0x52}, 0x01}, 578 + {0xd1, {0x02}, 0x01}, 579 + {0xd2, {0x88}, 0x01}, 580 + {0xd3, {0x02}, 0x01}, 581 + {0xd4, {0xaa}, 0x01}, 582 + {0xd5, {0x02}, 0x01}, 583 + {0xd6, {0xd7}, 0x01}, 584 + {0xd7, {0x02}, 0x01}, 585 + {0xd8, {0xf7}, 0x01}, 586 + {0xd9, {0x03}, 0x01}, 587 + {0xda, {0x21}, 0x01}, 588 + {0xdb, {0x03}, 0x01}, 589 + {0xdc, {0x2e}, 0x01}, 590 + {0xdd, {0x03}, 0x01}, 591 + {0xde, {0x3d}, 0x01}, 592 + {0xdf, {0x03}, 0x01}, 593 + {0xe0, {0x4c}, 0x01}, 594 + {0xe1, {0x03}, 0x01}, 595 + {0xe2, {0x5e}, 0x01}, 596 + {0xe3, {0x03}, 0x01}, 597 + {0xe4, {0x71}, 0x01}, 598 + {0xe5, {0x03}, 0x01}, 599 + {0xe6, {0x86}, 0x01}, 600 + {0xe7, {0x03}, 0x01}, 601 + {0xe8, {0x94}, 0x01}, 602 + {0xe9, {0x03}, 0x01}, 603 + {0xea, {0xfa}, 0x01}, 558 604 /* Select CMD2 Page0 (Undocumented) */ 559 - {0xff, 0x01}, 605 + {0xff, {0x01}, 0x01}, 560 606 /* Reload CMD1: Don't reload default value to register */ 561 - {0xfb, 0x01}, 607 + {0xfb, {0x01}, 0x01}, 562 608 /* Select CMD2 Page1 (Undocumented) */ 563 - {0xff, 0x02}, 609 + {0xff, {0x02}, 0x01}, 564 610 /* Reload CMD1: Don't reload default value to register */ 565 - {0xfb, 0x01}, 611 + {0xfb, {0x01}, 0x01}, 566 612 /* Select CMD2 Page3 (Undocumented) */ 567 - {0xff, 0x04}, 613 + {0xff, {0x04}, 0x01}, 568 614 /* Reload CMD1: Don't reload default value to register */ 569 - {0xfb, 0x01}, 615 + {0xfb, {0x01}, 0x01}, 570 616 /* Select CMD1 */ 571 - {0xff, 0x00}, 572 - {0xd3, 0x22}, /* RGBMIPICTRL: VSYNC back porch = 34 */ 573 - {0xd4, 0x04}, /* RGBMIPICTRL: VSYNC front porch = 4 */ 617 + {0xff, {0x00}, 0x01}, 618 + {0xd3, {0x22}, 0x01}, /* RGBMIPICTRL: VSYNC back porch = 34 */ 619 + {0xd4, {0x04}, 0x01}, /* RGBMIPICTRL: VSYNC front porch = 4 */ 620 + }; 621 + 622 + struct khadas_ts050_panel_data ts050_panel_data = { 623 + .init_code = (struct khadas_ts050_panel_cmd *)ts050_init_code, 624 + .len = ARRAY_SIZE(ts050_init_code) 625 + }; 626 + 627 + struct khadas_ts050_panel_data ts050v2_panel_data = { 628 + .init_code = (struct khadas_ts050_panel_cmd *)ts050v2_init_code, 629 + .len = ARRAY_SIZE(ts050v2_init_code) 574 630 }; 575 631 576 632 static inline ··· 671 613 672 614 msleep(100); 673 615 674 - for (i = 0; i < ARRAY_SIZE(init_code); i++) { 616 + for (i = 0; i < khadas_ts050->panel_data->len; i++) { 675 617 err = mipi_dsi_dcs_write(khadas_ts050->link, 676 - init_code[i].cmd, 677 - &init_code[i].data, 1); 618 + khadas_ts050->panel_data->init_code[i].cmd, 619 + &khadas_ts050->panel_data->init_code[i].data, 620 + khadas_ts050->panel_data->init_code[i].size); 678 621 if (err < 0) { 679 622 dev_err(panel->dev, "failed write cmds: %d\n", err); 680 623 goto poweroff; ··· 821 762 }; 822 763 823 764 static const struct of_device_id khadas_ts050_of_match[] = { 824 - { .compatible = "khadas,ts050", }, 765 + { .compatible = "khadas,ts050", .data = &ts050_panel_data, }, 766 + { .compatible = "khadas,ts050v2", .data = &ts050v2_panel_data, }, 825 767 { /* sentinel */ } 826 768 }; 827 769 MODULE_DEVICE_TABLE(of, khadas_ts050_of_match); ··· 866 806 struct khadas_ts050_panel *khadas_ts050; 867 807 int err; 868 808 809 + const void *data = of_device_get_match_data(&dsi->dev); 810 + 811 + if (!data) { 812 + dev_err(&dsi->dev, "No matching data\n"); 813 + return -ENODEV; 814 + } 815 + 869 816 dsi->lanes = 4; 870 817 dsi->format = MIPI_DSI_FMT_RGB888; 871 818 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | ··· 883 816 if (!khadas_ts050) 884 817 return -ENOMEM; 885 818 819 + khadas_ts050->panel_data = (struct khadas_ts050_panel_data *)data; 886 820 mipi_dsi_set_drvdata(dsi, khadas_ts050); 887 821 khadas_ts050->link = dsi; 888 822
+3 -8
drivers/gpu/drm/panel/panel-novatek-nt36672a.c
··· 605 605 struct device *dev = &pinfo->link->dev; 606 606 int i, ret; 607 607 608 - for (i = 0; i < ARRAY_SIZE(pinfo->supplies); i++) 608 + for (i = 0; i < ARRAY_SIZE(pinfo->supplies); i++) { 609 609 pinfo->supplies[i].supply = nt36672a_regulator_names[i]; 610 + pinfo->supplies[i].init_load_uA = nt36672a_regulator_enable_loads[i]; 611 + } 610 612 611 613 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pinfo->supplies), 612 614 pinfo->supplies); 613 615 if (ret < 0) 614 616 return dev_err_probe(dev, ret, "failed to get regulators\n"); 615 - 616 - for (i = 0; i < ARRAY_SIZE(pinfo->supplies); i++) { 617 - ret = regulator_set_load(pinfo->supplies[i].consumer, 618 - nt36672a_regulator_enable_loads[i]); 619 - if (ret) 620 - return dev_err_probe(dev, ret, "failed to set regulator enable loads\n"); 621 - } 622 617 623 618 pinfo->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 624 619 if (IS_ERR(pinfo->reset_gpio))
+4 -29
drivers/gpu/drm/panel/panel-novatek-nt36672e.c
··· 25 25 100000, 26 26 }; 27 27 28 - static const unsigned long regulator_disable_loads[] = { 29 - 80, 30 - 100, 31 - 100, 32 - }; 33 - 34 28 struct panel_desc { 35 29 const struct drm_display_mode *display_mode; 36 30 u32 width_mm; ··· 343 349 static int nt36672e_power_on(struct nt36672e_panel *ctx) 344 350 { 345 351 struct mipi_dsi_device *dsi = ctx->dsi; 346 - int ret, i; 347 - 348 - for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) { 349 - ret = regulator_set_load(ctx->supplies[i].consumer, 350 - regulator_enable_loads[i]); 351 - if (ret) { 352 - dev_err(&dsi->dev, "regulator set load failed for supply %s: %d\n", 353 - ctx->supplies[i].supply, ret); 354 - return ret; 355 - } 356 - } 352 + int ret; 357 353 358 354 ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 359 355 if (ret < 0) { ··· 369 385 { 370 386 struct mipi_dsi_device *dsi = ctx->dsi; 371 387 int ret = 0; 372 - int i; 373 388 374 389 gpiod_set_value(ctx->reset_gpio, 0); 375 - 376 - for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) { 377 - ret = regulator_set_load(ctx->supplies[i].consumer, 378 - regulator_disable_loads[i]); 379 - if (ret) { 380 - dev_err(&dsi->dev, "regulator set load failed for supply %s: %d\n", 381 - ctx->supplies[i].supply, ret); 382 - return ret; 383 - } 384 - } 385 390 386 391 ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 387 392 if (ret) ··· 540 567 return -ENODEV; 541 568 } 542 569 543 - for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) 570 + for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) { 544 571 ctx->supplies[i].supply = regulator_names[i]; 572 + ctx->supplies[i].init_load_uA = regulator_enable_loads[i]; 573 + } 545 574 546 575 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), 547 576 ctx->supplies);
+344
drivers/gpu/drm/panel/panel-raydium-rm69380.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree. 4 + * Copyright (c) 2024 David Wronek <david@mainlining.org> 5 + */ 6 + 7 + #include <linux/backlight.h> 8 + #include <linux/delay.h> 9 + #include <linux/gpio/consumer.h> 10 + #include <linux/module.h> 11 + #include <linux/of.h> 12 + #include <linux/of_device.h> 13 + #include <linux/of_graph.h> 14 + #include <linux/regulator/consumer.h> 15 + 16 + #include <video/mipi_display.h> 17 + 18 + #include <drm/drm_mipi_dsi.h> 19 + #include <drm/drm_modes.h> 20 + #include <drm/drm_panel.h> 21 + #include <drm/drm_probe_helper.h> 22 + 23 + struct rm69380_panel { 24 + struct drm_panel panel; 25 + struct mipi_dsi_device *dsi[2]; 26 + struct regulator_bulk_data supplies[2]; 27 + struct gpio_desc *reset_gpio; 28 + }; 29 + 30 + static inline 31 + struct rm69380_panel *to_rm69380_panel(struct drm_panel *panel) 32 + { 33 + return container_of(panel, struct rm69380_panel, panel); 34 + } 35 + 36 + static void rm69380_reset(struct rm69380_panel *ctx) 37 + { 38 + gpiod_set_value_cansleep(ctx->reset_gpio, 0); 39 + usleep_range(15000, 16000); 40 + gpiod_set_value_cansleep(ctx->reset_gpio, 1); 41 + usleep_range(10000, 11000); 42 + gpiod_set_value_cansleep(ctx->reset_gpio, 0); 43 + msleep(30); 44 + } 45 + 46 + static int rm69380_on(struct rm69380_panel *ctx) 47 + { 48 + struct mipi_dsi_device *dsi = ctx->dsi[0]; 49 + struct device *dev = &dsi->dev; 50 + int ret; 51 + 52 + dsi->mode_flags |= MIPI_DSI_MODE_LPM; 53 + if (ctx->dsi[1]) 54 + ctx->dsi[1]->mode_flags |= MIPI_DSI_MODE_LPM; 55 + 56 + mipi_dsi_dcs_write_seq(dsi, 0xfe, 0xd4); 57 + mipi_dsi_dcs_write_seq(dsi, 0x00, 0x80); 58 + mipi_dsi_dcs_write_seq(dsi, 0xfe, 0xd0); 59 + mipi_dsi_dcs_write_seq(dsi, 0x48, 0x00); 60 + mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x26); 61 + mipi_dsi_dcs_write_seq(dsi, 0x75, 0x3f); 62 + mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x1a); 63 + mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x00); 64 + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x28); 65 + mipi_dsi_dcs_write_seq(dsi, 0xc2, 0x08); 66 + 67 + ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); 68 + if (ret < 0) { 69 + dev_err(dev, "Failed to set tear on: %d\n", ret); 70 + return ret; 71 + } 72 + 73 + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); 74 + if (ret < 0) { 75 + dev_err(dev, "Failed to exit sleep mode: %d\n", ret); 76 + return ret; 77 + } 78 + msleep(20); 79 + 80 + ret = mipi_dsi_dcs_set_display_on(dsi); 81 + if (ret < 0) { 82 + dev_err(dev, "Failed to set display on: %d\n", ret); 83 + return ret; 84 + } 85 + msleep(36); 86 + 87 + return 0; 88 + } 89 + 90 + static int rm69380_off(struct rm69380_panel *ctx) 91 + { 92 + struct mipi_dsi_device *dsi = ctx->dsi[0]; 93 + struct device *dev = &dsi->dev; 94 + int ret; 95 + 96 + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 97 + if (ctx->dsi[1]) 98 + ctx->dsi[1]->mode_flags &= ~MIPI_DSI_MODE_LPM; 99 + 100 + ret = mipi_dsi_dcs_set_display_off(dsi); 101 + if (ret < 0) { 102 + dev_err(dev, "Failed to set display off: %d\n", ret); 103 + return ret; 104 + } 105 + msleep(35); 106 + 107 + ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 108 + if (ret < 0) { 109 + dev_err(dev, "Failed to enter sleep mode: %d\n", ret); 110 + return ret; 111 + } 112 + msleep(20); 113 + 114 + return 0; 115 + } 116 + 117 + static int rm69380_prepare(struct drm_panel *panel) 118 + { 119 + struct rm69380_panel *ctx = to_rm69380_panel(panel); 120 + struct device *dev = &ctx->dsi[0]->dev; 121 + int ret; 122 + 123 + ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 124 + if (ret < 0) { 125 + dev_err(dev, "Failed to enable regulators: %d\n", ret); 126 + return ret; 127 + } 128 + 129 + rm69380_reset(ctx); 130 + 131 + ret = rm69380_on(ctx); 132 + if (ret < 0) { 133 + dev_err(dev, "Failed to initialize panel: %d\n", ret); 134 + gpiod_set_value_cansleep(ctx->reset_gpio, 1); 135 + regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 136 + return ret; 137 + } 138 + 139 + return 0; 140 + } 141 + 142 + static int rm69380_unprepare(struct drm_panel *panel) 143 + { 144 + struct rm69380_panel *ctx = to_rm69380_panel(panel); 145 + struct device *dev = &ctx->dsi[0]->dev; 146 + int ret; 147 + 148 + ret = rm69380_off(ctx); 149 + if (ret < 0) 150 + dev_err(dev, "Failed to un-initialize panel: %d\n", ret); 151 + 152 + gpiod_set_value_cansleep(ctx->reset_gpio, 1); 153 + regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 154 + 155 + return 0; 156 + } 157 + 158 + static const struct drm_display_mode rm69380_mode = { 159 + .clock = (2560 + 32 + 12 + 38) * (1600 + 20 + 4 + 8) * 90 / 1000, 160 + .hdisplay = 2560, 161 + .hsync_start = 2560 + 32, 162 + .hsync_end = 2560 + 32 + 12, 163 + .htotal = 2560 + 32 + 12 + 38, 164 + .vdisplay = 1600, 165 + .vsync_start = 1600 + 20, 166 + .vsync_end = 1600 + 20 + 4, 167 + .vtotal = 1600 + 20 + 4 + 8, 168 + .width_mm = 248, 169 + .height_mm = 155, 170 + .type = DRM_MODE_TYPE_DRIVER, 171 + }; 172 + 173 + static int rm69380_get_modes(struct drm_panel *panel, 174 + struct drm_connector *connector) 175 + { 176 + return drm_connector_helper_get_modes_fixed(connector, &rm69380_mode); 177 + } 178 + 179 + static const struct drm_panel_funcs rm69380_panel_funcs = { 180 + .prepare = rm69380_prepare, 181 + .unprepare = rm69380_unprepare, 182 + .get_modes = rm69380_get_modes, 183 + }; 184 + 185 + static int rm69380_bl_update_status(struct backlight_device *bl) 186 + { 187 + struct mipi_dsi_device *dsi = bl_get_data(bl); 188 + u16 brightness = backlight_get_brightness(bl); 189 + int ret; 190 + 191 + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 192 + 193 + ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness); 194 + if (ret < 0) 195 + return ret; 196 + 197 + dsi->mode_flags |= MIPI_DSI_MODE_LPM; 198 + 199 + return 0; 200 + } 201 + 202 + static int rm69380_bl_get_brightness(struct backlight_device *bl) 203 + { 204 + struct mipi_dsi_device *dsi = bl_get_data(bl); 205 + u16 brightness; 206 + int ret; 207 + 208 + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 209 + 210 + ret = mipi_dsi_dcs_get_display_brightness_large(dsi, &brightness); 211 + if (ret < 0) 212 + return ret; 213 + 214 + dsi->mode_flags |= MIPI_DSI_MODE_LPM; 215 + 216 + return brightness; 217 + } 218 + 219 + static const struct backlight_ops rm69380_bl_ops = { 220 + .update_status = rm69380_bl_update_status, 221 + .get_brightness = rm69380_bl_get_brightness, 222 + }; 223 + 224 + static struct backlight_device * 225 + rm69380_create_backlight(struct mipi_dsi_device *dsi) 226 + { 227 + struct device *dev = &dsi->dev; 228 + const struct backlight_properties props = { 229 + .type = BACKLIGHT_RAW, 230 + .brightness = 511, 231 + .max_brightness = 2047, 232 + }; 233 + 234 + return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, 235 + &rm69380_bl_ops, &props); 236 + } 237 + 238 + static int rm69380_probe(struct mipi_dsi_device *dsi) 239 + { 240 + struct mipi_dsi_host *dsi_sec_host; 241 + struct rm69380_panel *ctx; 242 + struct device *dev = &dsi->dev; 243 + struct device_node *dsi_sec; 244 + int ret, i; 245 + 246 + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 247 + if (!ctx) 248 + return -ENOMEM; 249 + 250 + ctx->supplies[0].supply = "vddio"; 251 + ctx->supplies[1].supply = "avdd"; 252 + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), 253 + ctx->supplies); 254 + if (ret < 0) 255 + return dev_err_probe(dev, ret, "Failed to get regulators\n"); 256 + 257 + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 258 + if (IS_ERR(ctx->reset_gpio)) 259 + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), 260 + "Failed to get reset-gpios\n"); 261 + 262 + dsi_sec = of_graph_get_remote_node(dsi->dev.of_node, 1, -1); 263 + 264 + if (dsi_sec) { 265 + const struct mipi_dsi_device_info info = { "RM69380 DSI1", 0, 266 + dsi_sec }; 267 + 268 + dsi_sec_host = of_find_mipi_dsi_host_by_node(dsi_sec); 269 + of_node_put(dsi_sec); 270 + if (!dsi_sec_host) 271 + return dev_err_probe(dev, -EPROBE_DEFER, 272 + "Cannot get secondary DSI host\n"); 273 + 274 + ctx->dsi[1] = 275 + devm_mipi_dsi_device_register_full(dev, dsi_sec_host, &info); 276 + if (IS_ERR(ctx->dsi[1])) 277 + return dev_err_probe(dev, PTR_ERR(ctx->dsi[1]), 278 + "Cannot get secondary DSI node\n"); 279 + 280 + mipi_dsi_set_drvdata(ctx->dsi[1], ctx); 281 + } 282 + 283 + ctx->dsi[0] = dsi; 284 + mipi_dsi_set_drvdata(dsi, ctx); 285 + 286 + drm_panel_init(&ctx->panel, dev, &rm69380_panel_funcs, 287 + DRM_MODE_CONNECTOR_DSI); 288 + ctx->panel.prepare_prev_first = true; 289 + 290 + ctx->panel.backlight = rm69380_create_backlight(dsi); 291 + if (IS_ERR(ctx->panel.backlight)) 292 + return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight), 293 + "Failed to create backlight\n"); 294 + 295 + drm_panel_add(&ctx->panel); 296 + 297 + for (i = 0; i < ARRAY_SIZE(ctx->dsi); i++) { 298 + if (!ctx->dsi[i]) 299 + continue; 300 + 301 + dev_dbg(&ctx->dsi[i]->dev, "Binding DSI %d\n", i); 302 + 303 + ctx->dsi[i]->lanes = 4; 304 + ctx->dsi[i]->format = MIPI_DSI_FMT_RGB888; 305 + ctx->dsi[i]->mode_flags = MIPI_DSI_MODE_VIDEO_BURST | 306 + MIPI_DSI_CLOCK_NON_CONTINUOUS; 307 + 308 + ret = devm_mipi_dsi_attach(dev, ctx->dsi[i]); 309 + if (ret < 0) { 310 + drm_panel_remove(&ctx->panel); 311 + return dev_err_probe(dev, ret, 312 + "Failed to attach to DSI%d\n", i); 313 + } 314 + } 315 + 316 + return 0; 317 + } 318 + 319 + static void rm69380_remove(struct mipi_dsi_device *dsi) 320 + { 321 + struct rm69380_panel *ctx = mipi_dsi_get_drvdata(dsi); 322 + 323 + drm_panel_remove(&ctx->panel); 324 + } 325 + 326 + static const struct of_device_id rm69380_of_match[] = { 327 + { .compatible = "lenovo,j716f-edo-rm69380" }, 328 + { /* sentinel */ } 329 + }; 330 + MODULE_DEVICE_TABLE(of, rm69380_of_match); 331 + 332 + static struct mipi_dsi_driver rm69380_panel_driver = { 333 + .probe = rm69380_probe, 334 + .remove = rm69380_remove, 335 + .driver = { 336 + .name = "panel-raydium-rm69380", 337 + .of_match_table = rm69380_of_match, 338 + }, 339 + }; 340 + module_mipi_dsi_driver(rm69380_panel_driver); 341 + 342 + MODULE_AUTHOR("David Wronek <david@mainlining.org"); 343 + MODULE_DESCRIPTION("DRM driver for Raydium RM69380-equipped DSI panels"); 344 + MODULE_LICENSE("GPL");
+8 -5
drivers/gpu/drm/panel/panel-samsung-atna33xc20.c
··· 36 36 struct gpio_desc *el_on3_gpio; 37 37 struct drm_dp_aux *aux; 38 38 39 - struct edid *edid; 39 + const struct drm_edid *drm_edid; 40 40 41 41 ktime_t powered_off_time; 42 42 ktime_t powered_on_time; ··· 253 253 254 254 pm_runtime_get_sync(panel->dev); 255 255 256 - if (!p->edid) 257 - p->edid = drm_get_edid(connector, &aux_ep->aux->ddc); 258 - num = drm_add_edid_modes(connector, p->edid); 256 + if (!p->drm_edid) 257 + p->drm_edid = drm_edid_read_ddc(connector, &aux_ep->aux->ddc); 258 + 259 + drm_edid_connector_update(connector, p->drm_edid); 260 + 261 + num = drm_edid_connector_add_modes(connector); 259 262 260 263 pm_runtime_mark_last_busy(panel->dev); 261 264 pm_runtime_put_autosuspend(panel->dev); ··· 354 351 drm_panel_disable(&panel->base); 355 352 drm_panel_unprepare(&panel->base); 356 353 357 - kfree(panel->edid); 354 + drm_edid_free(panel->drm_edid); 358 355 } 359 356 360 357 static void atana33xc20_shutdown(struct dp_aux_ep_device *aux_ep)
+8 -7
drivers/gpu/drm/panel/panel-simple.c
··· 151 151 152 152 struct gpio_desc *enable_gpio; 153 153 154 - struct edid *edid; 154 + const struct drm_edid *drm_edid; 155 155 156 156 struct drm_display_mode override_mode; 157 157 ··· 309 309 regulator_disable(p->supply); 310 310 p->unprepared_time = ktime_get_boottime(); 311 311 312 - kfree(p->edid); 313 - p->edid = NULL; 312 + drm_edid_free(p->drm_edid); 313 + p->drm_edid = NULL; 314 314 315 315 return 0; 316 316 } ··· 399 399 if (p->ddc) { 400 400 pm_runtime_get_sync(panel->dev); 401 401 402 - if (!p->edid) 403 - p->edid = drm_get_edid(connector, p->ddc); 402 + if (!p->drm_edid) 403 + p->drm_edid = drm_edid_read_ddc(connector, p->ddc); 404 404 405 - if (p->edid) 406 - num += drm_add_edid_modes(connector, p->edid); 405 + drm_edid_connector_update(connector, p->drm_edid); 406 + 407 + num += drm_edid_connector_add_modes(connector); 407 408 408 409 pm_runtime_mark_last_busy(panel->dev); 409 410 pm_runtime_put_autosuspend(panel->dev);
+2 -14
drivers/gpu/drm/panel/panel-visionox-rm69299.c
··· 197 197 ctx->dsi = dsi; 198 198 199 199 ctx->supplies[0].supply = "vdda"; 200 + ctx->supplies[0].init_load_uA = 32000; 200 201 ctx->supplies[1].supply = "vdd3p3"; 202 + ctx->supplies[1].init_load_uA = 13200; 201 203 202 204 ret = devm_regulator_bulk_get(ctx->panel.dev, ARRAY_SIZE(ctx->supplies), 203 205 ctx->supplies); ··· 229 227 goto err_dsi_attach; 230 228 } 231 229 232 - ret = regulator_set_load(ctx->supplies[0].consumer, 32000); 233 - if (ret) { 234 - dev_err(dev, "regulator set load failed for vdda supply ret = %d\n", ret); 235 - goto err_set_load; 236 - } 237 - 238 - ret = regulator_set_load(ctx->supplies[1].consumer, 13200); 239 - if (ret) { 240 - dev_err(dev, "regulator set load failed for vdd3p3 supply ret = %d\n", ret); 241 - goto err_set_load; 242 - } 243 - 244 230 return 0; 245 231 246 - err_set_load: 247 - mipi_dsi_detach(dsi); 248 232 err_dsi_attach: 249 233 drm_panel_remove(&ctx->panel); 250 234 return ret;
+1 -1
drivers/gpu/drm/panthor/panthor_sched.c
··· 2546 2546 { 2547 2547 struct panthor_scheduler *sched = ptdev->scheduler; 2548 2548 struct panthor_csg_slots_upd_ctx upd_ctx; 2549 - u64 suspended_slots, faulty_slots; 2549 + u32 suspended_slots, faulty_slots; 2550 2550 struct panthor_group *group; 2551 2551 u32 i; 2552 2552
+1
drivers/gpu/drm/radeon/r100.c
··· 26 26 * Jerome Glisse 27 27 */ 28 28 29 + #include <linux/debugfs.h> 29 30 #include <linux/firmware.h> 30 31 #include <linux/module.h> 31 32 #include <linux/pci.h>
+1
drivers/gpu/drm/radeon/r300.c
··· 26 26 * Jerome Glisse 27 27 */ 28 28 29 + #include <linux/debugfs.h> 29 30 #include <linux/pci.h> 30 31 #include <linux/seq_file.h> 31 32 #include <linux/slab.h>
+1
drivers/gpu/drm/radeon/r420.c
··· 26 26 * Jerome Glisse 27 27 */ 28 28 29 + #include <linux/debugfs.h> 29 30 #include <linux/pci.h> 30 31 #include <linux/seq_file.h> 31 32 #include <linux/slab.h>
+2 -1
drivers/gpu/drm/radeon/r600.c
··· 26 26 * Jerome Glisse 27 27 */ 28 28 29 + #include <linux/debugfs.h> 29 30 #include <linux/firmware.h> 30 31 #include <linux/module.h> 31 32 #include <linux/pci.h> 32 - #include <linux/slab.h> 33 33 #include <linux/seq_file.h> 34 + #include <linux/slab.h> 34 35 35 36 #include <drm/drm_device.h> 36 37 #include <drm/drm_vblank.h>
+1
drivers/gpu/drm/radeon/radeon_fence.c
··· 30 30 */ 31 31 32 32 #include <linux/atomic.h> 33 + #include <linux/debugfs.h> 33 34 #include <linux/firmware.h> 34 35 #include <linux/kref.h> 35 36 #include <linux/sched/signal.h>
+1
drivers/gpu/drm/radeon/radeon_gem.c
··· 26 26 * Jerome Glisse 27 27 */ 28 28 29 + #include <linux/debugfs.h> 29 30 #include <linux/iosys-map.h> 30 31 #include <linux/pci.h> 31 32
+2
drivers/gpu/drm/radeon/radeon_ib.c
··· 27 27 * Christian König 28 28 */ 29 29 30 + #include <linux/debugfs.h> 31 + 30 32 #include <drm/drm_file.h> 31 33 32 34 #include "radeon.h"
+1
drivers/gpu/drm/radeon/radeon_pm.c
··· 21 21 * Alex Deucher <alexdeucher@gmail.com> 22 22 */ 23 23 24 + #include <linux/debugfs.h> 24 25 #include <linux/hwmon-sysfs.h> 25 26 #include <linux/hwmon.h> 26 27 #include <linux/pci.h>
+2
drivers/gpu/drm/radeon/radeon_ring.c
··· 27 27 * Christian König 28 28 */ 29 29 30 + #include <linux/debugfs.h> 31 + 30 32 #include <drm/drm_device.h> 31 33 #include <drm/drm_file.h> 32 34
+1
drivers/gpu/drm/radeon/radeon_ttm.c
··· 30 30 * Dave Airlie 31 31 */ 32 32 33 + #include <linux/debugfs.h> 33 34 #include <linux/dma-mapping.h> 34 35 #include <linux/pagemap.h> 35 36 #include <linux/pci.h>
+1
drivers/gpu/drm/radeon/rs400.c
··· 26 26 * Jerome Glisse 27 27 */ 28 28 29 + #include <linux/debugfs.h> 29 30 #include <linux/seq_file.h> 30 31 #include <linux/slab.h> 31 32
+1
drivers/gpu/drm/radeon/rv515.c
··· 26 26 * Jerome Glisse 27 27 */ 28 28 29 + #include <linux/debugfs.h> 29 30 #include <linux/seq_file.h> 30 31 #include <linux/slab.h> 31 32
+19 -15
drivers/gpu/drm/rockchip/cdn-dp-core.c
··· 262 262 static int cdn_dp_connector_get_modes(struct drm_connector *connector) 263 263 { 264 264 struct cdn_dp_device *dp = connector_to_dp(connector); 265 - struct edid *edid; 266 265 int ret = 0; 267 266 268 267 mutex_lock(&dp->lock); 269 - edid = dp->edid; 270 - if (edid) { 268 + 269 + if (dp->drm_edid) { 270 + /* FIXME: get rid of drm_edid_raw() */ 271 + const struct edid *edid = drm_edid_raw(dp->drm_edid); 272 + 271 273 DRM_DEV_DEBUG_KMS(dp->dev, "got edid: width[%d] x height[%d]\n", 272 274 edid->width_cm, edid->height_cm); 273 275 274 - dp->sink_has_audio = drm_detect_monitor_audio(edid); 275 - 276 - drm_connector_update_edid_property(connector, edid); 277 - ret = drm_add_edid_modes(connector, edid); 278 276 } 277 + 278 + ret = drm_edid_connector_add_modes(connector); 279 + 279 280 mutex_unlock(&dp->lock); 280 281 281 282 return ret; ··· 381 380 return ret; 382 381 } 383 382 384 - kfree(dp->edid); 385 - dp->edid = drm_do_get_edid(&dp->connector, 386 - cdn_dp_get_edid_block, dp); 383 + drm_edid_free(dp->drm_edid); 384 + dp->drm_edid = drm_edid_read_custom(&dp->connector, 385 + cdn_dp_get_edid_block, dp); 386 + drm_edid_connector_update(&dp->connector, dp->drm_edid); 387 + 388 + dp->sink_has_audio = dp->connector.display_info.has_audio; 389 + 387 390 return 0; 388 391 } 389 392 ··· 493 488 dp->max_lanes = 0; 494 489 dp->max_rate = 0; 495 490 if (!dp->connected) { 496 - kfree(dp->edid); 497 - dp->edid = NULL; 491 + drm_edid_free(dp->drm_edid); 492 + dp->drm_edid = NULL; 498 493 } 499 494 500 495 return 0; ··· 1136 1131 pm_runtime_disable(dev); 1137 1132 if (dp->fw_loaded) 1138 1133 release_firmware(dp->fw); 1139 - kfree(dp->edid); 1140 - dp->edid = NULL; 1134 + drm_edid_free(dp->drm_edid); 1135 + dp->drm_edid = NULL; 1141 1136 } 1142 1137 1143 1138 static const struct component_ops cdn_dp_component_ops = { ··· 1264 1259 .shutdown = cdn_dp_shutdown, 1265 1260 .driver = { 1266 1261 .name = "cdn-dp", 1267 - .owner = THIS_MODULE, 1268 1262 .of_match_table = cdn_dp_dt_ids, 1269 1263 .pm = &cdn_dp_pm_ops, 1270 1264 },
+1 -1
drivers/gpu/drm/rockchip/cdn-dp-core.h
··· 70 70 struct drm_display_mode mode; 71 71 struct platform_device *audio_pdev; 72 72 struct work_struct event_work; 73 - struct edid *edid; 73 + const struct drm_edid *drm_edid; 74 74 75 75 struct mutex lock; 76 76 bool connected;
+5 -7
drivers/gpu/drm/rockchip/inno_hdmi.c
··· 606 606 static int inno_hdmi_connector_get_modes(struct drm_connector *connector) 607 607 { 608 608 struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector); 609 - struct edid *edid; 609 + const struct drm_edid *drm_edid; 610 610 int ret = 0; 611 611 612 612 if (!hdmi->ddc) 613 613 return 0; 614 614 615 - edid = drm_get_edid(connector, hdmi->ddc); 616 - if (edid) { 617 - drm_connector_update_edid_property(connector, edid); 618 - ret = drm_add_edid_modes(connector, edid); 619 - kfree(edid); 620 - } 615 + drm_edid = drm_edid_read_ddc(connector, hdmi->ddc); 616 + drm_edid_connector_update(connector, drm_edid); 617 + ret = drm_edid_connector_add_modes(connector); 618 + drm_edid_free(drm_edid); 621 619 622 620 return ret; 623 621 }
+5 -7
drivers/gpu/drm/rockchip/rk3066_hdmi.c
··· 466 466 static int rk3066_hdmi_connector_get_modes(struct drm_connector *connector) 467 467 { 468 468 struct rk3066_hdmi *hdmi = connector_to_rk3066_hdmi(connector); 469 - struct edid *edid; 469 + const struct drm_edid *drm_edid; 470 470 int ret = 0; 471 471 472 472 if (!hdmi->ddc) 473 473 return 0; 474 474 475 - edid = drm_get_edid(connector, hdmi->ddc); 476 - if (edid) { 477 - drm_connector_update_edid_property(connector, edid); 478 - ret = drm_add_edid_modes(connector, edid); 479 - kfree(edid); 480 - } 475 + drm_edid = drm_edid_read_ddc(connector, hdmi->ddc); 476 + drm_edid_connector_update(connector, drm_edid); 477 + ret = drm_edid_connector_add_modes(connector); 478 + drm_edid_free(drm_edid); 481 479 482 480 return ret; 483 481 }
+12 -10
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
··· 706 706 const struct drm_format_info *info; 707 707 u16 hor_scl_mode, ver_scl_mode; 708 708 u16 hscl_filter_mode, vscl_filter_mode; 709 + uint16_t cbcr_src_w = src_w; 710 + uint16_t cbcr_src_h = src_h; 709 711 u8 gt2 = 0; 710 712 u8 gt4 = 0; 711 713 u32 val; ··· 765 763 vop2_win_write(win, VOP2_WIN_YRGB_VSCL_FILTER_MODE, vscl_filter_mode); 766 764 767 765 if (info->is_yuv) { 768 - src_w /= info->hsub; 769 - src_h /= info->vsub; 766 + cbcr_src_w /= info->hsub; 767 + cbcr_src_h /= info->vsub; 770 768 771 769 gt4 = 0; 772 770 gt2 = 0; 773 771 774 - if (src_h >= (4 * dst_h)) { 772 + if (cbcr_src_h >= (4 * dst_h)) { 775 773 gt4 = 1; 776 - src_h >>= 2; 777 - } else if (src_h >= (2 * dst_h)) { 774 + cbcr_src_h >>= 2; 775 + } else if (cbcr_src_h >= (2 * dst_h)) { 778 776 gt2 = 1; 779 - src_h >>= 1; 777 + cbcr_src_h >>= 1; 780 778 } 781 779 782 - hor_scl_mode = scl_get_scl_mode(src_w, dst_w); 783 - ver_scl_mode = scl_get_scl_mode(src_h, dst_h); 780 + hor_scl_mode = scl_get_scl_mode(cbcr_src_w, dst_w); 781 + ver_scl_mode = scl_get_scl_mode(cbcr_src_h, dst_h); 784 782 785 - val = vop2_scale_factor(src_w, dst_w); 783 + val = vop2_scale_factor(cbcr_src_w, dst_w); 786 784 vop2_win_write(win, VOP2_WIN_SCALE_CBCR_X, val); 787 785 788 - val = vop2_scale_factor(src_h, dst_h); 786 + val = vop2_scale_factor(cbcr_src_h, dst_h); 789 787 vop2_win_write(win, VOP2_WIN_SCALE_CBCR_Y, val); 790 788 791 789 vop2_win_write(win, VOP2_WIN_VSD_CBCR_GT4, gt4);
-1
drivers/gpu/drm/rockchip/rockchip_lvds.c
··· 17 17 #include <linux/regmap.h> 18 18 #include <linux/reset.h> 19 19 20 - #include <drm/display/drm_dp_helper.h> 21 20 #include <drm/drm_atomic_helper.h> 22 21 #include <drm/drm_bridge.h> 23 22 #include <drm/drm_bridge_connector.h>
+1
drivers/gpu/drm/sti/sti_drv.c
··· 5 5 */ 6 6 7 7 #include <linux/component.h> 8 + #include <linux/debugfs.h> 8 9 #include <linux/dma-mapping.h> 9 10 #include <linux/kernel.h> 10 11 #include <linux/module.h>
+11 -7
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
··· 214 214 static int sun4i_hdmi_get_modes(struct drm_connector *connector) 215 215 { 216 216 struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector); 217 - struct edid *edid; 217 + const struct drm_edid *drm_edid; 218 218 int ret; 219 219 220 - edid = drm_get_edid(connector, hdmi->ddc_i2c ?: hdmi->i2c); 221 - if (!edid) 220 + drm_edid = drm_edid_read_ddc(connector, hdmi->ddc_i2c ?: hdmi->i2c); 221 + 222 + drm_edid_connector_update(connector, drm_edid); 223 + cec_s_phys_addr(hdmi->cec_adap, 224 + connector->display_info.source_physical_address, false); 225 + 226 + if (!drm_edid) 222 227 return 0; 223 228 224 229 DRM_DEBUG_DRIVER("Monitor is %s monitor\n", 225 230 connector->display_info.is_hdmi ? "an HDMI" : "a DVI"); 226 231 227 - drm_connector_update_edid_property(connector, edid); 228 - cec_s_phys_addr_from_edid(hdmi->cec_adap, edid); 229 - ret = drm_add_edid_modes(connector, edid); 230 - kfree(edid); 232 + 233 + ret = drm_edid_connector_add_modes(connector); 234 + drm_edid_free(drm_edid); 231 235 232 236 return ret; 233 237 }
+157 -14
drivers/gpu/drm/tests/drm_buddy_test.c
··· 103 103 DRM_BUDDY_RANGE_ALLOCATION), 104 104 "buddy_alloc i failed with bias(%x-%x), size=%u, ps=%u\n", 105 105 bias_start, bias_end, bias_size, bias_size); 106 - drm_buddy_free_list(&mm, &tmp); 106 + drm_buddy_free_list(&mm, &tmp, 0); 107 107 108 108 /* single page with internal round_up */ 109 109 KUNIT_ASSERT_FALSE_MSG(test, ··· 113 113 DRM_BUDDY_RANGE_ALLOCATION), 114 114 "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n", 115 115 bias_start, bias_end, ps, bias_size); 116 - drm_buddy_free_list(&mm, &tmp); 116 + drm_buddy_free_list(&mm, &tmp, 0); 117 117 118 118 /* random size within */ 119 119 size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps); ··· 153 153 * unallocated, and ideally not always on the bias 154 154 * boundaries. 155 155 */ 156 - drm_buddy_free_list(&mm, &tmp); 156 + drm_buddy_free_list(&mm, &tmp, 0); 157 157 } else { 158 158 list_splice_tail(&tmp, &allocated); 159 159 } 160 160 } 161 161 162 162 kfree(order); 163 - drm_buddy_free_list(&mm, &allocated); 163 + drm_buddy_free_list(&mm, &allocated, 0); 164 164 drm_buddy_fini(&mm); 165 165 166 166 /* ··· 220 220 "buddy_alloc passed with bias(%x-%x), size=%u\n", 221 221 bias_start, bias_end, ps); 222 222 223 - drm_buddy_free_list(&mm, &allocated); 223 + drm_buddy_free_list(&mm, &allocated, 0); 224 + drm_buddy_fini(&mm); 225 + } 226 + 227 + static void drm_test_buddy_alloc_clear(struct kunit *test) 228 + { 229 + unsigned long n_pages, total, i = 0; 230 + DRM_RND_STATE(prng, random_seed); 231 + const unsigned long ps = SZ_4K; 232 + struct drm_buddy_block *block; 233 + const int max_order = 12; 234 + LIST_HEAD(allocated); 235 + struct drm_buddy mm; 236 + unsigned int order; 237 + u32 mm_size, size; 238 + LIST_HEAD(dirty); 239 + LIST_HEAD(clean); 240 + 241 + mm_size = SZ_4K << max_order; 242 + KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps)); 243 + 244 + KUNIT_EXPECT_EQ(test, mm.max_order, max_order); 245 + 246 + /* 247 + * Idea is to allocate and free some random portion of the address space, 248 + * returning those pages as non-dirty and randomly alternate between 249 + * requesting dirty and non-dirty pages (not going over the limit 250 + * we freed as non-dirty), putting that into two separate lists. 251 + * Loop over both lists at the end checking that the dirty list 252 + * is indeed all dirty pages and vice versa. Free it all again, 253 + * keeping the dirty/clear status. 254 + */ 255 + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, 256 + 5 * ps, ps, &allocated, 257 + DRM_BUDDY_TOPDOWN_ALLOCATION), 258 + "buddy_alloc hit an error size=%lu\n", 5 * ps); 259 + drm_buddy_free_list(&mm, &allocated, DRM_BUDDY_CLEARED); 260 + 261 + n_pages = 10; 262 + do { 263 + unsigned long flags; 264 + struct list_head *list; 265 + int slot = i % 2; 266 + 267 + if (slot == 0) { 268 + list = &dirty; 269 + flags = 0; 270 + } else { 271 + list = &clean; 272 + flags = DRM_BUDDY_CLEAR_ALLOCATION; 273 + } 274 + 275 + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, 276 + ps, ps, list, 277 + flags), 278 + "buddy_alloc hit an error size=%lu\n", ps); 279 + } while (++i < n_pages); 280 + 281 + list_for_each_entry(block, &clean, link) 282 + KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), true); 283 + 284 + list_for_each_entry(block, &dirty, link) 285 + KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), false); 286 + 287 + drm_buddy_free_list(&mm, &clean, DRM_BUDDY_CLEARED); 288 + 289 + /* 290 + * Trying to go over the clear limit for some allocation. 291 + * The allocation should never fail with reasonable page-size. 292 + */ 293 + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, 294 + 10 * ps, ps, &clean, 295 + DRM_BUDDY_CLEAR_ALLOCATION), 296 + "buddy_alloc hit an error size=%lu\n", 10 * ps); 297 + 298 + drm_buddy_free_list(&mm, &clean, DRM_BUDDY_CLEARED); 299 + drm_buddy_free_list(&mm, &dirty, 0); 300 + drm_buddy_fini(&mm); 301 + 302 + KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps)); 303 + 304 + /* 305 + * Create a new mm. Intentionally fragment the address space by creating 306 + * two alternating lists. Free both lists, one as dirty the other as clean. 307 + * Try to allocate double the previous size with matching min_page_size. The 308 + * allocation should never fail as it calls the force_merge. Also check that 309 + * the page is always dirty after force_merge. Free the page as dirty, then 310 + * repeat the whole thing, increment the order until we hit the max_order. 311 + */ 312 + 313 + i = 0; 314 + n_pages = mm_size / ps; 315 + do { 316 + struct list_head *list; 317 + int slot = i % 2; 318 + 319 + if (slot == 0) 320 + list = &dirty; 321 + else 322 + list = &clean; 323 + 324 + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, 325 + ps, ps, list, 0), 326 + "buddy_alloc hit an error size=%lu\n", ps); 327 + } while (++i < n_pages); 328 + 329 + drm_buddy_free_list(&mm, &clean, DRM_BUDDY_CLEARED); 330 + drm_buddy_free_list(&mm, &dirty, 0); 331 + 332 + order = 1; 333 + do { 334 + size = SZ_4K << order; 335 + 336 + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, 337 + size, size, &allocated, 338 + DRM_BUDDY_CLEAR_ALLOCATION), 339 + "buddy_alloc hit an error size=%u\n", size); 340 + total = 0; 341 + list_for_each_entry(block, &allocated, link) { 342 + if (size != mm_size) 343 + KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), false); 344 + total += drm_buddy_block_size(&mm, block); 345 + } 346 + KUNIT_EXPECT_EQ(test, total, size); 347 + 348 + drm_buddy_free_list(&mm, &allocated, 0); 349 + } while (++order <= max_order); 350 + 351 + drm_buddy_fini(&mm); 352 + 353 + /* 354 + * Create a new mm with a non power-of-two size. Allocate a random size, free as 355 + * cleared and then call fini. This will ensure the multi-root force merge during 356 + * fini. 357 + */ 358 + mm_size = 12 * SZ_4K; 359 + size = max(round_up(prandom_u32_state(&prng) % mm_size, ps), ps); 360 + KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps)); 361 + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, 362 + size, ps, &allocated, 363 + DRM_BUDDY_TOPDOWN_ALLOCATION), 364 + "buddy_alloc hit an error size=%u\n", size); 365 + drm_buddy_free_list(&mm, &allocated, DRM_BUDDY_CLEARED); 224 366 drm_buddy_fini(&mm); 225 367 } 226 368 ··· 411 269 DRM_BUDDY_CONTIGUOUS_ALLOCATION), 412 270 "buddy_alloc didn't error size=%lu\n", 3 * ps); 413 271 414 - drm_buddy_free_list(&mm, &middle); 272 + drm_buddy_free_list(&mm, &middle, 0); 415 273 KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, 416 274 3 * ps, ps, &allocated, 417 275 DRM_BUDDY_CONTIGUOUS_ALLOCATION), ··· 421 279 DRM_BUDDY_CONTIGUOUS_ALLOCATION), 422 280 "buddy_alloc didn't error size=%lu\n", 2 * ps); 423 281 424 - drm_buddy_free_list(&mm, &right); 282 + drm_buddy_free_list(&mm, &right, 0); 425 283 KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, 426 284 3 * ps, ps, &allocated, 427 285 DRM_BUDDY_CONTIGUOUS_ALLOCATION), ··· 436 294 DRM_BUDDY_CONTIGUOUS_ALLOCATION), 437 295 "buddy_alloc hit an error size=%lu\n", 2 * ps); 438 296 439 - drm_buddy_free_list(&mm, &left); 297 + drm_buddy_free_list(&mm, &left, 0); 440 298 KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, 441 299 3 * ps, ps, &allocated, 442 300 DRM_BUDDY_CONTIGUOUS_ALLOCATION), ··· 448 306 449 307 KUNIT_ASSERT_EQ(test, total, ps * 2 + ps * 3); 450 308 451 - drm_buddy_free_list(&mm, &allocated); 309 + drm_buddy_free_list(&mm, &allocated, 0); 452 310 drm_buddy_fini(&mm); 453 311 } 454 312 ··· 517 375 top, max_order); 518 376 } 519 377 520 - drm_buddy_free_list(&mm, &holes); 378 + drm_buddy_free_list(&mm, &holes, 0); 521 379 522 380 /* Nothing larger than blocks of chunk_size now available */ 523 381 for (order = 1; order <= max_order; order++) { ··· 529 387 } 530 388 531 389 list_splice_tail(&holes, &blocks); 532 - drm_buddy_free_list(&mm, &blocks); 390 + drm_buddy_free_list(&mm, &blocks, 0); 533 391 drm_buddy_fini(&mm); 534 392 } 535 393 ··· 624 482 625 483 list_del(&block->link); 626 484 drm_buddy_free_block(&mm, block); 627 - drm_buddy_free_list(&mm, &blocks); 485 + drm_buddy_free_list(&mm, &blocks, 0); 628 486 drm_buddy_fini(&mm); 629 487 } 630 488 ··· 670 528 size, size, &tmp, flags), 671 529 "buddy_alloc unexpectedly succeeded, it should be full!"); 672 530 673 - drm_buddy_free_list(&mm, &blocks); 531 + drm_buddy_free_list(&mm, &blocks, 0); 674 532 drm_buddy_fini(&mm); 675 533 } 676 534 ··· 705 563 drm_buddy_block_size(&mm, block), 706 564 BIT_ULL(mm.max_order) * PAGE_SIZE); 707 565 708 - drm_buddy_free_list(&mm, &allocated); 566 + drm_buddy_free_list(&mm, &allocated, 0); 709 567 drm_buddy_fini(&mm); 710 568 } 711 569 ··· 726 584 KUNIT_CASE(drm_test_buddy_alloc_pessimistic), 727 585 KUNIT_CASE(drm_test_buddy_alloc_pathological), 728 586 KUNIT_CASE(drm_test_buddy_alloc_contiguous), 587 + KUNIT_CASE(drm_test_buddy_alloc_clear), 729 588 KUNIT_CASE(drm_test_buddy_alloc_range_bias), 730 589 {} 731 590 };
+1
drivers/gpu/drm/ttm/ttm_device.c
··· 27 27 28 28 #define pr_fmt(fmt) "[TTM DEVICE] " fmt 29 29 30 + #include <linux/debugfs.h> 30 31 #include <linux/mm.h> 31 32 32 33 #include <drm/ttm/ttm_bo.h>
+2 -1
drivers/gpu/drm/ttm/ttm_resource.c
··· 22 22 * Authors: Christian König 23 23 */ 24 24 25 - #include <linux/iosys-map.h> 25 + #include <linux/debugfs.h> 26 26 #include <linux/io-mapping.h> 27 + #include <linux/iosys-map.h> 27 28 #include <linux/scatterlist.h> 28 29 29 30 #include <drm/ttm/ttm_bo.h>
+3 -2
drivers/gpu/drm/ttm/ttm_tt.c
··· 32 32 #define pr_fmt(fmt) "[TTM] " fmt 33 33 34 34 #include <linux/cc_platform.h> 35 - #include <linux/sched.h> 36 - #include <linux/shmem_fs.h> 35 + #include <linux/debugfs.h> 37 36 #include <linux/file.h> 38 37 #include <linux/module.h> 38 + #include <linux/sched.h> 39 + #include <linux/shmem_fs.h> 39 40 #include <drm/drm_cache.h> 40 41 #include <drm/drm_device.h> 41 42 #include <drm/drm_util.h>
+24 -9
drivers/gpu/drm/v3d/v3d_drv.c
··· 115 115 v3d_priv->v3d = v3d; 116 116 117 117 for (i = 0; i < V3D_MAX_QUEUES; i++) { 118 - v3d_priv->enabled_ns[i] = 0; 119 - v3d_priv->start_ns[i] = 0; 120 - v3d_priv->jobs_sent[i] = 0; 121 - 122 118 sched = &v3d->queue[i].sched; 123 119 drm_sched_entity_init(&v3d_priv->sched_entity[i], 124 120 DRM_SCHED_PRIORITY_NORMAL, &sched, 125 121 1, NULL); 122 + 123 + memset(&v3d_priv->stats[i], 0, sizeof(v3d_priv->stats[i])); 124 + seqcount_init(&v3d_priv->stats[i].lock); 126 125 } 127 126 128 127 v3d_perfmon_open_file(v3d_priv); ··· 143 144 kfree(v3d_priv); 144 145 } 145 146 147 + void v3d_get_stats(const struct v3d_stats *stats, u64 timestamp, 148 + u64 *active_runtime, u64 *jobs_completed) 149 + { 150 + unsigned int seq; 151 + 152 + do { 153 + seq = read_seqcount_begin(&stats->lock); 154 + *active_runtime = stats->enabled_ns; 155 + if (stats->start_ns) 156 + *active_runtime += timestamp - stats->start_ns; 157 + *jobs_completed = stats->jobs_completed; 158 + } while (read_seqcount_retry(&stats->lock, seq)); 159 + } 160 + 146 161 static void v3d_show_fdinfo(struct drm_printer *p, struct drm_file *file) 147 162 { 148 163 struct v3d_file_priv *file_priv = file->driver_priv; ··· 164 151 enum v3d_queue queue; 165 152 166 153 for (queue = 0; queue < V3D_MAX_QUEUES; queue++) { 154 + struct v3d_stats *stats = &file_priv->stats[queue]; 155 + u64 active_runtime, jobs_completed; 156 + 157 + v3d_get_stats(stats, timestamp, &active_runtime, &jobs_completed); 158 + 167 159 /* Note that, in case of a GPU reset, the time spent during an 168 160 * attempt of executing the job is not computed in the runtime. 169 161 */ 170 162 drm_printf(p, "drm-engine-%s: \t%llu ns\n", 171 - v3d_queue_to_string(queue), 172 - file_priv->start_ns[queue] ? file_priv->enabled_ns[queue] 173 - + timestamp - file_priv->start_ns[queue] 174 - : file_priv->enabled_ns[queue]); 163 + v3d_queue_to_string(queue), active_runtime); 175 164 176 165 /* Note that we only count jobs that completed. Therefore, jobs 177 166 * that were resubmitted due to a GPU reset are not computed. 178 167 */ 179 168 drm_printf(p, "v3d-jobs-%s: \t%llu jobs\n", 180 - v3d_queue_to_string(queue), file_priv->jobs_sent[queue]); 169 + v3d_queue_to_string(queue), jobs_completed); 181 170 } 182 171 } 183 172
+22 -8
drivers/gpu/drm/v3d/v3d_drv.h
··· 36 36 return "UNKNOWN"; 37 37 } 38 38 39 + struct v3d_stats { 40 + u64 start_ns; 41 + u64 enabled_ns; 42 + u64 jobs_completed; 43 + 44 + /* 45 + * This seqcount is used to protect the access to the GPU stats 46 + * variables. It must be used as, while we are reading the stats, 47 + * IRQs can happen and the stats can be updated. 48 + */ 49 + seqcount_t lock; 50 + }; 51 + 39 52 struct v3d_queue_state { 40 53 struct drm_gpu_scheduler sched; 41 54 42 55 u64 fence_context; 43 56 u64 emit_seqno; 44 57 45 - u64 start_ns; 46 - u64 enabled_ns; 47 - u64 jobs_sent; 58 + /* Stores the GPU stats for this queue in the global context. */ 59 + struct v3d_stats stats; 48 60 }; 49 61 50 62 /* Performance monitor object. The perform lifetime is controlled by userspace ··· 200 188 201 189 struct drm_sched_entity sched_entity[V3D_MAX_QUEUES]; 202 190 203 - u64 start_ns[V3D_MAX_QUEUES]; 204 - 205 - u64 enabled_ns[V3D_MAX_QUEUES]; 206 - 207 - u64 jobs_sent[V3D_MAX_QUEUES]; 191 + /* Stores the GPU stats for a specific queue for this fd. */ 192 + struct v3d_stats stats[V3D_MAX_QUEUES]; 208 193 }; 209 194 210 195 struct v3d_bo { ··· 517 508 /* v3d_debugfs.c */ 518 509 void v3d_debugfs_init(struct drm_minor *minor); 519 510 511 + /* v3d_drv.c */ 512 + void v3d_get_stats(const struct v3d_stats *stats, u64 timestamp, 513 + u64 *active_runtime, u64 *jobs_completed); 514 + 520 515 /* v3d_fence.c */ 521 516 extern const struct dma_fence_ops v3d_fence_ops; 522 517 struct dma_fence *v3d_fence_create(struct v3d_dev *v3d, enum v3d_queue queue); ··· 556 543 void v3d_mmu_remove_ptes(struct v3d_bo *bo); 557 544 558 545 /* v3d_sched.c */ 546 + void v3d_job_update_stats(struct v3d_job *job, enum v3d_queue queue); 559 547 int v3d_sched_init(struct v3d_dev *v3d); 560 548 void v3d_sched_fini(struct v3d_dev *v3d); 561 549
+5 -4
drivers/gpu/drm/v3d/v3d_gem.c
··· 247 247 int ret, i; 248 248 249 249 for (i = 0; i < V3D_MAX_QUEUES; i++) { 250 - v3d->queue[i].fence_context = dma_fence_context_alloc(1); 251 - v3d->queue[i].start_ns = 0; 252 - v3d->queue[i].enabled_ns = 0; 253 - v3d->queue[i].jobs_sent = 0; 250 + struct v3d_queue_state *queue = &v3d->queue[i]; 251 + 252 + queue->fence_context = dma_fence_context_alloc(1); 253 + memset(&queue->stats, 0, sizeof(queue->stats)); 254 + seqcount_init(&queue->stats.lock); 254 255 } 255 256 256 257 spin_lock_init(&v3d->mm_lock);
+4 -44
drivers/gpu/drm/v3d/v3d_irq.c
··· 102 102 if (intsts & V3D_INT_FLDONE) { 103 103 struct v3d_fence *fence = 104 104 to_v3d_fence(v3d->bin_job->base.irq_fence); 105 - struct v3d_file_priv *file = v3d->bin_job->base.file->driver_priv; 106 - u64 runtime = local_clock() - file->start_ns[V3D_BIN]; 107 105 108 - file->jobs_sent[V3D_BIN]++; 109 - v3d->queue[V3D_BIN].jobs_sent++; 110 - 111 - file->start_ns[V3D_BIN] = 0; 112 - v3d->queue[V3D_BIN].start_ns = 0; 113 - 114 - file->enabled_ns[V3D_BIN] += runtime; 115 - v3d->queue[V3D_BIN].enabled_ns += runtime; 116 - 106 + v3d_job_update_stats(&v3d->bin_job->base, V3D_BIN); 117 107 trace_v3d_bcl_irq(&v3d->drm, fence->seqno); 118 108 dma_fence_signal(&fence->base); 119 109 status = IRQ_HANDLED; ··· 112 122 if (intsts & V3D_INT_FRDONE) { 113 123 struct v3d_fence *fence = 114 124 to_v3d_fence(v3d->render_job->base.irq_fence); 115 - struct v3d_file_priv *file = v3d->render_job->base.file->driver_priv; 116 - u64 runtime = local_clock() - file->start_ns[V3D_RENDER]; 117 125 118 - file->jobs_sent[V3D_RENDER]++; 119 - v3d->queue[V3D_RENDER].jobs_sent++; 120 - 121 - file->start_ns[V3D_RENDER] = 0; 122 - v3d->queue[V3D_RENDER].start_ns = 0; 123 - 124 - file->enabled_ns[V3D_RENDER] += runtime; 125 - v3d->queue[V3D_RENDER].enabled_ns += runtime; 126 - 126 + v3d_job_update_stats(&v3d->render_job->base, V3D_RENDER); 127 127 trace_v3d_rcl_irq(&v3d->drm, fence->seqno); 128 128 dma_fence_signal(&fence->base); 129 129 status = IRQ_HANDLED; ··· 122 142 if (intsts & V3D_INT_CSDDONE(v3d->ver)) { 123 143 struct v3d_fence *fence = 124 144 to_v3d_fence(v3d->csd_job->base.irq_fence); 125 - struct v3d_file_priv *file = v3d->csd_job->base.file->driver_priv; 126 - u64 runtime = local_clock() - file->start_ns[V3D_CSD]; 127 145 128 - file->jobs_sent[V3D_CSD]++; 129 - v3d->queue[V3D_CSD].jobs_sent++; 130 - 131 - file->start_ns[V3D_CSD] = 0; 132 - v3d->queue[V3D_CSD].start_ns = 0; 133 - 134 - file->enabled_ns[V3D_CSD] += runtime; 135 - v3d->queue[V3D_CSD].enabled_ns += runtime; 136 - 146 + v3d_job_update_stats(&v3d->csd_job->base, V3D_CSD); 137 147 trace_v3d_csd_irq(&v3d->drm, fence->seqno); 138 148 dma_fence_signal(&fence->base); 139 149 status = IRQ_HANDLED; ··· 159 189 if (intsts & V3D_HUB_INT_TFUC) { 160 190 struct v3d_fence *fence = 161 191 to_v3d_fence(v3d->tfu_job->base.irq_fence); 162 - struct v3d_file_priv *file = v3d->tfu_job->base.file->driver_priv; 163 - u64 runtime = local_clock() - file->start_ns[V3D_TFU]; 164 192 165 - file->jobs_sent[V3D_TFU]++; 166 - v3d->queue[V3D_TFU].jobs_sent++; 167 - 168 - file->start_ns[V3D_TFU] = 0; 169 - v3d->queue[V3D_TFU].start_ns = 0; 170 - 171 - file->enabled_ns[V3D_TFU] += runtime; 172 - v3d->queue[V3D_TFU].enabled_ns += runtime; 173 - 193 + v3d_job_update_stats(&v3d->tfu_job->base, V3D_TFU); 174 194 trace_v3d_tfu_irq(&v3d->drm, fence->seqno); 175 195 dma_fence_signal(&fence->base); 176 196 status = IRQ_HANDLED;
+49 -45
drivers/gpu/drm/v3d/v3d_sched.c
··· 105 105 v3d_perfmon_start(v3d, job->perfmon); 106 106 } 107 107 108 + static void 109 + v3d_job_start_stats(struct v3d_job *job, enum v3d_queue queue) 110 + { 111 + struct v3d_dev *v3d = job->v3d; 112 + struct v3d_file_priv *file = job->file->driver_priv; 113 + struct v3d_stats *global_stats = &v3d->queue[queue].stats; 114 + struct v3d_stats *local_stats = &file->stats[queue]; 115 + u64 now = local_clock(); 116 + 117 + write_seqcount_begin(&local_stats->lock); 118 + local_stats->start_ns = now; 119 + write_seqcount_end(&local_stats->lock); 120 + 121 + write_seqcount_begin(&global_stats->lock); 122 + global_stats->start_ns = now; 123 + write_seqcount_end(&global_stats->lock); 124 + } 125 + 126 + static void 127 + v3d_stats_update(struct v3d_stats *stats, u64 now) 128 + { 129 + write_seqcount_begin(&stats->lock); 130 + stats->enabled_ns += now - stats->start_ns; 131 + stats->jobs_completed++; 132 + stats->start_ns = 0; 133 + write_seqcount_end(&stats->lock); 134 + } 135 + 136 + void 137 + v3d_job_update_stats(struct v3d_job *job, enum v3d_queue queue) 138 + { 139 + struct v3d_dev *v3d = job->v3d; 140 + struct v3d_file_priv *file = job->file->driver_priv; 141 + struct v3d_stats *global_stats = &v3d->queue[queue].stats; 142 + struct v3d_stats *local_stats = &file->stats[queue]; 143 + u64 now = local_clock(); 144 + 145 + v3d_stats_update(local_stats, now); 146 + v3d_stats_update(global_stats, now); 147 + } 148 + 108 149 static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job) 109 150 { 110 151 struct v3d_bin_job *job = to_bin_job(sched_job); 111 152 struct v3d_dev *v3d = job->base.v3d; 112 - struct v3d_file_priv *file = job->base.file->driver_priv; 113 153 struct drm_device *dev = &v3d->drm; 114 154 struct dma_fence *fence; 115 155 unsigned long irqflags; ··· 181 141 trace_v3d_submit_cl(dev, false, to_v3d_fence(fence)->seqno, 182 142 job->start, job->end); 183 143 184 - file->start_ns[V3D_BIN] = local_clock(); 185 - v3d->queue[V3D_BIN].start_ns = file->start_ns[V3D_BIN]; 186 - 144 + v3d_job_start_stats(&job->base, V3D_BIN); 187 145 v3d_switch_perfmon(v3d, &job->base); 188 146 189 147 /* Set the current and end address of the control list. ··· 206 168 { 207 169 struct v3d_render_job *job = to_render_job(sched_job); 208 170 struct v3d_dev *v3d = job->base.v3d; 209 - struct v3d_file_priv *file = job->base.file->driver_priv; 210 171 struct drm_device *dev = &v3d->drm; 211 172 struct dma_fence *fence; 212 173 ··· 233 196 trace_v3d_submit_cl(dev, true, to_v3d_fence(fence)->seqno, 234 197 job->start, job->end); 235 198 236 - file->start_ns[V3D_RENDER] = local_clock(); 237 - v3d->queue[V3D_RENDER].start_ns = file->start_ns[V3D_RENDER]; 238 - 199 + v3d_job_start_stats(&job->base, V3D_RENDER); 239 200 v3d_switch_perfmon(v3d, &job->base); 240 201 241 202 /* XXX: Set the QCFG */ ··· 252 217 { 253 218 struct v3d_tfu_job *job = to_tfu_job(sched_job); 254 219 struct v3d_dev *v3d = job->base.v3d; 255 - struct v3d_file_priv *file = job->base.file->driver_priv; 256 220 struct drm_device *dev = &v3d->drm; 257 221 struct dma_fence *fence; 258 222 ··· 266 232 267 233 trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno); 268 234 269 - file->start_ns[V3D_TFU] = local_clock(); 270 - v3d->queue[V3D_TFU].start_ns = file->start_ns[V3D_TFU]; 235 + v3d_job_start_stats(&job->base, V3D_TFU); 271 236 272 237 V3D_WRITE(V3D_TFU_IIA(v3d->ver), job->args.iia); 273 238 V3D_WRITE(V3D_TFU_IIS(v3d->ver), job->args.iis); ··· 293 260 { 294 261 struct v3d_csd_job *job = to_csd_job(sched_job); 295 262 struct v3d_dev *v3d = job->base.v3d; 296 - struct v3d_file_priv *file = job->base.file->driver_priv; 297 263 struct drm_device *dev = &v3d->drm; 298 264 struct dma_fence *fence; 299 265 int i, csd_cfg0_reg, csd_cfg_reg_count; ··· 311 279 312 280 trace_v3d_submit_csd(dev, to_v3d_fence(fence)->seqno); 313 281 314 - file->start_ns[V3D_CSD] = local_clock(); 315 - v3d->queue[V3D_CSD].start_ns = file->start_ns[V3D_CSD]; 316 - 282 + v3d_job_start_stats(&job->base, V3D_CSD); 317 283 v3d_switch_perfmon(v3d, &job->base); 318 284 319 285 csd_cfg0_reg = V3D_CSD_QUEUED_CFG0(v3d->ver); ··· 560 530 { 561 531 struct v3d_cpu_job *job = to_cpu_job(sched_job); 562 532 struct v3d_dev *v3d = job->base.v3d; 563 - struct v3d_file_priv *file = job->base.file->driver_priv; 564 - u64 runtime; 565 533 566 534 v3d->cpu_job = job; 567 535 ··· 568 540 return NULL; 569 541 } 570 542 571 - file->start_ns[V3D_CPU] = local_clock(); 572 - v3d->queue[V3D_CPU].start_ns = file->start_ns[V3D_CPU]; 573 - 543 + v3d_job_start_stats(&job->base, V3D_CPU); 574 544 trace_v3d_cpu_job_begin(&v3d->drm, job->job_type); 575 545 576 546 cpu_job_function[job->job_type](job); 577 547 578 548 trace_v3d_cpu_job_end(&v3d->drm, job->job_type); 579 - 580 - runtime = local_clock() - file->start_ns[V3D_CPU]; 581 - 582 - file->enabled_ns[V3D_CPU] += runtime; 583 - v3d->queue[V3D_CPU].enabled_ns += runtime; 584 - 585 - file->jobs_sent[V3D_CPU]++; 586 - v3d->queue[V3D_CPU].jobs_sent++; 587 - 588 - file->start_ns[V3D_CPU] = 0; 589 - v3d->queue[V3D_CPU].start_ns = 0; 549 + v3d_job_update_stats(&job->base, V3D_CPU); 590 550 591 551 return NULL; 592 552 } ··· 584 568 { 585 569 struct v3d_job *job = to_v3d_job(sched_job); 586 570 struct v3d_dev *v3d = job->v3d; 587 - struct v3d_file_priv *file = job->file->driver_priv; 588 - u64 runtime; 589 571 590 - file->start_ns[V3D_CACHE_CLEAN] = local_clock(); 591 - v3d->queue[V3D_CACHE_CLEAN].start_ns = file->start_ns[V3D_CACHE_CLEAN]; 572 + v3d_job_start_stats(job, V3D_CACHE_CLEAN); 592 573 593 574 v3d_clean_caches(v3d); 594 575 595 - runtime = local_clock() - file->start_ns[V3D_CACHE_CLEAN]; 596 - 597 - file->enabled_ns[V3D_CACHE_CLEAN] += runtime; 598 - v3d->queue[V3D_CACHE_CLEAN].enabled_ns += runtime; 599 - 600 - file->jobs_sent[V3D_CACHE_CLEAN]++; 601 - v3d->queue[V3D_CACHE_CLEAN].jobs_sent++; 602 - 603 - file->start_ns[V3D_CACHE_CLEAN] = 0; 604 - v3d->queue[V3D_CACHE_CLEAN].start_ns = 0; 576 + v3d_job_update_stats(job, V3D_CACHE_CLEAN); 605 577 606 578 return NULL; 607 579 }
+5 -8
drivers/gpu/drm/v3d/v3d_sysfs.c
··· 15 15 struct v3d_dev *v3d = to_v3d_dev(drm); 16 16 enum v3d_queue queue; 17 17 u64 timestamp = local_clock(); 18 - u64 active_runtime; 19 18 ssize_t len = 0; 20 19 21 20 len += sysfs_emit(buf, "queue\ttimestamp\tjobs\truntime\n"); 22 21 23 22 for (queue = 0; queue < V3D_MAX_QUEUES; queue++) { 24 - if (v3d->queue[queue].start_ns) 25 - active_runtime = timestamp - v3d->queue[queue].start_ns; 26 - else 27 - active_runtime = 0; 23 + struct v3d_stats *stats = &v3d->queue[queue].stats; 24 + u64 active_runtime, jobs_completed; 25 + 26 + v3d_get_stats(stats, timestamp, &active_runtime, &jobs_completed); 28 27 29 28 /* Each line will display the queue name, timestamp, the number 30 29 * of jobs sent to that queue and the runtime, as can be seem here: ··· 37 38 */ 38 39 len += sysfs_emit_at(buf, len, "%s\t%llu\t%llu\t%llu\n", 39 40 v3d_queue_to_string(queue), 40 - timestamp, 41 - v3d->queue[queue].jobs_sent, 42 - v3d->queue[queue].enabled_ns + active_runtime); 41 + timestamp, jobs_completed, active_runtime); 43 42 } 44 43 45 44 return len;
+1
drivers/gpu/drm/vc4/vc4_drv.h
··· 5 5 #ifndef _VC4_DRV_H_ 6 6 #define _VC4_DRV_H_ 7 7 8 + #include <linux/debugfs.h> 8 9 #include <linux/delay.h> 9 10 #include <linux/of.h> 10 11 #include <linux/refcount.h>
+25 -21
drivers/gpu/drm/vc4/vc4_hdmi.c
··· 412 412 enum drm_connector_status status) 413 413 { 414 414 struct drm_connector *connector = &vc4_hdmi->connector; 415 - struct edid *edid; 415 + const struct drm_edid *drm_edid; 416 416 int ret; 417 417 418 418 /* 419 - * NOTE: This function should really be called with 420 - * vc4_hdmi->mutex held, but doing so results in reentrancy 421 - * issues since cec_s_phys_addr_from_edid might call 422 - * .adap_enable, which leads to that funtion being called with 423 - * our mutex held. 419 + * NOTE: This function should really be called with vc4_hdmi->mutex 420 + * held, but doing so results in reentrancy issues since 421 + * cec_s_phys_addr() might call .adap_enable, which leads to that 422 + * funtion being called with our mutex held. 424 423 * 425 424 * A similar situation occurs with vc4_hdmi_reset_link() that 426 425 * will call into our KMS hooks if the scrambling was enabled. ··· 434 435 return; 435 436 } 436 437 437 - edid = drm_get_edid(connector, vc4_hdmi->ddc); 438 - if (!edid) 438 + drm_edid = drm_edid_read_ddc(connector, vc4_hdmi->ddc); 439 + 440 + drm_edid_connector_update(connector, drm_edid); 441 + cec_s_phys_addr(vc4_hdmi->cec_adap, 442 + connector->display_info.source_physical_address, false); 443 + 444 + if (!drm_edid) 439 445 return; 440 446 441 - cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); 442 - kfree(edid); 447 + drm_edid_free(drm_edid); 443 448 444 449 for (;;) { 445 450 ret = vc4_hdmi_reset_link(connector, ctx); ··· 495 492 { 496 493 struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); 497 494 struct vc4_dev *vc4 = to_vc4_dev(connector->dev); 495 + const struct drm_edid *drm_edid; 498 496 int ret = 0; 499 - struct edid *edid; 500 497 501 498 /* 502 - * NOTE: This function should really take vc4_hdmi->mutex, but 503 - * doing so results in reentrancy issues since 504 - * cec_s_phys_addr_from_edid might call .adap_enable, which 505 - * leads to that funtion being called with our mutex held. 499 + * NOTE: This function should really take vc4_hdmi->mutex, but doing so 500 + * results in reentrancy issues since cec_s_phys_addr() might call 501 + * .adap_enable, which leads to that funtion being called with our mutex 502 + * held. 506 503 * 507 504 * Concurrency isn't an issue at the moment since we don't share 508 505 * any state with any of the other frameworks so we can ignore 509 506 * the lock for now. 510 507 */ 511 508 512 - edid = drm_get_edid(connector, vc4_hdmi->ddc); 513 - cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); 514 - if (!edid) 509 + drm_edid = drm_edid_read_ddc(connector, vc4_hdmi->ddc); 510 + drm_edid_connector_update(connector, drm_edid); 511 + cec_s_phys_addr(vc4_hdmi->cec_adap, 512 + connector->display_info.source_physical_address, false); 513 + if (!drm_edid) 515 514 return 0; 516 515 517 - drm_connector_update_edid_property(connector, edid); 518 - ret = drm_add_edid_modes(connector, edid); 519 - kfree(edid); 516 + ret = drm_edid_connector_add_modes(connector); 517 + drm_edid_free(drm_edid); 520 518 521 519 if (!vc4->hvs->vc5_hdmi_enable_hdmi_20) { 522 520 struct drm_device *drm = connector->dev;
+2
drivers/gpu/drm/vmwgfx/vmwgfx_gem.c
··· 30 30 #include "drm/drm_prime.h" 31 31 #include "drm/drm_gem_ttm_helper.h" 32 32 33 + #include <linux/debugfs.h> 34 + 33 35 static void vmw_gem_object_free(struct drm_gem_object *gobj) 34 36 { 35 37 struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gobj);
+1
drivers/gpu/drm/xe/xe_debugfs.c
··· 5 5 6 6 #include "xe_debugfs.h" 7 7 8 + #include <linux/debugfs.h> 8 9 #include <linux/string_helpers.h> 9 10 10 11 #include <drm/drm_debugfs.h>
+2
drivers/gpu/drm/xe/xe_gt_debugfs.c
··· 5 5 6 6 #include "xe_gt_debugfs.h" 7 7 8 + #include <linux/debugfs.h> 9 + 8 10 #include <drm/drm_debugfs.h> 9 11 #include <drm/drm_managed.h> 10 12
+2 -2
drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
··· 196 196 return 0; 197 197 198 198 error_free_blocks: 199 - drm_buddy_free_list(mm, &vres->blocks); 199 + drm_buddy_free_list(mm, &vres->blocks, 0); 200 200 mutex_unlock(&mgr->lock); 201 201 error_fini: 202 202 ttm_resource_fini(man, &vres->base); ··· 214 214 struct drm_buddy *mm = &mgr->mm; 215 215 216 216 mutex_lock(&mgr->lock); 217 - drm_buddy_free_list(mm, &vres->blocks); 217 + drm_buddy_free_list(mm, &vres->blocks, 0); 218 218 mgr->visible_avail += vres->used_visible_size; 219 219 mutex_unlock(&mgr->lock); 220 220
+2
drivers/gpu/drm/xe/xe_uc_debugfs.c
··· 3 3 * Copyright © 2022 Intel Corporation 4 4 */ 5 5 6 + #include <linux/debugfs.h> 7 + 6 8 #include <drm/drm_debugfs.h> 7 9 8 10 #include "xe_gt.h"
+202 -27
drivers/gpu/drm/xlnx/zynqmp_disp.c
··· 18 18 #include <linux/dma/xilinx_dpdma.h> 19 19 #include <linux/dma-mapping.h> 20 20 #include <linux/dmaengine.h> 21 + #include <linux/media-bus-format.h> 21 22 #include <linux/module.h> 22 23 #include <linux/of.h> 23 24 #include <linux/platform_device.h> ··· 66 65 #define ZYNQMP_DISP_MAX_NUM_SUB_PLANES 3 67 66 68 67 /** 68 + * enum zynqmp_dpsub_layer_mode - Layer mode 69 + * @ZYNQMP_DPSUB_LAYER_NONLIVE: non-live (memory) mode 70 + * @ZYNQMP_DPSUB_LAYER_LIVE: live (stream) mode 71 + */ 72 + enum zynqmp_dpsub_layer_mode { 73 + ZYNQMP_DPSUB_LAYER_NONLIVE, 74 + ZYNQMP_DPSUB_LAYER_LIVE, 75 + }; 76 + 77 + /** 69 78 * struct zynqmp_disp_format - Display subsystem format information 70 79 * @drm_fmt: DRM format (4CC) 80 + * @bus_fmt: Media bus format 71 81 * @buf_fmt: AV buffer format 72 82 * @swap: Flag to swap R & B for RGB formats, and U & V for YUV formats 73 83 * @sf: Scaling factors for color components 74 84 */ 75 85 struct zynqmp_disp_format { 76 86 u32 drm_fmt; 87 + u32 bus_fmt; 77 88 u32 buf_fmt; 78 89 bool swap; 79 90 const u32 *sf; ··· 183 170 ZYNQMP_DISP_AV_BUF_5BIT_SF, 184 171 ZYNQMP_DISP_AV_BUF_6BIT_SF, 185 172 ZYNQMP_DISP_AV_BUF_5BIT_SF, 173 + }; 174 + 175 + static const u32 scaling_factors_666[] = { 176 + ZYNQMP_DISP_AV_BUF_6BIT_SF, 177 + ZYNQMP_DISP_AV_BUF_6BIT_SF, 178 + ZYNQMP_DISP_AV_BUF_6BIT_SF, 186 179 }; 187 180 188 181 static const u32 scaling_factors_888[] = { ··· 373 354 }, 374 355 }; 375 356 357 + /* List of live video layer formats */ 358 + static const struct zynqmp_disp_format avbuf_live_fmts[] = { 359 + { 360 + .drm_fmt = DRM_FORMAT_RGB565, 361 + .bus_fmt = MEDIA_BUS_FMT_RGB666_1X18, 362 + .buf_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_6 | 363 + ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB, 364 + .sf = scaling_factors_666, 365 + }, { 366 + .drm_fmt = DRM_FORMAT_RGB888, 367 + .bus_fmt = MEDIA_BUS_FMT_RGB888_1X24, 368 + .buf_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 | 369 + ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB, 370 + .sf = scaling_factors_888, 371 + }, { 372 + .drm_fmt = DRM_FORMAT_YUV422, 373 + .bus_fmt = MEDIA_BUS_FMT_UYVY8_1X16, 374 + .buf_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 | 375 + ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422, 376 + .sf = scaling_factors_888, 377 + }, { 378 + .drm_fmt = DRM_FORMAT_YUV444, 379 + .bus_fmt = MEDIA_BUS_FMT_VUY8_1X24, 380 + .buf_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 | 381 + ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444, 382 + .sf = scaling_factors_888, 383 + }, { 384 + .drm_fmt = DRM_FORMAT_P210, 385 + .bus_fmt = MEDIA_BUS_FMT_UYVY10_1X20, 386 + .buf_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10 | 387 + ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422, 388 + .sf = scaling_factors_101010, 389 + }, 390 + }; 391 + 376 392 static u32 zynqmp_disp_avbuf_read(struct zynqmp_disp *disp, int reg) 377 393 { 378 394 return readl(disp->avbuf.base + reg); ··· 436 382 const struct zynqmp_disp_format *fmt) 437 383 { 438 384 unsigned int i; 439 - u32 val; 385 + u32 val, reg; 440 386 441 - val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_FMT); 442 - val &= zynqmp_disp_layer_is_video(layer) 443 - ? ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK 444 - : ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK; 445 - val |= fmt->buf_fmt; 446 - zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_FMT, val); 387 + layer->disp_fmt = fmt; 388 + if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE) { 389 + reg = ZYNQMP_DISP_AV_BUF_FMT; 390 + val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_FMT); 391 + val &= zynqmp_disp_layer_is_video(layer) 392 + ? ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK 393 + : ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK; 394 + val |= fmt->buf_fmt; 395 + zynqmp_disp_avbuf_write(disp, reg, val); 396 + } else { 397 + reg = zynqmp_disp_layer_is_video(layer) 398 + ? ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG 399 + : ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG; 400 + val = fmt->buf_fmt; 401 + zynqmp_disp_avbuf_write(disp, reg, val); 402 + } 447 403 448 404 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++) { 449 - unsigned int reg = zynqmp_disp_layer_is_video(layer) 450 - ? ZYNQMP_DISP_AV_BUF_VID_COMP_SF(i) 451 - : ZYNQMP_DISP_AV_BUF_GFX_COMP_SF(i); 405 + reg = zynqmp_disp_layer_is_video(layer) 406 + ? ZYNQMP_DISP_AV_BUF_VID_COMP_SF(i) 407 + : ZYNQMP_DISP_AV_BUF_GFX_COMP_SF(i); 452 408 453 409 zynqmp_disp_avbuf_write(disp, reg, fmt->sf[i]); 454 410 } ··· 937 873 } 938 874 939 875 /** 876 + * zynqmp_disp_layer_find_live_format - Find format information for given 877 + * media bus format 878 + * @layer: The layer 879 + * @drm_fmt: Media bus format to search 880 + * 881 + * Search display subsystem format information corresponding to the given media 882 + * bus format @media_bus_format for the @layer, and return a pointer to the 883 + * format descriptor. 884 + * 885 + * Return: A pointer to the format descriptor if found, NULL otherwise 886 + */ 887 + static const struct zynqmp_disp_format * 888 + zynqmp_disp_layer_find_live_format(struct zynqmp_disp_layer *layer, 889 + u32 media_bus_format) 890 + { 891 + unsigned int i; 892 + 893 + for (i = 0; i < layer->info->num_formats; i++) 894 + if (layer->info->formats[i].bus_fmt == media_bus_format) 895 + return &layer->info->formats[i]; 896 + 897 + return NULL; 898 + } 899 + 900 + /** 940 901 * zynqmp_disp_layer_drm_formats - Return the DRM formats supported by the layer 941 902 * @layer: The layer 942 903 * @num_formats: Pointer to the returned number of formats 904 + * 905 + * NOTE: This function doesn't make sense for live video layers and will 906 + * always return an empty list in such cases. zynqmp_disp_live_layer_formats() 907 + * should be used to query a list of media bus formats supported by the live 908 + * video input layer. 943 909 * 944 910 * Return: A newly allocated u32 array that stores all the DRM formats 945 911 * supported by the layer. The number of formats in the array is returned ··· 981 887 unsigned int i; 982 888 u32 *formats; 983 889 890 + if (WARN_ON(!layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE)) { 891 + *num_formats = 0; 892 + return NULL; 893 + } 894 + 984 895 formats = kcalloc(layer->info->num_formats, sizeof(*formats), 985 896 GFP_KERNEL); 986 - if (!formats) 897 + if (!formats) { 898 + *num_formats = 0; 987 899 return NULL; 900 + } 988 901 989 902 for (i = 0; i < layer->info->num_formats; ++i) 990 903 formats[i] = layer->info->formats[i].drm_fmt; ··· 1001 900 } 1002 901 1003 902 /** 903 + * zynqmp_disp_live_layer_formats - Return the media bus formats supported by 904 + * the live video layer 905 + * @layer: The layer 906 + * @num_formats: Pointer to the returned number of formats 907 + * 908 + * NOTE: This function should be used only for live video input layers. 909 + * 910 + * Return: A newly allocated u32 array of media bus formats supported by the 911 + * layer. The number of formats in the array is returned through the 912 + * @num_formats argument. 913 + */ 914 + u32 *zynqmp_disp_live_layer_formats(struct zynqmp_disp_layer *layer, 915 + unsigned int *num_formats) 916 + { 917 + unsigned int i; 918 + u32 *formats; 919 + 920 + if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_LIVE)) { 921 + *num_formats = 0; 922 + return NULL; 923 + } 924 + 925 + formats = kcalloc(layer->info->num_formats, sizeof(*formats), 926 + GFP_KERNEL); 927 + if (!formats) { 928 + *num_formats = 0; 929 + return NULL; 930 + } 931 + 932 + for (i = 0; i < layer->info->num_formats; ++i) 933 + formats[i] = layer->info->formats[i].bus_fmt; 934 + 935 + *num_formats = layer->info->num_formats; 936 + return formats; 937 + } 938 + 939 + /** 1004 940 * zynqmp_disp_layer_enable - Enable a layer 1005 941 * @layer: The layer 1006 - * @mode: Operating mode of layer 1007 942 * 1008 943 * Enable the @layer in the audio/video buffer manager and the blender. DMA 1009 944 * channels are started separately by zynqmp_disp_layer_update(). 1010 945 */ 1011 - void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer, 1012 - enum zynqmp_dpsub_layer_mode mode) 946 + void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer) 1013 947 { 1014 - layer->mode = mode; 1015 948 zynqmp_disp_avbuf_enable_video(layer->disp, layer); 1016 949 zynqmp_disp_blend_layer_enable(layer->disp, layer); 1017 950 } ··· 1061 926 { 1062 927 unsigned int i; 1063 928 1064 - if (layer->disp->dpsub->dma_enabled) { 929 + if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE) { 1065 930 for (i = 0; i < layer->drm_fmt->num_planes; i++) 1066 931 dmaengine_terminate_sync(layer->dmas[i].chan); 1067 932 } ··· 1075 940 * @layer: The layer 1076 941 * @info: The format info 1077 942 * 943 + * NOTE: Use zynqmp_disp_layer_set_live_format() to set media bus format for 944 + * live video layers. 945 + * 1078 946 * Set the format for @layer to @info. The layer must be disabled. 1079 947 */ 1080 948 void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer, ··· 1085 947 { 1086 948 unsigned int i; 1087 949 950 + if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_NONLIVE)) 951 + return; 952 + 1088 953 layer->disp_fmt = zynqmp_disp_layer_find_format(layer, info->format); 954 + if (WARN_ON(!layer->disp_fmt)) 955 + return; 1089 956 layer->drm_fmt = info; 1090 957 1091 958 zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt); 1092 - 1093 - if (!layer->disp->dpsub->dma_enabled) 1094 - return; 1095 959 1096 960 /* 1097 961 * Set pconfig for each DMA channel to indicate they're part of a ··· 1115 975 } 1116 976 1117 977 /** 978 + * zynqmp_disp_layer_set_live_format - Set the live video layer format 979 + * @layer: The layer 980 + * @info: The format info 981 + * 982 + * NOTE: This function should not be used to set format for non-live video 983 + * layer. Use zynqmp_disp_layer_set_format() instead. 984 + * 985 + * Set the display format for the live @layer. The layer must be disabled. 986 + */ 987 + void zynqmp_disp_layer_set_live_format(struct zynqmp_disp_layer *layer, 988 + u32 media_bus_format) 989 + { 990 + if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_LIVE)) 991 + return; 992 + 993 + layer->disp_fmt = zynqmp_disp_layer_find_live_format(layer, 994 + media_bus_format); 995 + if (WARN_ON(!layer->disp_fmt)) 996 + return; 997 + 998 + zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt); 999 + 1000 + layer->drm_fmt = drm_format_info(layer->disp_fmt->drm_fmt); 1001 + } 1002 + 1003 + /** 1118 1004 * zynqmp_disp_layer_update - Update the layer framebuffer 1119 1005 * @layer: The layer 1120 1006 * @state: The plane state ··· 1156 990 const struct drm_format_info *info = layer->drm_fmt; 1157 991 unsigned int i; 1158 992 1159 - if (!layer->disp->dpsub->dma_enabled) 993 + if (layer->mode == ZYNQMP_DPSUB_LAYER_LIVE) 1160 994 return 0; 1161 995 1162 996 for (i = 0; i < info->num_planes; i++) { ··· 1206 1040 { 1207 1041 unsigned int i; 1208 1042 1209 - if (!layer->info || !disp->dpsub->dma_enabled) 1210 - return; 1211 - 1212 1043 for (i = 0; i < layer->info->num_channels; i++) { 1213 1044 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; 1214 1045 ··· 1246 1083 unsigned int i; 1247 1084 int ret; 1248 1085 1249 - if (!disp->dpsub->dma_enabled) 1250 - return 0; 1251 - 1252 1086 for (i = 0; i < layer->info->num_channels; i++) { 1253 1087 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; 1254 1088 char dma_channel_name[16]; ··· 1284 1124 .num_channels = 1, 1285 1125 }, 1286 1126 }; 1127 + static const struct zynqmp_disp_layer_info live_layer_info = { 1128 + .formats = avbuf_live_fmts, 1129 + .num_formats = ARRAY_SIZE(avbuf_live_fmts), 1130 + .num_channels = 0, 1131 + }; 1287 1132 1288 1133 unsigned int i; 1289 1134 int ret; ··· 1298 1133 1299 1134 layer->id = i; 1300 1135 layer->disp = disp; 1301 - layer->info = &layer_info[i]; 1136 + /* 1137 + * For now assume dpsub works in either live or non-live mode for both layers. 1138 + * Hybrid mode is not supported yet. 1139 + */ 1140 + if (disp->dpsub->dma_enabled) { 1141 + layer->mode = ZYNQMP_DPSUB_LAYER_NONLIVE; 1142 + layer->info = &layer_info[i]; 1143 + } else { 1144 + layer->mode = ZYNQMP_DPSUB_LAYER_LIVE; 1145 + layer->info = &live_layer_info; 1146 + } 1302 1147 1303 1148 ret = zynqmp_disp_layer_request_dma(disp, layer); 1304 1149 if (ret)
+5 -12
drivers/gpu/drm/xlnx/zynqmp_disp.h
··· 42 42 ZYNQMP_DPSUB_LAYER_GFX, 43 43 }; 44 44 45 - /** 46 - * enum zynqmp_dpsub_layer_mode - Layer mode 47 - * @ZYNQMP_DPSUB_LAYER_NONLIVE: non-live (memory) mode 48 - * @ZYNQMP_DPSUB_LAYER_LIVE: live (stream) mode 49 - */ 50 - enum zynqmp_dpsub_layer_mode { 51 - ZYNQMP_DPSUB_LAYER_NONLIVE, 52 - ZYNQMP_DPSUB_LAYER_LIVE, 53 - }; 54 - 55 45 void zynqmp_disp_enable(struct zynqmp_disp *disp); 56 46 void zynqmp_disp_disable(struct zynqmp_disp *disp); 57 47 int zynqmp_disp_setup_clock(struct zynqmp_disp *disp, ··· 52 62 53 63 u32 *zynqmp_disp_layer_drm_formats(struct zynqmp_disp_layer *layer, 54 64 unsigned int *num_formats); 55 - void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer, 56 - enum zynqmp_dpsub_layer_mode mode); 65 + u32 *zynqmp_disp_live_layer_formats(struct zynqmp_disp_layer *layer, 66 + unsigned int *num_formats); 67 + void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer); 57 68 void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer); 58 69 void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer, 59 70 const struct drm_format_info *info); 71 + void zynqmp_disp_layer_set_live_format(struct zynqmp_disp_layer *layer, 72 + u32 media_bus_format); 60 73 int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer, 61 74 struct drm_plane_state *state); 62 75
+4 -4
drivers/gpu/drm/xlnx/zynqmp_disp_regs.h
··· 165 165 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10 0x2 166 166 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_12 0x3 167 167 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_MASK GENMASK(2, 0) 168 - #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB 0x0 169 - #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444 0x1 170 - #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422 0x2 171 - #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YONLY 0x3 168 + #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB (0x0 << 4) 169 + #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444 (0x1 << 4) 170 + #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422 (0x2 << 4) 171 + #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YONLY (0x3 << 4) 172 172 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_MASK GENMASK(5, 4) 173 173 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_CB_FIRST BIT(8) 174 174 #define ZYNQMP_DISP_AV_BUF_PALETTE_MEMORY 0x400
+63 -18
drivers/gpu/drm/xlnx/zynqmp_dp.c
··· 22 22 #include <linux/delay.h> 23 23 #include <linux/device.h> 24 24 #include <linux/io.h> 25 + #include <linux/media-bus-format.h> 25 26 #include <linux/module.h> 26 27 #include <linux/platform_device.h> 27 28 #include <linux/pm_runtime.h> ··· 1277 1276 * DISP Configuration 1278 1277 */ 1279 1278 1279 + /** 1280 + * zynqmp_dp_disp_connected_live_layer - Return the first connected live layer 1281 + * @dp: DisplayPort IP core structure 1282 + * 1283 + * Return: The first connected live display layer or NULL if none of the live 1284 + * layers are connected. 1285 + */ 1286 + static struct zynqmp_disp_layer * 1287 + zynqmp_dp_disp_connected_live_layer(struct zynqmp_dp *dp) 1288 + { 1289 + if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) 1290 + return dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_VID]; 1291 + else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX)) 1292 + return dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_GFX]; 1293 + else 1294 + return NULL; 1295 + } 1296 + 1280 1297 static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp, 1281 1298 struct drm_bridge_state *old_bridge_state) 1282 1299 { 1283 - enum zynqmp_dpsub_layer_id layer_id; 1284 1300 struct zynqmp_disp_layer *layer; 1285 - const struct drm_format_info *info; 1301 + struct drm_bridge_state *bridge_state; 1302 + u32 bus_fmt; 1286 1303 1287 - if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) 1288 - layer_id = ZYNQMP_DPSUB_LAYER_VID; 1289 - else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX)) 1290 - layer_id = ZYNQMP_DPSUB_LAYER_GFX; 1291 - else 1304 + layer = zynqmp_dp_disp_connected_live_layer(dp); 1305 + if (!layer) 1292 1306 return; 1293 1307 1294 - layer = dp->dpsub->layers[layer_id]; 1308 + bridge_state = drm_atomic_get_new_bridge_state(old_bridge_state->base.state, 1309 + old_bridge_state->bridge); 1310 + if (WARN_ON(!bridge_state)) 1311 + return; 1295 1312 1296 - /* TODO: Make the format configurable. */ 1297 - info = drm_format_info(DRM_FORMAT_YUV422); 1298 - zynqmp_disp_layer_set_format(layer, info); 1299 - zynqmp_disp_layer_enable(layer, ZYNQMP_DPSUB_LAYER_LIVE); 1313 + bus_fmt = bridge_state->input_bus_cfg.format; 1314 + zynqmp_disp_layer_set_live_format(layer, bus_fmt); 1315 + zynqmp_disp_layer_enable(layer); 1300 1316 1301 - if (layer_id == ZYNQMP_DPSUB_LAYER_GFX) 1317 + if (layer == dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_GFX]) 1302 1318 zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, true, 255); 1303 1319 else 1304 1320 zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, false, 0); ··· 1328 1310 { 1329 1311 struct zynqmp_disp_layer *layer; 1330 1312 1331 - if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) 1332 - layer = dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_VID]; 1333 - else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX)) 1334 - layer = dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_GFX]; 1335 - else 1313 + layer = zynqmp_dp_disp_connected_live_layer(dp); 1314 + if (!layer) 1336 1315 return; 1337 1316 1338 1317 zynqmp_disp_disable(dp->dpsub->disp); ··· 1583 1568 return drm_edid_read_ddc(connector, &dp->aux.ddc); 1584 1569 } 1585 1570 1571 + static u32 *zynqmp_dp_bridge_default_bus_fmts(unsigned int *num_input_fmts) 1572 + { 1573 + u32 *formats = kzalloc(sizeof(*formats), GFP_KERNEL); 1574 + 1575 + if (formats) 1576 + *formats = MEDIA_BUS_FMT_FIXED; 1577 + *num_input_fmts = !!formats; 1578 + 1579 + return formats; 1580 + } 1581 + 1582 + static u32 * 1583 + zynqmp_dp_bridge_get_input_bus_fmts(struct drm_bridge *bridge, 1584 + struct drm_bridge_state *bridge_state, 1585 + struct drm_crtc_state *crtc_state, 1586 + struct drm_connector_state *conn_state, 1587 + u32 output_fmt, 1588 + unsigned int *num_input_fmts) 1589 + { 1590 + struct zynqmp_dp *dp = bridge_to_dp(bridge); 1591 + struct zynqmp_disp_layer *layer; 1592 + 1593 + layer = zynqmp_dp_disp_connected_live_layer(dp); 1594 + if (layer) 1595 + return zynqmp_disp_live_layer_formats(layer, num_input_fmts); 1596 + else 1597 + return zynqmp_dp_bridge_default_bus_fmts(num_input_fmts); 1598 + } 1599 + 1586 1600 static const struct drm_bridge_funcs zynqmp_dp_bridge_funcs = { 1587 1601 .attach = zynqmp_dp_bridge_attach, 1588 1602 .detach = zynqmp_dp_bridge_detach, ··· 1624 1580 .atomic_check = zynqmp_dp_bridge_atomic_check, 1625 1581 .detect = zynqmp_dp_bridge_detect, 1626 1582 .edid_read = zynqmp_dp_bridge_edid_read, 1583 + .atomic_get_input_bus_fmts = zynqmp_dp_bridge_get_input_bus_fmts, 1627 1584 }; 1628 1585 1629 1586 /* -----------------------------------------------------------------------------
+1 -1
drivers/gpu/drm/xlnx/zynqmp_kms.c
··· 122 122 123 123 /* Enable or re-enable the plane if the format has changed. */ 124 124 if (format_changed) 125 - zynqmp_disp_layer_enable(layer, ZYNQMP_DPSUB_LAYER_NONLIVE); 125 + zynqmp_disp_layer_enable(layer); 126 126 } 127 127 128 128 static const struct drm_plane_helper_funcs zynqmp_dpsub_plane_helper_funcs = {
+14 -2
include/drm/drm_buddy.h
··· 25 25 #define DRM_BUDDY_RANGE_ALLOCATION BIT(0) 26 26 #define DRM_BUDDY_TOPDOWN_ALLOCATION BIT(1) 27 27 #define DRM_BUDDY_CONTIGUOUS_ALLOCATION BIT(2) 28 + #define DRM_BUDDY_CLEAR_ALLOCATION BIT(3) 29 + #define DRM_BUDDY_CLEARED BIT(4) 28 30 29 31 struct drm_buddy_block { 30 32 #define DRM_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12) ··· 34 32 #define DRM_BUDDY_ALLOCATED (1 << 10) 35 33 #define DRM_BUDDY_FREE (2 << 10) 36 34 #define DRM_BUDDY_SPLIT (3 << 10) 35 + #define DRM_BUDDY_HEADER_CLEAR GENMASK_ULL(9, 9) 37 36 /* Free to be used, if needed in the future */ 38 - #define DRM_BUDDY_HEADER_UNUSED GENMASK_ULL(9, 6) 37 + #define DRM_BUDDY_HEADER_UNUSED GENMASK_ULL(8, 6) 39 38 #define DRM_BUDDY_HEADER_ORDER GENMASK_ULL(5, 0) 40 39 u64 header; 41 40 ··· 89 86 u64 chunk_size; 90 87 u64 size; 91 88 u64 avail; 89 + u64 clear_avail; 92 90 }; 93 91 94 92 static inline u64 ··· 114 110 drm_buddy_block_is_allocated(struct drm_buddy_block *block) 115 111 { 116 112 return drm_buddy_block_state(block) == DRM_BUDDY_ALLOCATED; 113 + } 114 + 115 + static inline bool 116 + drm_buddy_block_is_clear(struct drm_buddy_block *block) 117 + { 118 + return block->header & DRM_BUDDY_HEADER_CLEAR; 117 119 } 118 120 119 121 static inline bool ··· 160 150 161 151 void drm_buddy_free_block(struct drm_buddy *mm, struct drm_buddy_block *block); 162 152 163 - void drm_buddy_free_list(struct drm_buddy *mm, struct list_head *objects); 153 + void drm_buddy_free_list(struct drm_buddy *mm, 154 + struct list_head *objects, 155 + unsigned int flags); 164 156 165 157 void drm_buddy_print(struct drm_buddy *mm, struct drm_printer *p); 166 158 void drm_buddy_block_print(struct drm_buddy *mm,
+1 -1
include/drm/drm_mode_config.h
··· 953 953 struct drm_property *modifiers_property; 954 954 955 955 /** 956 - * @size_hints_propertty: Plane SIZE_HINTS property. 956 + * @size_hints_property: Plane SIZE_HINTS property. 957 957 */ 958 958 struct drm_property *size_hints_property; 959 959
+2 -2
include/drm/drm_print.h
··· 28 28 29 29 #include <linux/compiler.h> 30 30 #include <linux/printk.h> 31 - #include <linux/seq_file.h> 32 31 #include <linux/device.h> 33 - #include <linux/debugfs.h> 34 32 #include <linux/dynamic_debug.h> 35 33 36 34 #include <drm/drm.h> 37 35 36 + struct debugfs_regset32; 38 37 struct drm_device; 38 + struct seq_file; 39 39 40 40 /* Do *not* use outside of drm_print.[ch]! */ 41 41 extern unsigned long __drm_debug;