From f1db0120f15da7c6000b9f19aa9e15e6ba8afb2a Mon Sep 17 00:00:00 2001 From: Alessio Belle Date: Tue, 15 Sep 2026 11:03:45 +0300 Subject: [PATCH 01/92] drm/imagination: Treat FW connection ctl like other interface structures There is no particular reason for this structure to be allocated and freed on its own. Move the related logic to where there other firmware interface structures are allocated and freed. Signed-off-by: Alexandru Dadu Reviewed-by: Brajesh Gupta Link: https://patch.msgid.link/20260915-b4-do-not-map-if-structs-unnecessarily-v1-1-a0e2ccee154a@imgtec.com Signed-off-by: Alessio Belle --- drivers/gpu/drm/imagination/pvr_fw.c | 59 ++++++++++------------------ 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/imagination/pvr_fw.c b/drivers/gpu/drm/imagination/pvr_fw.c index c6c77b152342..6d18b50929ca 100644 --- a/drivers/gpu/drm/imagination/pvr_fw.c +++ b/drivers/gpu/drm/imagination/pvr_fw.c @@ -278,37 +278,6 @@ pvr_fw_find_mmu_segment(struct pvr_device *pvr_dev, u32 addr, u32 size, void *fw return -EINVAL; } -static int -pvr_fw_create_fwif_connection_ctl(struct pvr_device *pvr_dev) -{ - struct drm_device *drm_dev = from_pvr_device(pvr_dev); - struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev; - - fw_dev->fwif_connection_ctl = - pvr_fw_object_create_and_map_offset(pvr_dev, - fw_dev->fw_heap_info.config_offset + - PVR_ROGUE_FWIF_CONNECTION_CTL_OFFSET, - sizeof(*fw_dev->fwif_connection_ctl), - PVR_BO_FW_FLAGS_DEVICE_UNCACHED, - NULL, NULL, - &fw_dev->mem.fwif_connection_ctl_obj); - if (IS_ERR(fw_dev->fwif_connection_ctl)) { - drm_err(drm_dev, - "Unable to allocate FWIF connection control memory\n"); - return PTR_ERR(fw_dev->fwif_connection_ctl); - } - - return 0; -} - -static void -pvr_fw_fini_fwif_connection_ctl(struct pvr_device *pvr_dev) -{ - struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev; - - pvr_fw_object_unmap_and_destroy(fw_dev->mem.fwif_connection_ctl_obj); -} - static void fw_osinit_init(void *cpu_ptr, void *priv) { @@ -459,12 +428,28 @@ pvr_fw_create_structures(struct pvr_device *pvr_dev) struct pvr_fw_mem *fw_mem = &fw_dev->mem; int err; + fw_dev->fwif_connection_ctl = + pvr_fw_object_create_and_map_offset(pvr_dev, + fw_dev->fw_heap_info.config_offset + + PVR_ROGUE_FWIF_CONNECTION_CTL_OFFSET, + sizeof(*fw_dev->fwif_connection_ctl), + PVR_BO_FW_FLAGS_DEVICE_UNCACHED, + NULL, NULL, + &fw_mem->fwif_connection_ctl_obj); + + if (IS_ERR(fw_dev->fwif_connection_ctl)) { + drm_err(drm_dev, + "Unable to allocate FWIF connection control memory\n"); + return PTR_ERR(fw_dev->fwif_connection_ctl); + } + fw_dev->power_sync = pvr_fw_object_create_and_map(pvr_dev, sizeof(*fw_dev->power_sync), PVR_BO_FW_FLAGS_DEVICE_UNCACHED, NULL, NULL, &fw_mem->power_sync_obj); if (IS_ERR(fw_dev->power_sync)) { drm_err(drm_dev, "Unable to allocate FW power_sync structure\n"); - return PTR_ERR(fw_dev->power_sync); + err = PTR_ERR(fw_dev->power_sync); + goto err_release_connection_ctl; } fw_dev->hwrinfobuf = pvr_fw_object_create_and_map(pvr_dev, sizeof(*fw_dev->hwrinfobuf), @@ -594,6 +579,9 @@ pvr_fw_create_structures(struct pvr_device *pvr_dev) err_release_power_sync: pvr_fw_object_unmap_and_destroy(fw_mem->power_sync_obj); +err_release_connection_ctl: + pvr_fw_object_unmap_and_destroy(fw_mem->fwif_connection_ctl_obj); + return err; } @@ -615,6 +603,7 @@ pvr_fw_destroy_structures(struct pvr_device *pvr_dev) pvr_fw_object_unmap_and_destroy(fw_mem->power_sync_obj); pvr_fw_object_unmap_and_destroy(fw_mem->osdata_obj); pvr_fw_object_unmap_and_destroy(fw_mem->osinit_obj); + pvr_fw_object_unmap_and_destroy(fw_mem->fwif_connection_ctl_obj); } /** @@ -755,10 +744,6 @@ pvr_fw_process(struct pvr_device *pvr_dev) pvr_fw_object_vunmap(fw_mem->code_obj); fw_code_ptr = NULL; - err = pvr_fw_create_fwif_connection_ctl(pvr_dev); - if (err) - goto err_free_kdata; - return 0; err_free_kdata: @@ -842,8 +827,6 @@ pvr_fw_cleanup(struct pvr_device *pvr_dev) { struct pvr_fw_mem *fw_mem = &pvr_dev->fw_dev.mem; - pvr_fw_fini_fwif_connection_ctl(pvr_dev); - kfree(fw_mem->core_data); kfree(fw_mem->core_code); kfree(fw_mem->data); From c4c54ffd65555ac5316f8faf4d7dc8c815877937 Mon Sep 17 00:00:00 2001 From: Alessio Belle Date: Tue, 15 Sep 2026 11:03:46 +0300 Subject: [PATCH 02/92] drm/imagination: Don't map FW interface structures unnecessarily Connection control, OS init and HWR info buffer structures are currently not accessed by the driver during or after firmware initialisation. OS init is accessed during hard reset, but the common hard reset logic already takes care of temporarily mapping it again. Signed-off-by: Alexandru Dadu Reviewed-by: Brajesh Gupta Link: https://patch.msgid.link/20260915-b4-do-not-map-if-structs-unnecessarily-v1-2-a0e2ccee154a@imgtec.com Signed-off-by: Alessio Belle --- drivers/gpu/drm/imagination/pvr_fw.c | 97 +++++++++++++++++++--------- drivers/gpu/drm/imagination/pvr_fw.h | 18 ++---- 2 files changed, 72 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/imagination/pvr_fw.c b/drivers/gpu/drm/imagination/pvr_fw.c index 6d18b50929ca..c7988278df3f 100644 --- a/drivers/gpu/drm/imagination/pvr_fw.c +++ b/drivers/gpu/drm/imagination/pvr_fw.c @@ -428,19 +428,17 @@ pvr_fw_create_structures(struct pvr_device *pvr_dev) struct pvr_fw_mem *fw_mem = &fw_dev->mem; int err; - fw_dev->fwif_connection_ctl = - pvr_fw_object_create_and_map_offset(pvr_dev, - fw_dev->fw_heap_info.config_offset + - PVR_ROGUE_FWIF_CONNECTION_CTL_OFFSET, - sizeof(*fw_dev->fwif_connection_ctl), - PVR_BO_FW_FLAGS_DEVICE_UNCACHED, - NULL, NULL, - &fw_mem->fwif_connection_ctl_obj); - - if (IS_ERR(fw_dev->fwif_connection_ctl)) { + err = pvr_fw_object_create_offset(pvr_dev, + fw_dev->fw_heap_info.config_offset + + PVR_ROGUE_FWIF_CONNECTION_CTL_OFFSET, + sizeof(struct rogue_fwif_connection_ctl), + PVR_BO_FW_FLAGS_DEVICE_UNCACHED, + NULL, NULL, + &fw_mem->fwif_connection_ctl_obj); + if (err) { drm_err(drm_dev, "Unable to allocate FWIF connection control memory\n"); - return PTR_ERR(fw_dev->fwif_connection_ctl); + return err; } fw_dev->power_sync = pvr_fw_object_create_and_map(pvr_dev, sizeof(*fw_dev->power_sync), @@ -452,13 +450,12 @@ pvr_fw_create_structures(struct pvr_device *pvr_dev) goto err_release_connection_ctl; } - fw_dev->hwrinfobuf = pvr_fw_object_create_and_map(pvr_dev, sizeof(*fw_dev->hwrinfobuf), - PVR_BO_FW_FLAGS_DEVICE_UNCACHED, - NULL, NULL, &fw_mem->hwrinfobuf_obj); - if (IS_ERR(fw_dev->hwrinfobuf)) { + err = pvr_fw_object_create(pvr_dev, sizeof(struct rogue_fwif_hwrinfobuf), + PVR_BO_FW_FLAGS_DEVICE_UNCACHED, + NULL, NULL, &fw_mem->hwrinfobuf_obj); + if (err) { drm_err(drm_dev, "Unable to allocate FW hwrinfobuf structure\n"); - err = PTR_ERR(fw_dev->hwrinfobuf); goto err_release_power_sync; } @@ -521,16 +518,14 @@ pvr_fw_create_structures(struct pvr_device *pvr_dev) goto err_fw_trace_fini; } - fw_dev->fwif_osinit = - pvr_fw_object_create_and_map_offset(pvr_dev, - fw_dev->fw_heap_info.config_offset + - PVR_ROGUE_FWIF_OSINIT_OFFSET, - sizeof(*fw_dev->fwif_osinit), - PVR_BO_FW_FLAGS_DEVICE_UNCACHED, - fw_osinit_init, pvr_dev, &fw_mem->osinit_obj); - if (IS_ERR(fw_dev->fwif_osinit)) { + err = pvr_fw_object_create_offset(pvr_dev, + fw_dev->fw_heap_info.config_offset + + PVR_ROGUE_FWIF_OSINIT_OFFSET, + sizeof(struct rogue_fwif_osinit), + PVR_BO_FW_FLAGS_DEVICE_UNCACHED, + fw_osinit_init, pvr_dev, &fw_mem->osinit_obj); + if (err) { drm_err(drm_dev, "Unable to allocate FW OSINIT structure\n"); - err = PTR_ERR(fw_dev->fwif_osinit); goto err_release_osdata; } @@ -550,7 +545,7 @@ pvr_fw_create_structures(struct pvr_device *pvr_dev) return 0; err_release_osinit: - pvr_fw_object_unmap_and_destroy(fw_mem->osinit_obj); + pvr_fw_object_destroy(fw_mem->osinit_obj); err_release_osdata: pvr_fw_object_unmap_and_destroy(fw_mem->osdata_obj); @@ -574,13 +569,13 @@ pvr_fw_create_structures(struct pvr_device *pvr_dev) pvr_fw_object_destroy(fw_mem->mmucache_sync_obj); err_release_hwrinfobuf: - pvr_fw_object_unmap_and_destroy(fw_mem->hwrinfobuf_obj); + pvr_fw_object_destroy(fw_mem->hwrinfobuf_obj); err_release_power_sync: pvr_fw_object_unmap_and_destroy(fw_mem->power_sync_obj); err_release_connection_ctl: - pvr_fw_object_unmap_and_destroy(fw_mem->fwif_connection_ctl_obj); + pvr_fw_object_destroy(fw_mem->fwif_connection_ctl_obj); return err; } @@ -599,11 +594,11 @@ pvr_fw_destroy_structures(struct pvr_device *pvr_dev) pvr_fw_object_unmap_and_destroy(fw_mem->sysinit_obj); pvr_fw_object_destroy(fw_mem->mmucache_sync_obj); - pvr_fw_object_unmap_and_destroy(fw_mem->hwrinfobuf_obj); + pvr_fw_object_destroy(fw_mem->hwrinfobuf_obj); pvr_fw_object_unmap_and_destroy(fw_mem->power_sync_obj); pvr_fw_object_unmap_and_destroy(fw_mem->osdata_obj); - pvr_fw_object_unmap_and_destroy(fw_mem->osinit_obj); - pvr_fw_object_unmap_and_destroy(fw_mem->fwif_connection_ctl_obj); + pvr_fw_object_destroy(fw_mem->osinit_obj); + pvr_fw_object_destroy(fw_mem->fwif_connection_ctl_obj); } /** @@ -1385,6 +1380,46 @@ pvr_fw_object_create_and_map_offset(struct pvr_device *pvr_dev, fw_obj_out); } +/** + * pvr_fw_object_create_offset() - Create a FW object and map to firmware + * at the provided offset. + * @pvr_dev: PowerVR device pointer. + * @fw_addr: Base address of desired FW mapping, offset from start of FW heap. + * If a specific FW address is not required, pass %U32_MAX. + * @size: Size of object, in bytes. + * @flags: Options which affect both this operation and future mapping + * operations performed on the returned object. Must be a combination of + * DRM_PVR_BO_* and/or PVR_BO_* flags. + * @init: Initialisation callback. + * @init_priv: Private pointer to pass to initialisation callback. + * @fw_obj_out: Pointer to location to store created object pointer. + * + * %DRM_PVR_BO_DEVICE_PM_FW_PROTECT is implied for all FW objects. Consequently, + * this function will fail if @flags has %DRM_PVR_BO_CPU_ALLOW_USERSPACE_ACCESS + * set. + * + * Returns: + * * 0 on success, or + * * Any error returned by pvr_fw_object_create_and_map(). + */ +int +pvr_fw_object_create_offset(struct pvr_device *pvr_dev, u32 fw_addr, + size_t size, u64 flags, + void (*init)(void *cpu_ptr, void *priv), + void *init_priv, struct pvr_fw_object **fw_obj_out) +{ + void *cpu_ptr; + + cpu_ptr = pvr_fw_object_create_and_map_offset(pvr_dev, fw_addr, size, flags, + init, init_priv, fw_obj_out); + if (IS_ERR(cpu_ptr)) + return PTR_ERR(cpu_ptr); + + pvr_fw_object_vunmap(*fw_obj_out); + + return 0; +} + /** * pvr_fw_object_destroy() - Destroy a pvr_fw_object * @fw_obj: Pointer to object to destroy. diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h index 4b25291135b6..626a1fdb6a4d 100644 --- a/drivers/gpu/drm/imagination/pvr_fw.h +++ b/drivers/gpu/drm/imagination/pvr_fw.h @@ -349,30 +349,18 @@ struct pvr_fw_device { /** @fw_mm_base: Base address of address space managed by @fw_mm. */ u64 fw_mm_base; - /** - * @fwif_connection_ctl: Pointer to CPU mapping of FWIF connection - * control structure. - */ - struct rogue_fwif_connection_ctl *fwif_connection_ctl; - /** @fwif_sysinit: Pointer to CPU mapping of FW SYSINIT structure. */ struct rogue_fwif_sysinit *fwif_sysinit; /** @fwif_sysdata: Pointer to CPU mapping of FW SYSDATA structure. */ struct rogue_fwif_sysdata *fwif_sysdata; - /** @fwif_osinit: Pointer to CPU mapping of FW OSINIT structure. */ - struct rogue_fwif_osinit *fwif_osinit; - /** @fwif_osdata: Pointer to CPU mapping of FW OSDATA structure. */ struct rogue_fwif_osdata *fwif_osdata; /** @power_sync: Pointer to CPU mapping of power sync state. */ u32 *power_sync; - /** @hwrinfobuf: Pointer to CPU mapping of FW HWR info buffer. */ - struct rogue_fwif_hwrinfobuf *hwrinfobuf; - /** @fw_trace: Device firmware trace buffer state. */ struct pvr_fw_trace fw_trace; @@ -430,6 +418,12 @@ void *pvr_fw_object_create_and_map(struct pvr_device *pvr_dev, size_t size, u64 void (*init)(void *cpu_ptr, void *priv), void *init_priv, struct pvr_fw_object **pvr_obj_out); +int +pvr_fw_object_create_offset(struct pvr_device *pvr_dev, u32 fw_addr, + size_t size, u64 flags, + void (*init)(void *cpu_ptr, void *priv), + void *init_priv, struct pvr_fw_object **pvr_obj_out); + void * pvr_fw_object_create_and_map_offset(struct pvr_device *pvr_dev, u32 dev_offset, size_t size, u64 flags, void (*init)(void *cpu_ptr, void *priv), From 4eeeac9d7c3600a6cae75b2a7bc9c5b67530923c Mon Sep 17 00:00:00 2001 From: Casey Connolly Date: Tue, 8 Sep 2026 14:45:02 +0200 Subject: [PATCH 03/92] drm/panel: ebbg-ft8719: Set prepare_prev_first This corrects the host initialisation sequence so that we can send DSI/DCS commands in prepare(). Cc: stable@vger.kernel.org Fixes: b00de0e237da ("drm/panel: introduce ebbg,ft8719 panel") Signed-off-by: Casey Connolly Tested-by: Marco Mattiolo Reviewed-by: Neil Armstrong Signed-off-by: David Heidelberg Reviewed-by: Linus Walleij Signed-off-by: Neil Armstrong Link: https://patch.msgid.link/20260908-ebbg-ft8719-fixups-v2-1-5454ae1f5581@ixit.cz --- drivers/gpu/drm/panel/panel-ebbg-ft8719.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c index fb9f9f42be4f..1ab09c50a630 100644 --- a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c +++ b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c @@ -198,6 +198,8 @@ static int ebbg_ft8719_probe(struct mipi_dsi_device *dsi) dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_CLOCK_NON_CONTINUOUS; + ctx->panel.prepare_prev_first = true; + ret = drm_panel_of_backlight(&ctx->panel); if (ret) return dev_err_probe(dev, ret, "Failed to get backlight\n"); From b1885bd1c985999b8a5393f2e23eea8dde3109a9 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Tue, 8 Sep 2026 14:45:03 +0200 Subject: [PATCH 04/92] drm/panel: ebbg-ft8719: Fix the MODULE_LICENSE() string Replace the bogus "GPL v2" with "GPL" as MODULE_LICNSE() string. The value does not declare the module's exact license, but only lets the module loader test whether the module is Free Software or not. See commit bf7fbeeae6db ("module: Cure the MODULE_LICENSE "GPL" vs. "GPL v2" bogosity") in the details of the issue. The fix is to use "GPL" for all modules under any variant of the GPL. Reviewed-by: Neil Armstrong Signed-off-by: David Heidelberg Reviewed-by: Linus Walleij Signed-off-by: Neil Armstrong Link: https://patch.msgid.link/20260908-ebbg-ft8719-fixups-v2-2-5454ae1f5581@ixit.cz --- drivers/gpu/drm/panel/panel-ebbg-ft8719.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c index 1ab09c50a630..14982263a94f 100644 --- a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c +++ b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c @@ -246,4 +246,4 @@ module_mipi_dsi_driver(ebbg_ft8719_driver); MODULE_AUTHOR("Joel Selvaraj "); MODULE_DESCRIPTION("DRM driver for EBBG FT8719 video dsi panel"); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); From 012dc8a8e5b6bca57ef7bb62d6015faff7690e0a Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Tue, 8 Sep 2026 14:45:04 +0200 Subject: [PATCH 05/92] drm/panel: ebbg-ft8719: Split initialization into enable/disable fn Move the MIPI commands into enable/disable callbacks since they are called between prepare/unprepare callbacks. Signed-off-by: David Heidelberg Reviewed-by: Neil Armstrong Reviewed-by: Linus Walleij Signed-off-by: Neil Armstrong Link: https://patch.msgid.link/20260908-ebbg-ft8719-fixups-v2-3-5454ae1f5581@ixit.cz --- drivers/gpu/drm/panel/panel-ebbg-ft8719.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c index 14982263a94f..1652de70900f 100644 --- a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c +++ b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c @@ -54,8 +54,9 @@ static void ebbg_ft8719_reset(struct ebbg_ft8719 *ctx) usleep_range(15000, 16000); } -static int ebbg_ft8719_on(struct ebbg_ft8719 *ctx) +static int ebbg_ft8719_enable(struct drm_panel *panel) { + struct ebbg_ft8719 *ctx = to_ebbg_ft8719(panel); struct mipi_dsi_device *dsi = ctx->dsi; struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; @@ -72,19 +73,20 @@ static int ebbg_ft8719_on(struct ebbg_ft8719 *ctx) return dsi_ctx.accum_err; } -static int ebbg_ft8719_off(struct ebbg_ft8719 *ctx) +static int ebbg_ft8719_disable(struct drm_panel *panel) { + struct ebbg_ft8719 *ctx = to_ebbg_ft8719(panel); struct mipi_dsi_device *dsi = ctx->dsi; struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; - dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); mipi_dsi_usleep_range(&dsi_ctx, 10000, 11000); mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); mipi_dsi_msleep(&dsi_ctx, 90); - return dsi_ctx.accum_err; + return 0; } static int ebbg_ft8719_prepare(struct drm_panel *panel) @@ -98,12 +100,6 @@ static int ebbg_ft8719_prepare(struct drm_panel *panel) ebbg_ft8719_reset(ctx); - ret = ebbg_ft8719_on(ctx); - if (ret < 0) { - gpiod_set_value_cansleep(ctx->reset_gpio, 1); - return ret; - } - return 0; } @@ -111,7 +107,6 @@ static int ebbg_ft8719_unprepare(struct drm_panel *panel) { struct ebbg_ft8719 *ctx = to_ebbg_ft8719(panel); - ebbg_ft8719_off(ctx); gpiod_set_value_cansleep(ctx->reset_gpio, 1); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); @@ -153,6 +148,8 @@ static int ebbg_ft8719_get_modes(struct drm_panel *panel, static const struct drm_panel_funcs ebbg_ft8719_panel_funcs = { .prepare = ebbg_ft8719_prepare, + .enable = ebbg_ft8719_enable, + .disable = ebbg_ft8719_disable, .unprepare = ebbg_ft8719_unprepare, .get_modes = ebbg_ft8719_get_modes, }; From e40d71fa231fc510c87c92cfe40f60f18eaafa61 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 10 Sep 2026 20:18:42 +0200 Subject: [PATCH 06/92] dt-bindings: display: panel: Document 10" Raspberry Pi Touch Display 2 Document the 10" Raspberry Pi Touch Display 2 MIPI-DSI TFT LCD panel. The panel is based on the Ilitek IL79600A controller. Acked-by: Conor Dooley Signed-off-by: Marek Vasut Signed-off-by: Neil Armstrong Link: https://patch.msgid.link/20260910181918.31551-1-marek.vasut+renesas@mailbox.org --- .../bindings/display/panel/ilitek,il79900a.yaml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,il79900a.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,il79900a.yaml index 02f7fb1f16dc..f475302b87b0 100644 --- a/Documentation/devicetree/bindings/display/panel/ilitek,il79900a.yaml +++ b/Documentation/devicetree/bindings/display/panel/ilitek,il79900a.yaml @@ -14,10 +14,15 @@ allOf: properties: compatible: - items: - - enum: - - tianma,tl121bvms07-00 - - const: ilitek,il79900a + oneOf: + - items: + - enum: + - raspberrypi,dsi-10inch + - const: ilitek,il79600a + - items: + - enum: + - tianma,tl121bvms07-00 + - const: ilitek,il79900a reg: maxItems: 1 From 803d7e465616d2822deb10ec3bf8952e49ffd6ba Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 10 Sep 2026 20:18:43 +0200 Subject: [PATCH 07/92] drm/panel: ilitek-ili9882t: Make enable GPIO optional The enable GPIO may not be accessible on the panel, make it optional. This is the case on 10" Raspberry Pi Touch Display 2. Signed-off-by: Marek Vasut Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patch.msgid.link/20260910181918.31551-2-marek.vasut+renesas@mailbox.org --- drivers/gpu/drm/panel/panel-ilitek-ili9882t.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c index d4b383138488..69f6427bb4ff 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c @@ -787,7 +787,7 @@ static int ili9882t_add(struct ili9882t *ili) if (IS_ERR(ili->pp1800)) return PTR_ERR(ili->pp1800); - ili->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); + ili->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(ili->enable_gpio)) { dev_err(dev, "cannot get enable-gpios %ld\n", PTR_ERR(ili->enable_gpio)); From 20f01db1545252cf81a39202920d0b032fb4501a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 10 Sep 2026 20:18:44 +0200 Subject: [PATCH 08/92] drm/panel: ilitek-ili9882t: Set prepare_prev_first Sending DSI commands from the prepare() callback requires DSI link to be up at that point. For DSI hosts is guaranteed only if the panel driver sets the .prepare_prev_first flag. Set it to let these panels work with the DSI hosts which don't power on the link in their .mode_set callback. Reviewed-by: Neil Armstrong Signed-off-by: Marek Vasut Signed-off-by: Neil Armstrong Link: https://patch.msgid.link/20260910181918.31551-3-marek.vasut+renesas@mailbox.org --- drivers/gpu/drm/panel/panel-ilitek-ili9882t.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c index 69f6427bb4ff..862b1c81a609 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c @@ -808,6 +808,7 @@ static int ili9882t_add(struct ili9882t *ili) ili->base.funcs = &ili9882t_funcs; ili->base.dev = &ili->dsi->dev; + ili->base.prepare_prev_first = true; return devm_drm_panel_add(dev, &ili->base); } From 481b38467000602761215ba4a196e89f58248055 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 10 Sep 2026 20:18:45 +0200 Subject: [PATCH 09/92] drm/panel: ilitek-ili9882t: Add support for Ilitek IL79600A-based panels The Ilitek IL79600A display controller is similar to the ILI9882T and can be supported within the existing `panel-ilitek-ili9882t.c` driver. This patch extends the ILI9882T driver to handle IL79600A-based panels, such as the 10" Raspberry Pi Touch Display 2. The IL79600A uses a similar command sequence and initialization flow, with minor differences in power supply configuration and timing. Signed-off-by: Marek Vasut Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patch.msgid.link/20260910181918.31551-4-marek.vasut+renesas@mailbox.org --- drivers/gpu/drm/panel/panel-ilitek-ili9882t.c | 231 ++++++++++++++++++ 1 file changed, 231 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c index 862b1c81a609..bea5ca70c775 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c @@ -133,6 +133,207 @@ static const struct drm_dsc_config tianma_il79900a_dsc = { .flatness_min_qp = 3, }; +static int rpi_10inch_init(struct ili9882t *ili) +{ + struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi }; + + mipi_dsi_usleep_range(&ctx, 5000, 5100); + + il79900a_switch_page(&ctx, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x42); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x80); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x71); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x28); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x29); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3A, 0x13); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3B, 0x15); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3C, 0x17); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3D, 0x09); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3E, 0x0D); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3F, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x41, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x42, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x43, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x44, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x45, 0x02); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x49, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4A, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4B, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4C, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4D, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4E, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4F, 0x28); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x50, 0x29); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x51, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x52, 0x12); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x14); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x54, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x0C); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x57, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5A, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5B, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5C, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5D, 0x02); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2C, 0xB0); + + il79900a_switch_page(&ctx, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0xD2); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x1F); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5E, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x84, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x3A); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2A, 0x3B); + + il79900a_switch_page(&ctx, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x3C); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0xFA); + + il79900a_switch_page(&ctx, 0x12); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x2C); + + il79900a_switch_page(&ctx, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x8F); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6D, 0xBB); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5A, 0x7C); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x7C); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x54, 0x92); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x92); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0xD2); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x46, 0x70); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x47); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7A, 0x89); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xA4, 0x0B); + + il79900a_switch_page(&ctx, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xC0, 0x80); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xC1, 0x7); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xCA, 0x58); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xCB, 0x2); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xCE, 0x58); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xCF, 0x2); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x0); + + il79900a_switch_page(&ctx, 0x0b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x76, 0x55); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x78, 0x68); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0x0D); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x60); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7A, 0x10); + + il79900a_switch_page(&ctx, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, + 0xE0, 0x00, 0x1E, 0x3F, + 0x68, 0x7D, 0x72, 0x86, + 0x89, 0x92, 0x8E, 0xA5, + 0xA8, 0xAA, 0xBD, 0xB8, + 0xBE, 0xC5, 0xD6, 0xCD, + 0xC3, 0xDA, 0xEB, 0xED); + mipi_dsi_dcs_write_seq_multi(&ctx, + 0xE1, 0x00, 0x1E, 0x3F, + 0x68, 0x7D, 0x72, 0x86, + 0x89, 0x92, 0x8E, 0xA5, + 0xA8, 0xAA, 0xBD, 0xB8, + 0xBE, 0xC5, 0xD6, 0xCD, + 0xC3, 0xDA, 0xEB, 0xED); + + il79900a_switch_page(&ctx, 0x14); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x85, 0xCC); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x91); + + il79900a_switch_page(&ctx, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x3); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x34); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x1); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x4); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0xBB); + + il79900a_switch_page(&ctx, 0x0b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x94, 0x88); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x95, 0x23); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x96, 0x0B); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x97, 0x0B); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x98, 0xC6); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x99, 0xC6); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xA6, 0x47); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xA7, 0x77); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xA8, 0x5); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xA9, 0x5); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xAA, 0xBA); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xAB, 0xBA); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xBD, 0x92); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xBE, 0xE0); + + il79900a_switch_page(&ctx, 0x0e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0, 0x80); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x3); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x4); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x1); + + il79900a_switch_page(&ctx, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x82, 0x11); + il79900a_switch_page(&ctx, 0x12); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x82, 0x2C); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x85, 0x2C); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x2C); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x88, 0xEC); + il79900a_switch_page(&ctx, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4, 0x1); + il79900a_switch_page(&ctx, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0C, 0x80); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3C, 0x80); + + il79900a_switch_page(&ctx, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0E, 0x0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0E, 0x3F); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x0); + + il79900a_switch_page(&ctx, 0x00); + mipi_dsi_dcs_set_tear_on_multi(&ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + mipi_dsi_dcs_exit_sleep_mode_multi(&ctx); + + mipi_dsi_msleep(&ctx, 120); + + mipi_dsi_dcs_set_display_on_multi(&ctx); + + mipi_dsi_msleep(&ctx, 20); + + return ctx.accum_err; +}; + static int starry_ili9882t_init(struct ili9882t *ili) { struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi }; @@ -670,6 +871,19 @@ static int ili9882t_enable(struct drm_panel *panel) return 0; } +static const struct drm_display_mode rpi_10inch_default_mode = { + .clock = 166666, + .hdisplay = 1200, + .hsync_start = 1200 + 28, + .hsync_end = 1200 + 28 + 10, + .htotal = 1200 + 28 + 10 + 30, + .vdisplay = 1920, + .vsync_start = 1920 + 238, + .vsync_end = 1920 + 238 + 4, + .vtotal = 1920 + 238 + 4 + 28, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + static const struct drm_display_mode starry_ili9882t_default_mode = { .clock = 165280, .hdisplay = 1200, @@ -696,6 +910,20 @@ static const struct drm_display_mode tianma_il79900a_default_mode = { .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, }; +static const struct panel_desc rpi_10inch_desc = { + .modes = &rpi_10inch_default_mode, + .bpc = 8, + .size = { + .width_mm = 135, + .height_mm = 216, + }, + .lanes = 4, + .format = MIPI_DSI_FMT_RGB888, + .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_LPM, + .init = rpi_10inch_init, +}; + static const struct panel_desc starry_ili9882t_desc = { .modes = &starry_ili9882t_default_mode, .bpc = 8, @@ -847,6 +1075,9 @@ static int ili9882t_probe(struct mipi_dsi_device *dsi) } static const struct of_device_id ili9882t_of_match[] = { + { .compatible = "raspberrypi,dsi-10inch", + .data = &rpi_10inch_desc + }, { .compatible = "starry,ili9882t", .data = &starry_ili9882t_desc }, From 001a7baa873891b7558f6b91e36136bb8fc66fc3 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Thu, 17 Sep 2026 13:05:14 +0200 Subject: [PATCH 10/92] dt-bindings: display: simple: Add Truly TFT320240-229-E panel Document the compatible string for the Truly Semiconductors Limited TFT320240-229-E 3.5" QVGA (320 x 240) parallel RGB TFT LCD panel, which is driven by the panel-simple driver. Signed-off-by: Alexander Sverdlin Acked-by: Krzysztof Kozlowski Signed-off-by: Neil Armstrong Link: https://patch.msgid.link/20260917110517.1053556-2-alexander.sverdlin@siemens.com --- .../devicetree/bindings/display/panel/panel-simple.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml index 3d1cc11ba3aa..eb49832b26c4 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml @@ -338,6 +338,8 @@ properties: - tpk,f07a-0102 # TPK U.S.A. LLC Fusion 10.1" 1024 x 600 (WSVGA) LCD panel with capacitive touch - tpk,f10a-0102 + # Truly Semiconductors Limited 3.5" QVGA (320 x 240) TFT LCD panel + - truly,tft320240-229-e # United Radiant Technology UMSH-8596MD-xT 7.0" WVGA TFT LCD panel # Supported are LVDS versions (-11T, -19T) and parallel ones # (-T, -1T, -7T, -20T). From 45b46cd3c477a2e5ed547450a15dc80f0593f418 Mon Sep 17 00:00:00 2001 From: Frank Bodammer Date: Thu, 17 Sep 2026 13:05:15 +0200 Subject: [PATCH 11/92] drm/panel: simple: Add support for Truly TFT320240-229-E panel Add display mode and panel descriptor for the Truly TFT320240-229-E LCD panel. Register the panel in the of_device_id table with the compatible string "truly,tft320240-229-e". Signed-off-by: Frank Bodammer Signed-off-by: Alexander Sverdlin Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patch.msgid.link/20260917110517.1053556-3-alexander.sverdlin@siemens.com --- drivers/gpu/drm/panel/panel-simple.c | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index c95964ba25a9..bd7f6eaeb0de 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -5114,6 +5114,32 @@ static const struct panel_desc tpk_f10a_0102 = { }, }; +static const struct drm_display_mode truly_tft320240_229_e_mode = { + .clock = 6410, + .hdisplay = 320, + .hsync_start = 320 + 8, + .hsync_end = 320 + 8 + 39, + .htotal = 320 + 8 + 39 + 4, + .vdisplay = 240, + .vsync_start = 240 + 8, + .vsync_end = 240 + 8 + 8, + .vtotal = 240 + 8 + 8 + 4, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, +}; + +static const struct panel_desc truly_tft320240_229_e = { + .modes = &truly_tft320240_229_e_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 70, + .height = 53, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .bus_flags = DRM_BUS_FLAG_DE_HIGH, + .connector_type = DRM_MODE_CONNECTOR_DPI, +}; + static const struct display_timing urt_umsh_8596md_timing = { .pixelclock = { 33260000, 33260000, 33260000 }, .hactive = { 800, 800, 800 }, @@ -6167,6 +6193,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "tpk,f10a-0102", .data = &tpk_f10a_0102, + }, { + .compatible = "truly,tft320240-229-e", + .data = &truly_tft320240_229_e, }, { .compatible = "urt,umsh-8596md-t", .data = &urt_umsh_8596md_parallel, From fbbf93ab8bcb29ea741b99e7cd9bc2120c2a52b1 Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Thu, 3 Sep 2026 09:04:17 +0530 Subject: [PATCH 12/92] dt-bindings: display: simple: Add boe,dv215fhm-r01 compatible Add BOE DV215FHM-R01 21.5" FHD (1920x1080) dual-channel LVDS panel compatible string to the panel-simple-lvds-dual-ports binding. Acked-by: Krzysztof Kozlowski Acked-by: Liu Ying Signed-off-by: Vishnu Saini Signed-off-by: Neil Armstrong Link: https://patch.msgid.link/20260903-b4-lvds-panel-doc-v4-1-861738a0d5de@oss.qualcomm.com --- .../bindings/display/panel/panel-simple-lvds-dual-ports.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml index 8a2f6feafd37..68beb476fb48 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml @@ -44,6 +44,8 @@ properties: - auo,t215hvn01 # BOE AV123Z7M-N17 12.3" (1920x720) LVDS TFT LCD panel - boe,av123z7m-n17 + # BOE DV215FHM-R01 21.5" FHD (1920x1080) dual-channel LVDS panel + - boe,dv215fhm-r01 # InnoLux 15.6" FHD (1920x1080) TFT LCD panel - innolux,g156hce-l01 # Kaohsiung Opto-Electronics Inc. 10.1" WUXGA (1920 x 1200) LVDS TFT LCD panel From 92be213ad653a6b785bf465f0d259b4eba6d9207 Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Thu, 3 Sep 2026 09:04:18 +0530 Subject: [PATCH 13/92] drm/panel: simple: Add BOE DV215FHM-R01 panel Add the BOE DV215FHM-R01 21.5" FHD (1920x1080) dual-channel LVDS panel. Reviewed-by: Neil Armstrong Signed-off-by: Vishnu Saini Signed-off-by: Neil Armstrong Link: https://patch.msgid.link/20260903-b4-lvds-panel-doc-v4-2-861738a0d5de@oss.qualcomm.com --- drivers/gpu/drm/panel/panel-simple.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index bd7f6eaeb0de..d7dbd7442919 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1593,6 +1593,31 @@ static const struct panel_desc boe_bp101wx1_100 = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; +static const struct display_timing boe_dv215fhm_r01_timing = { + .pixelclock = { 148500000, 148500000, 148500000 }, + .hactive = { 1920, 1920, 1920 }, + .hfront_porch = { 88, 88, 88 }, + .hback_porch = { 148, 148, 148 }, + .hsync_len = { 44, 44, 44 }, + .vactive = { 1080, 1080, 1080 }, + .vfront_porch = { 4, 4, 4 }, + .vback_porch = { 36, 36, 36 }, + .vsync_len = { 5, 5, 5 }, + .flags = DISPLAY_FLAGS_DE_HIGH, +}; + +static const struct panel_desc boe_dv215fhm_r01 = { + .timings = &boe_dv215fhm_r01_timing, + .num_timings = 1, + .bpc = 8, + .size = { + .width = 476, + .height = 268, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + static const struct display_timing boe_ev121wxm_n10_1850_timing = { .pixelclock = { 69922000, 71000000, 72293000 }, .hactive = { 1280, 1280, 1280 }, @@ -5785,6 +5810,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "boe,bp101wx1-100", .data = &boe_bp101wx1_100, + }, { + .compatible = "boe,dv215fhm-r01", + .data = &boe_dv215fhm_r01, }, { .compatible = "boe,ev121wxm-n10-1850", .data = &boe_ev121wxm_n10_1850, From f7afecd54296cf7ad6fa36f692d2a7427e32f25d Mon Sep 17 00:00:00 2001 From: Lizhi Hou Date: Wed, 23 Sep 2026 13:05:01 -0700 Subject: [PATCH 14/92] accel/amdxdna: Preallocate hardware context schedulers The hardware context scheduler fence is exposed through drm_syncobj_add_point(). After a hardware context is destroyed, userspace can still call drm_sched_fence_get_timeline_name() on the fence through SYNC_IOC_FILE_INFO. This results in a use-after-free when accessing fence->sched->name. Preallocate hardware context schedulers and free them during device teardown instead. A destroyed hardware context no longer frees its scheduler, ensuring that the scheduler remains valid while its fences are still accessible. Fixes: aac243092b70 ("accel/amdxdna: Add command execution") Reported-by: Jonghyuk Kim(MalHyuk) Link: https://lore.kernel.org/dri-devel/20260902012712.880520-1-malhyuk97@gmail.com/ Reviewed-by: Max Zhen Signed-off-by: Lizhi Hou Link: https://patch.msgid.link/20260923200501.281208-1-lizhi.hou@amd.com --- drivers/accel/amdxdna/aie2_ctx.c | 117 +++++++++++++++++++++++-------- drivers/accel/amdxdna/aie2_pci.c | 15 +++- drivers/accel/amdxdna/aie2_pci.h | 6 +- 3 files changed, 105 insertions(+), 33 deletions(-) diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c index 164441e43940..d927c8c9d557 100644 --- a/drivers/accel/amdxdna/aie2_ctx.c +++ b/drivers/accel/amdxdna/aie2_ctx.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -99,9 +100,9 @@ static void aie2_job_put(struct amdxdna_sched_job *job) static void aie2_hwctx_stop(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwctx, struct drm_sched_job *bad_job) { - drm_sched_stop(&hwctx->priv->sched, bad_job); + drm_sched_stop(hwctx->priv->sched, bad_job); aie2_destroy_context(xdna->dev_handle, hwctx); - drm_sched_start(&hwctx->priv->sched, 0); + drm_sched_start(hwctx->priv->sched, 0); } static int aie2_hwctx_restart(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwctx) @@ -659,10 +660,19 @@ static void aie2_ctx_syncobj_destroy(struct amdxdna_hwctx *hwctx) drm_syncobj_put(hwctx->priv->syncobj); } -int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) +void aie2_hwctx_sched_fini(struct amdxdna_dev_hdl *ndev) { - struct amdxdna_client *client = hwctx->client; - struct amdxdna_dev *xdna = client->xdna; + int i; + + for (i = 0; i < ndev->priv->hwctx_limit; i++) + drm_sched_fini(&ndev->hwctx_sched[i]); + + ida_destroy(&ndev->hwctx_sched_ida); +} + +int aie2_hwctx_sched_init(struct amdxdna_dev_hdl *ndev) +{ + struct amdxdna_dev *xdna = ndev->aie.xdna; const struct drm_sched_init_args args = { .ops = &sched_ops, .num_rqs = DRM_SCHED_PRIORITY_COUNT, @@ -673,7 +683,55 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) .name = "amdxdna_js", .dev = xdna->ddev.dev, }; - struct drm_gpu_scheduler *sched; + int i, ret; + + ndev->hwctx_sched = drmm_kcalloc(&xdna->ddev, ndev->priv->hwctx_limit, + sizeof(*ndev->hwctx_sched), GFP_KERNEL); + if (!ndev->hwctx_sched) + return -ENOMEM; + + for (i = 0; i < ndev->priv->hwctx_limit; i++) { + ret = drm_sched_init(&ndev->hwctx_sched[i], &args); + if (ret) { + XDNA_ERR(xdna, "Failed to init DRM scheduler. ret %d", ret); + goto fini_sched; + } + } + + ida_init(&ndev->hwctx_sched_ida); + + return 0; + +fini_sched: + while (--i >= 0) + drm_sched_fini(&ndev->hwctx_sched[i]); + + return ret; +} + +static struct drm_gpu_scheduler *aie2_hwctx_sched_alloc(struct amdxdna_dev_hdl *ndev) +{ + int ret; + + ret = ida_alloc_range(&ndev->hwctx_sched_ida, 0, + ndev->priv->hwctx_limit - 1, GFP_KERNEL); + if (ret < 0) + return ERR_PTR(ret); + + return &ndev->hwctx_sched[ret]; +} + +static void aie2_hwctx_sched_free(struct amdxdna_dev_hdl *ndev, + struct drm_gpu_scheduler *sched) +{ + ida_free(&ndev->hwctx_sched_ida, sched - ndev->hwctx_sched); +} + +int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) +{ + struct amdxdna_client *client = hwctx->client; + struct amdxdna_dev *xdna = client->xdna; + struct amdxdna_dev_hdl *ndev = xdna->dev_handle; struct amdxdna_hwctx_priv *priv; struct amdxdna_gem_obj *heap; int i, ret; @@ -683,13 +741,26 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) return -ENOMEM; hwctx->priv = priv; + priv->sched = aie2_hwctx_sched_alloc(ndev); + if (IS_ERR(priv->sched)) { + ret = PTR_ERR(priv->sched); + goto free_priv; + } + + ret = drm_sched_entity_init(&priv->entity, DRM_SCHED_PRIORITY_NORMAL, + &priv->sched, 1, NULL); + if (ret) { + XDNA_ERR(xdna, "Failed to initial sched entity. ret %d", ret); + goto free_sched; + } + mutex_lock(&client->mm_lock); heap = xa_load(&client->dev_heap_xa, 0); if (!heap) { XDNA_ERR(xdna, "The client dev heap object not exist"); mutex_unlock(&client->mm_lock); ret = -ENOENT; - goto free_priv; + goto free_entity; } drm_gem_object_get(to_gobj(heap)); mutex_unlock(&client->mm_lock); @@ -722,30 +793,16 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) priv->cmd_buf[i] = abo; } - sched = &priv->sched; mutex_init(&priv->io_lock); fs_reclaim_acquire(GFP_KERNEL); might_lock(&priv->io_lock); fs_reclaim_release(GFP_KERNEL); - ret = drm_sched_init(sched, &args); - if (ret) { - XDNA_ERR(xdna, "Failed to init DRM scheduler. ret %d", ret); - goto free_cmd_bufs; - } - - ret = drm_sched_entity_init(&priv->entity, DRM_SCHED_PRIORITY_NORMAL, - &sched, 1, NULL); - if (ret) { - XDNA_ERR(xdna, "Failed to initial sched entiry. ret %d", ret); - goto free_sched; - } - ret = aie2_hwctx_col_list(hwctx); if (ret) { XDNA_ERR(xdna, "Create col list failed, ret %d", ret); - goto free_entity; + goto free_cmd_bufs; } ret = amdxdna_pm_resume_get_locked(xdna); @@ -791,10 +848,6 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) amdxdna_pm_suspend_put(xdna); free_col_list: kfree(hwctx->col_list); -free_entity: - drm_sched_entity_destroy(&priv->entity); -free_sched: - drm_sched_fini(&priv->sched); free_cmd_bufs: for (i = 0; i < ARRAY_SIZE(priv->cmd_buf); i++) { if (!priv->cmd_buf[i]) @@ -805,6 +858,10 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) amdxdna_gem_unpin(heap); put_heap: drm_gem_object_put(to_gobj(heap)); +free_entity: + drm_sched_entity_destroy(&priv->entity); +free_sched: + aie2_hwctx_sched_free(ndev, priv->sched); free_priv: kfree(priv); return ret; @@ -812,18 +869,20 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) void aie2_hwctx_fini(struct amdxdna_hwctx *hwctx) { + struct amdxdna_dev_hdl *ndev; struct amdxdna_dev *xdna; int idx; xdna = hwctx->client->xdna; + ndev = xdna->dev_handle; XDNA_DBG(xdna, "%s sequence number %lld", hwctx->name, hwctx->priv->seq); aie2_hwctx_wait_for_idle(hwctx); /* Request fw to destroy hwctx and cancel the rest pending requests */ - drm_sched_stop(&hwctx->priv->sched, NULL); + drm_sched_stop(hwctx->priv->sched, NULL); aie2_release_resource(hwctx); - drm_sched_start(&hwctx->priv->sched, 0); + drm_sched_start(hwctx->priv->sched, 0); mutex_unlock(&xdna->dev_lock); drm_sched_entity_destroy(&hwctx->priv->entity); @@ -834,7 +893,7 @@ void aie2_hwctx_fini(struct amdxdna_hwctx *hwctx) atomic64_read(&hwctx->job_free_cnt)); mutex_lock(&xdna->dev_lock); - drm_sched_fini(&hwctx->priv->sched); + aie2_hwctx_sched_free(ndev, hwctx->priv->sched); aie2_ctx_syncobj_destroy(hwctx); for (idx = 0; idx < ARRAY_SIZE(hwctx->priv->cmd_buf); idx++) { diff --git a/drivers/accel/amdxdna/aie2_pci.c b/drivers/accel/amdxdna/aie2_pci.c index daec1f6b4907..7a4314ca843b 100644 --- a/drivers/accel/amdxdna/aie2_pci.c +++ b/drivers/accel/amdxdna/aie2_pci.c @@ -503,10 +503,16 @@ static int aie2_init(struct amdxdna_dev *xdna) ndev->priv = xdna->dev_info->dev_priv; ndev->aie.xdna = xdna; + ret = aie2_hwctx_sched_init(ndev); + if (ret) + return ret; + for (i = 0; i < ARRAY_SIZE(npu_fw); i++) { fw_full_path = kasprintf(GFP_KERNEL, "%s%s", ndev->priv->fw_path, npu_fw[i]); - if (!fw_full_path) - return -ENOMEM; + if (!fw_full_path) { + ret = -ENOMEM; + goto free_hwctx_sched; + } ret = firmware_request_nowarn(&fw, fw_full_path, &pdev->dev); kfree(fw_full_path); @@ -519,7 +525,7 @@ static int aie2_init(struct amdxdna_dev *xdna) if (ret) { XDNA_ERR(xdna, "failed to request_firmware %s, ret %d", ndev->priv->fw_path, ret); - return ret; + goto free_hwctx_sched; } ret = pcim_enable_device(pdev); @@ -623,6 +629,8 @@ static int aie2_init(struct amdxdna_dev *xdna) aie2_hw_stop(xdna); release_fw: release_firmware(fw); +free_hwctx_sched: + aie2_hwctx_sched_fini(ndev); return ret; } @@ -631,6 +639,7 @@ static void aie2_fini(struct amdxdna_dev *xdna) { amdxdna_pm_fini(xdna); aie2_hw_stop(xdna); + aie2_hwctx_sched_fini(xdna->dev_handle); } static int aie2_get_aie_status(struct amdxdna_client *client, diff --git a/drivers/accel/amdxdna/aie2_pci.h b/drivers/accel/amdxdna/aie2_pci.h index ea1dac106400..2c7019bd26b5 100644 --- a/drivers/accel/amdxdna/aie2_pci.h +++ b/drivers/accel/amdxdna/aie2_pci.h @@ -107,7 +107,7 @@ struct amdxdna_hwctx_priv { struct amdxdna_gem_obj *heap; void *mbox_chann; - struct drm_gpu_scheduler sched; + struct drm_gpu_scheduler *sched; struct drm_sched_entity entity; struct mutex io_lock; /* protect seq and cmd order */ @@ -152,6 +152,8 @@ struct amdxdna_dev_hdl { u32 total_col; struct amdxdna_drm_query_aie_version version; struct aie2_exec_msg_ops *exec_msg_ops; + struct drm_gpu_scheduler *hwctx_sched; + struct ida hwctx_sched_ida; /* power management and clock*/ enum amdxdna_power_mode_type pw_mode; @@ -294,6 +296,8 @@ int aie2_update_prop_time_quota(struct amdxdna_dev_hdl *ndev, u32 us); /* aie2_hwctx.c */ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx); void aie2_hwctx_fini(struct amdxdna_hwctx *hwctx); +int aie2_hwctx_sched_init(struct amdxdna_dev_hdl *ndev); +void aie2_hwctx_sched_fini(struct amdxdna_dev_hdl *ndev); int aie2_hwctx_config(struct amdxdna_hwctx *hwctx, u32 type, u64 value, void *buf, u32 size); int aie2_hwctx_sync_debug_bo(struct amdxdna_hwctx *hwctx, u32 debug_bo_hdl); void aie2_hwctx_suspend(struct amdxdna_client *client); From 98c7fc4219b93f953ee85c07fb6c8256046aba73 Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Thu, 25 Jun 2026 12:49:04 +0200 Subject: [PATCH 15/92] drm/sched: Remove forgotten header sched_main.c still contains the spsc queue header, which is not needed anymore in that file. Remove the surplus header import. Reviewed-by: Marco Pagani Signed-off-by: Philipp Stanner Link: https://patch.msgid.link/20260625104903.1713213-2-phasta@kernel.org --- drivers/gpu/drm/scheduler/sched_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index aba5545033ac..b9580ce1ddec 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -77,7 +77,6 @@ #include #include #include -#include #include "sched_internal.h" From 0f5f6202d23d0fb3739a1532f533261343e60c30 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 21 Sep 2026 11:15:54 +0200 Subject: [PATCH 16/92] dt-bindings: display: faraday,tve200: Use a level-high interrupt The TVE200 vertical interrupt can remain pending after acknowledgment. Using rising-edge triggering can leave it unserviced when no new edge is generated, causing vblank and page-flip timeouts on the D-Link DIR-685. Use level-high triggering in the binding example so a pending interrupt is delivered again without requiring a new edge. Assisted-by: LLM Acked-by: Krzysztof Kozlowski Signed-off-by: Linus Walleij Link: https://patch.msgid.link/20260921-gemini-tve200-fix-v1-1-8be03ac2a8f7@kernel.org --- Documentation/devicetree/bindings/display/faraday,tve200.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/faraday,tve200.yaml b/Documentation/devicetree/bindings/display/faraday,tve200.yaml index b09628b69177..43dbe2778d6b 100644 --- a/Documentation/devicetree/bindings/display/faraday,tve200.yaml +++ b/Documentation/devicetree/bindings/display/faraday,tve200.yaml @@ -54,7 +54,7 @@ examples: display-controller@6a000000 { compatible = "faraday,tve200"; reg = <0x6a000000 0x1000>; - interrupts = <13 IRQ_TYPE_EDGE_RISING>; + interrupts = <13 IRQ_TYPE_LEVEL_HIGH>; resets = <&syscon GEMINI_RESET_TVC>; clocks = <&syscon GEMINI_CLK_GATE_TVC>, <&syscon GEMINI_CLK_TVC>; From 370c5d9004f8b754351981d59fc26851bf943e93 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 13 Sep 2026 14:33:32 +0200 Subject: [PATCH 17/92] dt-bindings: display: Use consistent indentation in the example Correct indentation in the examples to consistent 2- or 4-spaces indentation to fix dt-check-style warnings ("example 0 [indent-consistent] indent mismatch ..."). Preferred is 4-spaces, but re-indenting entire example just for that is too much churn. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Luca Ceresoli Reviewed-by: Javier Martinez Canillas Link: https://patch.msgid.link/20260913123331.100293-3-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Luca Ceresoli --- .../display/allwinner,sun6i-a31-mipi-dsi.yaml | 10 +-- .../display/bridge/fsl,imx8qxp-pxl2dpi.yaml | 4 +- .../display/bridge/lontium,lt8912b.yaml | 8 +- .../megachips,stdp2690-ge-b850v3-fw.yaml | 2 +- .../bindings/display/bridge/nxp,tda998x.yaml | 2 +- .../display/bridge/toshiba,tc358764.yaml | 2 +- .../display/bridge/toshiba,tc358775.yaml | 12 +-- .../bindings/display/himax,hx8357.yaml | 2 +- .../bindings/display/imx/fsl,imx-lcdc.yaml | 2 +- .../bindings/display/imx/fsl,imx6q-ldb.yaml | 54 +++++------ .../display/mediatek/mediatek,ethdr.yaml | 90 +++++++++---------- .../display/mediatek/mediatek,hdmi.yaml | 24 ++--- .../display/panel/samsung,ams495qa01.yaml | 2 +- .../bindings/display/sitronix,st7567.yaml | 4 +- .../bindings/display/st,stm32-dsi.yaml | 46 +++++----- .../bindings/display/st,stm32-ltdc.yaml | 6 +- .../bindings/display/st,stm32mp25-lvds.yaml | 4 +- 17 files changed, 137 insertions(+), 137 deletions(-) diff --git a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml index c731fbdc2fe0..7b11cb5e5f6d 100644 --- a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml +++ b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml @@ -119,11 +119,11 @@ examples: #size-cells = <0>; panel@0 { - compatible = "bananapi,lhr050h41", "ilitek,ili9881c"; - reg = <0>; - power-supply = <®_display>; - reset-gpios = <&r_pio 0 5 1>; /* PL05 */ - backlight = <&pwm_bl>; + compatible = "bananapi,lhr050h41", "ilitek,ili9881c"; + reg = <0>; + power-supply = <®_display>; + reset-gpios = <&r_pio 0 5 1>; /* PL05 */ + backlight = <&pwm_bl>; }; port { diff --git a/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pxl2dpi.yaml b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pxl2dpi.yaml index e4e77fad05f1..af9ad07ef08b 100644 --- a/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pxl2dpi.yaml +++ b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pxl2dpi.yaml @@ -84,8 +84,8 @@ examples: }; mipi_lvds_0_pxl2dpi_dc_pixel_link1: endpoint@1 { - reg = <1>; - remote-endpoint = <&dc_pixel_link1_mipi_lvds_0_pxl2dpi>; + reg = <1>; + remote-endpoint = <&dc_pixel_link1_mipi_lvds_0_pxl2dpi>; }; }; diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt8912b.yaml b/Documentation/devicetree/bindings/display/bridge/lontium,lt8912b.yaml index 988351f3cd01..2d2dc9c046fb 100644 --- a/Documentation/devicetree/bindings/display/bridge/lontium,lt8912b.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt8912b.yaml @@ -107,11 +107,11 @@ examples: }; port@1 { - reg = <1>; + reg = <1>; - endpoint { - remote-endpoint = <&hdmi_in>; - }; + endpoint { + remote-endpoint = <&hdmi_in>; + }; }; }; }; diff --git a/Documentation/devicetree/bindings/display/bridge/megachips,stdp2690-ge-b850v3-fw.yaml b/Documentation/devicetree/bindings/display/bridge/megachips,stdp2690-ge-b850v3-fw.yaml index dfa6ff6f115e..74539132bf94 100644 --- a/Documentation/devicetree/bindings/display/bridge/megachips,stdp2690-ge-b850v3-fw.yaml +++ b/Documentation/devicetree/bindings/display/bridge/megachips,stdp2690-ge-b850v3-fw.yaml @@ -104,7 +104,7 @@ examples: endpoint { remote-endpoint = <&stdp2690_in>; }; - }; + }; }; }; }; diff --git a/Documentation/devicetree/bindings/display/bridge/nxp,tda998x.yaml b/Documentation/devicetree/bindings/display/bridge/nxp,tda998x.yaml index 1205c8e9de32..0ad55ff8e330 100644 --- a/Documentation/devicetree/bindings/display/bridge/nxp,tda998x.yaml +++ b/Documentation/devicetree/bindings/display/bridge/nxp,tda998x.yaml @@ -106,7 +106,7 @@ examples: video-ports = <0x230145>; #sound-dai-cells = <1>; - /* DAI-format / AP_ENA reg value */ + /* DAI-format / AP_ENA reg value */ audio-ports = , ; diff --git a/Documentation/devicetree/bindings/display/bridge/toshiba,tc358764.yaml b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358764.yaml index 866607400514..23c5b254426b 100644 --- a/Documentation/devicetree/bindings/display/bridge/toshiba,tc358764.yaml +++ b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358764.yaml @@ -81,7 +81,7 @@ examples: port@1 { reg = <1>; lvds_ep: endpoint { - remote-endpoint = <&panel_ep>; + remote-endpoint = <&panel_ep>; }; }; }; diff --git a/Documentation/devicetree/bindings/display/bridge/toshiba,tc358775.yaml b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358775.yaml index 258dd9cfd770..8a0d8a66a9b0 100644 --- a/Documentation/devicetree/bindings/display/bridge/toshiba,tc358775.yaml +++ b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358775.yaml @@ -161,9 +161,9 @@ examples: dsi0_out: endpoint { remote-endpoint = <&d2l_in_test>; }; - }; - }; - }; + }; + }; + }; - | /* For dual-link LVDS display panel */ @@ -227,7 +227,7 @@ examples: dsi0_out_dual: endpoint { remote-endpoint = <&d2l_in_dual>; }; - }; - }; - }; + }; + }; + }; ... diff --git a/Documentation/devicetree/bindings/display/himax,hx8357.yaml b/Documentation/devicetree/bindings/display/himax,hx8357.yaml index 34c3b89bf003..bafcd4418d5a 100644 --- a/Documentation/devicetree/bindings/display/himax,hx8357.yaml +++ b/Documentation/devicetree/bindings/display/himax,hx8357.yaml @@ -74,5 +74,5 @@ examples: dc-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>; rotation = <90>; backlight = <&backlight>; - }; + }; }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx-lcdc.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx-lcdc.yaml index c2b29622bceb..84610b5690c4 100644 --- a/Documentation/devicetree/bindings/display/imx/fsl,imx-lcdc.yaml +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx-lcdc.yaml @@ -110,7 +110,7 @@ examples: port { parallel_out: endpoint { - remote-endpoint = <&panel_in>; + remote-endpoint = <&panel_in>; }; }; }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx6q-ldb.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx6q-ldb.yaml index 1646f41d8f72..cee1b504adf9 100644 --- a/Documentation/devicetree/bindings/display/imx/fsl,imx6q-ldb.yaml +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx6q-ldb.yaml @@ -150,44 +150,44 @@ examples: /* Using an of-graph endpoint link to connect the panel */ lvds-channel@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + port@0 { reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - port@0 { - reg = <0>; - - endpoint { - remote-endpoint = <&ipu_di0_lvds0>; - }; + endpoint { + remote-endpoint = <&ipu_di0_lvds0>; }; + }; - port@2 { - reg = <2>; + port@2 { + reg = <2>; - endpoint { - remote-endpoint = <&panel_in>; - }; - }; + endpoint { + remote-endpoint = <&panel_in>; + }; + }; }; /* Using display-timings and fsl,data-mapping/width instead */ lvds-channel@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + fsl,data-mapping = "spwg"; + fsl,data-width = <24>; + + display-timings {/* ... */ + }; + + port@1 { reg = <1>; - #address-cells = <1>; - #size-cells = <0>; - fsl,data-mapping = "spwg"; - fsl,data-width = <24>; - display-timings {/* ... */ - }; - - port@1 { - reg = <1>; - - endpoint { - remote-endpoint = <&ipu_di1_lvds1>; - }; + endpoint { + remote-endpoint = <&ipu_di1_lvds1>; }; + }; }; }; diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,ethdr.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,ethdr.yaml index 98db47894eeb..6c0edbae96d7 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,ethdr.yaml +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,ethdr.yaml @@ -158,51 +158,51 @@ examples: #size-cells = <2>; hdr-engine@1c114000 { - compatible = "mediatek,mt8195-disp-ethdr"; - reg = <0 0x1c114000 0 0x1000>, - <0 0x1c115000 0 0x1000>, - <0 0x1c117000 0 0x1000>, - <0 0x1c119000 0 0x1000>, - <0 0x1c11a000 0 0x1000>, - <0 0x1c11b000 0 0x1000>, - <0 0x1c11c000 0 0x1000>; - reg-names = "mixer", "vdo_fe0", "vdo_fe1", "gfx_fe0", "gfx_fe1", - "vdo_be", "adl_ds"; - mediatek,gce-client-reg = <&gce0 SUBSYS_1c11XXXX 0x4000 0x1000>, - <&gce0 SUBSYS_1c11XXXX 0x5000 0x1000>, - <&gce0 SUBSYS_1c11XXXX 0x7000 0x1000>, - <&gce0 SUBSYS_1c11XXXX 0x9000 0x1000>, - <&gce0 SUBSYS_1c11XXXX 0xa000 0x1000>, - <&gce0 SUBSYS_1c11XXXX 0xb000 0x1000>, - <&gce0 SUBSYS_1c11XXXX 0xc000 0x1000>; - clocks = <&vdosys1 CLK_VDO1_DISP_MIXER>, - <&vdosys1 CLK_VDO1_HDR_VDO_FE0>, - <&vdosys1 CLK_VDO1_HDR_VDO_FE1>, - <&vdosys1 CLK_VDO1_HDR_GFX_FE0>, - <&vdosys1 CLK_VDO1_HDR_GFX_FE1>, - <&vdosys1 CLK_VDO1_HDR_VDO_BE>, - <&vdosys1 CLK_VDO1_26M_SLOW>, - <&vdosys1 CLK_VDO1_HDR_VDO_FE0_DL_ASYNC>, - <&vdosys1 CLK_VDO1_HDR_VDO_FE1_DL_ASYNC>, - <&vdosys1 CLK_VDO1_HDR_GFX_FE0_DL_ASYNC>, - <&vdosys1 CLK_VDO1_HDR_GFX_FE1_DL_ASYNC>, - <&vdosys1 CLK_VDO1_HDR_VDO_BE_DL_ASYNC>, - <&topckgen CLK_TOP_ETHDR>; - clock-names = "mixer", "vdo_fe0", "vdo_fe1", "gfx_fe0", "gfx_fe1", - "vdo_be", "adl_ds", "vdo_fe0_async", "vdo_fe1_async", - "gfx_fe0_async", "gfx_fe1_async","vdo_be_async", - "ethdr_top"; - power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>; - iommus = <&iommu_vpp M4U_PORT_L3_HDR_DS>, - <&iommu_vpp M4U_PORT_L3_HDR_ADL>; - interrupts = ; /* disp mixer */ - resets = <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_FE0_DL_ASYNC>, - <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_FE1_DL_ASYNC>, - <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_GFX_FE0_DL_ASYNC>, - <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_GFX_FE1_DL_ASYNC>, - <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_BE_DL_ASYNC>; - reset-names = "vdo_fe0_async", "vdo_fe1_async", "gfx_fe0_async", - "gfx_fe1_async", "vdo_be_async"; + compatible = "mediatek,mt8195-disp-ethdr"; + reg = <0 0x1c114000 0 0x1000>, + <0 0x1c115000 0 0x1000>, + <0 0x1c117000 0 0x1000>, + <0 0x1c119000 0 0x1000>, + <0 0x1c11a000 0 0x1000>, + <0 0x1c11b000 0 0x1000>, + <0 0x1c11c000 0 0x1000>; + reg-names = "mixer", "vdo_fe0", "vdo_fe1", "gfx_fe0", "gfx_fe1", + "vdo_be", "adl_ds"; + mediatek,gce-client-reg = <&gce0 SUBSYS_1c11XXXX 0x4000 0x1000>, + <&gce0 SUBSYS_1c11XXXX 0x5000 0x1000>, + <&gce0 SUBSYS_1c11XXXX 0x7000 0x1000>, + <&gce0 SUBSYS_1c11XXXX 0x9000 0x1000>, + <&gce0 SUBSYS_1c11XXXX 0xa000 0x1000>, + <&gce0 SUBSYS_1c11XXXX 0xb000 0x1000>, + <&gce0 SUBSYS_1c11XXXX 0xc000 0x1000>; + clocks = <&vdosys1 CLK_VDO1_DISP_MIXER>, + <&vdosys1 CLK_VDO1_HDR_VDO_FE0>, + <&vdosys1 CLK_VDO1_HDR_VDO_FE1>, + <&vdosys1 CLK_VDO1_HDR_GFX_FE0>, + <&vdosys1 CLK_VDO1_HDR_GFX_FE1>, + <&vdosys1 CLK_VDO1_HDR_VDO_BE>, + <&vdosys1 CLK_VDO1_26M_SLOW>, + <&vdosys1 CLK_VDO1_HDR_VDO_FE0_DL_ASYNC>, + <&vdosys1 CLK_VDO1_HDR_VDO_FE1_DL_ASYNC>, + <&vdosys1 CLK_VDO1_HDR_GFX_FE0_DL_ASYNC>, + <&vdosys1 CLK_VDO1_HDR_GFX_FE1_DL_ASYNC>, + <&vdosys1 CLK_VDO1_HDR_VDO_BE_DL_ASYNC>, + <&topckgen CLK_TOP_ETHDR>; + clock-names = "mixer", "vdo_fe0", "vdo_fe1", "gfx_fe0", "gfx_fe1", + "vdo_be", "adl_ds", "vdo_fe0_async", "vdo_fe1_async", + "gfx_fe0_async", "gfx_fe1_async","vdo_be_async", + "ethdr_top"; + power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>; + iommus = <&iommu_vpp M4U_PORT_L3_HDR_DS>, + <&iommu_vpp M4U_PORT_L3_HDR_ADL>; + interrupts = ; /* disp mixer */ + resets = <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_FE0_DL_ASYNC>, + <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_FE1_DL_ASYNC>, + <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_GFX_FE0_DL_ASYNC>, + <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_GFX_FE1_DL_ASYNC>, + <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_BE_DL_ASYNC>; + reset-names = "vdo_fe0_async", "vdo_fe1_async", "gfx_fe0_async", + "gfx_fe1_async", "vdo_be_async"; }; }; ... diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.yaml index b90b6d18a828..9af876329e6a 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.yaml +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.yaml @@ -112,24 +112,24 @@ examples: mediatek,syscon-hdmi = <&mmsys 0x900>; ports { - #address-cells = <1>; - #size-cells = <0>; + #address-cells = <1>; + #size-cells = <0>; - port@0 { - reg = <0>; + port@0 { + reg = <0>; - hdmi0_in: endpoint { - remote-endpoint = <&dpi0_out>; + hdmi0_in: endpoint { + remote-endpoint = <&dpi0_out>; + }; }; - }; - port@1 { - reg = <1>; + port@1 { + reg = <1>; - hdmi0_out: endpoint { - remote-endpoint = <&hdmi_con_in>; + hdmi0_out: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; }; - }; }; }; diff --git a/Documentation/devicetree/bindings/display/panel/samsung,ams495qa01.yaml b/Documentation/devicetree/bindings/display/panel/samsung,ams495qa01.yaml index e081c84a932b..6db87f7d70d8 100644 --- a/Documentation/devicetree/bindings/display/panel/samsung,ams495qa01.yaml +++ b/Documentation/devicetree/bindings/display/panel/samsung,ams495qa01.yaml @@ -51,7 +51,7 @@ examples: port { mipi_in_panel: endpoint { - remote-endpoint = <&mipi_out_panel>; + remote-endpoint = <&mipi_out_panel>; }; }; }; diff --git a/Documentation/devicetree/bindings/display/sitronix,st7567.yaml b/Documentation/devicetree/bindings/display/sitronix,st7567.yaml index 2eb6d00b5a25..c007718541f6 100644 --- a/Documentation/devicetree/bindings/display/sitronix,st7567.yaml +++ b/Documentation/devicetree/bindings/display/sitronix,st7567.yaml @@ -64,5 +64,5 @@ examples: vfront-porch = <0>; vsync-len = <0>; }; - }; - }; + }; + }; diff --git a/Documentation/devicetree/bindings/display/st,stm32-dsi.yaml b/Documentation/devicetree/bindings/display/st,stm32-dsi.yaml index 53560052aaf0..1b5f4317dab2 100644 --- a/Documentation/devicetree/bindings/display/st,stm32-dsi.yaml +++ b/Documentation/devicetree/bindings/display/st,stm32-dsi.yaml @@ -101,35 +101,35 @@ examples: #size-cells = <0>; ports { - #address-cells = <1>; - #size-cells = <0>; + #address-cells = <1>; + #size-cells = <0>; - port@0 { - reg = <0>; - dsi_in: endpoint { - remote-endpoint = <<dc_ep1_out>; - }; - }; + port@0 { + reg = <0>; + dsi_in: endpoint { + remote-endpoint = <<dc_ep1_out>; + }; + }; - port@1 { - reg = <1>; - dsi_out: endpoint { - remote-endpoint = <&panel_in>; - }; - }; + port@1 { + reg = <1>; + dsi_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; }; panel@0 { - compatible = "orisetech,otm8009a"; - reg = <0>; - reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>; - power-supply = <&v3v3>; + compatible = "orisetech,otm8009a"; + reg = <0>; + reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>; + power-supply = <&v3v3>; - port { - panel_in: endpoint { - remote-endpoint = <&dsi_out>; - }; - }; + port { + panel_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; }; }; diff --git a/Documentation/devicetree/bindings/display/st,stm32-ltdc.yaml b/Documentation/devicetree/bindings/display/st,stm32-ltdc.yaml index 77058a5ccf68..81c7772de25b 100644 --- a/Documentation/devicetree/bindings/display/st,stm32-ltdc.yaml +++ b/Documentation/devicetree/bindings/display/st,stm32-ltdc.yaml @@ -119,9 +119,9 @@ examples: resets = <&rcc LTDC_R>; port { - ltdc_out_dsi: endpoint { - remote-endpoint = <&dsi_in>; - }; + ltdc_out_dsi: endpoint { + remote-endpoint = <&dsi_in>; + }; }; }; diff --git a/Documentation/devicetree/bindings/display/st,stm32mp25-lvds.yaml b/Documentation/devicetree/bindings/display/st,stm32mp25-lvds.yaml index 14e042156179..f8e43c5a656a 100644 --- a/Documentation/devicetree/bindings/display/st,stm32mp25-lvds.yaml +++ b/Documentation/devicetree/bindings/display/st,stm32mp25-lvds.yaml @@ -114,14 +114,14 @@ examples: port@0 { reg = <0>; lvds_in: endpoint { - remote-endpoint = <<dc_ep1_out>; + remote-endpoint = <<dc_ep1_out>; }; }; port@1 { reg = <1>; lvds_out0: endpoint { - remote-endpoint = <&lvds_panel_in>; + remote-endpoint = <&lvds_panel_in>; }; }; }; From 8ea0903c62e1fd2d53f68af671635a532bd7dbac Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 15 Sep 2026 18:46:14 +0200 Subject: [PATCH 18/92] drm/bridge: tc358764: don't select unused DRM_PANEL This driver does not use the drm_panel APIs at all, so no need to select DRM_PANEL. Cc: Marek Szyprowski Cc: Marek Vasut Cc: Jagan Teki Reviewed-by: Paul Cercueil Link: https://patch.msgid.link/20260915-drm-bridge-drm_panel-cleanup-v4-1-30401d9406f3@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 837db36cdf48..a402f8c5b321 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -388,7 +388,6 @@ config DRM_TOSHIBA_TC358764 depends on OF select DRM_MIPI_DSI select DRM_KMS_HELPER - select DRM_PANEL help Toshiba TC358764 DSI/LVDS bridge driver. From 184046c9f35222fa3784f960ed3780b2793d62ea Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 15 Sep 2026 18:46:15 +0200 Subject: [PATCH 19/92] drm/bridge: ti-dlpc3433: don't depend on DRM_PANEL, select DRM_PANEL_BRIDGE This driver does not use the drm_panel APIs at all, so no need to select DRM_PANEL. But it uses devm_drm_of_get_bridge(), which is enabled by DRM_PANEL_BRIDGE. Cc: Jagan Teki Cc: Christopher Vollo Reviewed-by: Paul Cercueil Link: https://patch.msgid.link/20260915-drm-bridge-drm_panel-cleanup-v4-2-30401d9406f3@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index a402f8c5b321..c98f62b23b1d 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -428,9 +428,10 @@ config DRM_TOSHIBA_TC358775 config DRM_TI_DLPC3433 tristate "TI DLPC3433 Display controller" - depends on DRM && DRM_PANEL + depends on DRM depends on OF select DRM_MIPI_DSI + select DRM_PANEL_BRIDGE help TI DLPC3433 is a MIPI DSI based display controller bridge for processing high resolution DMD based projectors. From 7dda59aea6288025fd861cd8467af456f9dc26ae Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 15 Sep 2026 18:46:16 +0200 Subject: [PATCH 20/92] drm/bridge: nxp-ptn3460: select DRM_PANEL_BRIDGE, not DRM_PANEL This driver does not use the drm_panel APIs at all, so no need to select DRM_PANEL. But it uses devm_drm_of_get_bridge(), which is enabled by DRM_PANEL_BRIDGE. Cc: Sean Paul Reviewed-by: Paul Cercueil Link: https://patch.msgid.link/20260915-drm-bridge-drm_panel-cleanup-v4-3-30401d9406f3@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index c98f62b23b1d..1d4db73bd760 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -259,7 +259,7 @@ config DRM_NXP_PTN3460 tristate "NXP PTN3460 DP/LVDS bridge" depends on OF select DRM_KMS_HELPER - select DRM_PANEL + select DRM_PANEL_BRIDGE help NXP PTN3460 eDP-LVDS bridge chip driver. From f378fbe78e6e87a3657f1e6286ea3964b99f30cf Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 15 Sep 2026 18:46:17 +0200 Subject: [PATCH 21/92] drm/bridge: parade-ps8622: select DRM_PANEL_BRIDGE, not DRM_PANEL This driver does not use the drm_panel APIs at all, so no need to select DRM_PANEL. But it uses devm_drm_of_get_bridge(), which is enabled by DRM_PANEL_BRIDGE. Cc: Vincent Palatin Reviewed-by: Paul Cercueil Link: https://patch.msgid.link/20260915-drm-bridge-drm_panel-cleanup-v4-4-30401d9406f3@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 1d4db73bd760..65f4d9d9b67d 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -276,7 +276,7 @@ config DRM_OF_DISPLAY_MODE_BRIDGE config DRM_PARADE_PS8622 tristate "Parade eDP/LVDS bridge" depends on OF - select DRM_PANEL + select DRM_PANEL_BRIDGE select DRM_KMS_HELPER select BACKLIGHT_CLASS_DEVICE help From c76257183d3d20ce4986d86814676ff2377c24a8 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 15 Sep 2026 18:46:18 +0200 Subject: [PATCH 22/92] drm/bridge: tc358775: select DRM_PANEL_BRIDGE, not DRM_PANEL This driver does not use the drm_panel APIs at all, so no need to select DRM_PANEL. But it uses devm_drm_of_get_bridge(), which is enabled by DRM_PANEL_BRIDGE. Cc: Tony Lindgren Cc: Michael Walle Cc: Vinay Simha BN Reviewed-by: Michael Walle Reviewed-by: Paul Cercueil Link: https://patch.msgid.link/20260915-drm-bridge-drm_panel-cleanup-v4-5-30401d9406f3@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 65f4d9d9b67d..e2ee76899468 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -421,7 +421,7 @@ config DRM_TOSHIBA_TC358775 select DRM_DISPLAY_HELPER select DRM_KMS_HELPER select REGMAP_I2C - select DRM_PANEL + select DRM_PANEL_BRIDGE select DRM_MIPI_DSI help Toshiba TC358775 DSI/LVDS bridge chip driver. From 65a55bb11116c080ed8e408ef95706a9c8bb393f Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 15 Sep 2026 18:46:19 +0200 Subject: [PATCH 23/92] drm/bridge: tc358767: select DRM_PANEL_BRIDGE This driver uses devm_drm_panel_bridge_add(), which is enabled by DRM_PANEL_BRIDGE. Leave the 'select DRM_PANEL' because it is needed for drm_panel_put() which the driver uses. Cc: Maoyi Xie Cc: Andy Yan Cc: Andrey Gusakov Reviewed-by: Paul Cercueil Link: https://patch.msgid.link/20260915-drm-bridge-drm_panel-cleanup-v4-6-30401d9406f3@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index e2ee76899468..a4bc1b5401c0 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -400,6 +400,7 @@ config DRM_TOSHIBA_TC358767 select REGMAP_I2C select DRM_MIPI_DSI select DRM_PANEL + select DRM_PANEL_BRIDGE help Toshiba TC358767 eDP bridge chip driver. From a269221bf5c304d64d6a6aceded710f8c737113c Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 15 Sep 2026 18:46:20 +0200 Subject: [PATCH 24/92] drm/bridge: tc358768: select DRM_PANEL_BRIDGE This driver uses drm_panel_bridge_add_typed() and drm_panel_bridge_remove(), which are enabled by DRM_PANEL_BRIDGE. Leave the 'select DRM_PANEL' because it is needed for drm_panel_put() which the driver uses. Cc: Tomi Valkeinen Cc: Peter Ujfalusi Reviewed-by: Paul Cercueil Link: https://patch.msgid.link/20260915-drm-bridge-drm_panel-cleanup-v4-7-30401d9406f3@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index a4bc1b5401c0..73e13ad59a93 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -410,6 +410,7 @@ config DRM_TOSHIBA_TC358768 select DRM_KMS_HELPER select REGMAP_I2C select DRM_PANEL + select DRM_PANEL_BRIDGE select DRM_MIPI_DSI select VIDEOMODE_HELPERS help From 9e0156ff263020fd4a10d5b6bc5ee550a7837c2c Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 15 Sep 2026 18:46:21 +0200 Subject: [PATCH 25/92] drm/bridge: ssd2825: select DRM_PANEL_BRIDGE This driver uses drm_panel_bridge_add_typed() and drm_panel_bridge_remove(), which are enabled by DRM_PANEL_BRIDGE. Leave the 'select DRM_PANEL' because it is needed for drm_panel_put() and drm_panel_enable() which the driver uses. Cc: Svyatoslav Ryhel Reviewed-by: Svyatoslav Ryhel Reviewed-by: Paul Cercueil Link: https://patch.msgid.link/20260915-drm-bridge-drm_panel-cleanup-v4-8-30401d9406f3@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 73e13ad59a93..92938df3b747 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -351,6 +351,7 @@ config DRM_SOLOMON_SSD2825 select DRM_MIPI_DSI select DRM_KMS_HELPER select DRM_PANEL + select DRM_PANEL_BRIDGE help Say Y here if you want support for the Solomon SSD2825 RGB/DSI SPI bridge driver. From 6095cb1190585793055953d5ee76ff3871681c6e Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 15 Sep 2026 18:46:22 +0200 Subject: [PATCH 26/92] drm/bridge: tc358764: select DRM_PANEL_BRIDGE This driver uses devm_drm_of_get_bridge(), which is enabled by DRM_PANEL_BRIDGE. Cc: Marek Szyprowski Cc: Marek Vasut Cc: Sam Ravnborg Cc: Jagan Teki Suggested-by: sashiko-bot@kernel.org Link: https://lore.kernel.org/all/20260825103234.3F2B71F000E9@smtp.kernel.org/ Reviewed-by: Paul Cercueil Link: https://patch.msgid.link/20260915-drm-bridge-drm_panel-cleanup-v4-9-30401d9406f3@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 92938df3b747..f2db7f60d40f 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -389,6 +389,7 @@ config DRM_TOSHIBA_TC358764 depends on OF select DRM_MIPI_DSI select DRM_KMS_HELPER + select DRM_PANEL_BRIDGE help Toshiba TC358764 DSI/LVDS bridge driver. From 139e3d9cb4fa92dd2e356bc15759f53f54e81a21 Mon Sep 17 00:00:00 2001 From: Andrzej Kacprowski Date: Thu, 24 Sep 2026 12:59:06 +0200 Subject: [PATCH 27/92] accel/ivpu: Make BO free helper NULL-safe Handle NULL buffers in ivpu_bo_free() so callers can use it as a kfree-like cleanup helper. Use the NULL-safe helper to simplify error paths and teardown code in firmware, IPC, preemption buffer, and metric streamer cleanup. This removes redundant conditional frees and collapses unwind labels that only differed by which BOs had been allocated. Signed-off-by: Andrzej Kacprowski Reviewed-by: Dawid Osuchowski Reviewed-by: Karol Wachowski Signed-off-by: Karol Wachowski Link: https://patch.msgid.link/20260924105906.489378-1-andrzej.kacprowski@linux.intel.com --- drivers/accel/ivpu/ivpu_fw.c | 65 +++++++++++++++-------------------- drivers/accel/ivpu/ivpu_gem.c | 3 ++ drivers/accel/ivpu/ivpu_ipc.c | 11 +++--- drivers/accel/ivpu/ivpu_job.c | 6 ++-- drivers/accel/ivpu/ivpu_ms.c | 17 ++++----- 5 files changed, 44 insertions(+), 58 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c index b78b7c35cd9b..f9ddaa2420c4 100644 --- a/drivers/accel/ivpu/ivpu_fw.c +++ b/drivers/accel/ivpu/ivpu_fw.c @@ -364,6 +364,25 @@ static void ivpu_fw_release(struct ivpu_device *vdev) } +static void ivpu_fw_mem_fini(struct ivpu_device *vdev) +{ + struct ivpu_fw_info *fw = vdev->fw; + + ivpu_bo_free(fw->mem_shave_nn); + ivpu_bo_free(fw->mem_log_verb); + ivpu_bo_free(fw->mem_log_crit); + ivpu_bo_free(fw->mem); + ivpu_bo_free(fw->mem_fw_ver); + ivpu_bo_free(fw->mem_bp); + + fw->mem_shave_nn = NULL; + fw->mem_log_verb = NULL; + fw->mem_log_crit = NULL; + fw->mem = NULL; + fw->mem_fw_ver = NULL; + fw->mem_bp = NULL; +} + static int ivpu_fw_mem_init(struct ivpu_device *vdev) { struct ivpu_fw_info *fw = vdev->fw; @@ -382,7 +401,7 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev) if (!fw->mem_fw_ver) { ivpu_err(vdev, "Failed to create firmware version memory buffer\n"); ret = -ENOMEM; - goto err_free_bp; + goto err_free; } fw->mem = ivpu_bo_create_runtime(vdev, fw->runtime_addr, fw->runtime_size, @@ -390,14 +409,14 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev) if (!fw->mem) { ivpu_err(vdev, "Failed to create firmware runtime memory buffer\n"); ret = -ENOMEM; - goto err_free_fw_ver; + goto err_free; } ret = ivpu_mmu_context_set_pages_ro(vdev, &vdev->gctx, fw->read_only_addr, fw->read_only_size); if (ret) { ivpu_err(vdev, "Failed to set firmware image read-only\n"); - goto err_free_fw_mem; + goto err_free; } fw->mem_log_crit = ivpu_bo_create_global(vdev, IVPU_FW_CRITICAL_BUFFER_SIZE, @@ -405,7 +424,7 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev) if (!fw->mem_log_crit) { ivpu_err(vdev, "Failed to create critical log buffer\n"); ret = -ENOMEM; - goto err_free_fw_mem; + goto err_free; } if (ivpu_fw_log_level <= IVPU_FW_LOG_INFO) @@ -418,7 +437,7 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev) if (!fw->mem_log_verb) { ivpu_err(vdev, "Failed to create verbose log buffer\n"); ret = -ENOMEM; - goto err_free_log_crit; + goto err_free; } if (fw->shave_nn_size) { @@ -427,47 +446,17 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev) if (!fw->mem_shave_nn) { ivpu_err(vdev, "Failed to create shavenn buffer\n"); ret = -ENOMEM; - goto err_free_log_verb; + goto err_free; } } return 0; -err_free_log_verb: - ivpu_bo_free(fw->mem_log_verb); -err_free_log_crit: - ivpu_bo_free(fw->mem_log_crit); -err_free_fw_mem: - ivpu_bo_free(fw->mem); -err_free_fw_ver: - ivpu_bo_free(fw->mem_fw_ver); -err_free_bp: - ivpu_bo_free(fw->mem_bp); +err_free: + ivpu_fw_mem_fini(vdev); return ret; } -static void ivpu_fw_mem_fini(struct ivpu_device *vdev) -{ - struct ivpu_fw_info *fw = vdev->fw; - - if (fw->mem_shave_nn) { - ivpu_bo_free(fw->mem_shave_nn); - fw->mem_shave_nn = NULL; - } - - ivpu_bo_free(fw->mem_log_verb); - ivpu_bo_free(fw->mem_log_crit); - ivpu_bo_free(fw->mem); - ivpu_bo_free(fw->mem_fw_ver); - ivpu_bo_free(fw->mem_bp); - - fw->mem_log_verb = NULL; - fw->mem_log_crit = NULL; - fw->mem = NULL; - fw->mem_fw_ver = NULL; - fw->mem_bp = NULL; -} - int ivpu_fw_init(struct ivpu_device *vdev) { int ret; diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/ivpu_gem.c index 4f2005a8d496..62dbc2ef6e9d 100644 --- a/drivers/accel/ivpu/ivpu_gem.c +++ b/drivers/accel/ivpu/ivpu_gem.c @@ -471,6 +471,9 @@ struct ivpu_bo *ivpu_bo_create_global(struct ivpu_device *vdev, u64 size, u32 fl void ivpu_bo_free(struct ivpu_bo *bo) { + if (!bo) + return; + struct iosys_map map = IOSYS_MAP_INIT_VADDR(bo->base.vaddr); if (bo->flags & DRM_IVPU_BO_MAPPABLE) { diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c index 8e960293b77a..79d34f9b1f07 100644 --- a/drivers/accel/ivpu/ivpu_ipc.c +++ b/drivers/accel/ivpu/ivpu_ipc.c @@ -509,7 +509,7 @@ int ivpu_ipc_init(struct ivpu_device *vdev) if (!ipc->mem_rx) { ivpu_err(vdev, "Failed to allocate mem_rx\n"); ret = -ENOMEM; - goto err_free_tx; + goto err_free_bo; } ipc->mm_tx = devm_gen_pool_create(vdev->drm.dev, __ffs(IVPU_IPC_ALIGNMENT), @@ -517,13 +517,13 @@ int ivpu_ipc_init(struct ivpu_device *vdev) if (IS_ERR(ipc->mm_tx)) { ret = PTR_ERR(ipc->mm_tx); ivpu_err(vdev, "Failed to create gen pool, %pe\n", ipc->mm_tx); - goto err_free_rx; + goto err_free_bo; } ret = gen_pool_add(ipc->mm_tx, ipc->mem_tx->vpu_addr, ivpu_bo_size(ipc->mem_tx), -1); if (ret) { ivpu_err(vdev, "gen_pool_add failed, ret %d\n", ret); - goto err_free_rx; + goto err_free_bo; } spin_lock_init(&ipc->cons_lock); @@ -532,14 +532,13 @@ int ivpu_ipc_init(struct ivpu_device *vdev) ret = drmm_mutex_init(&vdev->drm, &ipc->lock); if (ret) { ivpu_err(vdev, "Failed to initialize ipc->lock, ret %d\n", ret); - goto err_free_rx; + goto err_free_bo; } ivpu_ipc_reset(vdev); return 0; -err_free_rx: +err_free_bo: ivpu_bo_free(ipc->mem_rx); -err_free_tx: ivpu_bo_free(ipc->mem_tx); err_destroy_cache: kmem_cache_destroy(ipc->rx_msg_cache); diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index 96023221eb55..bfdee29cd91c 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -64,10 +64,8 @@ static int ivpu_preemption_buffers_create(struct ivpu_device *vdev, static void ivpu_preemption_buffers_free(struct ivpu_device *vdev, struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) { - if (cmdq->primary_preempt_buf) - ivpu_bo_free(cmdq->primary_preempt_buf); - if (cmdq->secondary_preempt_buf) - ivpu_bo_free(cmdq->secondary_preempt_buf); + ivpu_bo_free(cmdq->primary_preempt_buf); + ivpu_bo_free(cmdq->secondary_preempt_buf); } static int ivpu_preemption_job_init(struct ivpu_device *vdev, struct ivpu_file_priv *file_priv, diff --git a/drivers/accel/ivpu/ivpu_ms.c b/drivers/accel/ivpu/ivpu_ms.c index cd176e77b9a0..489ab51d3341 100644 --- a/drivers/accel/ivpu/ivpu_ms.c +++ b/drivers/accel/ivpu/ivpu_ms.c @@ -69,7 +69,7 @@ int ivpu_ms_start_ioctl(struct drm_device *dev, void *data, struct drm_file *fil ret = ivpu_jsm_metric_streamer_info(vdev, ms->mask, 0, 0, &sample_size, NULL); if (ret) - goto err_free_ms; + goto err_free; buf_size = PAGE_ALIGN((u64)args->read_period_samples * sample_size * MS_READ_PERIOD_MULTIPLIER * MS_NUM_BUFFERS); @@ -77,14 +77,14 @@ int ivpu_ms_start_ioctl(struct drm_device *dev, void *data, struct drm_file *fil ivpu_dbg(vdev, IOCTL, "Requested MS buffer size %llu exceeds range size %llu\n", buf_size, ivpu_hw_range_size(&vdev->hw->ranges.global)); ret = -EINVAL; - goto err_free_ms; + goto err_free; } ms->bo = ivpu_bo_create_global(vdev, buf_size, DRM_IVPU_BO_CACHED | DRM_IVPU_BO_MAPPABLE); if (!ms->bo) { ivpu_dbg(vdev, IOCTL, "Failed to allocate MS buffer (size %llu)\n", buf_size); ret = -ENOMEM; - goto err_free_ms; + goto err_free; } ms->buff_size = ivpu_bo_size(ms->bo) / MS_NUM_BUFFERS; @@ -96,16 +96,15 @@ int ivpu_ms_start_ioctl(struct drm_device *dev, void *data, struct drm_file *fil ret = ivpu_jsm_metric_streamer_start(vdev, ms->mask, args->sampling_period_ns, ms->active_buff_vpu_addr, ms->buff_size); if (ret) - goto err_free_bo; + goto err_free; args->sample_size = sample_size; args->max_data_size = ivpu_bo_size(ms->bo); list_add_tail(&ms->ms_instance_node, &file_priv->ms_instance_list); goto unlock; -err_free_bo: +err_free: ivpu_bo_free(ms->bo); -err_free_ms: kfree(ms); unlock: mutex_unlock(&file_priv->ms_lock); @@ -322,10 +321,8 @@ void ivpu_ms_cleanup(struct ivpu_file_priv *file_priv) mutex_lock(&file_priv->ms_lock); - if (file_priv->ms_info_bo) { - ivpu_bo_free(file_priv->ms_info_bo); - file_priv->ms_info_bo = NULL; - } + ivpu_bo_free(file_priv->ms_info_bo); + file_priv->ms_info_bo = NULL; list_for_each_entry_safe(ms, tmp, &file_priv->ms_instance_list, ms_instance_node) free_instance(file_priv, ms); From bf30039e4b87d64fe3ef24db0ffff8d72bc11f3c Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 16 Sep 2026 15:45:25 +0200 Subject: [PATCH 28/92] drm: of: move drm_of_find_panel_or_bridge() from drm_of.c to drm_panel.c We want to move drm_panel.o from the main drm module to a new drm_panel module, but there is one function in the drm module that calls into drm_panel.c code: drm_of_find_panel_or_bridge() (drm_of.c, drm module) -> calls of_drm_find_panel (drm_panel.c, future drm_panel module) Avoid this issue by moving drm_of_find_panel_or_bridge() to drm_panel.c. Update Kconfig symbols of drivers calling drm_of_find_panel_or_bridge() to select DRM_PANEL when this is not done already. No functional changes, just moving code around. Suggested-by: Maxime Ripard Acked-by: Maxime Ripard Link: https://patch.msgid.link/20260916-drm-bridge-every-panel-v3-1-83afb4f1a707@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/Kconfig | 2 + drivers/gpu/drm/bridge/analogix/Kconfig | 2 + drivers/gpu/drm/drm_of.c | 63 ------------------------- drivers/gpu/drm/drm_panel.c | 63 +++++++++++++++++++++++++ drivers/gpu/drm/imx/dcss/Kconfig | 1 + drivers/gpu/drm/ingenic/Kconfig | 1 + drivers/gpu/drm/logicvc/Kconfig | 1 + drivers/gpu/drm/mcde/Kconfig | 1 + drivers/gpu/drm/pl111/Kconfig | 1 + drivers/gpu/drm/rockchip/Kconfig | 2 + drivers/gpu/drm/stm/Kconfig | 1 + drivers/gpu/drm/tidss/Kconfig | 1 + drivers/gpu/drm/tve200/Kconfig | 1 + include/drm/drm_of.h | 12 ----- include/drm/drm_panel.h | 13 +++++ 15 files changed, 90 insertions(+), 75 deletions(-) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index f2db7f60d40f..89e87460aefc 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -151,6 +151,7 @@ config DRM_LONTIUM_LT8912B config DRM_LONTIUM_LT9211 tristate "Lontium LT9211 DSI/LVDS/DPI bridge" depends on OF + select DRM_PANEL select DRM_PANEL_BRIDGE select DRM_KMS_HELPER select DRM_MIPI_DSI @@ -498,6 +499,7 @@ config DRM_WAVESHARE_BRIDGE tristate "Waveshare DSI bridge" depends on OF depends on BACKLIGHT_CLASS_DEVICE + select DRM_PANEL select DRM_PANEL_BRIDGE select DRM_KMS_HELPER select DRM_MIPI_DSI diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig b/drivers/gpu/drm/bridge/analogix/Kconfig index 57bb2daa5aaf..da156fd15764 100644 --- a/drivers/gpu/drm/bridge/analogix/Kconfig +++ b/drivers/gpu/drm/bridge/analogix/Kconfig @@ -6,6 +6,7 @@ config DRM_ANALOGIX_ANX6345 select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_HELPER select DRM_KMS_HELPER + select DRM_PANEL select REGMAP_I2C help ANX6345 is an ultra-low power Full-HD DisplayPort/eDP @@ -32,6 +33,7 @@ config DRM_ANALOGIX_DP depends on DRM depends on OF select DRM_DISPLAY_DP_AUX_BUS + select DRM_PANEL config DRM_ANALOGIX_ANX7625 tristate "Analogix Anx7625 MIPI to DP interface support" diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c index 2b53124ded68..411f258d9f91 100644 --- a/drivers/gpu/drm/drm_of.c +++ b/drivers/gpu/drm/drm_of.c @@ -264,69 +264,6 @@ int drm_of_get_panel_orientation(const struct device_node *np, } EXPORT_SYMBOL_GPL(drm_of_get_panel_orientation); -/** - * drm_of_find_panel_or_bridge - return connected panel or bridge device - * @np: device tree node containing encoder output ports - * @port: port in the device tree node - * @endpoint: endpoint in the device tree node - * @panel: pointer to hold returned drm_panel, must not be NULL. On success - * the caller must call drm_panel_put() when done with the panel - * @bridge: pointer to hold returned drm_bridge - * - * Given a DT node's port and endpoint number, find the connected node and - * return either the associated struct drm_panel or drm_bridge device. - * - * This function is deprecated and should not be used in new drivers. Use - * of_drm_get_bridge_by_endpoint() instead when not looking for a panel, or - * devm_drm_of_get_bridge() otherwise. - * - * Returns zero if successful, or one of the standard error codes if it fails. - */ -int drm_of_find_panel_or_bridge(const struct device_node *np, - int port, int endpoint, - struct drm_panel **panel, - struct drm_bridge **bridge) -{ - if (WARN_ON(!panel)) - return -EINVAL; - - *panel = NULL; - if (bridge) - *bridge = NULL; - - /* - * of_graph_get_remote_node() produces a noisy error message if port - * node isn't found and the absence of the port is a legit case here, - * so at first we silently check whether a graph is present in the - * device-tree node. - */ - if (!of_graph_is_present(np)) - return -ENODEV; - - struct device_node *remote __free(device_node) = - of_graph_get_remote_node(np, port, endpoint); - if (!remote) - return -ENODEV; - - *panel = of_drm_find_panel(remote); - if (!IS_ERR(*panel)) - return 0; - - *panel = NULL; - - if (bridge) { - /* No panel found yet, check for a bridge next. */ - *bridge = of_drm_find_bridge(remote); - if (*bridge) - return 0; - - *bridge = NULL; - } - - return -EPROBE_DEFER; -} -EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge); - enum drm_of_lvds_pixels { DRM_OF_LVDS_EVEN = BIT(0), DRM_OF_LVDS_ODD = BIT(1), diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index f8f6082e637f..e1f8a4ff37d2 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -498,6 +498,69 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np) return ERR_PTR(-EPROBE_DEFER); } EXPORT_SYMBOL(of_drm_find_panel); + +/** + * drm_of_find_panel_or_bridge - return connected panel or bridge device + * @np: device tree node containing encoder output ports + * @port: port in the device tree node + * @endpoint: endpoint in the device tree node + * @panel: pointer to hold returned drm_panel, must not be NULL. On success + * the caller must call drm_panel_put() when done with the panel + * @bridge: pointer to hold returned drm_bridge + * + * Given a DT node's port and endpoint number, find the connected node and + * return either the associated struct drm_panel or drm_bridge device. + * + * This function is deprecated and should not be used in new drivers. Use + * of_drm_get_bridge_by_endpoint() instead when not looking for a panel, or + * devm_drm_of_get_bridge() otherwise. + * + * Returns zero if successful, or one of the standard error codes if it fails. + */ +int drm_of_find_panel_or_bridge(const struct device_node *np, + int port, int endpoint, + struct drm_panel **panel, + struct drm_bridge **bridge) +{ + if (WARN_ON(!panel)) + return -EINVAL; + + *panel = NULL; + if (bridge) + *bridge = NULL; + + /* + * of_graph_get_remote_node() produces a noisy error message if port + * node isn't found and the absence of the port is a legit case here, + * so at first we silently check whether a graph is present in the + * device-tree node. + */ + if (!of_graph_is_present(np)) + return -ENODEV; + + struct device_node *remote __free(device_node) = + of_graph_get_remote_node(np, port, endpoint); + if (!remote) + return -ENODEV; + + *panel = of_drm_find_panel(remote); + if (!IS_ERR(*panel)) + return 0; + + *panel = NULL; + + if (bridge) { + /* No panel found yet, check for a bridge next. */ + *bridge = of_drm_find_bridge(remote); + if (*bridge) + return 0; + + *bridge = NULL; + } + + return -EPROBE_DEFER; +} +EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge); #endif /* diff --git a/drivers/gpu/drm/imx/dcss/Kconfig b/drivers/gpu/drm/imx/dcss/Kconfig index e014ed3ae66c..d278bebfc33c 100644 --- a/drivers/gpu/drm/imx/dcss/Kconfig +++ b/drivers/gpu/drm/imx/dcss/Kconfig @@ -6,6 +6,7 @@ config DRM_IMX_DCSS select DRM_DISPLAY_HELPER select DRM_BRIDGE_CONNECTOR select DRM_GEM_DMA_HELPER + select DRM_PANEL select VIDEOMODE_HELPERS depends on DRM && ((ARCH_MXC && ARM64) || COMPILE_TEST) help diff --git a/drivers/gpu/drm/ingenic/Kconfig b/drivers/gpu/drm/ingenic/Kconfig index 04ecfb0c5dd6..987ed42f6f7a 100644 --- a/drivers/gpu/drm/ingenic/Kconfig +++ b/drivers/gpu/drm/ingenic/Kconfig @@ -7,6 +7,7 @@ config DRM_INGENIC depends on COMMON_CLK select DRM_BRIDGE select DRM_CLIENT_SELECTION + select DRM_PANEL select DRM_PANEL_BRIDGE select DRM_KMS_HELPER select DRM_DISPLAY_HELPER diff --git a/drivers/gpu/drm/logicvc/Kconfig b/drivers/gpu/drm/logicvc/Kconfig index 11aae1626199..95cdc5cb8cd5 100644 --- a/drivers/gpu/drm/logicvc/Kconfig +++ b/drivers/gpu/drm/logicvc/Kconfig @@ -5,6 +5,7 @@ config DRM_LOGICVC select DRM_CLIENT_SELECTION select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER + select DRM_PANEL select REGMAP select REGMAP_MMIO help diff --git a/drivers/gpu/drm/mcde/Kconfig b/drivers/gpu/drm/mcde/Kconfig index 3516c8d2a5d9..6ebfb930cbfa 100644 --- a/drivers/gpu/drm/mcde/Kconfig +++ b/drivers/gpu/drm/mcde/Kconfig @@ -9,6 +9,7 @@ config DRM_MCDE select DRM_CLIENT_SELECTION select DRM_MIPI_DSI select DRM_BRIDGE + select DRM_PANEL select DRM_PANEL_BRIDGE select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER diff --git a/drivers/gpu/drm/pl111/Kconfig b/drivers/gpu/drm/pl111/Kconfig index 82e918820950..20201ec20aa7 100644 --- a/drivers/gpu/drm/pl111/Kconfig +++ b/drivers/gpu/drm/pl111/Kconfig @@ -9,6 +9,7 @@ config DRM_PL111 select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER select DRM_BRIDGE + select DRM_PANEL select DRM_PANEL_BRIDGE help Choose this option for DRM support for the PL111 CLCD controller. diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 4e58685f58ff..754d9b977ff1 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -125,6 +125,7 @@ config ROCKCHIP_LVDS depends on PINCTRL && OF select DRM_DISPLAY_HELPER select DRM_BRIDGE_CONNECTOR + select DRM_PANEL help Choose this option to enable support for Rockchip LVDS controllers. Rockchip rk3288 SoC has LVDS TX Controller can be used, and it @@ -137,6 +138,7 @@ config ROCKCHIP_RGB depends on PINCTRL select DRM_DISPLAY_HELPER select DRM_BRIDGE_CONNECTOR + select DRM_PANEL help Choose this option to enable support for Rockchip RGB output. Some Rockchip CRTCs, like rv1108, can directly output parallel diff --git a/drivers/gpu/drm/stm/Kconfig b/drivers/gpu/drm/stm/Kconfig index 635be0ac00af..1e3205aa2c7e 100644 --- a/drivers/gpu/drm/stm/Kconfig +++ b/drivers/gpu/drm/stm/Kconfig @@ -6,6 +6,7 @@ config DRM_STM select DRM_CLIENT_SELECTION select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER + select DRM_PANEL select DRM_PANEL_BRIDGE select VIDEOMODE_HELPERS select FB_PROVIDE_GET_FB_UNMAPPED_AREA if FB diff --git a/drivers/gpu/drm/tidss/Kconfig b/drivers/gpu/drm/tidss/Kconfig index 31ad582b7602..52a64fa1ad5d 100644 --- a/drivers/gpu/drm/tidss/Kconfig +++ b/drivers/gpu/drm/tidss/Kconfig @@ -7,6 +7,7 @@ config DRM_TIDSS select DRM_DISPLAY_HELPER select DRM_BRIDGE_CONNECTOR select DRM_GEM_DMA_HELPER + select DRM_PANEL help The TI Keystone family SoCs introduced a new generation of Display SubSystem. There is currently three Keystone family diff --git a/drivers/gpu/drm/tve200/Kconfig b/drivers/gpu/drm/tve200/Kconfig index a9d6fe535d88..c0746ae8f703 100644 --- a/drivers/gpu/drm/tve200/Kconfig +++ b/drivers/gpu/drm/tve200/Kconfig @@ -7,6 +7,7 @@ config DRM_TVE200 depends on OF select DRM_BRIDGE select DRM_CLIENT_SELECTION + select DRM_PANEL select DRM_PANEL_BRIDGE select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h index ebebed14c611..402f5db11e47 100644 --- a/include/drm/drm_of.h +++ b/include/drm/drm_of.h @@ -51,10 +51,6 @@ int drm_of_encoder_active_endpoint(struct device_node *node, struct of_endpoint *endpoint); int drm_of_get_panel_orientation(const struct device_node *np, enum drm_panel_orientation *orientation); -int drm_of_find_panel_or_bridge(const struct device_node *np, - int port, int endpoint, - struct drm_panel **panel, - struct drm_bridge **bridge); int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1, const struct device_node *port2); int drm_of_lvds_get_dual_link_pixel_order_sink(struct device_node *port1, @@ -112,14 +108,6 @@ static inline int drm_of_get_panel_orientation(const struct device_node *np, return -EINVAL; } -static inline int drm_of_find_panel_or_bridge(const struct device_node *np, - int port, int endpoint, - struct drm_panel **panel, - struct drm_bridge **bridge) -{ - return -EINVAL; -} - static inline int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1, const struct device_node *port2) diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index b87323443f49..bf15e40fd796 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -33,6 +33,7 @@ struct backlight_device; struct dentry; struct device_node; +struct drm_bridge; struct drm_connector; struct drm_panel_follower; struct drm_panel; @@ -337,11 +338,23 @@ int drm_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); +int drm_of_find_panel_or_bridge(const struct device_node *np, + int port, int endpoint, + struct drm_panel **panel, + struct drm_bridge **bridge); #else static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) { return ERR_PTR(-ENODEV); } + +static inline int drm_of_find_panel_or_bridge(const struct device_node *np, + int port, int endpoint, + struct drm_panel **panel, + struct drm_bridge **bridge) +{ + return -EINVAL; +} #endif #if defined(CONFIG_DRM_PANEL) From 5dcf3fed0c94df57397a3082f0a572075c7121e6 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 16 Sep 2026 15:45:26 +0200 Subject: [PATCH 29/92] drm: of: remove now unnecessary forward declarations These forward declarations are now redundant after having moved drm_of_find_panel_or_bridge(): * struct drm_panel is not referenced in this file * struct drm_bridge is now referenced only inside an #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DRM_PANEL_BRIDGE) block, and in this case struct drm_bridge is already declared thanks to these lines: #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DRM_PANEL_BRIDGE) ... #include #endif Acked-by: Maxime Ripard Link: https://patch.msgid.link/20260916-drm-bridge-every-panel-v3-2-83afb4f1a707@bootlin.com Signed-off-by: Luca Ceresoli --- include/drm/drm_of.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h index 402f5db11e47..f6dad2c6e9b9 100644 --- a/include/drm/drm_of.h +++ b/include/drm/drm_of.h @@ -14,8 +14,6 @@ struct component_match; struct device; struct drm_device; struct drm_encoder; -struct drm_panel; -struct drm_bridge; struct device_node; struct mipi_dsi_device_info; struct mipi_dsi_host; From 667746d16329d2292bc4d36aad703ddd0279526b Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 16 Sep 2026 15:45:27 +0200 Subject: [PATCH 30/92] drm/panel: move to a new module Work is in progress for every drm_panel to embed a drm_bridge, which will make the drm_panel code (currently in the drm module) depend on the drm_kms_helper module. To avoid the main drm module to depend on other drm modules and create a depepdency loop, move drm_panel.o to a new drm_panel module, so the module dependency will be drm_panel -> drm_kms_helper instead. Reviewed-by: Maxime Ripard Link: https://patch.msgid.link/20260916-drm-bridge-every-panel-v3-3-83afb4f1a707@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/panel/Kconfig | 2 +- include/drm/drm_panel.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index f0c340aa2ec6..93bb20a461a2 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -79,7 +79,6 @@ drm-$(CONFIG_DRM_CLIENT) += \ drm_client_modeset.o \ drm_client_sysrq.o drm-$(CONFIG_COMPAT) += drm_ioc32.o -drm-$(CONFIG_DRM_PANEL) += drm_panel.o drm-$(CONFIG_OF) += drm_of.o drm-$(CONFIG_PCI) += drm_pci.o drm-$(CONFIG_DEBUG_FS) += \ @@ -95,6 +94,7 @@ drm-$(CONFIG_DRM_DRAW) += drm_draw.o drm-$(CONFIG_DRM_RAS) += drm_ras.o drm_ras_nl.o drm_ras_genl_family.o obj-$(CONFIG_DRM) += drm.o +obj-$(CONFIG_DRM_PANEL) += drm_panel.o obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o obj-$(CONFIG_DRM_PANEL_BACKLIGHT_QUIRKS) += drm_panel_backlight_quirks.o diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 747f47347521..0a79a0558101 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only config DRM_PANEL - bool + tristate depends on DRM help Panel registration and lookup framework. diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index bf15e40fd796..34fcbcdda2c8 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -336,7 +336,7 @@ void drm_panel_disable(struct drm_panel *panel); int drm_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector); -#if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) +#if defined(CONFIG_OF) && IS_ENABLED(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); int drm_of_find_panel_or_bridge(const struct device_node *np, int port, int endpoint, @@ -357,7 +357,7 @@ static inline int drm_of_find_panel_or_bridge(const struct device_node *np, } #endif -#if defined(CONFIG_DRM_PANEL) +#if IS_ENABLED(CONFIG_DRM_PANEL) bool drm_is_panel_follower(struct device *dev); int drm_panel_add_follower(struct device *follower_dev, struct drm_panel_follower *follower); From aa8a8c7e4641ebcef02dd6fa387ca334857367f4 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 16 Sep 2026 15:45:28 +0200 Subject: [PATCH 31/92] drm/bridge: panel: move all code to drm_panel.c Work is in progress for every drm_panel to embed a drm_bridge, replacing the panel_bridge entirely. However most of the panel_bridge code will be reused for the drm_bridge embedded into the drm_panel, so just move the code there. Adapt users of the moved functions to include drm_panel.h when necessary. No functional changes, just moving code around. Suggested-by: Maxime Ripard Acked-by: Maxime Ripard Link: https://patch.msgid.link/20260916-drm-bridge-every-panel-v3-4-83afb4f1a707@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/Makefile | 1 - drivers/gpu/drm/adp/adp-mipi.c | 1 + .../gpu/drm/arm/display/komeda/komeda_crtc.c | 1 + drivers/gpu/drm/bridge/aux-bridge.c | 1 + .../gpu/drm/bridge/cadence/cdns-dsi-core.c | 1 + drivers/gpu/drm/bridge/imx/imx93-pdfc.c | 1 + drivers/gpu/drm/bridge/panel.c | 563 ----------------- drivers/gpu/drm/bridge/ti-tdp158.c | 1 + .../gpu/drm/display/drm_bridge_connector.c | 1 + drivers/gpu/drm/drm_panel.c | 574 +++++++++++++++++- drivers/gpu/drm/imx/dc/dc-kms.c | 1 + drivers/gpu/drm/mcde/mcde_display.c | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 1 + drivers/gpu/drm/msm/dsi/dsi.c | 3 +- drivers/gpu/drm/tegra/rgb.c | 1 + include/drm/drm_bridge.h | 52 -- include/drm/drm_of.h | 1 + include/drm/drm_panel.h | 53 ++ 18 files changed, 622 insertions(+), 636 deletions(-) delete mode 100644 drivers/gpu/drm/bridge/panel.c diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 93bb20a461a2..cadc8529c995 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -155,7 +155,6 @@ drm_kms_helper-y := \ drm_self_refresh_helper.o \ drm_simple_kms_helper.o \ drm_vblank_helper.o -drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o drm_kms_helper-$(CONFIG_DRM_PANIC_HELPER) += drm_panic_helper.o drm_kms_helper-$(CONFIG_DRM_PANIC_SCREEN_QR_CODE) += drm_panic_helper_qr.o drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o diff --git a/drivers/gpu/drm/adp/adp-mipi.c b/drivers/gpu/drm/adp/adp-mipi.c index 232bb9539423..956533870781 100644 --- a/drivers/gpu/drm/adp/adp-mipi.c +++ b/drivers/gpu/drm/adp/adp-mipi.c @@ -8,6 +8,7 @@ #include #include #include +#include #define DSI_GEN_HDR 0x6c #define DSI_GEN_PLD_DATA 0x70 diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c index 3d81b413efae..0fd069fc3386 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "komeda_dev.h" #include "komeda_kms.h" diff --git a/drivers/gpu/drm/bridge/aux-bridge.c b/drivers/gpu/drm/bridge/aux-bridge.c index 169939d23310..90f76bb529cc 100644 --- a/drivers/gpu/drm/bridge/aux-bridge.c +++ b/drivers/gpu/drm/bridge/aux-bridge.c @@ -12,6 +12,7 @@ #include #include #include +#include static DEFINE_IDA(drm_aux_bridge_ida); diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c index c3e466ded84a..1e28ea579b06 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c @@ -7,6 +7,7 @@ #include #include +#include #include #include