From ef595c04e843592481443b63e7790f44d52a5a19 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 7 Mar 2025 08:24:49 +0200 Subject: [PATCH 01/84] drm/msm/dpu: don't overwrite CTL_MERGE_3D_ACTIVE register In case of complex pipelines (e.g. the forthcoming quad-pipe) the DPU might use more that one MERGE_3D block for a single output. Follow the pattern and extend the CTL_MERGE_3D_ACTIVE active register instead of simply writing new value there. Currently at most one MERGE_3D block is being used, so this has no impact on existing targets. Reviewed-by: Marijn Suijten Tested-by: Neil Armstrong # on SM8550-QRD Signed-off-by: Dmitry Baryshkov Reviewed-by: Jessica Zhang Patchwork: https://patchwork.freedesktop.org/patch/641580/ Link: https://lore.kernel.org/r/20250307-dpu-active-ctl-v3-1-5d20655f10ca@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index 411a7cf088eb..cef3bfaa4af8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -563,6 +563,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, u32 wb_active = 0; u32 cwb_active = 0; u32 mode_sel = 0; + u32 merge_3d_active = 0; /* CTL_TOP[31:28] carries group_id to collate CTL paths * per VM. Explicitly disable it until VM support is @@ -578,6 +579,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE); cwb_active = DPU_REG_READ(c, CTL_CWB_ACTIVE); dsc_active = DPU_REG_READ(c, CTL_DSC_ACTIVE); + merge_3d_active = DPU_REG_READ(c, CTL_MERGE_3D_ACTIVE); if (cfg->intf) intf_active |= BIT(cfg->intf - INTF_0); @@ -591,15 +593,15 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, if (cfg->dsc) dsc_active |= cfg->dsc; + if (cfg->merge_3d) + merge_3d_active |= BIT(cfg->merge_3d - MERGE_3D_0); + DPU_REG_WRITE(c, CTL_TOP, mode_sel); DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active); DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active); DPU_REG_WRITE(c, CTL_CWB_ACTIVE, cwb_active); DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active); - - if (cfg->merge_3d) - DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, - BIT(cfg->merge_3d - MERGE_3D_0)); + DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, merge_3d_active); if (cfg->cdm) DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cfg->cdm); From 6a013b60cf44604f9400be15166d3aba07bd7662 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 7 Mar 2025 08:24:50 +0200 Subject: [PATCH 02/84] drm/msm/dpu: program master INTF value If several interfaces are being handled through a single CTL, a main ('master') INTF needs to be programmed into a separate register. Write corresponding value into that register. Co-developed-by: Marijn Suijten Signed-off-by: Marijn Suijten Reviewed-by: Marijn Suijten Tested-by: Neil Armstrong # on SM8550-QRD Signed-off-by: Dmitry Baryshkov Reviewed-by: Jessica Zhang Patchwork: https://patchwork.freedesktop.org/patch/641581/ Link: https://lore.kernel.org/r/20250307-dpu-active-ctl-v3-2-5d20655f10ca@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 12 ++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index cef3bfaa4af8..21f4d403e3c2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -603,6 +603,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active); DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, merge_3d_active); + if (cfg->intf_master) + DPU_REG_WRITE(c, CTL_INTF_MASTER, BIT(cfg->intf_master - INTF_0)); + if (cfg->cdm) DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cfg->cdm); } @@ -645,6 +648,7 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx, { struct dpu_hw_blk_reg_map *c = &ctx->hw; u32 intf_active = 0; + u32 intf_master = 0; u32 wb_active = 0; u32 cwb_active = 0; u32 merge3d_active = 0; @@ -672,6 +676,14 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx, intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE); intf_active &= ~BIT(cfg->intf - INTF_0); DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active); + + intf_master = DPU_REG_READ(c, CTL_INTF_MASTER); + + /* Unset this intf as master, if it is the current master */ + if (intf_master == BIT(cfg->intf - INTF_0)) { + DPU_DEBUG_DRIVER("Unsetting INTF_%d master\n", cfg->intf - INTF_0); + DPU_REG_WRITE(c, CTL_INTF_MASTER, 0); + } } if (cfg->cwb) { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h index 080a9550a0cc..cea23436fc80 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h @@ -36,6 +36,7 @@ struct dpu_hw_stage_cfg { /** * struct dpu_hw_intf_cfg :Describes how the DPU writes data to output interface * @intf : Interface id + * @intf_master: Master interface id in the dual pipe topology * @mode_3d: 3d mux configuration * @merge_3d: 3d merge block used * @intf_mode_sel: Interface mode, cmd / vid @@ -46,6 +47,7 @@ struct dpu_hw_stage_cfg { */ struct dpu_hw_intf_cfg { enum dpu_intf intf; + enum dpu_intf intf_master; enum dpu_wb wb; enum dpu_3d_blend_mode mode_3d; enum dpu_merge_3d merge_3d; From 696707d3d22c5daf485952d0753b903fe6eb7b77 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 7 Mar 2025 08:24:51 +0200 Subject: [PATCH 03/84] drm/msm/dpu: pass master interface to CTL configuration Active controls require setup of the master interface. Pass the selected interface to CTL configuration. Reviewed-by: Marijn Suijten Tested-by: Neil Armstrong # on SM8550-QRD Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/641583/ Link: https://lore.kernel.org/r/20250307-dpu-active-ctl-v3-3-5d20655f10ca@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 2 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index da9994a79ca2..a0ba55ab3c89 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -60,6 +60,8 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg( return; intf_cfg.intf = phys_enc->hw_intf->idx; + if (phys_enc->split_role == ENC_ROLE_MASTER) + intf_cfg.intf_master = phys_enc->hw_intf->idx; intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD; intf_cfg.stream_sel = cmd_enc->stream_sel; intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index abd6600046cb..232055473ba5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -298,6 +298,8 @@ static void dpu_encoder_phys_vid_setup_timing_engine( if (phys_enc->hw_cdm) intf_cfg.cdm = phys_enc->hw_cdm->idx; intf_cfg.intf = phys_enc->hw_intf->idx; + if (phys_enc->split_role == ENC_ROLE_MASTER) + intf_cfg.intf_master = phys_enc->hw_intf->idx; intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_VID; intf_cfg.stream_sel = 0; /* Don't care value for video mode */ intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); From df99bdfcb2d58045b0ed808a1c174f53676b08a0 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 7 Mar 2025 08:24:52 +0200 Subject: [PATCH 04/84] drm/msm/dpu: use single CTL if it is the only CTL returned by RM On DPU >= 5.0 CTL blocks were reworked in order to support using a single CTL for all outputs. In preparation of reworking the RM code to return single CTL make sure that dpu_encoder can cope with that. Reviewed-by: Marijn Suijten Tested-by: Neil Armstrong # on SM8550-QRD Signed-off-by: Dmitry Baryshkov Reviewed-by: Jessica Zhang Patchwork: https://patchwork.freedesktop.org/patch/641582/ Link: https://lore.kernel.org/r/20250307-dpu-active-ctl-v3-4-5d20655f10ca@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 862e9e6bf0a5..f9c46180b8f7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1246,7 +1246,11 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, return; } - phys->hw_ctl = i < num_ctl ? to_dpu_hw_ctl(hw_ctl[i]) : NULL; + /* Use first (and only) CTL if active CTLs are supported */ + if (num_ctl == 1) + phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[0]); + else + phys->hw_ctl = i < num_ctl ? to_dpu_hw_ctl(hw_ctl[i]) : NULL; if (!phys->hw_ctl) { DPU_ERROR_ENC(dpu_enc, "no ctl block assigned at idx: %d\n", i); From e93eee524bb78f3ee4b78654d0083382f98b3d23 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 7 Mar 2025 08:24:53 +0200 Subject: [PATCH 05/84] drm/msm/dpu: don't select single flush for active CTL blocks In case of ACTIVE CTLs, a single CTL is being used for flushing all INTF blocks. Don't skip programming the CTL on those targets. Tested-by: Neil Armstrong # on SM8550-QRD Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/641585/ Link: https://lore.kernel.org/r/20250307-dpu-active-ctl-v3-5-5d20655f10ca@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index 232055473ba5..8a618841e3ea 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -374,7 +374,8 @@ static void dpu_encoder_phys_vid_underrun_irq(void *arg) static bool dpu_encoder_phys_vid_needs_single_flush( struct dpu_encoder_phys *phys_enc) { - return phys_enc->split_role != ENC_ROLE_SOLO; + return !(phys_enc->hw_ctl->caps->features & BIT(DPU_CTL_ACTIVE_CFG)) && + phys_enc->split_role != ENC_ROLE_SOLO; } static void dpu_encoder_phys_vid_atomic_mode_set( From c1824a7992da788b43b9f91d816059f626882a10 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 7 Mar 2025 08:24:54 +0200 Subject: [PATCH 06/84] drm/msm/dpu: allocate single CTL for DPU >= 5.0 Unlike previous generation, since DPU 5.0 it is possible to use just one CTL to handle all INTF and WB blocks for a single output. And one has to use single CTL to support bonded DSI config. Allocate single CTL for these DPU versions. Reviewed-by: Marijn Suijten Tested-by: Neil Armstrong # on SM8550-QRD Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/641587/ Link: https://lore.kernel.org/r/20250307-dpu-active-ctl-v3-6-5d20655f10ca@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 28 ++++++++++++++------------ drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 ++ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index 3efbba425ca6..c72b968d58a6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -53,6 +53,8 @@ int dpu_rm_init(struct drm_device *dev, /* Clear, setup lists */ memset(rm, 0, sizeof(*rm)); + rm->has_legacy_ctls = (cat->mdss_ver->core_major_ver < 5); + /* Interrogate HW catalog and create tracking items for hw blocks */ for (i = 0; i < cat->mixer_count; i++) { struct dpu_hw_mixer *hw; @@ -434,20 +436,19 @@ static int _dpu_rm_reserve_ctls( int i = 0, j, num_ctls; bool needs_split_display; - /* - * For non-CWB mode, each hw_intf needs its own hw_ctl to program its - * control path. - * - * Hardcode num_ctls to 1 if CWB is enabled because in CWB, both the - * writeback and real-time encoders must be driven by the same control - * path - */ - if (top->cwb_enabled) - num_ctls = 1; - else + if (rm->has_legacy_ctls) { + /* + * TODO: check if there is a need for special handling if + * DPU < 5.0 get CWB support. + */ num_ctls = top->num_intf; - needs_split_display = _dpu_rm_needs_split_display(top); + needs_split_display = _dpu_rm_needs_split_display(top); + } else { + /* use single CTL */ + num_ctls = 1; + needs_split_display = false; + } for (j = 0; j < ARRAY_SIZE(rm->ctl_blks); j++) { const struct dpu_hw_ctl *ctl; @@ -465,7 +466,8 @@ static int _dpu_rm_reserve_ctls( DPU_DEBUG("ctl %d caps 0x%lX\n", j + CTL_0, features); - if (needs_split_display != has_split_display) + if (rm->has_legacy_ctls && + needs_split_display != has_split_display) continue; ctl_idx[i] = j; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h index a19dbdb1b6f4..aa62966056d4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h @@ -24,6 +24,7 @@ struct dpu_global_state; * @dspp_blks: array of dspp hardware resources * @hw_sspp: array of sspp hardware resources * @cdm_blk: cdm hardware resource + * @has_legacy_ctls: DPU uses pre-ACTIVE CTL blocks. */ struct dpu_rm { struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0]; @@ -37,6 +38,7 @@ struct dpu_rm { struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0]; struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE]; struct dpu_hw_blk *cdm_blk; + bool has_legacy_ctls; }; struct dpu_rm_sspp_requirements { From a2649952f66ebf41dc188de9a2c2e6d47a8b9cc4 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 7 Mar 2025 08:24:55 +0200 Subject: [PATCH 07/84] drm/msm/dpu: remove DPU_CTL_SPLIT_DISPLAY from CTL blocks on DPU >= 5.0 Since DPU 5.0 CTL blocks do not require DPU_CTL_SPLIT_DISPLAY, as single CTL is used for both interfaces. As both RM and encoder now handle active CTLs, drop that feature bit. Reviewed-by: Marijn Suijten Tested-by: Neil Armstrong # on SM8550-QRD Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/641592/ Link: https://lore.kernel.org/r/20250307-dpu-active-ctl-v3-7-5d20655f10ca@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h | 5 ++--- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h | 5 ++--- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h | 4 ++-- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h | 4 ++-- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h | 5 ++--- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h | 5 ++--- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h | 5 ++--- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h | 5 ++--- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h | 5 ++--- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h | 5 ++--- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h | 5 ++--- 11 files changed, 22 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h index 6ac97c378056..ffc4d4257ae5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h @@ -27,17 +27,16 @@ static const struct dpu_mdp_cfg sm8650_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sm8650_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x1000, - .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x1000, - .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h index 979527d98fbc..c20a26fb39ef 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h @@ -37,17 +37,16 @@ static const struct dpu_mdp_cfg sm8150_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sm8150_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x1000, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x1200, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h index d76b8992a6c1..5300c246b67b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h @@ -41,12 +41,12 @@ static const struct dpu_ctl_cfg sc8180x_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x1000, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x1200, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h index 83db11339b29..614ea64fca8c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h @@ -38,12 +38,12 @@ static const struct dpu_ctl_cfg sm7150_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x1000, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x1200, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h index 47e01c3c242f..a86fdb33ebdd 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h @@ -35,17 +35,16 @@ static const struct dpu_mdp_cfg sm8250_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sm8250_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x1000, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x1200, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h index 0c860e804cab..90e86063a372 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h @@ -35,17 +35,16 @@ static const struct dpu_mdp_cfg sm8350_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sm8350_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x1e8, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, + .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x1e8, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, + .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h index fcee1c3665f8..426a8d76c707 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h @@ -35,17 +35,16 @@ static const struct dpu_mdp_cfg sc8280xp_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sc8280xp_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x204, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, + .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x204, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, + .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h index 19b2ee8bbd5f..461294143a90 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h @@ -36,17 +36,16 @@ static const struct dpu_mdp_cfg sm8450_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sm8450_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x204, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, + .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x204, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, + .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h index 4d96ce71746f..c248b3b55c41 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h @@ -35,17 +35,16 @@ static const struct dpu_mdp_cfg sa8775p_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sa8775p_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x204, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, + .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x204, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, + .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h index 24f988465bf6..b1c1707571cf 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h @@ -27,17 +27,16 @@ static const struct dpu_mdp_cfg sm8550_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sm8550_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x290, - .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x290, - .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h index 6417baa84f82..52cc10aec1f9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h @@ -26,17 +26,16 @@ static const struct dpu_mdp_cfg x1e80100_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg x1e80100_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x290, - .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x290, - .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, From 1fb28a8a984e9189f64f617f364b058605616009 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 7 Mar 2025 08:24:56 +0200 Subject: [PATCH 08/84] drm/msm/dpu: drop now-unused condition for has_legacy_ctls Now as we have dropped the DPU_CTL_SPLIT_DISPLAY from DPU >= 5.0 configuration, drop the rm->has_legacy_ctl condition which short-cutted the check for those platforms. Suggested-by: Marijn Suijten Reviewed-by: Marijn Suijten Tested-by: Neil Armstrong # on SM8550-QRD Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/641586/ Link: https://lore.kernel.org/r/20250307-dpu-active-ctl-v3-8-5d20655f10ca@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index c72b968d58a6..2e296f79cba1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -466,8 +466,7 @@ static int _dpu_rm_reserve_ctls( DPU_DEBUG("ctl %d caps 0x%lX\n", j + CTL_0, features); - if (rm->has_legacy_ctls && - needs_split_display != has_split_display) + if (needs_split_display != has_split_display) continue; ctl_idx[i] = j; From 5db5401c24553d17a087ff5a90789226e4192144 Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Thu, 10 Apr 2025 10:52:21 +0800 Subject: [PATCH 09/84] drm/msm: Convert comma to semicolon Replace comma between expressions with semicolons. Using a ',' in place of a ';' can have unintended side effects. Although that is not the case here, it is seems best to use ';' unless ',' is intended. Found by inspection. No functional change intended. Compile tested only. Signed-off-by: Chen Ni Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/647875/ Link: https://lore.kernel.org/r/20250410025221.3358387-1-nichen@iscas.ac.cn Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/msm_ringbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index c5651c39ac2a..89dce15eed3b 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c @@ -93,7 +93,7 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, } msm_gem_object_set_name(ring->bo, "ring%d", id); - args.name = to_msm_bo(ring->bo)->name, + args.name = to_msm_bo(ring->bo)->name; ring->end = ring->start + (MSM_GPU_RINGBUFFER_SZ >> 2); ring->next = ring->start; From 6694d17843e82c30287418ea8c244038e336754d Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Sun, 20 Apr 2025 17:12:43 +0200 Subject: [PATCH 10/84] dt-bindings: msm: qcom,mdss: Document interconnect paths Document two interconnect paths found on the MDSS on MSM8953. Acked-by: Rob Herring (Arm) Signed-off-by: Luca Weiss Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/649391/ Link: https://lore.kernel.org/r/20250420-msm8953-interconnect-v2-1-828715dcb674@lucaweiss.eu Signed-off-by: Dmitry Baryshkov --- .../devicetree/bindings/display/msm/qcom,mdss.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml index 7c6462caa442..db9c43b20e2a 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml @@ -84,6 +84,18 @@ properties: items: - description: MDSS_CORE reset + interconnects: + minItems: 1 + items: + - description: Interconnect path from mdp0 (or a single mdp) port to the data bus + - description: Interconnect path from CPU to the reg bus + + interconnect-names: + minItems: 1 + items: + - const: mdp0-mem + - const: cpu-cfg + required: - compatible - reg From 2f1d131147aadf41d376dbd01d0d83eca8054deb Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 25 Apr 2025 12:51:51 +0300 Subject: [PATCH 11/84] dt-bindings: display: msm: mdp4: add LCDC clock and PLL source Add the LCDC / LVDS clock input and the XO used to drive internal LVDS PLL to MDP4 controller bindings. The controller also provides LVDS PHY PLL, so add optional #clock-cells to the device. Acked-by: Rob Herring (Arm) Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/650278/ Link: https://lore.kernel.org/r/20250425-fd-mdp4-lvds-v4-1-6b212160b44c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- Documentation/devicetree/bindings/display/msm/mdp4.yaml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/msm/mdp4.yaml b/Documentation/devicetree/bindings/display/msm/mdp4.yaml index 35204a287579..03ee09faa335 100644 --- a/Documentation/devicetree/bindings/display/msm/mdp4.yaml +++ b/Documentation/devicetree/bindings/display/msm/mdp4.yaml @@ -18,9 +18,10 @@ properties: clocks: minItems: 6 - maxItems: 6 + maxItems: 8 clock-names: + minItems: 6 items: - const: core_clk - const: iface_clk @@ -28,6 +29,12 @@ properties: - const: lut_clk - const: hdmi_clk - const: tv_clk + - const: lcdc_clk + - const: pxo + description: XO used to drive the internal LVDS PLL + + '#clock-cells': + const: 0 reg: maxItems: 1 From f6720d64d8eb859bb7c3c2bab85896c53fcccf21 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 25 Apr 2025 12:51:52 +0300 Subject: [PATCH 12/84] drm/msm/mdp4: drop mpd4_lvds_pll_init stub Drop the !COMMON_CLK stub for mpd4_lvds_pll_init(), the DRM_MSM driver depends on COMMON_CLK. Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/650281/ Link: https://lore.kernel.org/r/20250425-fd-mdp4-lvds-v4-2-6b212160b44c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h index 94b1ba92785f..142ccb68b435 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h @@ -207,13 +207,6 @@ static inline struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev) } #endif -#ifdef CONFIG_COMMON_CLK struct clk *mpd4_lvds_pll_init(struct drm_device *dev); -#else -static inline struct clk *mpd4_lvds_pll_init(struct drm_device *dev) -{ - return ERR_PTR(-ENODEV); -} -#endif #endif /* __MDP4_KMS_H__ */ From 9c2f63da6a70d38c32fd1ea3126be0c2989a6d1d Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 25 Apr 2025 12:51:53 +0300 Subject: [PATCH 13/84] drm/msm/mdp4: register the LVDS PLL as a clock provider The LVDS/LCDC controller uses pixel clock coming from the multimedia controller (mmcc) rather than using the PLL directly. Stop using LVDS PLL directly and register it as a clock provider. Use lcdc_clk as a pixel clock for the LCDC. Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/650280/ Link: https://lore.kernel.org/r/20250425-fd-mdp4-lvds-v4-3-6b212160b44c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h | 2 +- .../gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c | 3 +- drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_pll.c | 45 +++++++++++++------ 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h index 142ccb68b435..3d7ffd874e0d 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h @@ -207,6 +207,6 @@ static inline struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev) } #endif -struct clk *mpd4_lvds_pll_init(struct drm_device *dev); +struct clk *mpd4_get_lcdc_clock(struct drm_device *dev); #endif /* __MDP4_KMS_H__ */ diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c index 8bbc7fb881d5..8694e5d7d3f0 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c @@ -380,8 +380,7 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, drm_encoder_helper_add(encoder, &mdp4_lcdc_encoder_helper_funcs); - /* TODO: do we need different pll in other cases? */ - mdp4_lcdc_encoder->lcdc_clk = mpd4_lvds_pll_init(dev); + mdp4_lcdc_encoder->lcdc_clk = mpd4_get_lcdc_clock(dev); if (IS_ERR(mdp4_lcdc_encoder->lcdc_clk)) { DRM_DEV_ERROR(dev->dev, "failed to get lvds_clk\n"); return ERR_CAST(mdp4_lcdc_encoder->lcdc_clk); diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_pll.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_pll.c index ab8c0c187fb2..df2bbd475cc2 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_pll.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_pll.c @@ -133,29 +133,48 @@ static struct clk_init_data pll_init = { .num_parents = ARRAY_SIZE(mpd4_lvds_pll_parents), }; -struct clk *mpd4_lvds_pll_init(struct drm_device *dev) +static struct clk_hw *mpd4_lvds_pll_init(struct drm_device *dev) { struct mdp4_lvds_pll *lvds_pll; - struct clk *clk; int ret; lvds_pll = devm_kzalloc(dev->dev, sizeof(*lvds_pll), GFP_KERNEL); - if (!lvds_pll) { - ret = -ENOMEM; - goto fail; - } + if (!lvds_pll) + return ERR_PTR(-ENOMEM); lvds_pll->dev = dev; lvds_pll->pll_hw.init = &pll_init; - clk = devm_clk_register(dev->dev, &lvds_pll->pll_hw); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - goto fail; + ret = devm_clk_hw_register(dev->dev, &lvds_pll->pll_hw); + if (ret) + return ERR_PTR(ret); + + ret = devm_of_clk_add_hw_provider(dev->dev, of_clk_hw_simple_get, &lvds_pll->pll_hw); + if (ret) + return ERR_PTR(ret); + + return &lvds_pll->pll_hw; +} + +struct clk *mpd4_get_lcdc_clock(struct drm_device *dev) +{ + struct clk_hw *hw; + struct clk *clk; + + + /* TODO: do we need different pll in other cases? */ + hw = mpd4_lvds_pll_init(dev); + if (IS_ERR(hw)) { + DRM_DEV_ERROR(dev->dev, "failed to register LVDS PLL\n"); + return ERR_CAST(hw); + } + + clk = devm_clk_get(dev->dev, "lcdc_clk"); + if (clk == ERR_PTR(-ENOENT)) { + drm_warn(dev, "can't get LCDC clock, using PLL directly\n"); + + return devm_clk_hw_get_clk(dev->dev, hw, "lcdc_clk"); } return clk; - -fail: - return ERR_PTR(ret); } From b641bf534cf445d869edf1a3f334a9b4214bc214 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 25 Apr 2025 12:51:54 +0300 Subject: [PATCH 14/84] drm/msm/mdp4: use parent_data for LVDS PLL Instead of using .parent_names, use .parent_data, which binds parent clocks by using relative names specified in DT in addition to using global system clock names. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Reviewed-by: Konrad Dybcio Patchwork: https://patchwork.freedesktop.org/patch/650284/ Link: https://lore.kernel.org/r/20250425-fd-mdp4-lvds-v4-4-6b212160b44c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_pll.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_pll.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_pll.c index df2bbd475cc2..fa2c29470510 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_pll.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_pll.c @@ -122,14 +122,14 @@ static const struct clk_ops mpd4_lvds_pll_ops = { .set_rate = mpd4_lvds_pll_set_rate, }; -static const char *mpd4_lvds_pll_parents[] = { - "pxo", +static const struct clk_parent_data mpd4_lvds_pll_parents[] = { + { .fw_name = "pxo", .name = "pxo", }, }; static struct clk_init_data pll_init = { .name = "mpd4_lvds_pll", .ops = &mpd4_lvds_pll_ops, - .parent_names = mpd4_lvds_pll_parents, + .parent_data = mpd4_lvds_pll_parents, .num_parents = ARRAY_SIZE(mpd4_lvds_pll_parents), }; From f26b80359bc71127c7f572ce0e83e222122c31a3 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 25 Apr 2025 12:51:55 +0300 Subject: [PATCH 15/84] drm/msm/mdp4: move move_valid callback to lcdc_encoder We can check the LCDC clock directly from the LCDC encoder driver, so remove it from the LVDS connector. Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/650285/ Link: https://lore.kernel.org/r/20250425-fd-mdp4-lvds-v4-5-6b212160b44c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h | 1 - .../gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c | 27 ++++++++++++++----- .../drm/msm/disp/mdp4/mdp4_lvds_connector.c | 21 --------------- 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h index 3d7ffd874e0d..66f5009fdf8a 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h @@ -191,7 +191,6 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate); struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev); -long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate); struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, struct device_node *panel_node); diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c index 8694e5d7d3f0..7f4e8005bc4a 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c @@ -348,19 +348,32 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) mdp4_lcdc_encoder->enabled = true; } +static enum drm_mode_status +mdp4_lcdc_encoder_mode_valid(struct drm_encoder *encoder, + const struct drm_display_mode *mode) +{ + struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = + to_mdp4_lcdc_encoder(encoder); + long actual, requested; + + requested = 1000 * mode->clock; + actual = clk_round_rate(mdp4_lcdc_encoder->lcdc_clk, requested); + + DBG("requested=%ld, actual=%ld", requested, actual); + + if (actual != requested) + return MODE_CLOCK_RANGE; + + return MODE_OK; +} + static const struct drm_encoder_helper_funcs mdp4_lcdc_encoder_helper_funcs = { .mode_set = mdp4_lcdc_encoder_mode_set, .disable = mdp4_lcdc_encoder_disable, .enable = mdp4_lcdc_encoder_enable, + .mode_valid = mdp4_lcdc_encoder_mode_valid, }; -long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate) -{ - struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = - to_mdp4_lcdc_encoder(encoder); - return clk_round_rate(mdp4_lcdc_encoder->lcdc_clk, rate); -} - /* initialize encoder */ struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, struct device_node *panel_node) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c index 52e728181b52..4755eb13ef79 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c @@ -56,26 +56,6 @@ static int mdp4_lvds_connector_get_modes(struct drm_connector *connector) return ret; } -static enum drm_mode_status -mdp4_lvds_connector_mode_valid(struct drm_connector *connector, - const struct drm_display_mode *mode) -{ - struct mdp4_lvds_connector *mdp4_lvds_connector = - to_mdp4_lvds_connector(connector); - struct drm_encoder *encoder = mdp4_lvds_connector->encoder; - long actual, requested; - - requested = 1000 * mode->clock; - actual = mdp4_lcdc_round_pixclk(encoder, requested); - - DBG("requested=%ld, actual=%ld", requested, actual); - - if (actual != requested) - return MODE_CLOCK_RANGE; - - return MODE_OK; -} - static const struct drm_connector_funcs mdp4_lvds_connector_funcs = { .detect = mdp4_lvds_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, @@ -87,7 +67,6 @@ static const struct drm_connector_funcs mdp4_lvds_connector_funcs = { static const struct drm_connector_helper_funcs mdp4_lvds_connector_helper_funcs = { .get_modes = mdp4_lvds_connector_get_modes, - .mode_valid = mdp4_lvds_connector_mode_valid, }; /* initialize connector */ From 9b565edc44b65adc51df6dcaf1b2bc00fac53110 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 25 Apr 2025 12:51:56 +0300 Subject: [PATCH 16/84] drm/msm/mdp4: switch LVDS to use drm_bridge/_connector LVDS support in MDP4 driver makes use of drm_connector directly. However LCDC encoder and LVDS connector are wrappers around drm_panel. Switch them to use drm_panel_bridge/drm_bridge_connector. This allows using standard interface for the drm_panel and also inserting additional bridges between encoder and panel. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/650290/ Link: https://lore.kernel.org/r/20250425-fd-mdp4-lvds-v4-6-6b212160b44c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/Makefile | 1 - drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 34 ++++-- drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h | 6 +- .../gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c | 20 +--- .../drm/msm/disp/mdp4/mdp4_lvds_connector.c | 100 ------------------ 5 files changed, 28 insertions(+), 133 deletions(-) delete mode 100644 drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 5df20cbeafb8..7a2ada6e2d74 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -48,7 +48,6 @@ msm-display-$(CONFIG_DRM_MSM_MDP4) += \ disp/mdp4/mdp4_dsi_encoder.o \ disp/mdp4/mdp4_dtv_encoder.o \ disp/mdp4/mdp4_lcdc_encoder.o \ - disp/mdp4/mdp4_lvds_connector.o \ disp/mdp4/mdp4_lvds_pll.o \ disp/mdp4/mdp4_irq.o \ disp/mdp4/mdp4_kms.o \ diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c index c469e66cfc11..7e942c1337b3 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c @@ -6,6 +6,8 @@ #include +#include +#include #include #include "msm_drv.h" @@ -189,7 +191,7 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, struct msm_drm_private *priv = dev->dev_private; struct drm_encoder *encoder; struct drm_connector *connector; - struct device_node *panel_node; + struct drm_bridge *next_bridge; int dsi_id; int ret; @@ -199,27 +201,43 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, * bail out early if there is no panel node (no need to * initialize LCDC encoder and LVDS connector) */ - panel_node = of_graph_get_remote_node(dev->dev->of_node, 0, 0); - if (!panel_node) - return 0; + next_bridge = devm_drm_of_get_bridge(dev->dev, dev->dev->of_node, 0, 0); + if (IS_ERR(next_bridge)) { + ret = PTR_ERR(next_bridge); + if (ret == -ENODEV) + return 0; + return ret; + } - encoder = mdp4_lcdc_encoder_init(dev, panel_node); + encoder = mdp4_lcdc_encoder_init(dev); if (IS_ERR(encoder)) { DRM_DEV_ERROR(dev->dev, "failed to construct LCDC encoder\n"); - of_node_put(panel_node); return PTR_ERR(encoder); } /* LCDC can be hooked to DMA_P (TODO: Add DMA_S later?) */ encoder->possible_crtcs = 1 << DMA_P; - connector = mdp4_lvds_connector_init(dev, panel_node, encoder); + ret = drm_bridge_attach(encoder, next_bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); + if (ret) { + DRM_DEV_ERROR(dev->dev, "failed to attach LVDS panel/bridge: %d\n", ret); + + return ret; + } + + connector = drm_bridge_connector_init(dev, encoder); if (IS_ERR(connector)) { DRM_DEV_ERROR(dev->dev, "failed to initialize LVDS connector\n"); - of_node_put(panel_node); return PTR_ERR(connector); } + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) { + DRM_DEV_ERROR(dev->dev, "failed to attach LVDS connector: %d\n", ret); + + return ret; + } + break; case DRM_MODE_ENCODER_TMDS: encoder = mdp4_dtv_encoder_init(dev); diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h index 66f5009fdf8a..f9d988076337 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h @@ -191,11 +191,7 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate); struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev); -struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, - struct device_node *panel_node); - -struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev, - struct device_node *panel_node, struct drm_encoder *encoder); +struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev); #ifdef CONFIG_DRM_MSM_DSI struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev); diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c index 7f4e8005bc4a..06a307c1272d 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c @@ -14,7 +14,6 @@ struct mdp4_lcdc_encoder { struct drm_encoder base; - struct device_node *panel_node; struct drm_panel *panel; struct clk *lcdc_clk; unsigned long int pixclock; @@ -262,19 +261,12 @@ static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder) struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); struct mdp4_kms *mdp4_kms = get_kms(encoder); - struct drm_panel *panel; if (WARN_ON(!mdp4_lcdc_encoder->enabled)) return; mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0); - panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node); - if (!IS_ERR(panel)) { - drm_panel_disable(panel); - drm_panel_unprepare(panel); - } - /* * Wait for a vsync so we know the ENABLE=0 latched before * the (connector) source of the vsync's gets disabled, @@ -300,7 +292,6 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) to_mdp4_lcdc_encoder(encoder); unsigned long pc = mdp4_lcdc_encoder->pixclock; struct mdp4_kms *mdp4_kms = get_kms(encoder); - struct drm_panel *panel; uint32_t config; int ret; @@ -335,12 +326,6 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) if (ret) DRM_DEV_ERROR(dev->dev, "failed to enable lcdc_clk: %d\n", ret); - panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node); - if (!IS_ERR(panel)) { - drm_panel_prepare(panel); - drm_panel_enable(panel); - } - setup_phy(encoder); mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1); @@ -375,8 +360,7 @@ static const struct drm_encoder_helper_funcs mdp4_lcdc_encoder_helper_funcs = { }; /* initialize encoder */ -struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, - struct device_node *panel_node) +struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev) { struct drm_encoder *encoder; struct mdp4_lcdc_encoder *mdp4_lcdc_encoder; @@ -387,8 +371,6 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, if (IS_ERR(mdp4_lcdc_encoder)) return ERR_CAST(mdp4_lcdc_encoder); - mdp4_lcdc_encoder->panel_node = panel_node; - encoder = &mdp4_lcdc_encoder->base; drm_encoder_helper_add(encoder, &mdp4_lcdc_encoder_helper_funcs); diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c deleted file mode 100644 index 4755eb13ef79..000000000000 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2014 Red Hat - * Author: Rob Clark - * Author: Vinay Simha - */ - -#include "mdp4_kms.h" - -struct mdp4_lvds_connector { - struct drm_connector base; - struct drm_encoder *encoder; - struct device_node *panel_node; - struct drm_panel *panel; -}; -#define to_mdp4_lvds_connector(x) container_of(x, struct mdp4_lvds_connector, base) - -static enum drm_connector_status mdp4_lvds_connector_detect( - struct drm_connector *connector, bool force) -{ - struct mdp4_lvds_connector *mdp4_lvds_connector = - to_mdp4_lvds_connector(connector); - - if (!mdp4_lvds_connector->panel) { - mdp4_lvds_connector->panel = - of_drm_find_panel(mdp4_lvds_connector->panel_node); - if (IS_ERR(mdp4_lvds_connector->panel)) - mdp4_lvds_connector->panel = NULL; - } - - return mdp4_lvds_connector->panel ? - connector_status_connected : - connector_status_disconnected; -} - -static void mdp4_lvds_connector_destroy(struct drm_connector *connector) -{ - struct mdp4_lvds_connector *mdp4_lvds_connector = - to_mdp4_lvds_connector(connector); - - drm_connector_cleanup(connector); - - kfree(mdp4_lvds_connector); -} - -static int mdp4_lvds_connector_get_modes(struct drm_connector *connector) -{ - struct mdp4_lvds_connector *mdp4_lvds_connector = - to_mdp4_lvds_connector(connector); - struct drm_panel *panel = mdp4_lvds_connector->panel; - int ret = 0; - - if (panel) - ret = drm_panel_get_modes(panel, connector); - - return ret; -} - -static const struct drm_connector_funcs mdp4_lvds_connector_funcs = { - .detect = mdp4_lvds_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = mdp4_lvds_connector_destroy, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -static const struct drm_connector_helper_funcs mdp4_lvds_connector_helper_funcs = { - .get_modes = mdp4_lvds_connector_get_modes, -}; - -/* initialize connector */ -struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev, - struct device_node *panel_node, struct drm_encoder *encoder) -{ - struct drm_connector *connector = NULL; - struct mdp4_lvds_connector *mdp4_lvds_connector; - - mdp4_lvds_connector = kzalloc(sizeof(*mdp4_lvds_connector), GFP_KERNEL); - if (!mdp4_lvds_connector) - return ERR_PTR(-ENOMEM); - - mdp4_lvds_connector->encoder = encoder; - mdp4_lvds_connector->panel_node = panel_node; - - connector = &mdp4_lvds_connector->base; - - drm_connector_init(dev, connector, &mdp4_lvds_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); - drm_connector_helper_add(connector, &mdp4_lvds_connector_helper_funcs); - - connector->polled = 0; - - connector->interlace_allowed = 0; - connector->doublescan_allowed = 0; - - drm_connector_attach_encoder(connector, encoder); - - return connector; -} From 3ed12a3664b362e3462cca61d41f9a9460c9e260 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 26 Apr 2025 07:51:17 +0300 Subject: [PATCH 17/84] drm/msm/dpu: allow sharing SSPP between planes Since SmartDMA planes provide two rectangles, it is possible to use them to drive two different DRM planes, first plane getting the rect_0, another one using rect_1 of the same SSPP. The sharing algorithm is pretty simple, it requires that each of the planes can be driven by the single rectangle and only consecutive planes are considered. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/650441/ Link: https://lore.kernel.org/r/20250426-dpu-share-sspp-v7-1-6f4c719e373c@oss.qualcomm.com Reviewed-by: Konrad Dybcio --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 156 ++++++++++++++++++---- 1 file changed, 130 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index e03d6091f736..421138bc3cb7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -915,10 +915,9 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane, return 0; } -static int dpu_plane_is_multirect_parallel_capable(struct dpu_hw_sspp *sspp, - struct dpu_sw_pipe_cfg *pipe_cfg, - const struct msm_format *fmt, - uint32_t max_linewidth) +static int dpu_plane_is_multirect_capable(struct dpu_hw_sspp *sspp, + struct dpu_sw_pipe_cfg *pipe_cfg, + const struct msm_format *fmt) { if (drm_rect_width(&pipe_cfg->src_rect) != drm_rect_width(&pipe_cfg->dst_rect) || drm_rect_height(&pipe_cfg->src_rect) != drm_rect_height(&pipe_cfg->dst_rect)) @@ -930,10 +929,6 @@ static int dpu_plane_is_multirect_parallel_capable(struct dpu_hw_sspp *sspp, if (MSM_FORMAT_IS_YUV(fmt)) return false; - if (MSM_FORMAT_IS_UBWC(fmt) && - drm_rect_width(&pipe_cfg->src_rect) > max_linewidth / 2) - return false; - if (!test_bit(DPU_SSPP_SMART_DMA_V1, &sspp->cap->features) && !test_bit(DPU_SSPP_SMART_DMA_V2, &sspp->cap->features)) return false; @@ -941,6 +936,27 @@ static int dpu_plane_is_multirect_parallel_capable(struct dpu_hw_sspp *sspp, return true; } +static int dpu_plane_is_parallel_capable(struct dpu_sw_pipe_cfg *pipe_cfg, + const struct msm_format *fmt, + uint32_t max_linewidth) +{ + if (MSM_FORMAT_IS_UBWC(fmt) && + drm_rect_width(&pipe_cfg->src_rect) > max_linewidth / 2) + return false; + + return true; +} + +static int dpu_plane_is_multirect_parallel_capable(struct dpu_hw_sspp *sspp, + struct dpu_sw_pipe_cfg *pipe_cfg, + const struct msm_format *fmt, + uint32_t max_linewidth) +{ + return dpu_plane_is_multirect_capable(sspp, pipe_cfg, fmt) && + dpu_plane_is_parallel_capable(pipe_cfg, fmt, max_linewidth); +} + + static int dpu_plane_atomic_check_sspp(struct drm_plane *plane, struct drm_atomic_state *state, const struct drm_crtc_state *crtc_state) @@ -1002,6 +1018,69 @@ static bool dpu_plane_try_multirect_parallel(struct dpu_sw_pipe *pipe, struct dp return true; } +static int dpu_plane_try_multirect_shared(struct dpu_plane_state *pstate, + struct dpu_plane_state *prev_adjacent_pstate, + const struct msm_format *fmt, + uint32_t max_linewidth) +{ + struct dpu_sw_pipe *pipe = &pstate->pipe; + struct dpu_sw_pipe *r_pipe = &pstate->r_pipe; + struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg; + struct dpu_sw_pipe *prev_pipe = &prev_adjacent_pstate->pipe; + struct dpu_sw_pipe_cfg *prev_pipe_cfg = &prev_adjacent_pstate->pipe_cfg; + const struct msm_format *prev_fmt = msm_framebuffer_format(prev_adjacent_pstate->base.fb); + u16 max_tile_height = 1; + + if (prev_adjacent_pstate->r_pipe.sspp != NULL || + prev_pipe->multirect_mode != DPU_SSPP_MULTIRECT_NONE) + return false; + + if (!dpu_plane_is_multirect_capable(pipe->sspp, pipe_cfg, fmt) || + !dpu_plane_is_multirect_capable(prev_pipe->sspp, prev_pipe_cfg, prev_fmt)) + return false; + + if (MSM_FORMAT_IS_UBWC(fmt)) + max_tile_height = max(max_tile_height, fmt->tile_height); + + if (MSM_FORMAT_IS_UBWC(prev_fmt)) + max_tile_height = max(max_tile_height, prev_fmt->tile_height); + + r_pipe->multirect_index = DPU_SSPP_RECT_SOLO; + r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; + + r_pipe->sspp = NULL; + + if (dpu_plane_is_parallel_capable(pipe_cfg, fmt, max_linewidth) && + dpu_plane_is_parallel_capable(prev_pipe_cfg, prev_fmt, max_linewidth) && + (pipe_cfg->dst_rect.x1 >= prev_pipe_cfg->dst_rect.x2 || + prev_pipe_cfg->dst_rect.x1 >= pipe_cfg->dst_rect.x2)) { + pipe->sspp = prev_pipe->sspp; + + pipe->multirect_index = DPU_SSPP_RECT_1; + pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL; + + prev_pipe->multirect_index = DPU_SSPP_RECT_0; + prev_pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL; + + return true; + } + + if (pipe_cfg->dst_rect.y1 >= prev_pipe_cfg->dst_rect.y2 + 2 * max_tile_height || + prev_pipe_cfg->dst_rect.y1 >= pipe_cfg->dst_rect.y2 + 2 * max_tile_height) { + pipe->sspp = prev_pipe->sspp; + + pipe->multirect_index = DPU_SSPP_RECT_1; + pipe->multirect_mode = DPU_SSPP_MULTIRECT_TIME_MX; + + prev_pipe->multirect_index = DPU_SSPP_RECT_0; + prev_pipe->multirect_mode = DPU_SSPP_MULTIRECT_TIME_MX; + + return true; + } + + return false; +} + static int dpu_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state) { @@ -1102,13 +1181,14 @@ static int dpu_plane_virtual_atomic_check(struct drm_plane *plane, static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc, struct dpu_global_state *global_state, struct drm_atomic_state *state, - struct drm_plane_state *plane_state) + struct drm_plane_state *plane_state, + struct drm_plane_state *prev_adjacent_plane_state) { const struct drm_crtc_state *crtc_state = NULL; struct drm_plane *plane = plane_state->plane; struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); struct dpu_rm_sspp_requirements reqs; - struct dpu_plane_state *pstate; + struct dpu_plane_state *pstate, *prev_adjacent_pstate; struct dpu_sw_pipe *pipe; struct dpu_sw_pipe *r_pipe; struct dpu_sw_pipe_cfg *pipe_cfg; @@ -1120,6 +1200,8 @@ static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc, plane_state->crtc); pstate = to_dpu_plane_state(plane_state); + prev_adjacent_pstate = prev_adjacent_plane_state ? + to_dpu_plane_state(prev_adjacent_plane_state) : NULL; pipe = &pstate->pipe; r_pipe = &pstate->r_pipe; pipe_cfg = &pstate->pipe_cfg; @@ -1138,24 +1220,42 @@ static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc, reqs.rot90 = drm_rotation_90_or_270(plane_state->rotation); - pipe->sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, &reqs); - if (!pipe->sspp) - return -ENODEV; + if (drm_rect_width(&r_pipe_cfg->src_rect) == 0) { + if (!prev_adjacent_pstate || + !dpu_plane_try_multirect_shared(pstate, prev_adjacent_pstate, fmt, + dpu_kms->catalog->caps->max_linewidth)) { + pipe->sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, &reqs); + if (!pipe->sspp) + return -ENODEV; - if (!dpu_plane_try_multirect_parallel(pipe, pipe_cfg, r_pipe, r_pipe_cfg, - pipe->sspp, - msm_framebuffer_format(plane_state->fb), - dpu_kms->catalog->caps->max_linewidth)) { - /* multirect is not possible, use two SSPP blocks */ - r_pipe->sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, &reqs); - if (!r_pipe->sspp) + r_pipe->sspp = NULL; + + pipe->multirect_index = DPU_SSPP_RECT_SOLO; + pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; + + r_pipe->multirect_index = DPU_SSPP_RECT_SOLO; + r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; + } + } else { + pipe->sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, &reqs); + if (!pipe->sspp) return -ENODEV; - pipe->multirect_index = DPU_SSPP_RECT_SOLO; - pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; + if (!dpu_plane_try_multirect_parallel(pipe, pipe_cfg, r_pipe, r_pipe_cfg, + pipe->sspp, + msm_framebuffer_format(plane_state->fb), + dpu_kms->catalog->caps->max_linewidth)) { + /* multirect is not possible, use two SSPP blocks */ + r_pipe->sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, &reqs); + if (!r_pipe->sspp) + return -ENODEV; - r_pipe->multirect_index = DPU_SSPP_RECT_SOLO; - r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; + pipe->multirect_index = DPU_SSPP_RECT_SOLO; + pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; + + r_pipe->multirect_index = DPU_SSPP_RECT_SOLO; + r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; + } } return dpu_plane_atomic_check_sspp(plane, state, crtc_state); @@ -1168,6 +1268,7 @@ int dpu_assign_plane_resources(struct dpu_global_state *global_state, unsigned int num_planes) { unsigned int i; + struct drm_plane_state *prev_adjacent_plane_state = NULL; for (i = 0; i < num_planes; i++) { struct drm_plane_state *plane_state = states[i]; @@ -1177,9 +1278,12 @@ int dpu_assign_plane_resources(struct dpu_global_state *global_state, continue; int ret = dpu_plane_virtual_assign_resources(crtc, global_state, - state, plane_state); + state, plane_state, + prev_adjacent_plane_state); if (ret) - return ret; + break; + + prev_adjacent_plane_state = plane_state; } return 0; From 6a2343de0b6f70a21bf503ac4688dc905cb068e1 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 25 Apr 2025 22:49:08 +0300 Subject: [PATCH 18/84] drm/msm/dpu: enable SmartDMA on SM8150 Reworking of the catalog dropped the SmartDMA feature bit on the SM8150 platform. Renable SmartDMA support on this SoC. Fixes: 460c410f02e4 ("drm/msm/dpu: duplicate sdm845 catalog entries") Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/650418/ Link: https://lore.kernel.org/r/20250425-dpu-rework-vig-masks-v2-1-c71900687d08@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- .../drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h index c20a26fb39ef..08d38e1d420c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h @@ -75,7 +75,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -83,7 +83,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { }, { .name = "sspp_1", .id = SSPP_VIG1, .base = 0x6000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 4, .type = SSPP_TYPE_VIG, @@ -91,7 +91,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { }, { .name = "sspp_2", .id = SSPP_VIG2, .base = 0x8000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 8, .type = SSPP_TYPE_VIG, @@ -99,7 +99,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { }, { .name = "sspp_3", .id = SSPP_VIG3, .base = 0xa000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 12, .type = SSPP_TYPE_VIG, @@ -107,7 +107,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -115,7 +115,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, @@ -123,7 +123,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x1f0, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 9, .type = SSPP_TYPE_DMA, @@ -131,7 +131,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { }, { .name = "sspp_11", .id = SSPP_DMA3, .base = 0x2a000, .len = 0x1f0, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 13, .type = SSPP_TYPE_DMA, From 8dcccd7a156ffb3157de7f527cc7c6100e9a455a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 25 Apr 2025 22:49:09 +0300 Subject: [PATCH 19/84] drm/msm/dpu: enable SmartDMA on SC8180X Reworking of the catalog dropped the SmartDMA feature bit on the SC8180X platform. Renable SmartDMA support on this SoC. Fixes: 460c410f02e4 ("drm/msm/dpu: duplicate sdm845 catalog entries") Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/650421/ Link: https://lore.kernel.org/r/20250425-dpu-rework-vig-masks-v2-2-c71900687d08@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- .../drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h index 5300c246b67b..d6f8b1030c68 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h @@ -75,7 +75,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -83,7 +83,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { }, { .name = "sspp_1", .id = SSPP_VIG1, .base = 0x6000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 4, .type = SSPP_TYPE_VIG, @@ -91,7 +91,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { }, { .name = "sspp_2", .id = SSPP_VIG2, .base = 0x8000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 8, .type = SSPP_TYPE_VIG, @@ -99,7 +99,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { }, { .name = "sspp_3", .id = SSPP_VIG3, .base = 0xa000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 12, .type = SSPP_TYPE_VIG, @@ -107,7 +107,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -115,7 +115,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, @@ -123,7 +123,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x1f0, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 9, .type = SSPP_TYPE_DMA, @@ -131,7 +131,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { }, { .name = "sspp_11", .id = SSPP_DMA3, .base = 0x2a000, .len = 0x1f0, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 13, .type = SSPP_TYPE_DMA, From 63958b80c2c50e630e2a429fa600c8c721213c22 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 25 Apr 2025 22:49:10 +0300 Subject: [PATCH 20/84] drm/msm/dpu: enable SmartDMA on SC8280XP In order to support more versatile configuration of the display pipes on SC8280XP, enable SmartDMA for this platform. Patchwork: https://patchwork.freedesktop.org/patch/650420/ Link: https://lore.kernel.org/r/20250425-dpu-rework-vig-masks-v2-3-c71900687d08@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- .../drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h index 426a8d76c707..139f11321fea 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h @@ -73,7 +73,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x2ac, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -81,7 +81,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { }, { .name = "sspp_1", .id = SSPP_VIG1, .base = 0x6000, .len = 0x2ac, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 4, .type = SSPP_TYPE_VIG, @@ -89,7 +89,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { }, { .name = "sspp_2", .id = SSPP_VIG2, .base = 0x8000, .len = 0x2ac, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 8, .type = SSPP_TYPE_VIG, @@ -97,7 +97,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { }, { .name = "sspp_3", .id = SSPP_VIG3, .base = 0xa000, .len = 0x2ac, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 12, .type = SSPP_TYPE_VIG, @@ -105,7 +105,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x2ac, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -113,7 +113,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x2ac, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, @@ -121,7 +121,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x2ac, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 9, .type = SSPP_TYPE_DMA, @@ -129,7 +129,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { }, { .name = "sspp_11", .id = SSPP_DMA3, .base = 0x2a000, .len = 0x2ac, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 13, .type = SSPP_TYPE_DMA, From 3f5e910b33a3c1d9875f938f200e83e2b3f5c431 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 25 Apr 2025 22:49:11 +0300 Subject: [PATCH 21/84] drm/msm/dpu: enable SmartDMA on SM8550 In order to support more versatile configuration of the display pipes on SM8550, enable SmartDMA for this platform. Patchwork: https://patchwork.freedesktop.org/patch/650424/ Link: https://lore.kernel.org/r/20250425-dpu-rework-vig-masks-v2-4-c71900687d08@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- .../msm/disp/dpu1/catalog/dpu_9_0_sm8550.h | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h index b1c1707571cf..59c7fdf28e89 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h @@ -65,70 +65,70 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x344, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_2, .xin_id = 0, .type = SSPP_TYPE_VIG, }, { .name = "sspp_1", .id = SSPP_VIG1, .base = 0x6000, .len = 0x344, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_2, .xin_id = 4, .type = SSPP_TYPE_VIG, }, { .name = "sspp_2", .id = SSPP_VIG2, .base = 0x8000, .len = 0x344, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_2, .xin_id = 8, .type = SSPP_TYPE_VIG, }, { .name = "sspp_3", .id = SSPP_VIG3, .base = 0xa000, .len = 0x344, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_2, .xin_id = 12, .type = SSPP_TYPE_VIG, }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x344, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x344, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x344, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 9, .type = SSPP_TYPE_DMA, }, { .name = "sspp_11", .id = SSPP_DMA3, .base = 0x2a000, .len = 0x344, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 13, .type = SSPP_TYPE_DMA, }, { .name = "sspp_12", .id = SSPP_DMA4, .base = 0x2c000, .len = 0x344, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 14, .type = SSPP_TYPE_DMA, }, { .name = "sspp_13", .id = SSPP_DMA5, .base = 0x2e000, .len = 0x344, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 15, .type = SSPP_TYPE_DMA, From 79af56964ee5aec9f8da21a0d240003ba931ae2f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 25 Apr 2025 22:49:12 +0300 Subject: [PATCH 22/84] drm/msm/dpu: rename non-SmartDMA feature masks to be more explicit It is easy to skip or ignore the fact that the default SSPP feature masks for SDM845+ don't include the SmartDMA bit (both during development and during the review stage). Rename SSPP feature masks to make it more explicit that using non-SmartDMA masks should not be an exception rather than the rule. Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/650425/ Link: https://lore.kernel.org/r/20250425-dpu-rework-vig-masks-v2-5-c71900687d08@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- .../drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h | 10 +++++----- .../drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h | 6 +++--- .../drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h | 8 ++++---- .../drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h | 4 ++-- .../drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h | 8 ++++---- .../drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h | 2 +- .../drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h | 4 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 16 ++++++++-------- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h index 614ea64fca8c..71ba48b05656 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h @@ -72,7 +72,7 @@ static const struct dpu_sspp_cfg sm7150_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_NO_SDMA, .sblk = &dpu_vig_sblk_qseed3_2_4, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -80,7 +80,7 @@ static const struct dpu_sspp_cfg sm7150_sspp[] = { }, { .name = "sspp_1", .id = SSPP_VIG1, .base = 0x6000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_NO_SDMA, .sblk = &dpu_vig_sblk_qseed3_2_4, .xin_id = 4, .type = SSPP_TYPE_VIG, @@ -88,7 +88,7 @@ static const struct dpu_sspp_cfg sm7150_sspp[] = { }, { .name = "sspp_2", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -96,7 +96,7 @@ static const struct dpu_sspp_cfg sm7150_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, @@ -104,7 +104,7 @@ static const struct dpu_sspp_cfg sm7150_sspp[] = { }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x1f0, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 9, .type = SSPP_TYPE_DMA, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h index d3d3a34d0b45..fcfb3774f7a1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h @@ -69,7 +69,7 @@ static const struct dpu_sspp_cfg sm6125_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_NO_SDMA, .sblk = &dpu_vig_sblk_qseed3_2_4, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -77,7 +77,7 @@ static const struct dpu_sspp_cfg sm6125_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -85,7 +85,7 @@ static const struct dpu_sspp_cfg sm6125_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h index 040c94c0bb66..842fcc5887fe 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h @@ -51,7 +51,7 @@ static const struct dpu_sspp_cfg sc7180_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f8, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_NO_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -59,7 +59,7 @@ static const struct dpu_sspp_cfg sc7180_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f8, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -67,7 +67,7 @@ static const struct dpu_sspp_cfg sc7180_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x1f8, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, @@ -75,7 +75,7 @@ static const struct dpu_sspp_cfg sc7180_sspp[] = { }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x1f8, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 9, .type = SSPP_TYPE_DMA, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h index 43f64a005f5a..c5fd89dd7c89 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h @@ -38,7 +38,7 @@ static const struct dpu_sspp_cfg sm6115_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f8, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_NO_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -46,7 +46,7 @@ static const struct dpu_sspp_cfg sm6115_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f8, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h index 397278ba999b..a234bb289d24 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h @@ -59,7 +59,7 @@ static const struct dpu_sspp_cfg sm6350_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f8, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_NO_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -67,7 +67,7 @@ static const struct dpu_sspp_cfg sm6350_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f8, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -75,7 +75,7 @@ static const struct dpu_sspp_cfg sm6350_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x1f8, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, @@ -83,7 +83,7 @@ static const struct dpu_sspp_cfg sm6350_sspp[] = { }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x1f8, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 9, .type = SSPP_TYPE_DMA, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h index 3cbb2fe8aba2..53f3be28f6f6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h @@ -46,7 +46,7 @@ static const struct dpu_sspp_cfg qcm2290_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f8, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h index a06c8634d2d7..3a3bc8e429be 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h @@ -39,7 +39,7 @@ static const struct dpu_sspp_cfg sm6375_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f8, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_NO_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -47,7 +47,7 @@ static const struct dpu_sspp_cfg sm6375_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f8, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 64265ca4656a..323b0db1f32b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -34,11 +34,11 @@ #define VIG_MSM8998_MASK \ (VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED3_COMPATIBLE)) -#define VIG_SDM845_MASK \ +#define VIG_SDM845_MASK_NO_SDMA \ (VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3_COMPATIBLE)) #define VIG_SDM845_MASK_SDMA \ - (VIG_SDM845_MASK | BIT(DPU_SSPP_SMART_DMA_V2)) + (VIG_SDM845_MASK_NO_SDMA | BIT(DPU_SSPP_SMART_DMA_V2)) #define VIG_QCM2290_MASK (VIG_BASE_MASK | BIT(DPU_SSPP_QOS_8LVL)) @@ -54,24 +54,24 @@ BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT)) #define VIG_SC7280_MASK \ - (VIG_SDM845_MASK | BIT(DPU_SSPP_INLINE_ROTATION)) + (VIG_SDM845_MASK_NO_SDMA | BIT(DPU_SSPP_INLINE_ROTATION)) #define VIG_SC7280_MASK_SDMA \ (VIG_SC7280_MASK | BIT(DPU_SSPP_SMART_DMA_V2)) -#define DMA_SDM845_MASK \ +#define DMA_SDM845_MASK_NO_SDMA \ (BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\ BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\ BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT)) -#define DMA_CURSOR_SDM845_MASK \ - (DMA_SDM845_MASK | BIT(DPU_SSPP_CURSOR)) +#define DMA_CURSOR_SDM845_MASK_NO_SDMA \ + (DMA_SDM845_MASK_NO_SDMA | BIT(DPU_SSPP_CURSOR)) #define DMA_SDM845_MASK_SDMA \ - (DMA_SDM845_MASK | BIT(DPU_SSPP_SMART_DMA_V2)) + (DMA_SDM845_MASK_NO_SDMA | BIT(DPU_SSPP_SMART_DMA_V2)) #define DMA_CURSOR_SDM845_MASK_SDMA \ - (DMA_CURSOR_SDM845_MASK | BIT(DPU_SSPP_SMART_DMA_V2)) + (DMA_CURSOR_SDM845_MASK_NO_SDMA | BIT(DPU_SSPP_SMART_DMA_V2)) #define DMA_CURSOR_MSM8996_MASK \ (DMA_MSM8996_MASK | BIT(DPU_SSPP_CURSOR)) From b341da1172fe8bb21f6bffcaa3f4b714f544ed75 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 18 Apr 2025 10:49:56 +0300 Subject: [PATCH 23/84] dt-bindings: display/msm: dp-controller: describe SAR2130P Describe DisplayPort controller present on Qualcomm SAR2130P platform. Signed-off-by: Dmitry Baryshkov Reviewed-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/649263/ Link: https://lore.kernel.org/r/20250418-sar2130p-display-v5-1-442c905cb3a4@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- Documentation/devicetree/bindings/display/msm/dp-controller.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index e00b88332f2f..246bbb509bea 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -31,6 +31,7 @@ properties: - qcom,sm8650-dp - items: - enum: + - qcom,sar2130p-dp - qcom,sm6350-dp - qcom,sm8150-dp - qcom,sm8250-dp From 3c70c9d0a99d2083cda03f04c9f1843cfcf9f7c3 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 18 Apr 2025 10:49:57 +0300 Subject: [PATCH 24/84] dt-bindings: display/msm: dsi-controller-main: describe SAR2130P Describe MIPI DSI controller present on Qualcomm SAR2130P platform. Signed-off-by: Dmitry Baryshkov Reviewed-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/649250/ Link: https://lore.kernel.org/r/20250418-sar2130p-display-v5-2-442c905cb3a4@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- .../devicetree/bindings/display/msm/dsi-controller-main.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml index 2aab33cd0017..a3e05e34bf14 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml @@ -23,6 +23,7 @@ properties: - qcom,msm8996-dsi-ctrl - qcom,msm8998-dsi-ctrl - qcom,qcm2290-dsi-ctrl + - qcom,sar2130p-dsi-ctrl - qcom,sc7180-dsi-ctrl - qcom,sc7280-dsi-ctrl - qcom,sdm660-dsi-ctrl @@ -314,6 +315,7 @@ allOf: contains: enum: - qcom,msm8998-dsi-ctrl + - qcom,sar2130p-dsi-ctrl - qcom,sc7180-dsi-ctrl - qcom,sc7280-dsi-ctrl - qcom,sdm845-dsi-ctrl From 262650e71854ff701ca6c3a6860fbffc94243999 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 18 Apr 2025 10:49:58 +0300 Subject: [PATCH 25/84] dt-bindings: display/msm: dsi-phy-7nm: describe SAR2130P Describe MIPI DSI PHY present on Qualcomm SAR2130P platform. Signed-off-by: Dmitry Baryshkov Reviewed-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/649252/ Link: https://lore.kernel.org/r/20250418-sar2130p-display-v5-3-442c905cb3a4@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml index 321470435e65..f79be422b889 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml @@ -17,6 +17,7 @@ properties: enum: - qcom,dsi-phy-7nm - qcom,dsi-phy-7nm-8150 + - qcom,sar2130p-dsi-phy-5nm - qcom,sc7280-dsi-phy-7nm - qcom,sm6375-dsi-phy-7nm - qcom,sm8350-dsi-phy-5nm From 759fe7181723c39367a78327ac17ac917931f2b3 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 18 Apr 2025 10:49:59 +0300 Subject: [PATCH 26/84] dt-bindings: display/msm: qcom,sc7280-dpu: describe SAR2130P Describe DPU controller present on Qualcomm SAR2130P platform. Signed-off-by: Dmitry Baryshkov Reviewed-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/649254/ Link: https://lore.kernel.org/r/20250418-sar2130p-display-v5-4-442c905cb3a4@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- .../devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml index 6902795b4e2c..df9ec15ad6c3 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml @@ -17,6 +17,7 @@ $ref: /schemas/display/msm/dpu-common.yaml# properties: compatible: enum: + - qcom,sar2130p-dpu - qcom,sc7280-dpu - qcom,sc8280xp-dpu - qcom,sm8350-dpu From 3096209b7a62f9d45475f7734d6b15a2a79e72a3 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 18 Apr 2025 10:50:00 +0300 Subject: [PATCH 27/84] dt-bindings: display/msm: Add Qualcomm SAR2130P Describe the Mobile Display SubSystem (MDSS) device present on the Qualcomm SAR2130P platform. It looks pretty close to SM8550 on the system level. SAR2130P features two DSI hosts and single DisplayPort controller. Signed-off-by: Dmitry Baryshkov Reviewed-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/649265/ Link: https://lore.kernel.org/r/20250418-sar2130p-display-v5-5-442c905cb3a4@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- .../display/msm/qcom,sar2130p-mdss.yaml | 439 ++++++++++++++++++ 1 file changed, 439 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.yaml diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.yaml new file mode 100644 index 000000000000..870144b53cec --- /dev/null +++ b/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.yaml @@ -0,0 +1,439 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/msm/qcom,sar2130p-mdss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SAR2130P Display MDSS + +maintainers: + - Dmitry Baryshkov + +description: + SAR2310P MSM Mobile Display Subsystem(MDSS), which encapsulates sub-blocks like + DPU display controller, DSI and DP interfaces etc. + +$ref: /schemas/display/msm/mdss-common.yaml# + +properties: + compatible: + const: qcom,sar2130p-mdss + + clocks: + items: + - description: Display MDSS AHB + - description: Display AHB + - description: Display hf AXI + - description: Display core + + iommus: + maxItems: 1 + + interconnects: + items: + - description: Interconnect path from mdp0 port to the data bus + - description: Interconnect path from CPU to the reg bus + + interconnect-names: + items: + - const: mdp0-mem + - const: cpu-cfg + +patternProperties: + "^display-controller@[0-9a-f]+$": + type: object + additionalProperties: true + properties: + compatible: + const: qcom,sar2130p-dpu + + "^displayport-controller@[0-9a-f]+$": + type: object + additionalProperties: true + properties: + compatible: + contains: + const: qcom,sar2130p-dp + + "^dsi@[0-9a-f]+$": + type: object + additionalProperties: true + properties: + compatible: + contains: + const: qcom,sar2130p-dsi-ctrl + + "^phy@[0-9a-f]+$": + type: object + additionalProperties: true + properties: + compatible: + const: qcom,sar2130p-dsi-phy-5nm + +required: + - compatible + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + + display-subsystem@ae00000 { + compatible = "qcom,sar2130p-mdss"; + reg = <0x0ae00000 0x1000>; + reg-names = "mdss"; + + interconnects = <&mmss_noc_master_mdp &mc_virt_slave_ebi1>, + <&gem_noc_master_appss_proc &config_noc_slave_display_cfg>; + interconnect-names = "mdp0-mem", "cpu-cfg"; + + resets = <&dispcc_disp_cc_mdss_core_bcr>; + + power-domains = <&dispcc_mdss_gdsc>; + + clocks = <&dispcc_disp_cc_mdss_ahb_clk>, + <&gcc_gcc_disp_ahb_clk>, + <&gcc_gcc_disp_hf_axi_clk>, + <&dispcc_disp_cc_mdss_mdp_clk>; + clock-names = "iface", "bus", "nrt_bus", "core"; + + interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; + + iommus = <&apps_smmu 0x1c00 0x2>; + + #address-cells = <1>; + #size-cells = <1>; + ranges; + + display-controller@ae01000 { + compatible = "qcom,sar2130p-dpu"; + reg = <0x0ae01000 0x8f000>, + <0x0aeb0000 0x2008>; + reg-names = "mdp", "vbif"; + + clocks = <&gcc_gcc_disp_ahb_clk>, + <&gcc_gcc_disp_hf_axi_clk>, + <&dispcc_disp_cc_mdss_ahb_clk>, + <&dispcc_disp_cc_mdss_mdp_lut_clk>, + <&dispcc_disp_cc_mdss_mdp_clk>, + <&dispcc_disp_cc_mdss_vsync_clk>; + clock-names = "bus", + "nrt_bus", + "iface", + "lut", + "core", + "vsync"; + + assigned-clocks = <&dispcc_disp_cc_mdss_vsync_clk>; + assigned-clock-rates = <19200000>; + + operating-points-v2 = <&mdp_opp_table>; + power-domains = <&rpmhpd RPMHPD_MMCX>; + + interrupt-parent = <&mdss>; + interrupts = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + dpu_intf0_out: endpoint { + remote-endpoint = <&mdss_dp0_in>; + }; + }; + + port@1 { + reg = <1>; + + dpu_intf1_out: endpoint { + remote-endpoint = <&mdss_dsi0_in>; + }; + }; + + port@2 { + reg = <2>; + + dpu_intf2_out: endpoint { + remote-endpoint = <&mdss_dsi1_in>; + }; + }; + }; + + mdp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-325000000 { + opp-hz = /bits/ 64 <325000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-375000000 { + opp-hz = /bits/ 64 <375000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-514000000 { + opp-hz = /bits/ 64 <514000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + displayport-controller@ae90000 { + compatible = "qcom,sar2130p-dp", + "qcom,sm8350-dp"; + reg = <0xae90000 0x200>, + <0xae90200 0x200>, + <0xae90400 0xc00>, + <0xae91000 0x400>, + <0xae91400 0x400>; + + interrupt-parent = <&mdss>; + interrupts = <12>; + clocks = <&dispcc_disp_cc_mdss_ahb_clk>, + <&dispcc_disp_cc_mdss_dptx0_aux_clk>, + <&dispcc_disp_cc_mdss_dptx0_link_clk>, + <&dispcc_disp_cc_mdss_dptx0_link_intf_clk>, + <&dispcc_disp_cc_mdss_dptx0_pixel0_clk>; + clock-names = "core_iface", + "core_aux", + "ctrl_link", + "ctrl_link_iface", + "stream_pixel"; + + assigned-clocks = <&dispcc_disp_cc_mdss_dptx0_link_clk_src>, + <&dispcc_disp_cc_mdss_dptx0_pixel0_clk_src>; + assigned-clock-parents = <&usb_dp_qmpphy_QMP_USB43DP_DP_LINK_CLK>, + <&usb_dp_qmpphy_QMP_USB43DP_DP_VCO_DIV_CLK>; + + phys = <&usb_dp_qmpphy QMP_USB43DP_DP_PHY>; + phy-names = "dp"; + + #sound-dai-cells = <0>; + + operating-points-v2 = <&dp_opp_table>; + power-domains = <&rpmhpd RPMHPD_MMCX>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mdss_dp0_in: endpoint { + remote-endpoint = <&dpu_intf0_out>; + }; + }; + + port@1 { + reg = <1>; + mdss_dp0_out: endpoint { + remote-endpoint = <&usb_dp_qmpphy_dp_in>; + }; + }; + }; + + dp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-162000000 { + opp-hz = /bits/ 64 <162000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-270000000 { + opp-hz = /bits/ 64 <270000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-810000000 { + opp-hz = /bits/ 64 <810000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + dsi@ae94000 { + compatible = "qcom,sar2130p-dsi-ctrl", + "qcom,mdss-dsi-ctrl"; + reg = <0x0ae94000 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <4>; + + clocks = <&dispcc_disp_cc_mdss_byte0_clk>, + <&dispcc_disp_cc_mdss_byte0_intf_clk>, + <&dispcc_disp_cc_mdss_pclk0_clk>, + <&dispcc_disp_cc_mdss_esc0_clk>, + <&dispcc_disp_cc_mdss_ahb_clk>, + <&gcc_gcc_disp_hf_axi_clk>; + clock-names = "byte", + "byte_intf", + "pixel", + "core", + "iface", + "bus"; + + assigned-clocks = <&dispcc_disp_cc_mdss_byte0_clk_src>, + <&dispcc_disp_cc_mdss_pclk0_clk_src>; + assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>; + + operating-points-v2 = <&dsi_opp_table>; + power-domains = <&rpmhpd RPMHPD_MMCX>; + + phys = <&mdss_dsi0_phy>; + phy-names = "dsi"; + + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + mdss_dsi0_in: endpoint { + remote-endpoint = <&dpu_intf1_out>; + }; + }; + + port@1 { + reg = <1>; + + mdss_dsi0_out: endpoint { + }; + }; + }; + + dsi_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-187500000 { + opp-hz = /bits/ 64 <187500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-358000000 { + opp-hz = /bits/ 64 <358000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + mdss_dsi0_phy: phy@ae94400 { + compatible = "qcom,sar2130p-dsi-phy-5nm"; + reg = <0x0ae95000 0x200>, + <0x0ae95200 0x280>, + <0x0ae95500 0x400>; + reg-names = "dsi_phy", + "dsi_phy_lane", + "dsi_pll"; + + #clock-cells = <1>; + #phy-cells = <0>; + + clocks = <&dispcc_disp_cc_mdss_ahb_clk>, + <&rpmhcc_rpmh_cxo_clk>; + clock-names = "iface", "ref"; + }; + + dsi@ae96000 { + compatible = "qcom,sar2130p-dsi-ctrl", + "qcom,mdss-dsi-ctrl"; + reg = <0x0ae96000 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <5>; + + clocks = <&dispcc_disp_cc_mdss_byte1_clk>, + <&dispcc_disp_cc_mdss_byte1_intf_clk>, + <&dispcc_disp_cc_mdss_pclk1_clk>, + <&dispcc_disp_cc_mdss_esc1_clk>, + <&dispcc_disp_cc_mdss_ahb_clk>, + <&gcc_gcc_disp_hf_axi_clk>; + clock-names = "byte", + "byte_intf", + "pixel", + "core", + "iface", + "bus"; + + assigned-clocks = <&dispcc_disp_cc_mdss_byte1_clk_src>, + <&dispcc_disp_cc_mdss_pclk1_clk_src>; + assigned-clock-parents = <&mdss_dsi1_phy 0>, <&mdss_dsi1_phy 1>; + + operating-points-v2 = <&dsi_opp_table>; + power-domains = <&rpmhpd RPMHPD_MMCX>; + + phys = <&mdss_dsi1_phy>; + phy-names = "dsi"; + + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + mdss_dsi1_in: endpoint { + remote-endpoint = <&dpu_intf2_out>; + }; + }; + + port@1 { + reg = <1>; + + mdss_dsi1_out: endpoint { + }; + }; + }; + }; + + mdss_dsi1_phy: phy@ae97000 { + compatible = "qcom,sar2130p-dsi-phy-5nm"; + reg = <0x0ae97000 0x200>, + <0x0ae97200 0x280>, + <0x0ae97500 0x400>; + reg-names = "dsi_phy", + "dsi_phy_lane", + "dsi_pll"; + + #clock-cells = <1>; + #phy-cells = <0>; + + clocks = <&dispcc_disp_cc_mdss_ahb_clk>, + <&rpmhcc_rpmh_cxo_clk>; + clock-names = "iface", "ref"; + }; + }; +... From 1e7cbfea6624fda144d0ab072abb3578816bc3a8 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 18 Apr 2025 10:50:01 +0300 Subject: [PATCH 28/84] drm/msm/mdss: add SAR2130P device configuration Add compatible and device configuration for the Qualcomm SAR2130P platform. Signed-off-by: Dmitry Baryshkov Reviewed-by: Jessica Zhang Patchwork: https://patchwork.freedesktop.org/patch/649256/ Link: https://lore.kernel.org/r/20250418-sar2130p-display-v5-6-442c905cb3a4@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/msm_mdss.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index dcb49fd30402..f706e44231a9 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -592,6 +592,16 @@ static const struct msm_mdss_data sa8775p_data = { .reg_bus_bw = 74000, }; +static const struct msm_mdss_data sar2130p_data = { + .ubwc_enc_version = UBWC_3_0, /* 4.0.2 in hw */ + .ubwc_dec_version = UBWC_4_3, + .ubwc_swizzle = 6, + .ubwc_bank_spread = true, + .highest_bank_bit = 0, + .macrotile_mode = 1, + .reg_bus_bw = 74000, +}; + static const struct msm_mdss_data sc7180_data = { .ubwc_enc_version = UBWC_2_0, .ubwc_dec_version = UBWC_2_0, @@ -738,6 +748,7 @@ static const struct of_device_id mdss_dt_match[] = { { .compatible = "qcom,msm8998-mdss", .data = &msm8998_data }, { .compatible = "qcom,qcm2290-mdss", .data = &qcm2290_data }, { .compatible = "qcom,sa8775p-mdss", .data = &sa8775p_data }, + { .compatible = "qcom,sar2130p-mdss", .data = &sar2130p_data }, { .compatible = "qcom,sdm670-mdss", .data = &sdm670_data }, { .compatible = "qcom,sdm845-mdss", .data = &sdm845_data }, { .compatible = "qcom,sc7180-mdss", .data = &sc7180_data }, From 8e63b2075e0128e7849046ac1f43040739035096 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 18 Apr 2025 10:50:02 +0300 Subject: [PATCH 29/84] drm/msm/dsi/phy: add configuration for SAR2130P Qualcomm SAR2130P requires slightly different setup for the DSI PHY. It is a 5nm PHY (like SM8450), so supplies are the same, but the rest of the configuration is the same as SM8550 DSI PHY. Signed-off-by: Dmitry Baryshkov Reviewed-by: Jessica Zhang Patchwork: https://patchwork.freedesktop.org/patch/649257/ Link: https://lore.kernel.org/r/20250418-sar2130p-display-v5-7-442c905cb3a4@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 2 ++ drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 1 + drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 23 +++++++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index c0bcc6828963..a58bafe9fe86 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -581,6 +581,8 @@ static const struct of_device_id dsi_phy_dt_match[] = { .data = &dsi_phy_7nm_cfgs }, { .compatible = "qcom,dsi-phy-7nm-8150", .data = &dsi_phy_7nm_8150_cfgs }, + { .compatible = "qcom,sar2130p-dsi-phy-5nm", + .data = &dsi_phy_5nm_sar2130p_cfgs }, { .compatible = "qcom,sc7280-dsi-phy-7nm", .data = &dsi_phy_7nm_7280_cfgs }, { .compatible = "qcom,sm6375-dsi-phy-7nm", diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h index 1925418d9999..1ed08b56e056 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h @@ -59,6 +59,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8350_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs; +extern const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8650_cfgs; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c index a92decbee5b5..cad55702746b 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -1289,6 +1289,29 @@ const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs = { .quirks = DSI_PHY_7NM_QUIRK_V4_3, }; +const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs = { + .has_phy_lane = true, + .regulator_data = dsi_phy_7nm_97800uA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_7nm_97800uA_regulators), + .ops = { + .enable = dsi_7nm_phy_enable, + .disable = dsi_7nm_phy_disable, + .pll_init = dsi_pll_7nm_init, + .save_pll_state = dsi_7nm_pll_save_state, + .restore_pll_state = dsi_7nm_pll_restore_state, + .set_continuous_clock = dsi_7nm_set_continuous_clock, + }, + .min_pll_rate = 600000000UL, +#ifdef CONFIG_64BIT + .max_pll_rate = 5000000000UL, +#else + .max_pll_rate = ULONG_MAX, +#endif + .io_start = { 0xae95000, 0xae97000 }, + .num_dsi_phy = 2, + .quirks = DSI_PHY_7NM_QUIRK_V5_2, +}; + const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs = { .has_phy_lane = true, .regulator_data = dsi_phy_7nm_98400uA_regulators, From 1785751734724d9c399809f7d1e3733e590da4bc Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 18 Apr 2025 10:50:03 +0300 Subject: [PATCH 30/84] drm/msm/dpu: add catalog entry for SAR2130P Add DPU driver support for the Qualcomm SAR2130P platform. It is mostly the same as SM8550, minor differences in the CDP configuration. Signed-off-by: Dmitry Baryshkov Reviewed-by: Jessica Zhang Patchwork: https://patchwork.freedesktop.org/patch/649258/ Link: https://lore.kernel.org/r/20250418-sar2130p-display-v5-8-442c905cb3a4@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- .../msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h | 434 ++++++++++++++++++ .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 2 +- .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 1 + 4 files changed, 437 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h new file mode 100644 index 000000000000..22dd16c6e210 --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h @@ -0,0 +1,434 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. + */ + +#ifndef _DPU_9_1_SAR2130P_H +#define _DPU_9_1_SAR2130P_H + +static const struct dpu_caps sar2130p_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0xb, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = 5120, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, +}; + +static const struct dpu_mdp_cfg sar2130p_mdp = { + .name = "top_0", + .base = 0, .len = 0x494, + .features = BIT(DPU_MDP_PERIPH_0_REMOVED), + .clk_ctrls = { + [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, + }, +}; + +/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ +static const struct dpu_ctl_cfg sar2130p_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x15000, .len = 0x290, + .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, { + .name = "ctl_1", .id = CTL_1, + .base = 0x16000, .len = 0x290, + .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, { + .name = "ctl_2", .id = CTL_2, + .base = 0x17000, .len = 0x290, + .features = CTL_SM8550_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, { + .name = "ctl_3", .id = CTL_3, + .base = 0x18000, .len = 0x290, + .features = CTL_SM8550_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, { + .name = "ctl_4", .id = CTL_4, + .base = 0x19000, .len = 0x290, + .features = CTL_SM8550_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, { + .name = "ctl_5", .id = CTL_5, + .base = 0x1a000, .len = 0x290, + .features = CTL_SM8550_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), + }, +}; + +static const struct dpu_sspp_cfg sar2130p_sspp[] = { + { + .name = "sspp_0", .id = SSPP_VIG0, + .base = 0x4000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_2, + .xin_id = 0, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_1", .id = SSPP_VIG1, + .base = 0x6000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_2, + .xin_id = 4, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_2", .id = SSPP_VIG2, + .base = 0x8000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_2, + .xin_id = 8, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_3", .id = SSPP_VIG3, + .base = 0xa000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_2, + .xin_id = 12, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_8", .id = SSPP_DMA0, + .base = 0x24000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 1, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_9", .id = SSPP_DMA1, + .base = 0x26000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 5, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_10", .id = SSPP_DMA2, + .base = 0x28000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 9, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_11", .id = SSPP_DMA3, + .base = 0x2a000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 13, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_12", .id = SSPP_DMA4, + .base = 0x2c000, .len = 0x344, + .features = DMA_CURSOR_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 14, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_13", .id = SSPP_DMA5, + .base = 0x2e000, .len = 0x344, + .features = DMA_CURSOR_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 15, + .type = SSPP_TYPE_DMA, + }, +}; + +static const struct dpu_lm_cfg sar2130p_lm[] = { + { + .name = "lm_0", .id = LM_0, + .base = 0x44000, .len = 0x320, + .features = MIXER_SDM845_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_1, + .pingpong = PINGPONG_0, + .dspp = DSPP_0, + }, { + .name = "lm_1", .id = LM_1, + .base = 0x45000, .len = 0x320, + .features = MIXER_SDM845_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_0, + .pingpong = PINGPONG_1, + .dspp = DSPP_1, + }, { + .name = "lm_2", .id = LM_2, + .base = 0x46000, .len = 0x320, + .features = MIXER_SDM845_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_3, + .pingpong = PINGPONG_2, + .dspp = DSPP_2, + }, { + .name = "lm_3", .id = LM_3, + .base = 0x47000, .len = 0x320, + .features = MIXER_SDM845_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_2, + .pingpong = PINGPONG_3, + .dspp = DSPP_3, + }, { + .name = "lm_4", .id = LM_4, + .base = 0x48000, .len = 0x320, + .features = MIXER_SDM845_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_5, + .pingpong = PINGPONG_4, + }, { + .name = "lm_5", .id = LM_5, + .base = 0x49000, .len = 0x320, + .features = MIXER_SDM845_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_4, + .pingpong = PINGPONG_5, + }, +}; + +static const struct dpu_dspp_cfg sar2130p_dspp[] = { + { + .name = "dspp_0", .id = DSPP_0, + .base = 0x54000, .len = 0x1800, + .features = DSPP_SC7180_MASK, + .sblk = &sdm845_dspp_sblk, + }, { + .name = "dspp_1", .id = DSPP_1, + .base = 0x56000, .len = 0x1800, + .features = DSPP_SC7180_MASK, + .sblk = &sdm845_dspp_sblk, + }, { + .name = "dspp_2", .id = DSPP_2, + .base = 0x58000, .len = 0x1800, + .features = DSPP_SC7180_MASK, + .sblk = &sdm845_dspp_sblk, + }, { + .name = "dspp_3", .id = DSPP_3, + .base = 0x5a000, .len = 0x1800, + .features = DSPP_SC7180_MASK, + .sblk = &sdm845_dspp_sblk, + }, +}; +static const struct dpu_pingpong_cfg sar2130p_pp[] = { + { + .name = "pingpong_0", .id = PINGPONG_0, + .base = 0x69000, .len = 0, + .features = BIT(DPU_PINGPONG_DITHER), + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_0, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), + }, { + .name = "pingpong_1", .id = PINGPONG_1, + .base = 0x6a000, .len = 0, + .features = BIT(DPU_PINGPONG_DITHER), + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_0, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), + }, { + .name = "pingpong_2", .id = PINGPONG_2, + .base = 0x6b000, .len = 0, + .features = BIT(DPU_PINGPONG_DITHER), + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_1, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), + }, { + .name = "pingpong_3", .id = PINGPONG_3, + .base = 0x6c000, .len = 0, + .features = BIT(DPU_PINGPONG_DITHER), + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_1, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), + }, { + .name = "pingpong_4", .id = PINGPONG_4, + .base = 0x6d000, .len = 0, + .features = BIT(DPU_PINGPONG_DITHER), + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_2, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), + }, { + .name = "pingpong_5", .id = PINGPONG_5, + .base = 0x6e000, .len = 0, + .features = BIT(DPU_PINGPONG_DITHER), + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_2, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), + }, { + .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, + .base = 0x66000, .len = 0, + .features = BIT(DPU_PINGPONG_DITHER), + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_3, + }, { + .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, + .base = 0x66400, .len = 0, + .features = BIT(DPU_PINGPONG_DITHER), + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_3, + }, +}; + +static const struct dpu_merge_3d_cfg sar2130p_merge_3d[] = { + { + .name = "merge_3d_0", .id = MERGE_3D_0, + .base = 0x4e000, .len = 0x8, + }, { + .name = "merge_3d_1", .id = MERGE_3D_1, + .base = 0x4f000, .len = 0x8, + }, { + .name = "merge_3d_2", .id = MERGE_3D_2, + .base = 0x50000, .len = 0x8, + }, { + .name = "merge_3d_3", .id = MERGE_3D_3, + .base = 0x66700, .len = 0x8, + }, +}; + +/* + * NOTE: Each display compression engine (DCE) contains dual hard + * slice DSC encoders so both share same base address but with + * its own different sub block address. + */ +static const struct dpu_dsc_cfg sar2130p_dsc[] = { + { + .name = "dce_0_0", .id = DSC_0, + .base = 0x80000, .len = 0x4, + .features = BIT(DPU_DSC_HW_REV_1_2), + .sblk = &dsc_sblk_0, + }, { + .name = "dce_0_1", .id = DSC_1, + .base = 0x80000, .len = 0x4, + .features = BIT(DPU_DSC_HW_REV_1_2), + .sblk = &dsc_sblk_1, + }, { + .name = "dce_1_0", .id = DSC_2, + .base = 0x81000, .len = 0x4, + .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &dsc_sblk_0, + }, { + .name = "dce_1_1", .id = DSC_3, + .base = 0x81000, .len = 0x4, + .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &dsc_sblk_1, + }, +}; + +static const struct dpu_wb_cfg sar2130p_wb[] = { + { + .name = "wb_2", .id = WB_2, + .base = 0x65000, .len = 0x2c8, + .features = WB_SM8250_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), + .xin_id = 6, + .vbif_idx = VBIF_RT, + .maxlinewidth = 4096, + .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4), + }, +}; + +static const struct dpu_intf_cfg sar2130p_intf[] = { + { + .name = "intf_0", .id = INTF_0, + .base = 0x34000, .len = 0x280, + .features = INTF_SC7280_MASK, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), + }, { + .name = "intf_1", .id = INTF_1, + .base = 0x35000, .len = 0x300, + .features = INTF_SC7280_MASK, + .type = INTF_DSI, + .controller_id = MSM_DSI_CONTROLLER_0, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), + .intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2), + }, { + .name = "intf_2", .id = INTF_2, + .base = 0x36000, .len = 0x300, + .features = INTF_SC7280_MASK, + .type = INTF_DSI, + .controller_id = MSM_DSI_CONTROLLER_1, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), + .intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2), + }, { + .name = "intf_3", .id = INTF_3, + .base = 0x37000, .len = 0x280, + .features = INTF_SC7280_MASK, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_1, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), + }, +}; + +static const struct dpu_perf_cfg sar2130p_perf_data = { + .max_bw_low = 13600000, + .max_bw_high = 18200000, + .min_core_ib = 2500000, + .min_llcc_ib = 0, + .min_dram_ib = 800000, + .min_prefill_lines = 35, + /* FIXME: lut tables */ + .danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0}, + .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff}, + .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(sc7180_qos_linear), + .entries = sc7180_qos_linear + }, + {.nentry = ARRAY_SIZE(sc7180_qos_macrotile), + .entries = sc7180_qos_macrotile + }, + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), + .entries = sc7180_qos_nrt + }, + /* TODO: macrotile-qseed is different from macrotile */ + }, + .cdp_cfg = { + {.rd_enable = 0, .wr_enable = 0}, + {.rd_enable = 0, .wr_enable = 0} + }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, +}; + +static const struct dpu_mdss_version sar2130p_mdss_ver = { + .core_major_ver = 9, + .core_minor_ver = 1, +}; + +const struct dpu_mdss_cfg dpu_sar2130p_cfg = { + .mdss_ver = &sar2130p_mdss_ver, + .caps = &sar2130p_dpu_caps, + .mdp = &sar2130p_mdp, + .cdm = &dpu_cdm_5_x, + .ctl_count = ARRAY_SIZE(sar2130p_ctl), + .ctl = sar2130p_ctl, + .sspp_count = ARRAY_SIZE(sar2130p_sspp), + .sspp = sar2130p_sspp, + .mixer_count = ARRAY_SIZE(sar2130p_lm), + .mixer = sar2130p_lm, + .dspp_count = ARRAY_SIZE(sar2130p_dspp), + .dspp = sar2130p_dspp, + .pingpong_count = ARRAY_SIZE(sar2130p_pp), + .pingpong = sar2130p_pp, + .dsc_count = ARRAY_SIZE(sar2130p_dsc), + .dsc = sar2130p_dsc, + .merge_3d_count = ARRAY_SIZE(sar2130p_merge_3d), + .merge_3d = sar2130p_merge_3d, + .wb_count = ARRAY_SIZE(sar2130p_wb), + .wb = sar2130p_wb, + .intf_count = ARRAY_SIZE(sar2130p_intf), + .intf = sar2130p_intf, + .vbif_count = ARRAY_SIZE(sm8550_vbif), + .vbif = sm8550_vbif, + .perf = &sar2130p_perf_data, +}; + +#endif diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 323b0db1f32b..14cd588a56ee 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -759,7 +759,7 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = { #include "catalog/dpu_8_4_sa8775p.h" #include "catalog/dpu_9_0_sm8550.h" - +#include "catalog/dpu_9_1_sar2130p.h" #include "catalog/dpu_9_2_x1e80100.h" #include "catalog/dpu_10_0_sm8650.h" diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index 4cea19e1a203..e9b627e02c89 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -841,6 +841,7 @@ extern const struct dpu_mdss_cfg dpu_msm8937_cfg; extern const struct dpu_mdss_cfg dpu_msm8953_cfg; extern const struct dpu_mdss_cfg dpu_msm8996_cfg; extern const struct dpu_mdss_cfg dpu_msm8998_cfg; +extern const struct dpu_mdss_cfg dpu_sar2130p_cfg; extern const struct dpu_mdss_cfg dpu_sdm630_cfg; extern const struct dpu_mdss_cfg dpu_sdm660_cfg; extern const struct dpu_mdss_cfg dpu_sdm845_cfg; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 3305ad0623ca..1fd82b6747e9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1512,6 +1512,7 @@ static const struct of_device_id dpu_dt_match[] = { { .compatible = "qcom,msm8998-dpu", .data = &dpu_msm8998_cfg, }, { .compatible = "qcom,qcm2290-dpu", .data = &dpu_qcm2290_cfg, }, { .compatible = "qcom,sa8775p-dpu", .data = &dpu_sa8775p_cfg, }, + { .compatible = "qcom,sar2130p-dpu", .data = &dpu_sar2130p_cfg, }, { .compatible = "qcom,sdm630-mdp5", .data = &dpu_sdm630_cfg, }, { .compatible = "qcom,sdm660-mdp5", .data = &dpu_sdm660_cfg, }, { .compatible = "qcom,sdm670-dpu", .data = &dpu_sdm670_cfg, }, From 1735917ac44a0e28d7f247936736a2292c50bba3 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 8 Apr 2025 16:54:26 +0300 Subject: [PATCH 31/84] drm/msm/hdmi: move msm_hdmi_audio_update() out of msm_hdmi_set_timings() There is a duplication between msm_hdmi_audio_update() calls in msm_hdmi_set_timings() and msm_hdmi_bridge_atomic_pre_enable(). Merge those two calls to be performed unconditionally at msm_hdmi_bridge_atomic_pre_enable(). Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/647505/ Link: https://lore.kernel.org/r/20250408-drm-hdmi-acr-v2-2-dee7298ab1af@oss.qualcomm.com --- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 7f71956806a2..9f1191e4c020 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -324,10 +324,11 @@ static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge, msm_hdmi_phy_resource_enable(phy); msm_hdmi_power_on(bridge); hdmi->power_on = true; - if (connector->display_info.is_hdmi) - msm_hdmi_audio_update(hdmi); } + if (connector->display_info.is_hdmi) + msm_hdmi_audio_update(hdmi); + drm_atomic_helper_connector_hdmi_update_infoframes(connector, state); msm_hdmi_phy_powerup(phy, hdmi->pixclock); @@ -411,9 +412,6 @@ static void msm_hdmi_set_timings(struct hdmi *hdmi, frame_ctrl |= HDMI_FRAME_CTRL_INTERLACED_EN; DBG("frame_ctrl=%08x", frame_ctrl); hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl); - - if (hdmi->connector->display_info.is_hdmi) - msm_hdmi_audio_update(hdmi); } static const struct drm_edid *msm_hdmi_bridge_edid_read(struct drm_bridge *bridge, From 88321e3529f1e4541fef25a5625b18ce234765de Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 8 Apr 2025 16:54:27 +0300 Subject: [PATCH 32/84] drm/msm/hdmi: use new helper for ACR tables Use new drm_hdmi_acr_get_n_cts() helper instead of hand-coding the tables. Instead of storing the rate 'index', store the audio sample rate in hdmi->audio.rate, removing the need for even more defines. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/647507/ Link: https://lore.kernel.org/r/20250408-drm-hdmi-acr-v2-3-dee7298ab1af@oss.qualcomm.com --- drivers/gpu/drm/msm/hdmi/hdmi_audio.c | 107 +++----------------------- 1 file changed, 9 insertions(+), 98 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_audio.c b/drivers/gpu/drm/msm/hdmi/hdmi_audio.c index 8bb975e82c17..b9ec14ef2c20 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_audio.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_audio.c @@ -4,6 +4,7 @@ * Author: Rob Clark */ +#include #include #include @@ -12,71 +13,9 @@ #include "hdmi.h" -/* Supported HDMI Audio sample rates */ -#define MSM_HDMI_SAMPLE_RATE_32KHZ 0 -#define MSM_HDMI_SAMPLE_RATE_44_1KHZ 1 -#define MSM_HDMI_SAMPLE_RATE_48KHZ 2 -#define MSM_HDMI_SAMPLE_RATE_88_2KHZ 3 -#define MSM_HDMI_SAMPLE_RATE_96KHZ 4 -#define MSM_HDMI_SAMPLE_RATE_176_4KHZ 5 -#define MSM_HDMI_SAMPLE_RATE_192KHZ 6 -#define MSM_HDMI_SAMPLE_RATE_MAX 7 - - -struct hdmi_msm_audio_acr { - uint32_t n; /* N parameter for clock regeneration */ - uint32_t cts; /* CTS parameter for clock regeneration */ -}; - -struct hdmi_msm_audio_arcs { - unsigned long int pixclock; - struct hdmi_msm_audio_acr lut[MSM_HDMI_SAMPLE_RATE_MAX]; -}; - -#define HDMI_MSM_AUDIO_ARCS(pclk, ...) { (1000 * (pclk)), __VA_ARGS__ } - -/* Audio constants lookup table for hdmi_msm_audio_acr_setup */ -/* Valid Pixel-Clock rates: 25.2MHz, 27MHz, 27.03MHz, 74.25MHz, 148.5MHz */ -static const struct hdmi_msm_audio_arcs acr_lut[] = { - /* 25.200MHz */ - HDMI_MSM_AUDIO_ARCS(25200, { - {4096, 25200}, {6272, 28000}, {6144, 25200}, {12544, 28000}, - {12288, 25200}, {25088, 28000}, {24576, 25200} }), - /* 27.000MHz */ - HDMI_MSM_AUDIO_ARCS(27000, { - {4096, 27000}, {6272, 30000}, {6144, 27000}, {12544, 30000}, - {12288, 27000}, {25088, 30000}, {24576, 27000} }), - /* 27.027MHz */ - HDMI_MSM_AUDIO_ARCS(27030, { - {4096, 27027}, {6272, 30030}, {6144, 27027}, {12544, 30030}, - {12288, 27027}, {25088, 30030}, {24576, 27027} }), - /* 74.250MHz */ - HDMI_MSM_AUDIO_ARCS(74250, { - {4096, 74250}, {6272, 82500}, {6144, 74250}, {12544, 82500}, - {12288, 74250}, {25088, 82500}, {24576, 74250} }), - /* 148.500MHz */ - HDMI_MSM_AUDIO_ARCS(148500, { - {4096, 148500}, {6272, 165000}, {6144, 148500}, {12544, 165000}, - {12288, 148500}, {25088, 165000}, {24576, 148500} }), -}; - -static const struct hdmi_msm_audio_arcs *get_arcs(unsigned long int pixclock) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(acr_lut); i++) { - const struct hdmi_msm_audio_arcs *arcs = &acr_lut[i]; - if (arcs->pixclock == pixclock) - return arcs; - } - - return NULL; -} - int msm_hdmi_audio_update(struct hdmi *hdmi) { struct hdmi_audio *audio = &hdmi->audio; - const struct hdmi_msm_audio_arcs *arcs = NULL; bool enabled = audio->enabled; uint32_t acr_pkt_ctrl, vbi_pkt_ctrl, aud_pkt_ctrl; uint32_t audio_config; @@ -94,15 +33,6 @@ int msm_hdmi_audio_update(struct hdmi *hdmi) enabled = false; } - if (enabled) { - arcs = get_arcs(hdmi->pixclock); - if (!arcs) { - DBG("disabling audio: unsupported pixclock: %lu", - hdmi->pixclock); - enabled = false; - } - } - /* Read first before writing */ acr_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_ACR_PKT_CTRL); vbi_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_VBI_PKT_CTRL); @@ -116,15 +46,12 @@ int msm_hdmi_audio_update(struct hdmi *hdmi) uint32_t n, cts, multiplier; enum hdmi_acr_cts select; - n = arcs->lut[audio->rate].n; - cts = arcs->lut[audio->rate].cts; + drm_hdmi_acr_get_n_cts(hdmi->pixclock, audio->rate, &n, &cts); - if ((MSM_HDMI_SAMPLE_RATE_192KHZ == audio->rate) || - (MSM_HDMI_SAMPLE_RATE_176_4KHZ == audio->rate)) { + if (audio->rate == 192000 || audio->rate == 176400) { multiplier = 4; n >>= 2; /* divide N by 4 and use multiplier */ - } else if ((MSM_HDMI_SAMPLE_RATE_96KHZ == audio->rate) || - (MSM_HDMI_SAMPLE_RATE_88_2KHZ == audio->rate)) { + } else if (audio->rate == 96000 || audio->rate == 88200) { multiplier = 2; n >>= 1; /* divide N by 2 and use multiplier */ } else { @@ -137,13 +64,11 @@ int msm_hdmi_audio_update(struct hdmi *hdmi) acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_AUDIO_PRIORITY; acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_N_MULTIPLIER(multiplier); - if ((MSM_HDMI_SAMPLE_RATE_48KHZ == audio->rate) || - (MSM_HDMI_SAMPLE_RATE_96KHZ == audio->rate) || - (MSM_HDMI_SAMPLE_RATE_192KHZ == audio->rate)) + if (audio->rate == 48000 || audio->rate == 96000 || + audio->rate == 192000) select = ACR_48; - else if ((MSM_HDMI_SAMPLE_RATE_44_1KHZ == audio->rate) || - (MSM_HDMI_SAMPLE_RATE_88_2KHZ == audio->rate) || - (MSM_HDMI_SAMPLE_RATE_176_4KHZ == audio->rate)) + else if (audio->rate == 44100 || audio->rate == 88200 || + audio->rate == 176400) select = ACR_44; else /* default to 32k */ select = ACR_32; @@ -204,7 +129,6 @@ int msm_hdmi_bridge_audio_prepare(struct drm_connector *connector, { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; - unsigned int rate; int ret; drm_dbg_driver(bridge->dev, "%u Hz, %d bit, %d channels\n", @@ -214,25 +138,12 @@ int msm_hdmi_bridge_audio_prepare(struct drm_connector *connector, switch (params->sample_rate) { case 32000: - rate = MSM_HDMI_SAMPLE_RATE_32KHZ; - break; case 44100: - rate = MSM_HDMI_SAMPLE_RATE_44_1KHZ; - break; case 48000: - rate = MSM_HDMI_SAMPLE_RATE_48KHZ; - break; case 88200: - rate = MSM_HDMI_SAMPLE_RATE_88_2KHZ; - break; case 96000: - rate = MSM_HDMI_SAMPLE_RATE_96KHZ; - break; case 176400: - rate = MSM_HDMI_SAMPLE_RATE_176_4KHZ; - break; case 192000: - rate = MSM_HDMI_SAMPLE_RATE_192KHZ; break; default: drm_err(bridge->dev, "rate[%d] not supported!\n", @@ -245,7 +156,7 @@ int msm_hdmi_bridge_audio_prepare(struct drm_connector *connector, if (ret) return ret; - hdmi->audio.rate = rate; + hdmi->audio.rate = params->sample_rate; hdmi->audio.channels = params->cea.channels; hdmi->audio.enabled = true; From b43c524134e0b0ae38acecc4e1dc585940ff6f88 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 1 Mar 2025 11:24:54 +0200 Subject: [PATCH 33/84] drm/msm/dpu: remove DSC feature bit for PINGPONG on MSM8937 The MSM8937 platform doesn't have DSC blocks nor does have it DSC registers in the PINGPONG block. Drop the DPU_PINGPONG_DSC feature bit from the PINGPONG's feature mask and, as it is the only remaining bit, drop the .features assignment completely. Fixes: c079680bb0fa ("drm/msm/dpu: Add support for MSM8937") Reported-by: Abhinav Kumar Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/640299/ Link: https://lore.kernel.org/r/20250301-dpu-fix-catalog-v2-1-498271be8b50@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h index ad60089f18ea..39027a21c6fe 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h @@ -100,14 +100,12 @@ static const struct dpu_pingpong_cfg msm8937_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_MSM8996_MASK, .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_MSM8996_MASK, .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), From 5be98120115c46907921e29344291628cf79912a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 1 Mar 2025 11:24:55 +0200 Subject: [PATCH 34/84] drm/msm/dpu: remove DSC feature bit for PINGPONG on MSM8917 The MSM8917 platform doesn't have DSC blocks nor does have it DSC registers in the PINGPONG block. Drop the DPU_PINGPONG_DSC feature bit from the PINGPONG's feature mask and, as it is the only remaining bit, drop the .features assignment completely. Fixes: 62af6e1cb596 ("drm/msm/dpu: Add support for MSM8917") Reported-by: Abhinav Kumar Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/640301/ Link: https://lore.kernel.org/r/20250301-dpu-fix-catalog-v2-2-498271be8b50@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h index a1cf89a0a42d..8d1b43ea1663 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h @@ -93,7 +93,6 @@ static const struct dpu_pingpong_cfg msm8917_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_MSM8996_MASK, .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), From 5232a29ebc74df4abf790147a06db451d824cd92 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 1 Mar 2025 11:24:56 +0200 Subject: [PATCH 35/84] drm/msm/dpu: remove DSC feature bit for PINGPONG on MSM8953 The MSM8953 platform doesn't have DSC blocks nor does have it DSC registers in the PINGPONG block. Drop the DPU_PINGPONG_DSC feature bit from the PINGPONG's feature mask and, as it is the only remaining bit, drop the .features assignment completely. Fixes: 7a6109ce1c2c ("drm/msm/dpu: Add support for MSM8953") Reported-by: Abhinav Kumar Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/640303/ Link: https://lore.kernel.org/r/20250301-dpu-fix-catalog-v2-3-498271be8b50@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h index eea9b80e2287..16c12499b24b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h @@ -100,14 +100,12 @@ static const struct dpu_pingpong_cfg msm8953_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_MSM8996_MASK, .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_MSM8996_MASK, .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), From e1fbb0d78e86eb8d6b11ae7a48905943e8c7b0bd Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 1 Mar 2025 11:24:57 +0200 Subject: [PATCH 36/84] drm/msm/dpu: drop TE2 definitions Neither DPU driver nor vendor SDE driver do not use TE2 definitions (and, in case of SDE driver, never did). Semantics of the TE2 feature bit and .te2 sblk are not completely clear. Drop these bits from the catalog with the possibility of reintroducing them later if we need to support ppsplit. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/640305/ Link: https://lore.kernel.org/r/20250301-dpu-fix-catalog-v2-4-498271be8b50@linaro.org Signed-off-by: Dmitry Baryshkov --- .../drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h | 8 ++++---- .../drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h | 8 ++++---- .../drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h | 8 ++++---- .../drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h | 4 ++-- .../drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h | 8 ++++---- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 17 ----------------- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 6 +----- 7 files changed, 19 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h index ae18a354e5d2..91f514d28ac6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h @@ -181,15 +181,15 @@ static const struct dpu_pingpong_cfg msm8996_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_MSM8996_TE2_MASK, - .sblk = &msm8996_pp_sblk_te, + .features = PINGPONG_MSM8996_MASK, + .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_MSM8996_TE2_MASK, - .sblk = &msm8996_pp_sblk_te, + .features = PINGPONG_MSM8996_MASK, + .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), }, { diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h index 746474679ef5..413cd59dc0c4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h @@ -170,15 +170,15 @@ static const struct dpu_pingpong_cfg msm8998_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SDM845_TE2_MASK, - .sblk = &sdm845_pp_sblk_te, + .features = PINGPONG_SDM845_MASK, + .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_SDM845_TE2_MASK, - .sblk = &sdm845_pp_sblk_te, + .features = PINGPONG_SDM845_MASK, + .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), }, { diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h index bb89da0a481d..b2eb7ca699e3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h @@ -141,15 +141,15 @@ static const struct dpu_pingpong_cfg sdm660_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SDM845_TE2_MASK, - .sblk = &sdm845_pp_sblk_te, + .features = PINGPONG_SDM845_MASK, + .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_SDM845_TE2_MASK, - .sblk = &sdm845_pp_sblk_te, + .features = PINGPONG_SDM845_MASK, + .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), }, { diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h index 7caf876ca3e3..c9e485e11b53 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h @@ -115,8 +115,8 @@ static const struct dpu_pingpong_cfg sdm630_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SDM845_TE2_MASK, - .sblk = &sdm845_pp_sblk_te, + .features = PINGPONG_SDM845_MASK, + .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h index ab7b4822ca63..49363d7d5b93 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h @@ -194,15 +194,15 @@ static const struct dpu_pingpong_cfg sdm845_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SDM845_TE2_MASK, - .sblk = &sdm845_pp_sblk_te, + .features = PINGPONG_SDM845_MASK, + .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_SDM845_TE2_MASK, - .sblk = &sdm845_pp_sblk_te, + .features = PINGPONG_SDM845_MASK, + .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), }, { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 14cd588a56ee..338fdec761d4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -98,15 +98,9 @@ #define PINGPONG_MSM8996_MASK \ (BIT(DPU_PINGPONG_DSC)) -#define PINGPONG_MSM8996_TE2_MASK \ - (PINGPONG_MSM8996_MASK | BIT(DPU_PINGPONG_TE2)) - #define PINGPONG_SDM845_MASK \ (BIT(DPU_PINGPONG_DITHER) | BIT(DPU_PINGPONG_DSC)) -#define PINGPONG_SDM845_TE2_MASK \ - (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2)) - #define PINGPONG_SM8150_MASK \ (BIT(DPU_PINGPONG_DITHER) | BIT(DPU_PINGPONG_DSC)) @@ -434,22 +428,11 @@ static const struct dpu_dspp_sub_blks sdm845_dspp_sblk = { /************************************************************* * PINGPONG sub blocks config *************************************************************/ -static const struct dpu_pingpong_sub_blks msm8996_pp_sblk_te = { - .te2 = {.name = "te2", .base = 0x2000, .len = 0x0, - .version = 0x1}, -}; static const struct dpu_pingpong_sub_blks msm8996_pp_sblk = { /* No dither block */ }; -static const struct dpu_pingpong_sub_blks sdm845_pp_sblk_te = { - .te2 = {.name = "te2", .base = 0x2000, .len = 0x0, - .version = 0x1}, - .dither = {.name = "dither", .base = 0x30e0, - .len = 0x20, .version = 0x10000}, -}; - static const struct dpu_pingpong_sub_blks sdm845_pp_sblk = { .dither = {.name = "dither", .base = 0x30e0, .len = 0x20, .version = 0x10000}, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index e9b627e02c89..01dd6e65f777 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -115,7 +115,6 @@ enum { /** * PINGPONG sub-blocks - * @DPU_PINGPONG_TE2 Additional tear check block for split pipes * @DPU_PINGPONG_SPLIT PP block supports split fifo * @DPU_PINGPONG_SLAVE PP block is a suitable slave for split fifo * @DPU_PINGPONG_DITHER Dither blocks @@ -123,8 +122,7 @@ enum { * @DPU_PINGPONG_MAX */ enum { - DPU_PINGPONG_TE2 = 0x1, - DPU_PINGPONG_SPLIT, + DPU_PINGPONG_SPLIT = 0x1, DPU_PINGPONG_SLAVE, DPU_PINGPONG_DITHER, DPU_PINGPONG_DSC, @@ -404,8 +402,6 @@ struct dpu_dspp_sub_blks { }; struct dpu_pingpong_sub_blks { - struct dpu_pp_blk te; - struct dpu_pp_blk te2; struct dpu_pp_blk dither; }; From 075667e986f33ca6e897094b1f0fc92c2745d99b Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 1 Mar 2025 11:24:58 +0200 Subject: [PATCH 37/84] drm/msm/dpu: remove DSC feature bit for PINGPONG on SDM630 The SDM630 platform doesn't have DSC blocks nor does have it DSC registers in the PINGPONG block. Drop the DPU_PINGPONG_DSC feature bit from the PINGPONG's feature mask, replacing PINGPONG_SDM845_MASK with BIT(DPU_PINGPONG_DITHER). Fixes: 7204df5e7e68 ("drm/msm/dpu: add support for SDM660 and SDM630 platforms") Reported-by: Abhinav Kumar Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/640308/ Link: https://lore.kernel.org/r/20250301-dpu-fix-catalog-v2-5-498271be8b50@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h index c9e485e11b53..85e121ad84a0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h @@ -115,14 +115,14 @@ static const struct dpu_pingpong_cfg sdm630_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SDM845_MASK, + .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x71000, .len = 0xd4, - .features = PINGPONG_SDM845_MASK, + .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14), From 98a8920e7b07641eb1996b3c39b9ce27fc05dbb9 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 2 May 2025 01:41:42 +0300 Subject: [PATCH 38/84] drm/msm/dp: reuse generic HDMI codec implementation The MSM DisplayPort driver implements several HDMI codec functions in the driver, e.g. it manually manages HDMI codec device registration, returning ELD and plugged_cb support. In order to reduce code duplication reuse drm_hdmi_audio_* helpers and drm_bridge_connector integration. Signed-off-by: Dmitry Baryshkov Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/649728/ Link: https://lore.kernel.org/r/20250423-dp-hdmi-audio-v7-1-8407a23e55b2@oss.qualcomm.com --- drivers/gpu/drm/msm/Kconfig | 1 + drivers/gpu/drm/msm/dp/dp_audio.c | 131 +++------------------------- drivers/gpu/drm/msm/dp/dp_audio.h | 27 ++---- drivers/gpu/drm/msm/dp/dp_display.c | 28 +----- drivers/gpu/drm/msm/dp/dp_display.h | 6 -- drivers/gpu/drm/msm/dp/dp_drm.c | 8 ++ 6 files changed, 31 insertions(+), 170 deletions(-) diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 974bc7c0ea76..7f127e2ae442 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -104,6 +104,7 @@ config DRM_MSM_DPU config DRM_MSM_DP bool "Enable DisplayPort support in MSM DRM driver" depends on DRM_MSM + select DRM_DISPLAY_HDMI_AUDIO_HELPER select RATIONAL default y help diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index 70fdc9fe228a..f8bfb908f9b4 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -13,13 +13,13 @@ #include "dp_catalog.h" #include "dp_audio.h" +#include "dp_drm.h" #include "dp_panel.h" #include "dp_reg.h" #include "dp_display.h" #include "dp_utils.h" struct msm_dp_audio_private { - struct platform_device *audio_pdev; struct platform_device *pdev; struct drm_device *drm_dev; struct msm_dp_catalog *catalog; @@ -160,24 +160,11 @@ static void msm_dp_audio_enable(struct msm_dp_audio_private *audio, bool enable) msm_dp_catalog_audio_enable(catalog, enable); } -static struct msm_dp_audio_private *msm_dp_audio_get_data(struct platform_device *pdev) +static struct msm_dp_audio_private *msm_dp_audio_get_data(struct msm_dp *msm_dp_display) { struct msm_dp_audio *msm_dp_audio; - struct msm_dp *msm_dp_display; - - if (!pdev) { - DRM_ERROR("invalid input\n"); - return ERR_PTR(-ENODEV); - } - - msm_dp_display = platform_get_drvdata(pdev); - if (!msm_dp_display) { - DRM_ERROR("invalid input\n"); - return ERR_PTR(-ENODEV); - } msm_dp_audio = msm_dp_display->msm_dp_audio; - if (!msm_dp_audio) { DRM_ERROR("invalid msm_dp_audio data\n"); return ERR_PTR(-EINVAL); @@ -186,68 +173,16 @@ static struct msm_dp_audio_private *msm_dp_audio_get_data(struct platform_device return container_of(msm_dp_audio, struct msm_dp_audio_private, msm_dp_audio); } -static int msm_dp_audio_hook_plugged_cb(struct device *dev, void *data, - hdmi_codec_plugged_cb fn, - struct device *codec_dev) -{ - - struct platform_device *pdev; - struct msm_dp *msm_dp_display; - - pdev = to_platform_device(dev); - if (!pdev) { - pr_err("invalid input\n"); - return -ENODEV; - } - - msm_dp_display = platform_get_drvdata(pdev); - if (!msm_dp_display) { - pr_err("invalid input\n"); - return -ENODEV; - } - - return msm_dp_display_set_plugged_cb(msm_dp_display, fn, codec_dev); -} - -static int msm_dp_audio_get_eld(struct device *dev, - void *data, uint8_t *buf, size_t len) -{ - struct platform_device *pdev; - struct msm_dp *msm_dp_display; - - pdev = to_platform_device(dev); - - if (!pdev) { - DRM_ERROR("invalid input\n"); - return -ENODEV; - } - - msm_dp_display = platform_get_drvdata(pdev); - if (!msm_dp_display) { - DRM_ERROR("invalid input\n"); - return -ENODEV; - } - - mutex_lock(&msm_dp_display->connector->eld_mutex); - memcpy(buf, msm_dp_display->connector->eld, - min(sizeof(msm_dp_display->connector->eld), len)); - mutex_unlock(&msm_dp_display->connector->eld_mutex); - - return 0; -} - -int msm_dp_audio_hw_params(struct device *dev, - void *data, - struct hdmi_codec_daifmt *daifmt, - struct hdmi_codec_params *params) +int msm_dp_audio_prepare(struct drm_connector *connector, + struct drm_bridge *bridge, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params) { int rc = 0; struct msm_dp_audio_private *audio; - struct platform_device *pdev; struct msm_dp *msm_dp_display; - pdev = to_platform_device(dev); - msm_dp_display = platform_get_drvdata(pdev); + msm_dp_display = to_dp_bridge(bridge)->msm_dp_display; /* * there could be cases where sound card can be opened even @@ -262,7 +197,7 @@ int msm_dp_audio_hw_params(struct device *dev, goto end; } - audio = msm_dp_audio_get_data(pdev); + audio = msm_dp_audio_get_data(msm_dp_display); if (IS_ERR(audio)) { rc = PTR_ERR(audio); goto end; @@ -281,15 +216,14 @@ int msm_dp_audio_hw_params(struct device *dev, return rc; } -static void msm_dp_audio_shutdown(struct device *dev, void *data) +void msm_dp_audio_shutdown(struct drm_connector *connector, + struct drm_bridge *bridge) { struct msm_dp_audio_private *audio; - struct platform_device *pdev; struct msm_dp *msm_dp_display; - pdev = to_platform_device(dev); - msm_dp_display = platform_get_drvdata(pdev); - audio = msm_dp_audio_get_data(pdev); + msm_dp_display = to_dp_bridge(bridge)->msm_dp_display; + audio = msm_dp_audio_get_data(msm_dp_display); if (IS_ERR(audio)) { DRM_ERROR("failed to get audio data\n"); return; @@ -311,47 +245,6 @@ static void msm_dp_audio_shutdown(struct device *dev, void *data) msm_dp_display_signal_audio_complete(msm_dp_display); } -static const struct hdmi_codec_ops msm_dp_audio_codec_ops = { - .hw_params = msm_dp_audio_hw_params, - .audio_shutdown = msm_dp_audio_shutdown, - .get_eld = msm_dp_audio_get_eld, - .hook_plugged_cb = msm_dp_audio_hook_plugged_cb, -}; - -static struct hdmi_codec_pdata codec_data = { - .ops = &msm_dp_audio_codec_ops, - .max_i2s_channels = 8, - .i2s = 1, -}; - -void msm_dp_unregister_audio_driver(struct device *dev, struct msm_dp_audio *msm_dp_audio) -{ - struct msm_dp_audio_private *audio_priv; - - audio_priv = container_of(msm_dp_audio, struct msm_dp_audio_private, msm_dp_audio); - - if (audio_priv->audio_pdev) { - platform_device_unregister(audio_priv->audio_pdev); - audio_priv->audio_pdev = NULL; - } -} - -int msm_dp_register_audio_driver(struct device *dev, - struct msm_dp_audio *msm_dp_audio) -{ - struct msm_dp_audio_private *audio_priv; - - audio_priv = container_of(msm_dp_audio, - struct msm_dp_audio_private, msm_dp_audio); - - audio_priv->audio_pdev = platform_device_register_data(dev, - HDMI_CODEC_DRV_NAME, - PLATFORM_DEVID_AUTO, - &codec_data, - sizeof(codec_data)); - return PTR_ERR_OR_ZERO(audio_priv->audio_pdev); -} - struct msm_dp_audio *msm_dp_audio_get(struct platform_device *pdev, struct msm_dp_catalog *catalog) { diff --git a/drivers/gpu/drm/msm/dp/dp_audio.h b/drivers/gpu/drm/msm/dp/dp_audio.h index beea34cbab77..58fc14693e48 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.h +++ b/drivers/gpu/drm/msm/dp/dp_audio.h @@ -35,23 +35,6 @@ struct msm_dp_audio { struct msm_dp_audio *msm_dp_audio_get(struct platform_device *pdev, struct msm_dp_catalog *catalog); -/** - * msm_dp_register_audio_driver() - * - * Registers DP device with hdmi_codec interface. - * - * @dev: DP device instance. - * @msm_dp_audio: an instance of msm_dp_audio module. - * - * - * Returns the error code in case of failure, otherwise - * zero on success. - */ -int msm_dp_register_audio_driver(struct device *dev, - struct msm_dp_audio *msm_dp_audio); - -void msm_dp_unregister_audio_driver(struct device *dev, struct msm_dp_audio *msm_dp_audio); - /** * msm_dp_audio_put() * @@ -61,10 +44,12 @@ void msm_dp_unregister_audio_driver(struct device *dev, struct msm_dp_audio *msm */ void msm_dp_audio_put(struct msm_dp_audio *msm_dp_audio); -int msm_dp_audio_hw_params(struct device *dev, - void *data, - struct hdmi_codec_daifmt *daifmt, - struct hdmi_codec_params *params); +int msm_dp_audio_prepare(struct drm_connector *connector, + struct drm_bridge *bridge, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params); +void msm_dp_audio_shutdown(struct drm_connector *connector, + struct drm_bridge *bridge); #endif /* _DP_AUDIO_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index bbc47d86ae9e..ece184d20c0f 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "msm_drv.h" @@ -288,13 +289,6 @@ static int msm_dp_display_bind(struct device *dev, struct device *master, goto end; } - - rc = msm_dp_register_audio_driver(dev, dp->audio); - if (rc) { - DRM_ERROR("Audio registration Dp failed\n"); - goto end; - } - rc = msm_dp_hpd_event_thread_start(dp); if (rc) { DRM_ERROR("Event thread create failed\n"); @@ -316,7 +310,6 @@ static void msm_dp_display_unbind(struct device *dev, struct device *master, of_dp_aux_depopulate_bus(dp->aux); - msm_dp_unregister_audio_driver(dev, dp->audio); msm_dp_aux_unregister(dp->aux); dp->drm_dev = NULL; dp->aux->drm_dev = NULL; @@ -626,9 +619,9 @@ static void msm_dp_display_handle_plugged_change(struct msm_dp *msm_dp_display, struct msm_dp_display_private, msm_dp_display); /* notify audio subsystem only if sink supports audio */ - if (msm_dp_display->plugged_cb && msm_dp_display->codec_dev && - dp->audio_supported) - msm_dp_display->plugged_cb(msm_dp_display->codec_dev, plugged); + if (dp->audio_supported) + drm_connector_hdmi_audio_plugged_notify(msm_dp_display->connector, + plugged); } static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp, u32 data) @@ -907,19 +900,6 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp) return 0; } -int msm_dp_display_set_plugged_cb(struct msm_dp *msm_dp_display, - hdmi_codec_plugged_cb fn, struct device *codec_dev) -{ - bool plugged; - - msm_dp_display->plugged_cb = fn; - msm_dp_display->codec_dev = codec_dev; - plugged = msm_dp_display->link_ready; - msm_dp_display_handle_plugged_change(msm_dp_display, plugged); - - return 0; -} - /** * msm_dp_bridge_mode_valid - callback to determine if specified mode is valid * @bridge: Pointer to drm bridge structure diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index ecbc2d92f546..cc6e2cab36e9 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -7,7 +7,6 @@ #define _DP_DISPLAY_H_ #include "dp_panel.h" -#include #include "disp/msm_disp_snapshot.h" #define DP_MAX_PIXEL_CLK_KHZ 675000 @@ -15,7 +14,6 @@ struct msm_dp { struct drm_device *drm_dev; struct platform_device *pdev; - struct device *codec_dev; struct drm_connector *connector; struct drm_bridge *next_bridge; bool link_ready; @@ -25,14 +23,10 @@ struct msm_dp { bool is_edp; bool internal_hpd; - hdmi_codec_plugged_cb plugged_cb; - struct msm_dp_audio *msm_dp_audio; bool psr_supported; }; -int msm_dp_display_set_plugged_cb(struct msm_dp *msm_dp_display, - hdmi_codec_plugged_cb fn, struct device *codec_dev); int msm_dp_display_get_modes(struct msm_dp *msm_dp_display); bool msm_dp_display_check_video_test(struct msm_dp *msm_dp_display); int msm_dp_display_get_test_bpp(struct msm_dp *msm_dp_display); diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index 293f4745f1e2..f222d7ccaa88 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -12,6 +12,7 @@ #include "msm_drv.h" #include "msm_kms.h" +#include "dp_audio.h" #include "dp_drm.h" /** @@ -114,6 +115,9 @@ static const struct drm_bridge_funcs msm_dp_bridge_ops = { .hpd_disable = msm_dp_bridge_hpd_disable, .hpd_notify = msm_dp_bridge_hpd_notify, .debugfs_init = msm_dp_bridge_debugfs_init, + + .dp_audio_prepare = msm_dp_audio_prepare, + .dp_audio_shutdown = msm_dp_audio_shutdown, }; static int msm_edp_bridge_atomic_check(struct drm_bridge *drm_bridge, @@ -321,9 +325,13 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev, */ if (!msm_dp_display->is_edp) { bridge->ops = + DRM_BRIDGE_OP_DP_AUDIO | DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_MODES; + bridge->hdmi_audio_dev = &msm_dp_display->pdev->dev; + bridge->hdmi_audio_max_i2s_playback_channels = 8; + bridge->hdmi_audio_dai_port = -1; } rc = devm_drm_bridge_add(dev->dev, bridge); From 60b8d3a2365a30aadd514aaf571c6baecd9885ba Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Thu, 6 Mar 2025 19:11:14 +0100 Subject: [PATCH 39/84] dt-bindings: display: msm: sm8350-mdss: Describe the CPU-CFG icc path There's a separate path that allows register access from CPUSS. Describe it. Signed-off-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/641464/ Link: https://lore.kernel.org/r/20250306-topic-dt_bindings_fixups-v1-2-0c84aceb0ef9@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- .../devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml index 163fc83c1e80..3733d8cd2ae0 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml @@ -38,12 +38,16 @@ properties: maxItems: 1 interconnects: - maxItems: 2 + items: + - description: Interconnect path from the MDP0 port to the data bus + - description: Interconnect path from the MDP1 port to the data bus + - description: Interconnect path from the CPU to the reg bus interconnect-names: items: - const: mdp0-mem - const: mdp1-mem + - const: cpu-cfg patternProperties: "^display-controller@[0-9a-f]+$": From 850e13b65e3ce47c88aedae812352e55848a21c2 Mon Sep 17 00:00:00 2001 From: Ayushi Makhija Date: Thu, 24 Apr 2025 11:54:21 +0530 Subject: [PATCH 40/84] dt-bindings: display: msm-dsi-phy-7nm: document the SA8775P DSI PHY Document the DSI PHY on the SA8775P Platform. Signed-off-by: Ayushi Makhija Acked-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/649838/ Link: https://lore.kernel.org/r/20250424062431.2040692-2-quic_amakhija@quicinc.com Signed-off-by: Dmitry Baryshkov --- Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml index f79be422b889..3c75ff42999a 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml @@ -17,6 +17,7 @@ properties: enum: - qcom,dsi-phy-7nm - qcom,dsi-phy-7nm-8150 + - qcom,sa8775p-dsi-phy-5nm - qcom,sar2130p-dsi-phy-5nm - qcom,sc7280-dsi-phy-7nm - qcom,sm6375-dsi-phy-7nm From 2a0195b94cbc0583c05cb4c9b1b57ba637a25180 Mon Sep 17 00:00:00 2001 From: Ayushi Makhija Date: Thu, 24 Apr 2025 11:54:22 +0530 Subject: [PATCH 41/84] dt-bindings: msm: dsi-controller-main: document the SA8775P DSI CTRL Document the DSI CTRL on the SA8775P Platform. Signed-off-by: Ayushi Makhija Reviewed-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/649855/ Link: https://lore.kernel.org/r/20250424062431.2040692-3-quic_amakhija@quicinc.com Signed-off-by: Dmitry Baryshkov --- .../devicetree/bindings/display/msm/dsi-controller-main.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml index a3e05e34bf14..82fe95a6d959 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml @@ -23,6 +23,7 @@ properties: - qcom,msm8996-dsi-ctrl - qcom,msm8998-dsi-ctrl - qcom,qcm2290-dsi-ctrl + - qcom,sa8775p-dsi-ctrl - qcom,sar2130p-dsi-ctrl - qcom,sc7180-dsi-ctrl - qcom,sc7280-dsi-ctrl @@ -315,6 +316,7 @@ allOf: contains: enum: - qcom,msm8998-dsi-ctrl + - qcom,sa8775p-dsi-ctrl - qcom,sar2130p-dsi-ctrl - qcom,sc7180-dsi-ctrl - qcom,sc7280-dsi-ctrl From a6f2524f4d5e3cfcc17a6de646cb978007d7832f Mon Sep 17 00:00:00 2001 From: Ayushi Makhija Date: Thu, 24 Apr 2025 11:54:23 +0530 Subject: [PATCH 42/84] dt-bindings: display: msm: document DSI controller and phy on SA8775P Document DSI controller and phy on SA8775P platform. Signed-off-by: Ayushi Makhija Reviewed-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/649839/ Link: https://lore.kernel.org/r/20250424062431.2040692-4-quic_amakhija@quicinc.com Signed-off-by: Dmitry Baryshkov --- .../display/msm/qcom,sa8775p-mdss.yaml | 181 +++++++++++++++++- 1 file changed, 180 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml index 5fac3e266703..1053b3bc4908 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml @@ -52,12 +52,23 @@ patternProperties: items: - const: qcom,sa8775p-dp + "^dsi@[0-9a-f]+$": + type: object + additionalProperties: true + properties: + compatible: + contains: + const: qcom,sa8775p-dsi-ctrl + "^phy@[0-9a-f]+$": type: object additionalProperties: true properties: compatible: - const: qcom,sa8775p-edp-phy + contains: + enum: + - qcom,sa8775p-dsi-phy-5nm + - qcom,sa8775p-edp-phy required: - compatible @@ -139,6 +150,20 @@ examples: remote-endpoint = <&mdss0_dp0_in>; }; }; + + port@1 { + reg = <1>; + dpu_intf1_out: endpoint { + remote-endpoint = <&mdss0_dsi0_in>; + }; + }; + + port@2 { + reg = <2>; + dpu_intf2_out: endpoint { + remote-endpoint = <&mdss0_dsi1_in>; + }; + }; }; mdss0_mdp_opp_table: opp-table { @@ -186,6 +211,160 @@ examples: vdda-pll-supply = <&vreg_l4a>; }; + dsi@ae94000 { + compatible = "qcom,sa8775p-dsi-ctrl", "qcom,mdss-dsi-ctrl"; + reg = <0x0ae94000 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <4>; + + clocks = <&dispc_byte_clk>, + <&dispcc_intf_clk>, + <&dispcc_pclk>, + <&dispcc_esc_clk>, + <&dispcc_ahb_clk>, + <&gcc_bus_clk>; + clock-names = "byte", + "byte_intf", + "pixel", + "core", + "iface", + "bus"; + assigned-clocks = <&dispcc_byte_clk>, + <&dispcc_pclk>; + assigned-clock-parents = <&mdss0_dsi0_phy 0>, <&mdss0_dsi0_phy 1>; + phys = <&mdss0_dsi0_phy>; + + operating-points-v2 = <&dsi0_opp_table>; + power-domains = <&rpmhpd SA8775P_MMCX>; + + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mdss0_dsi0_in: endpoint { + remote-endpoint = <&dpu_intf1_out>; + }; + }; + + port@1 { + reg = <1>; + mdss0_dsi0_out: endpoint { }; + }; + }; + + dsi0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-358000000 { + opp-hz = /bits/ 64 <358000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + mdss0_dsi0_phy: phy@ae94400 { + compatible = "qcom,sa8775p-dsi-phy-5nm"; + reg = <0x0ae94400 0x200>, + <0x0ae94600 0x280>, + <0x0ae94900 0x27c>; + reg-names = "dsi_phy", + "dsi_phy_lane", + "dsi_pll"; + + #clock-cells = <1>; + #phy-cells = <0>; + + clocks = <&dispcc_iface_clk>, + <&rpmhcc_ref_clk>; + clock-names = "iface", "ref"; + + vdds-supply = <&vreg_dsi_supply>; + }; + + dsi@ae96000 { + compatible = "qcom,sa8775p-dsi-ctrl", "qcom,mdss-dsi-ctrl"; + reg = <0x0ae96000 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <4>; + + clocks = <&dispc_byte_clk>, + <&dispcc_intf_clk>, + <&dispcc_pclk>, + <&dispcc_esc_clk>, + <&dispcc_ahb_clk>, + <&gcc_bus_clk>; + clock-names = "byte", + "byte_intf", + "pixel", + "core", + "iface", + "bus"; + assigned-clocks = <&dispcc_byte_clk>, + <&dispcc_pclk>; + assigned-clock-parents = <&mdss0_dsi1_phy 0>, <&mdss0_dsi1_phy 1>; + phys = <&mdss0_dsi1_phy>; + + operating-points-v2 = <&dsi1_opp_table>; + power-domains = <&rpmhpd SA8775P_MMCX>; + + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mdss0_dsi1_in: endpoint { + remote-endpoint = <&dpu_intf2_out>; + }; + }; + + port@1 { + reg = <1>; + mdss0_dsi1_out: endpoint { }; + }; + }; + + dsi1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-358000000 { + opp-hz = /bits/ 64 <358000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + mdss0_dsi1_phy: phy@ae96400 { + compatible = "qcom,sa8775p-dsi-phy-5nm"; + reg = <0x0ae96400 0x200>, + <0x0ae96600 0x280>, + <0x0ae96900 0x27c>; + reg-names = "dsi_phy", + "dsi_phy_lane", + "dsi_pll"; + + #clock-cells = <1>; + #phy-cells = <0>; + + clocks = <&dispcc_iface_clk>, + <&rpmhcc_ref_clk>; + clock-names = "iface", "ref"; + + vdds-supply = <&vreg_dsi_supply>; + }; + displayport-controller@af54000 { compatible = "qcom,sa8775p-dp"; From d3979192fac52ef5d158ca494db25bc4fe3166bf Mon Sep 17 00:00:00 2001 From: Ayushi Makhija Date: Thu, 24 Apr 2025 11:54:24 +0530 Subject: [PATCH 43/84] drm/msm/dsi: add DSI PHY configuration on SA8775P The SA8775P SoC uses the 5nm (v4.2) DSI PHY driver with different enable regulator load. Signed-off-by: Ayushi Makhija Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/649842/ Link: https://lore.kernel.org/r/20250424062431.2040692-5-quic_amakhija@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 2 ++ drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 1 + drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 27 +++++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index a58bafe9fe86..5973d7325699 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -581,6 +581,8 @@ static const struct of_device_id dsi_phy_dt_match[] = { .data = &dsi_phy_7nm_cfgs }, { .compatible = "qcom,dsi-phy-7nm-8150", .data = &dsi_phy_7nm_8150_cfgs }, + { .compatible = "qcom,sa8775p-dsi-phy-5nm", + .data = &dsi_phy_5nm_8775p_cfgs }, { .compatible = "qcom,sar2130p-dsi-phy-5nm", .data = &dsi_phy_5nm_sar2130p_cfgs }, { .compatible = "qcom,sc7280-dsi-phy-7nm", diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h index 1ed08b56e056..7ea608f620fe 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h @@ -59,6 +59,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8350_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs; +extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8775p_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8650_cfgs; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c index cad55702746b..c19890358b74 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -1147,6 +1147,10 @@ static const struct regulator_bulk_data dsi_phy_7nm_37750uA_regulators[] = { { .supply = "vdds", .init_load_uA = 37550 }, }; +static const struct regulator_bulk_data dsi_phy_7nm_48000uA_regulators[] = { + { .supply = "vdds", .init_load_uA = 48000 }, +}; + static const struct regulator_bulk_data dsi_phy_7nm_98000uA_regulators[] = { { .supply = "vdds", .init_load_uA = 98000 }, }; @@ -1289,6 +1293,29 @@ const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs = { .quirks = DSI_PHY_7NM_QUIRK_V4_3, }; +const struct msm_dsi_phy_cfg dsi_phy_5nm_8775p_cfgs = { + .has_phy_lane = true, + .regulator_data = dsi_phy_7nm_48000uA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_7nm_48000uA_regulators), + .ops = { + .enable = dsi_7nm_phy_enable, + .disable = dsi_7nm_phy_disable, + .pll_init = dsi_pll_7nm_init, + .save_pll_state = dsi_7nm_pll_save_state, + .restore_pll_state = dsi_7nm_pll_restore_state, + .set_continuous_clock = dsi_7nm_set_continuous_clock, + }, + .min_pll_rate = 600000000UL, +#ifdef CONFIG_64BIT + .max_pll_rate = 5000000000UL, +#else + .max_pll_rate = ULONG_MAX, +#endif + .io_start = { 0xae94400, 0xae96400 }, + .num_dsi_phy = 2, + .quirks = DSI_PHY_7NM_QUIRK_V4_2, +}; + const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs = { .has_phy_lane = true, .regulator_data = dsi_phy_7nm_97800uA_regulators, From 249a965c3759f6a7bffa6e84e33b7020dc0d4d1c Mon Sep 17 00:00:00 2001 From: Ayushi Makhija Date: Fri, 2 May 2025 01:44:35 +0300 Subject: [PATCH 44/84] drm/msm/dsi: add DSI support for SA8775P Add DSI Controller v2.5.1 support for SA8775P SoC. Signed-off-by: Ayushi Makhija Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/651433/ Link: https://lore.kernel.org/r/20250424062431.2040692-6-quic_amakhija@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/dsi_cfg.c | 18 ++++++++++++++++++ drivers/gpu/drm/msm/dsi/dsi_cfg.h | 1 + 2 files changed, 19 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c index 7754dcec33d0..7675558ae2e5 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c @@ -221,6 +221,22 @@ static const struct msm_dsi_config sc7280_dsi_cfg = { }, }; +static const struct regulator_bulk_data sa8775p_dsi_regulators[] = { + { .supply = "vdda", .init_load_uA = 8300 }, /* 1.2 V */ + { .supply = "refgen" }, +}; + +static const struct msm_dsi_config sa8775p_dsi_cfg = { + .io_offset = DSI_6G_REG_SHIFT, + .regulator_data = sa8775p_dsi_regulators, + .num_regulators = ARRAY_SIZE(sa8775p_dsi_regulators), + .bus_clk_names = dsi_v2_4_clk_names, + .num_bus_clks = ARRAY_SIZE(dsi_v2_4_clk_names), + .io_start = { + { 0xae94000, 0xae96000 }, + }, +}; + static const struct msm_dsi_host_cfg_ops msm_dsi_v2_host_ops = { .link_clk_set_rate = dsi_link_clk_set_rate_v2, .link_clk_enable = dsi_link_clk_enable_v2, @@ -294,6 +310,8 @@ static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = { &sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_5_0, &sc7280_dsi_cfg, &msm_dsi_6g_v2_host_ops}, + {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_5_1, + &sa8775p_dsi_cfg, &msm_dsi_6g_v2_host_ops}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_6_0, &sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_7_0, diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h b/drivers/gpu/drm/msm/dsi/dsi_cfg.h index 120cb65164c1..65b0705fac0e 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h @@ -27,6 +27,7 @@ #define MSM_DSI_6G_VER_MINOR_V2_4_0 0x20040000 #define MSM_DSI_6G_VER_MINOR_V2_4_1 0x20040001 #define MSM_DSI_6G_VER_MINOR_V2_5_0 0x20050000 +#define MSM_DSI_6G_VER_MINOR_V2_5_1 0x20050001 #define MSM_DSI_6G_VER_MINOR_V2_6_0 0x20060000 #define MSM_DSI_6G_VER_MINOR_V2_7_0 0x20070000 #define MSM_DSI_6G_VER_MINOR_V2_8_0 0x20080000 From 07a5ebfe04b179b535e3a4cd38722671d87565d4 Mon Sep 17 00:00:00 2001 From: Vignesh Raman Date: Fri, 28 Mar 2025 16:32:33 +0530 Subject: [PATCH 45/84] drm/ci: uprev mesa The current s3cp implementation does not work anymore after the migration, and instead of fixing it and propagating the fix down to us, it's simpler to directly use curl. Uprev mesa [1][2] to adapt these changes. Also replace broken s3cp command with a curl wrapper call in drm-ci. [1] https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34120 [2] https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34244 Signed-off-by: Vignesh Raman Patchwork: https://patchwork.freedesktop.org/patch/645597/ Signed-off-by: Rob Clark --- drivers/gpu/drm/ci/build-igt.sh | 2 +- drivers/gpu/drm/ci/build.sh | 6 +++--- drivers/gpu/drm/ci/gitlab-ci.yml | 6 ++++-- drivers/gpu/drm/ci/image-tags.yml | 2 +- drivers/gpu/drm/ci/lava-submit.sh | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/ci/build-igt.sh b/drivers/gpu/drm/ci/build-igt.sh index eddb5f782a5e..caa2f4804ed5 100644 --- a/drivers/gpu/drm/ci/build-igt.sh +++ b/drivers/gpu/drm/ci/build-igt.sh @@ -71,4 +71,4 @@ tar -cf artifacts/igt.tar /igt # Pass needed files to the test stage S3_ARTIFACT_NAME="igt.tar.gz" gzip -c artifacts/igt.tar > ${S3_ARTIFACT_NAME} -ci-fairy s3cp --token-file "${S3_JWT_FILE}" ${S3_ARTIFACT_NAME} https://${PIPELINE_ARTIFACTS_BASE}/${KERNEL_ARCH}/${S3_ARTIFACT_NAME} +s3_upload ${S3_ARTIFACT_NAME} https://${PIPELINE_ARTIFACTS_BASE}/${KERNEL_ARCH}/ diff --git a/drivers/gpu/drm/ci/build.sh b/drivers/gpu/drm/ci/build.sh index 284873e94d8d..6fb74c51abe2 100644 --- a/drivers/gpu/drm/ci/build.sh +++ b/drivers/gpu/drm/ci/build.sh @@ -148,13 +148,13 @@ if [[ "$UPLOAD_TO_MINIO" = "1" ]]; then ls -l "${S3_JWT_FILE}" for f in $FILES_TO_UPLOAD; do - ci-fairy s3cp --token-file "${S3_JWT_FILE}" /kernel/$f \ - https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/$f + s3_upload /kernel/$f \ + https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/ done S3_ARTIFACT_NAME="kernel-files.tar.zst" tar --zstd -cf $S3_ARTIFACT_NAME install - ci-fairy s3cp --token-file "${S3_JWT_FILE}" ${S3_ARTIFACT_NAME} https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/${S3_ARTIFACT_NAME} + s3_upload ${S3_ARTIFACT_NAME} https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/ echo "Download vmlinux.xz from https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/vmlinux.xz" fi diff --git a/drivers/gpu/drm/ci/gitlab-ci.yml b/drivers/gpu/drm/ci/gitlab-ci.yml index 65adcd97e06b..ba75b3a7eca4 100644 --- a/drivers/gpu/drm/ci/gitlab-ci.yml +++ b/drivers/gpu/drm/ci/gitlab-ci.yml @@ -1,6 +1,6 @@ variables: DRM_CI_PROJECT_PATH: &drm-ci-project-path mesa/mesa - DRM_CI_COMMIT_SHA: &drm-ci-commit-sha 82ab58f6c6f94fa80ca7e1615146f08356e3ba69 + DRM_CI_COMMIT_SHA: &drm-ci-commit-sha f73132f1215a37ce8ffc711a0136c90649aaf128 UPSTREAM_REPO: https://gitlab.freedesktop.org/drm/kernel.git TARGET_BRANCH: drm-next @@ -20,8 +20,10 @@ variables: rm download-git-cache.sh set +o xtrace S3_JWT_FILE: /s3_jwt + S3_JWT_HEADER_FILE: /s3_jwt_header S3_JWT_FILE_SCRIPT: |- echo -n '${S3_JWT}' > '${S3_JWT_FILE}' && + echo -n "Authorization: Bearer ${S3_JWT}" > '${S3_JWT_HEADER_FILE}' && unset CI_JOB_JWT S3_JWT # Unsetting vulnerable env variables S3_HOST: s3.freedesktop.org # This bucket is used to fetch the kernel image @@ -251,7 +253,7 @@ make git archive: - tar -cvzf ../$CI_PROJECT_NAME.tar.gz . # Use id_tokens for JWT auth - - ci-fairy s3cp --token-file "${S3_JWT_FILE}" ../$CI_PROJECT_NAME.tar.gz https://$S3_HOST/${S3_GITCACHE_BUCKET}/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/$CI_PROJECT_NAME.tar.gz + - s3_upload ../$CI_PROJECT_NAME.tar.gz https://$S3_HOST/${S3_GITCACHE_BUCKET}/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/ # Sanity checks of MR settings and commit logs diff --git a/drivers/gpu/drm/ci/image-tags.yml b/drivers/gpu/drm/ci/image-tags.yml index c04ba0e69935..53fe34b86578 100644 --- a/drivers/gpu/drm/ci/image-tags.yml +++ b/drivers/gpu/drm/ci/image-tags.yml @@ -1,5 +1,5 @@ variables: - CONTAINER_TAG: "20250307-mesa-uprev" + CONTAINER_TAG: "20250328-mesa-uprev" DEBIAN_X86_64_BUILD_BASE_IMAGE: "debian/x86_64_build-base" DEBIAN_BASE_TAG: "${CONTAINER_TAG}" diff --git a/drivers/gpu/drm/ci/lava-submit.sh b/drivers/gpu/drm/ci/lava-submit.sh index f22720359b33..a1e8b34fb2d4 100755 --- a/drivers/gpu/drm/ci/lava-submit.sh +++ b/drivers/gpu/drm/ci/lava-submit.sh @@ -54,7 +54,7 @@ cp artifacts/ci-common/init-*.sh results/job-rootfs-overlay/ cp "$SCRIPTS_DIR"/setup-test-env.sh results/job-rootfs-overlay/ tar zcf job-rootfs-overlay.tar.gz -C results/job-rootfs-overlay/ . -ci-fairy s3cp --token-file "${S3_JWT_FILE}" job-rootfs-overlay.tar.gz "https://${JOB_ROOTFS_OVERLAY_PATH}" +s3_upload job-rootfs-overlay.tar.gz "https://${JOB_ARTIFACTS_BASE}" # Prepare env vars for upload. section_switch variables "Environment variables passed through to device:" From b71717735be48d7743a34897e9e44a0b53e30c0e Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Tue, 29 Apr 2025 10:33:56 +0200 Subject: [PATCH 46/84] drm/msm/gpu: Fix crash when throttling GPU immediately during boot There is a small chance that the GPU is already hot during boot. In that case, the call to of_devfreq_cooling_register() will immediately try to apply devfreq cooling, as seen in the following crash: Unable to handle kernel paging request at virtual address 0000000000014110 pc : a6xx_gpu_busy+0x1c/0x58 [msm] lr : msm_devfreq_get_dev_status+0xbc/0x140 [msm] Call trace: a6xx_gpu_busy+0x1c/0x58 [msm] (P) devfreq_simple_ondemand_func+0x3c/0x150 devfreq_update_target+0x44/0xd8 qos_max_notifier_call+0x30/0x84 blocking_notifier_call_chain+0x6c/0xa0 pm_qos_update_target+0xd0/0x110 freq_qos_apply+0x3c/0x74 apply_constraint+0x88/0x148 __dev_pm_qos_update_request+0x7c/0xcc dev_pm_qos_update_request+0x38/0x5c devfreq_cooling_set_cur_state+0x98/0xf0 __thermal_cdev_update+0x64/0xb4 thermal_cdev_update+0x4c/0x58 step_wise_manage+0x1f0/0x318 __thermal_zone_device_update+0x278/0x424 __thermal_cooling_device_register+0x2bc/0x308 thermal_of_cooling_device_register+0x10/0x1c of_devfreq_cooling_register_power+0x240/0x2bc of_devfreq_cooling_register+0x14/0x20 msm_devfreq_init+0xc4/0x1a0 [msm] msm_gpu_init+0x304/0x574 [msm] adreno_gpu_init+0x1c4/0x2e0 [msm] a6xx_gpu_init+0x5c8/0x9c8 [msm] adreno_bind+0x2a8/0x33c [msm] ... At this point we haven't initialized the GMU at all yet, so we cannot read the GMU registers inside a6xx_gpu_busy(). A similar issue was fixed before in commit 6694482a70e9 ("drm/msm: Avoid unclocked GMU register access in 6xx gpu_busy"): msm_devfreq_init() does call devfreq_suspend_device(), but unlike msm_devfreq_suspend(), it doesn't set the df->suspended flag accordingly. This means the df->suspended flag does not match the actual devfreq state after initialization and msm_devfreq_get_dev_status() will end up accessing GMU registers, causing the crash. Fix this by setting df->suspended correctly during initialization. Cc: stable@vger.kernel.org Fixes: 6694482a70e9 ("drm/msm: Avoid unclocked GMU register access in 6xx gpu_busy") Signed-off-by: Stephan Gerhold Reviewed-by: Douglas Anderson Reviewed-by: Konrad Dybcio Patchwork: https://patchwork.freedesktop.org/patch/650772/ Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gpu_devfreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c index 6970b0f7f457..2e1d5c343272 100644 --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c @@ -156,6 +156,7 @@ void msm_devfreq_init(struct msm_gpu *gpu) priv->gpu_devfreq_config.downdifferential = 10; mutex_init(&df->lock); + df->suspended = true; ret = dev_pm_qos_add_request(&gpu->pdev->dev, &df->boost_freq, DEV_PM_QOS_MIN_FREQUENCY, 0); From c0134808a9d6c364b7568546be9489ce3337c7f8 Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Thu, 24 Apr 2025 09:30:17 -0400 Subject: [PATCH 47/84] drm/msm: Be more robust when HFI response times out If the GMU takes too long to respond to an HFI message, we may return early. If the GMU does eventually respond, and then we send a second message, we will see the response for the first, throw another error, and keep going. But we don't currently wait for the interrupt from the GMU again, so if the second response isn't there immediately we may prematurely return. This can cause a continuous cycle of missed HFI messages, and for reasons I don't quite understand the GMU does not shut down properly when this happens. Fix this by waiting for the GMU interrupt when we see an empty queue. If the GMU never responds then the queue really is empty and we quit. We can't wait for the interrupt when we see a wrong response seqnum because the GMU might have already queued both responses by the time we clear the interrupt the first time so we do need to check the queue before waiting on the interrupt again. Signed-off-by: Connor Abbott Reviewed-by: Konrad Dybcio Patchwork: https://patchwork.freedesktop.org/patch/650013/ Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 35 ++++++++++++++++++++------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c index 0989aee3dd2c..1bc40d667281 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c @@ -100,12 +100,10 @@ static int a6xx_hfi_queue_write(struct a6xx_gmu *gmu, return 0; } -static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum, - u32 *payload, u32 payload_size) +static int a6xx_hfi_wait_for_msg_interrupt(struct a6xx_gmu *gmu, u32 id, u32 seqnum) { - struct a6xx_hfi_queue *queue = &gmu->queues[HFI_RESPONSE_QUEUE]; - u32 val; int ret; + u32 val; /* Wait for a response */ ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO, val, @@ -122,6 +120,19 @@ static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum, gmu_write(gmu, REG_A6XX_GMU_GMU2HOST_INTR_CLR, A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ); + return 0; +} + +static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum, + u32 *payload, u32 payload_size) +{ + struct a6xx_hfi_queue *queue = &gmu->queues[HFI_RESPONSE_QUEUE]; + int ret; + + ret = a6xx_hfi_wait_for_msg_interrupt(gmu, id, seqnum); + if (ret) + return ret; + for (;;) { struct a6xx_hfi_msg_response resp; @@ -129,12 +140,18 @@ static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum, ret = a6xx_hfi_queue_read(gmu, queue, (u32 *) &resp, sizeof(resp) >> 2); - /* If the queue is empty our response never made it */ + /* If the queue is empty, there may have been previous missed + * responses that preceded the response to our packet. Wait + * further before we give up. + */ if (!ret) { - DRM_DEV_ERROR(gmu->dev, - "The HFI response queue is unexpectedly empty\n"); - - return -ENOENT; + ret = a6xx_hfi_wait_for_msg_interrupt(gmu, id, seqnum); + if (ret) { + DRM_DEV_ERROR(gmu->dev, + "The HFI response queue is unexpectedly empty\n"); + return ret; + } + continue; } if (HFI_HEADER_ID(resp.header) == HFI_F2H_MSG_ERROR) { From dda72ac390bfd2f3f69c5c3d8e1113abca99d4af Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 21 Apr 2025 10:21:43 -0700 Subject: [PATCH 48/84] drm/msm/adreno: Drop fictional address_space_size Really the only purpose of this was to limit the address space size to 4GB to avoid 32b rollover problems in 64b pointer math in older sqe fw. So replace the address_space_size with a quirk limiting the address space to 4GB. In all other cases, use the SMMU input address size (IAS) to determine the address space size. v2: Properly account for vm_start Signed-off-by: Rob Clark Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/649467/ --- drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 33 +++++++++++------------ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 19 ++++++++++--- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 4 ++- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c index 53e2ff4406d8..f85b7e89bafb 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c @@ -681,6 +681,7 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_SQE] = "a630_sqe.fw", }, .gmem = (SZ_128K + SZ_4K), + .quirks = ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a6xx_gpu_init, .zapfw = "a610_zap.mdt", @@ -713,6 +714,7 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_GMU] = "a630_gmu.bin", }, .gmem = SZ_512K, + .quirks = ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a6xx_gpu_init, .zapfw = "a615_zap.mdt", @@ -743,7 +745,8 @@ static const struct adreno_info a6xx_gpus[] = { }, .gmem = SZ_512K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_4GB_VA, .init = a6xx_gpu_init, .zapfw = "a615_zap.mbn", .a6xx = &(const struct a6xx_info) { @@ -769,7 +772,8 @@ static const struct adreno_info a6xx_gpus[] = { }, .gmem = SZ_512K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_4GB_VA, .init = a6xx_gpu_init, .a6xx = &(const struct a6xx_info) { .protect = &a630_protect, @@ -791,6 +795,7 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_GMU] = "a619_gmu.bin", }, .gmem = SZ_512K, + .quirks = ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a6xx_gpu_init, .zapfw = "a615_zap.mdt", @@ -815,6 +820,7 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_GMU] = "a619_gmu.bin", }, .gmem = SZ_512K, + .quirks = ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a6xx_gpu_init, .zapfw = "a615_zap.mdt", @@ -838,8 +844,9 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_GMU] = "a619_gmu.bin", }, .gmem = SZ_512K, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, .init = a6xx_gpu_init, .zapfw = "a615_zap.mdt", .a6xx = &(const struct a6xx_info) { @@ -874,7 +881,6 @@ static const struct adreno_info a6xx_gpus[] = { .gmu_cgc_mode = 0x00020200, .prim_fifo_threshold = 0x00010000, }, - .address_space_size = SZ_16G, .speedbins = ADRENO_SPEEDBINS( { 0, 0 }, { 137, 1 }, @@ -907,7 +913,6 @@ static const struct adreno_info a6xx_gpus[] = { { /* sentinel */ }, }, }, - .address_space_size = SZ_16G, }, { .chip_ids = ADRENO_CHIP_IDS( 0x06030001, @@ -920,8 +925,9 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_GMU] = "a630_gmu.bin", }, .gmem = SZ_1M, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, .init = a6xx_gpu_init, .zapfw = "a630_zap.mdt", .a6xx = &(const struct a6xx_info) { @@ -939,8 +945,9 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_GMU] = "a640_gmu.bin", }, .gmem = SZ_1M, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, .init = a6xx_gpu_init, .zapfw = "a640_zap.mdt", .a6xx = &(const struct a6xx_info) { @@ -973,7 +980,6 @@ static const struct adreno_info a6xx_gpus[] = { .gmu_cgc_mode = 0x00020202, .prim_fifo_threshold = 0x00300200, }, - .address_space_size = SZ_16G, .speedbins = ADRENO_SPEEDBINS( { 0, 0 }, { 1, 1 }, @@ -1000,7 +1006,6 @@ static const struct adreno_info a6xx_gpus[] = { .gmu_cgc_mode = 0x00020000, .prim_fifo_threshold = 0x00300200, }, - .address_space_size = SZ_16G, }, { .chip_ids = ADRENO_CHIP_IDS(0x06060300), .family = ADRENO_6XX_GEN4, @@ -1019,7 +1024,6 @@ static const struct adreno_info a6xx_gpus[] = { .gmu_cgc_mode = 0x00020200, .prim_fifo_threshold = 0x00300200, }, - .address_space_size = SZ_16G, }, { .chip_ids = ADRENO_CHIP_IDS(0x06030500), .family = ADRENO_6XX_GEN4, @@ -1039,7 +1043,6 @@ static const struct adreno_info a6xx_gpus[] = { .gmu_cgc_mode = 0x00020202, .prim_fifo_threshold = 0x00200200, }, - .address_space_size = SZ_16G, .speedbins = ADRENO_SPEEDBINS( { 0, 0 }, { 117, 0 }, @@ -1056,8 +1059,9 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_GMU] = "a640_gmu.bin", }, .gmem = SZ_2M, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, .init = a6xx_gpu_init, .zapfw = "a640_zap.mdt", .a6xx = &(const struct a6xx_info) { @@ -1085,7 +1089,6 @@ static const struct adreno_info a6xx_gpus[] = { .gmu_cgc_mode = 0x00020200, .prim_fifo_threshold = 0x00800200, }, - .address_space_size = SZ_16G, } }; DECLARE_ADRENO_GPULIST(a6xx); @@ -1395,7 +1398,6 @@ static const struct adreno_info a7xx_gpus[] = { .pwrup_reglist = &a7xx_pwrup_reglist, .gmu_cgc_mode = 0x00020000, }, - .address_space_size = SZ_16G, .preempt_record_size = 2860 * SZ_1K, }, { .chip_ids = ADRENO_CHIP_IDS(0x43050a01), /* "C510v2" */ @@ -1429,7 +1431,6 @@ static const struct adreno_info a7xx_gpus[] = { { /* sentinel */ }, }, }, - .address_space_size = SZ_16G, .preempt_record_size = 4192 * SZ_1K, }, { .chip_ids = ADRENO_CHIP_IDS(0x43050c01), /* "C512v2" */ @@ -1451,7 +1452,6 @@ static const struct adreno_info a7xx_gpus[] = { .gmu_chipid = 0x7050001, .gmu_cgc_mode = 0x00020202, }, - .address_space_size = SZ_256G, .preempt_record_size = 4192 * SZ_1K, }, { .chip_ids = ADRENO_CHIP_IDS(0x43051401), /* "C520v2" */ @@ -1484,7 +1484,6 @@ static const struct adreno_info a7xx_gpus[] = { { /* sentinel */ }, }, }, - .address_space_size = SZ_16G, .preempt_record_size = 3572 * SZ_1K, } }; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 242d02d48c0c..2289fecbbbf1 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -2268,7 +2268,7 @@ a6xx_create_private_address_space(struct msm_gpu *gpu) return ERR_CAST(mmu); return msm_gem_address_space_create(mmu, - "gpu", 0x100000000ULL, + "gpu", ADRENO_VM_START, adreno_private_address_space_size(gpu)); } diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 26db1f4b5fb9..2348ffb35f7e 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -236,14 +236,27 @@ adreno_iommu_create_address_space(struct msm_gpu *gpu, u64 adreno_private_address_space_size(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(&gpu->pdev->dev); + const struct io_pgtable_cfg *ttbr1_cfg; if (address_space_size) return address_space_size; - if (adreno_gpu->info->address_space_size) - return adreno_gpu->info->address_space_size; + if (adreno_gpu->info->quirks & ADRENO_QUIRK_4GB_VA) + return SZ_4G; - return SZ_4G; + if (!adreno_smmu || !adreno_smmu->get_ttbr1_cfg) + return SZ_4G; + + ttbr1_cfg = adreno_smmu->get_ttbr1_cfg(adreno_smmu->cookie); + + /* + * Userspace VM is actually using TTBR0, but both are the same size, + * with b48 (sign bit) selecting which TTBRn to use. So if IAS is + * 48, the total (kernel+user) address space size is effectively + * 49 bits. But what userspace is control of is the lower 48. + */ + return BIT(ttbr1_cfg->ias) - ADRENO_VM_START; } #define ARM_SMMU_FSR_TF BIT(1) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 92caba3584da..a8f4bf416e64 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -57,6 +57,7 @@ enum adreno_family { #define ADRENO_QUIRK_HAS_HW_APRIV BIT(3) #define ADRENO_QUIRK_HAS_CACHED_COHERENT BIT(4) #define ADRENO_QUIRK_PREEMPTION BIT(5) +#define ADRENO_QUIRK_4GB_VA BIT(6) /* Helper for formating the chip_id in the way that userspace tools like * crashdec expect. @@ -104,7 +105,6 @@ struct adreno_info { union { const struct a6xx_info *a6xx; }; - u64 address_space_size; /** * @speedbins: Optional table of fuse to speedbin mappings * @@ -578,6 +578,8 @@ static inline int adreno_is_a7xx(struct adreno_gpu *gpu) adreno_is_a740_family(gpu); } +/* Put vm_start above 32b to catch issues with not setting xyz_BASE_HI */ +#define ADRENO_VM_START 0x100000000ULL u64 adreno_private_address_space_size(struct msm_gpu *gpu); int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx, uint32_t param, uint64_t *value, uint32_t *len); From b733fe7bff8bd14b9e0e2fd8f4de61696cb9f52e Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Sat, 19 Apr 2025 20:21:30 +0530 Subject: [PATCH 49/84] drm/msm/adreno: Add support for ACD ACD a.k.a Adaptive Clock Distribution is a feature which helps to reduce the power consumption. In some chipsets, it is also a requirement to support higher GPU frequencies. This patch adds support for GPU ACD by sending necessary data to GMU and AOSS. The feature support for the chipset is detected based on devicetree data. Signed-off-by: Akhil P Oommen Tested-by: Maya Matuszczyk Tested-by: Anthony Ruhier Reviewed-by: Konrad Dybcio Patchwork: https://patchwork.freedesktop.org/patch/649342/ Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 84 +++++++++++++++++++++++---- drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 1 + drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 36 ++++++++++++ drivers/gpu/drm/msm/adreno/a6xx_hfi.h | 21 +++++++ 4 files changed, 132 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index c8711938a5f4..6bd6d7c67f98 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -1064,14 +1064,6 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) gmu->hung = false; - /* Notify AOSS about the ACD state (unimplemented for now => disable it) */ - if (!IS_ERR(gmu->qmp)) { - ret = qmp_send(gmu->qmp, "{class: gpu, res: acd, val: %d}", - 0 /* Hardcode ACD to be disabled for now */); - if (ret) - dev_err(gmu->dev, "failed to send GPU ACD state\n"); - } - /* Turn on the resources */ pm_runtime_get_sync(gmu->dev); @@ -1671,6 +1663,68 @@ static int a6xx_gmu_pwrlevels_probe(struct a6xx_gmu *gmu) return a6xx_gmu_rpmh_votes_init(gmu); } +static int a6xx_gmu_acd_probe(struct a6xx_gmu *gmu) +{ + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); + struct a6xx_hfi_acd_table *cmd = &gmu->acd_table; + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + struct msm_gpu *gpu = &adreno_gpu->base; + int ret, i, cmd_idx = 0; + + cmd->version = 1; + cmd->stride = 1; + cmd->enable_by_level = 0; + + /* Skip freq = 0 and parse acd-level for rest of the OPPs */ + for (i = 1; i < gmu->nr_gpu_freqs; i++) { + struct dev_pm_opp *opp; + struct device_node *np; + unsigned long freq; + u32 val; + + freq = gmu->gpu_freqs[i]; + opp = dev_pm_opp_find_freq_exact(&gpu->pdev->dev, freq, true); + np = dev_pm_opp_get_of_node(opp); + + ret = of_property_read_u32(np, "qcom,opp-acd-level", &val); + of_node_put(np); + dev_pm_opp_put(opp); + if (ret == -EINVAL) + continue; + else if (ret) { + DRM_DEV_ERROR(gmu->dev, "Unable to read acd level for freq %lu\n", freq); + return ret; + } + + cmd->enable_by_level |= BIT(i); + cmd->data[cmd_idx++] = val; + } + + cmd->num_levels = cmd_idx; + + /* It is a problem if qmp node is unavailable when ACD is required */ + if (cmd->enable_by_level && IS_ERR_OR_NULL(gmu->qmp)) { + DRM_DEV_ERROR(gmu->dev, "Unable to send ACD state to AOSS\n"); + return -EINVAL; + } + + /* Otherwise, nothing to do if qmp is unavailable */ + if (IS_ERR_OR_NULL(gmu->qmp)) + return 0; + + /* + * Notify AOSS about the ACD state. AOSS is supposed to assume that ACD is disabled on + * system reset. So it is harmless if we couldn't notify 'OFF' state + */ + ret = qmp_send(gmu->qmp, "{class: gpu, res: acd, val: %d}", !!cmd->enable_by_level); + if (ret && cmd->enable_by_level) { + DRM_DEV_ERROR(gmu->dev, "Failed to send ACD state to AOSS\n"); + return ret; + } + + return 0; +} + static int a6xx_gmu_clocks_probe(struct a6xx_gmu *gmu) { int ret = devm_clk_bulk_get_all(gmu->dev, &gmu->clocks); @@ -1992,7 +2046,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) gmu->qmp = qmp_get(gmu->dev); if (IS_ERR(gmu->qmp) && adreno_is_a7xx(adreno_gpu)) { ret = PTR_ERR(gmu->qmp); - goto remove_device_link; + goto detach_gxpd; } init_completion(&gmu->pd_gate); @@ -2008,6 +2062,10 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) /* Get the power levels for the GMU and GPU */ a6xx_gmu_pwrlevels_probe(gmu); + ret = a6xx_gmu_acd_probe(gmu); + if (ret) + goto detach_gxpd; + /* Set up the HFI queues */ a6xx_hfi_init(gmu); @@ -2018,7 +2076,13 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) return 0; -remove_device_link: +detach_gxpd: + if (!IS_ERR_OR_NULL(gmu->gxpd)) + dev_pm_domain_detach(gmu->gxpd, false); + + if (!IS_ERR_OR_NULL(gmu->qmp)) + qmp_put(gmu->qmp); + device_link_del(link); detach_cxpd: diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h index 0c888b326cfb..b2d4489b4024 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h @@ -93,6 +93,7 @@ struct a6xx_gmu { int nr_gpu_freqs; unsigned long gpu_freqs[GMU_MAX_GX_FREQS]; u32 gx_arc_votes[GMU_MAX_GX_FREQS]; + struct a6xx_hfi_acd_table acd_table; int nr_gpu_bws; unsigned long gpu_bw_table[GMU_MAX_GX_FREQS]; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c index 1bc40d667281..3cab07f62285 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c @@ -765,6 +765,38 @@ static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu) NULL, 0); } +#define HFI_FEATURE_ACD 12 + +static int a6xx_hfi_enable_acd(struct a6xx_gmu *gmu) +{ + struct a6xx_hfi_acd_table *acd_table = &gmu->acd_table; + struct a6xx_hfi_msg_feature_ctrl msg = { + .feature = HFI_FEATURE_ACD, + .enable = 1, + .data = 0, + }; + int ret; + + if (!acd_table->enable_by_level) + return 0; + + /* Enable ACD feature at GMU */ + ret = a6xx_hfi_send_msg(gmu, HFI_H2F_FEATURE_CTRL, &msg, sizeof(msg), NULL, 0); + if (ret) { + DRM_DEV_ERROR(gmu->dev, "Unable to enable ACD (%d)\n", ret); + return ret; + } + + /* Send ACD table to GMU */ + ret = a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_ACD, acd_table, sizeof(*acd_table), NULL, 0); + if (ret) { + DRM_DEV_ERROR(gmu->dev, "Unable to ACD table (%d)\n", ret); + return ret; + } + + return 0; +} + static int a6xx_hfi_send_test(struct a6xx_gmu *gmu) { struct a6xx_hfi_msg_test msg = { 0 }; @@ -862,6 +894,10 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state) if (ret) return ret; + ret = a6xx_hfi_enable_acd(gmu); + if (ret) + return ret; + ret = a6xx_hfi_send_core_fw_start(gmu); if (ret) return ret; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h index 52ba4a07d7b9..653ef720e2da 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h @@ -151,12 +151,33 @@ struct a6xx_hfi_msg_test { u32 header; }; +#define HFI_H2F_MSG_ACD 7 +#define MAX_ACD_STRIDE 2 + +struct a6xx_hfi_acd_table { + u32 header; + u32 version; + u32 enable_by_level; + u32 stride; + u32 num_levels; + u32 data[16 * MAX_ACD_STRIDE]; +}; + #define HFI_H2F_MSG_START 10 struct a6xx_hfi_msg_start { u32 header; }; +#define HFI_H2F_FEATURE_CTRL 11 + +struct a6xx_hfi_msg_feature_ctrl { + u32 header; + u32 feature; + u32 enable; + u32 data; +}; + #define HFI_H2F_MSG_CORE_FW_START 14 struct a6xx_hfi_msg_core_fw_start { From 5f02f5e78ec9688e29b6857813185b1181796abe Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Sat, 19 Apr 2025 20:21:31 +0530 Subject: [PATCH 50/84] drm/msm/a6xx: Increase HFI response timeout When ACD feature is enabled, it triggers some internal calibrations which result in a pretty long delay during the first HFI perf vote. So, increase the HFI response timeout to match the downstream driver. Signed-off-by: Akhil P Oommen Tested-by: Maya Matuszczyk Tested-by: Anthony Ruhier Patchwork: https://patchwork.freedesktop.org/patch/649344/ Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c index 3cab07f62285..8e69b1e84657 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c @@ -107,7 +107,7 @@ static int a6xx_hfi_wait_for_msg_interrupt(struct a6xx_gmu *gmu, u32 id, u32 seq /* Wait for a response */ ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO, val, - val & A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ, 100, 5000); + val & A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ, 100, 1000000); if (ret) { DRM_DEV_ERROR(gmu->dev, From 8e98a81da283b9d2ca140b2bdd3767677e875ff3 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Sat, 19 Apr 2025 20:21:32 +0530 Subject: [PATCH 51/84] drm/msm: a6x: Rework qmp_get() error handling Fix the following for qmp_get() errors: 1. Correctly handle probe defer for A6x GPUs 2. Ignore other errors because those are okay when GPU ACD is not required. They are checked again during gpu acd probe. Signed-off-by: Akhil P Oommen Reviewed-by: Konrad Dybcio Tested-by: Maya Matuszczyk Tested-by: Anthony Ruhier Patchwork: https://patchwork.freedesktop.org/patch/649346/ Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 6bd6d7c67f98..48b4ca8894ba 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -2043,9 +2043,10 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) goto detach_cxpd; } + /* Other errors are handled during GPU ACD probe */ gmu->qmp = qmp_get(gmu->dev); - if (IS_ERR(gmu->qmp) && adreno_is_a7xx(adreno_gpu)) { - ret = PTR_ERR(gmu->qmp); + if (PTR_ERR_OR_ZERO(gmu->qmp) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; goto detach_gxpd; } From 19c17841e3b62f45b01ae33db43de1a24e186adb Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Sat, 19 Apr 2025 20:21:33 +0530 Subject: [PATCH 52/84] drm/msm/adreno: Add module param to disable ACD Add a module param to disable ACD which will help to quickly rule it out for any GPU issues. Signed-off-by: Akhil P Oommen Tested-by: Maya Matuszczyk Tested-by: Anthony Ruhier Reviewed-by: Konrad Dybcio Patchwork: https://patchwork.freedesktop.org/patch/649349/ Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 7 +++++++ drivers/gpu/drm/msm/adreno/adreno_device.c | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 48b4ca8894ba..38c0f8ef85c3 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -1670,6 +1670,13 @@ static int a6xx_gmu_acd_probe(struct a6xx_gmu *gmu) struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; struct msm_gpu *gpu = &adreno_gpu->base; int ret, i, cmd_idx = 0; + extern bool disable_acd; + + /* Skip ACD probe if requested via module param */ + if (disable_acd) { + DRM_DEV_ERROR(gmu->dev, "Skipping GPU ACD probe\n"); + return 0; + } cmd->version = 1; cmd->stride = 1; diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 236b25c094cd..f5e1490d07c1 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -24,6 +24,10 @@ int enable_preemption = -1; MODULE_PARM_DESC(enable_preemption, "Enable preemption (A7xx only) (1=on , 0=disable, -1=auto (default))"); module_param(enable_preemption, int, 0600); +bool disable_acd; +MODULE_PARM_DESC(disable_acd, "Forcefully disable GPU ACD"); +module_param_unsafe(disable_acd, bool, 0400); + extern const struct adreno_gpulist a2xx_gpulist; extern const struct adreno_gpulist a3xx_gpulist; extern const struct adreno_gpulist a4xx_gpulist; From db76003ade5953d4a83c2bdc6e15c2d1c33e7350 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Sat, 19 Apr 2025 20:21:34 +0530 Subject: [PATCH 53/84] dt-bindings: opp: Add v2-qcom-adreno vendor bindings Add a new schema which extends opp-v2 to support a new vendor specific property required for Adreno GPUs found in Qualcomm's SoCs. The new property called "qcom,opp-acd-level" carries a u32 value recommended for each opp needs to be shared to GMU during runtime. Also, update MAINTAINERS file include the new opp-v2-qcom-adreno.yaml. Cc: Rob Clark Signed-off-by: Akhil P Oommen Tested-by: Maya Matuszczyk Tested-by: Anthony Ruhier Reviewed-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/649351/ Signed-off-by: Rob Clark --- .../bindings/opp/opp-v2-qcom-adreno.yaml | 96 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 97 insertions(+) create mode 100644 Documentation/devicetree/bindings/opp/opp-v2-qcom-adreno.yaml diff --git a/Documentation/devicetree/bindings/opp/opp-v2-qcom-adreno.yaml b/Documentation/devicetree/bindings/opp/opp-v2-qcom-adreno.yaml new file mode 100644 index 000000000000..a27ba7b663d4 --- /dev/null +++ b/Documentation/devicetree/bindings/opp/opp-v2-qcom-adreno.yaml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/opp/opp-v2-qcom-adreno.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Adreno compatible OPP supply + +description: + Adreno GPUs present in Qualcomm's Snapdragon chipsets uses an OPP specific + ACD related information tailored for the specific chipset. This binding + provides the information needed to describe such a hardware value. + +maintainers: + - Rob Clark + +allOf: + - $ref: opp-v2-base.yaml# + +properties: + compatible: + contains: + const: operating-points-v2-adreno + +patternProperties: + '^opp-[0-9]+$': + type: object + additionalProperties: false + + properties: + opp-hz: true + + opp-level: true + + opp-peak-kBps: true + + opp-supported-hw: true + + qcom,opp-acd-level: + description: | + A positive value representing the ACD (Adaptive Clock Distribution, + a fancy name for clk throttling during voltage droop) level associated + with this OPP node. This value is shared to a co-processor inside GPU + (called Graphics Management Unit a.k.a GMU) during wake up. It may not + be present for some OPPs and GMU will disable ACD while transitioning + to that OPP. This value encodes a voltage threshold, delay cycles & + calibration margins which are identified by characterization of the + SoC. So, it doesn't have any unit. This data is passed to GMU firmware + via 'HFI_H2F_MSG_ACD' packet. + $ref: /schemas/types.yaml#/definitions/uint32 + + required: + - opp-hz + - opp-level + +required: + - compatible + +additionalProperties: false + +examples: + - | + #include + + gpu_opp_table: opp-table { + compatible = "operating-points-v2-adreno", "operating-points-v2"; + + opp-687000000 { + opp-hz = /bits/ 64 <687000000>; + opp-level = ; + opp-peak-kBps = <8171875>; + qcom,opp-acd-level = <0x882e5ffd>; + }; + + opp-550000000 { + opp-hz = /bits/ 64 <550000000>; + opp-level = ; + opp-peak-kBps = <6074219>; + qcom,opp-acd-level = <0xc0285ffd>; + }; + + opp-390000000 { + opp-hz = /bits/ 64 <390000000>; + opp-level = ; + opp-peak-kBps = <3000000>; + qcom,opp-acd-level = <0xc0285ffd>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + opp-level = ; + opp-peak-kBps = <2136719>; + /* Intentionally left out qcom,opp-acd-level property here */ + }; + + }; diff --git a/MAINTAINERS b/MAINTAINERS index 81b81cc68ca2..62c9f1ddfb63 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7512,6 +7512,7 @@ S: Maintained B: https://gitlab.freedesktop.org/drm/msm/-/issues T: git https://gitlab.freedesktop.org/drm/msm.git F: Documentation/devicetree/bindings/display/msm/gpu.yaml +F: Documentation/devicetree/bindings/opp/opp-v2-qcom-adreno.yaml F: drivers/gpu/drm/msm/adreno/ F: drivers/gpu/drm/msm/msm_gpu.* F: drivers/gpu/drm/msm/msm_gpu_devfreq.* From e153e35bb12fe14042e2ae793410a36202bc2424 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Sat, 19 Apr 2025 20:21:35 +0530 Subject: [PATCH 54/84] arm64: dts: qcom: x1e80100: Add ACD levels for GPU Update GPU node to include acd level values. Signed-off-by: Akhil P Oommen Reviewed-by: Konrad Dybcio Tested-by: Maya Matuszczyk Tested-by: Anthony Ruhier Acked-by: Bjorn Andersson Patchwork: https://patchwork.freedesktop.org/patch/649352/ Signed-off-by: Rob Clark --- arch/arm64/boot/dts/qcom/x1e80100.dtsi | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi index 4936fa5b98ff..a9c8cca1c635 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi +++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi @@ -3752,60 +3752,69 @@ zap-shader { }; gpu_opp_table: opp-table { - compatible = "operating-points-v2"; + compatible = "operating-points-v2-adreno", "operating-points-v2"; opp-1100000000 { opp-hz = /bits/ 64 <1100000000>; opp-level = ; opp-peak-kBps = <16500000>; + qcom,opp-acd-level = <0xa82a5ffd>; }; opp-1000000000 { opp-hz = /bits/ 64 <1000000000>; opp-level = ; opp-peak-kBps = <14398438>; + qcom,opp-acd-level = <0xa82b5ffd>; }; opp-925000000 { opp-hz = /bits/ 64 <925000000>; opp-level = ; opp-peak-kBps = <14398438>; + qcom,opp-acd-level = <0xa82b5ffd>; }; opp-800000000 { opp-hz = /bits/ 64 <800000000>; opp-level = ; opp-peak-kBps = <12449219>; + qcom,opp-acd-level = <0xa82c5ffd>; }; opp-744000000 { opp-hz = /bits/ 64 <744000000>; opp-level = ; opp-peak-kBps = <10687500>; + qcom,opp-acd-level = <0x882e5ffd>; }; opp-687000000 { opp-hz = /bits/ 64 <687000000>; opp-level = ; opp-peak-kBps = <8171875>; + qcom,opp-acd-level = <0x882e5ffd>; }; opp-550000000 { opp-hz = /bits/ 64 <550000000>; opp-level = ; opp-peak-kBps = <6074219>; + qcom,opp-acd-level = <0xc0285ffd>; }; opp-390000000 { opp-hz = /bits/ 64 <390000000>; opp-level = ; opp-peak-kBps = <3000000>; + qcom,opp-acd-level = <0xc0285ffd>; }; opp-300000000 { opp-hz = /bits/ 64 <300000000>; opp-level = ; opp-peak-kBps = <2136719>; + qcom,opp-acd-level = <0xc02b5ffd>; }; }; }; From 25f0f9be831e0d2a87196f42d6015eaeb4842091 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Sat, 19 Apr 2025 20:21:36 +0530 Subject: [PATCH 55/84] arm64: dts: qcom: x1e80100: Add OPPs up to Turbo L3 for GPU Now that we have ACD support for GPU, add additional OPPs up to Turbo L3 which are supported across all existing SKUs. Signed-off-by: Akhil P Oommen Reviewed-by: Konrad Dybcio Tested-by: Maya Matuszczyk Tested-by: Anthony Ruhier Acked-by: Bjorn Andersson Patchwork: https://patchwork.freedesktop.org/patch/649354/ Signed-off-by: Rob Clark --- arch/arm64/boot/dts/qcom/x1e80100.dtsi | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi index a9c8cca1c635..8eddf0c96098 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi +++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi @@ -3754,10 +3754,24 @@ zap-shader { gpu_opp_table: opp-table { compatible = "operating-points-v2-adreno", "operating-points-v2"; + opp-1250000000 { + opp-hz = /bits/ 64 <1250000000>; + opp-level = ; + opp-peak-kBps = <16500000>; + qcom,opp-acd-level = <0xa82a5ffd>; + }; + + opp-1175000000 { + opp-hz = /bits/ 64 <1175000000>; + opp-level = ; + opp-peak-kBps = <14398438>; + qcom,opp-acd-level = <0xa82a5ffd>; + }; + opp-1100000000 { opp-hz = /bits/ 64 <1100000000>; opp-level = ; - opp-peak-kBps = <16500000>; + opp-peak-kBps = <14398438>; qcom,opp-acd-level = <0xa82a5ffd>; }; From 5a9c1bea011fb42088ba08ceaa252fb20e695626 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Mon, 5 May 2025 13:13:40 +0200 Subject: [PATCH 56/84] drm/msm/a6xx: Disable rgb565_predicator on Adreno 7c3 This feature is supposed to be enabled with UBWC v4 or later. Implementations of this SKU feature an effective UBWC version of 3, so disable it, in line with the BSP kernel. Reported-by: Dmitry Baryshkov Reviewed-by: Akhil P Oommen Fixes: 192f4ee3e408 ("drm/msm/a6xx: Add support for Adreno 7c Gen 3 gpu") Signed-off-by: Konrad Dybcio Patchwork: https://patchwork.freedesktop.org/patch/651759/ Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 2289fecbbbf1..bf3758f010f4 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -655,7 +655,6 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu) if (adreno_is_7c3(gpu)) { gpu->ubwc_config.highest_bank_bit = 14; gpu->ubwc_config.amsbc = 1; - gpu->ubwc_config.rgb565_predicator = 1; gpu->ubwc_config.uavflagprd_inv = 2; gpu->ubwc_config.macrotile_mode = 1; } From 8f5264d302e803e7ef82a61f9632a0d2ef67413f Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 7 May 2025 08:47:22 -0700 Subject: [PATCH 57/84] drm/msm/adreno: Remove MODULE_FIRMWARE()'s The driver handles the case where gpu fw is not in the initrd. OTOH it doesn't always handle the case where _some_ fw is in the initrd, but others are not. In particular the zap fw tends to be signed with an OEM specific key, so the paths/names differ across devices with the same SoC/GPU, so we cannot sanely list them with MODULE_FIRMWARE(). So MODULE_FIRMWARE() just ends up causing problems without actually solving anything. Remove them! Signed-off-by: Rob Clark Reviewed-by: Konrad Dybcio Patchwork: https://patchwork.freedesktop.org/patch/652195/ --- drivers/gpu/drm/msm/adreno/a2xx_catalog.c | 5 ----- drivers/gpu/drm/msm/adreno/a3xx_catalog.c | 5 ----- drivers/gpu/drm/msm/adreno/a4xx_catalog.c | 3 --- drivers/gpu/drm/msm/adreno/a5xx_catalog.c | 9 --------- drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 11 ----------- 5 files changed, 33 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a2xx_catalog.c b/drivers/gpu/drm/msm/adreno/a2xx_catalog.c index 9ddb7b31fd98..5ddd015f930d 100644 --- a/drivers/gpu/drm/msm/adreno/a2xx_catalog.c +++ b/drivers/gpu/drm/msm/adreno/a2xx_catalog.c @@ -45,8 +45,3 @@ static const struct adreno_info a2xx_gpus[] = { } }; DECLARE_ADRENO_GPULIST(a2xx); - -MODULE_FIRMWARE("qcom/leia_pfp_470.fw"); -MODULE_FIRMWARE("qcom/leia_pm4_470.fw"); -MODULE_FIRMWARE("qcom/yamato_pfp.fw"); -MODULE_FIRMWARE("qcom/yamato_pm4.fw"); diff --git a/drivers/gpu/drm/msm/adreno/a3xx_catalog.c b/drivers/gpu/drm/msm/adreno/a3xx_catalog.c index 2eb6c3e93748..1498e6532f62 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_catalog.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_catalog.c @@ -85,8 +85,3 @@ static const struct adreno_info a3xx_gpus[] = { } }; DECLARE_ADRENO_GPULIST(a3xx); - -MODULE_FIRMWARE("qcom/a300_pm4.fw"); -MODULE_FIRMWARE("qcom/a300_pfp.fw"); -MODULE_FIRMWARE("qcom/a330_pm4.fw"); -MODULE_FIRMWARE("qcom/a330_pfp.fw"); diff --git a/drivers/gpu/drm/msm/adreno/a4xx_catalog.c b/drivers/gpu/drm/msm/adreno/a4xx_catalog.c index 93519f807f87..09f9f228b75e 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_catalog.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_catalog.c @@ -45,6 +45,3 @@ static const struct adreno_info a4xx_gpus[] = { } }; DECLARE_ADRENO_GPULIST(a4xx); - -MODULE_FIRMWARE("qcom/a420_pm4.fw"); -MODULE_FIRMWARE("qcom/a420_pfp.fw"); diff --git a/drivers/gpu/drm/msm/adreno/a5xx_catalog.c b/drivers/gpu/drm/msm/adreno/a5xx_catalog.c index 633f31539162..b48a636d8237 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_catalog.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_catalog.c @@ -150,12 +150,3 @@ static const struct adreno_info a5xx_gpus[] = { } }; DECLARE_ADRENO_GPULIST(a5xx); - -MODULE_FIRMWARE("qcom/a530_pm4.fw"); -MODULE_FIRMWARE("qcom/a530_pfp.fw"); -MODULE_FIRMWARE("qcom/a530v3_gpmu.fw2"); -MODULE_FIRMWARE("qcom/a530_zap.mdt"); -MODULE_FIRMWARE("qcom/a530_zap.b00"); -MODULE_FIRMWARE("qcom/a530_zap.b01"); -MODULE_FIRMWARE("qcom/a530_zap.b02"); -MODULE_FIRMWARE("qcom/a540_gpmu.fw2"); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c index f85b7e89bafb..70f7ad806c34 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c @@ -1093,17 +1093,6 @@ static const struct adreno_info a6xx_gpus[] = { }; DECLARE_ADRENO_GPULIST(a6xx); -MODULE_FIRMWARE("qcom/a615_zap.mbn"); -MODULE_FIRMWARE("qcom/a619_gmu.bin"); -MODULE_FIRMWARE("qcom/a630_sqe.fw"); -MODULE_FIRMWARE("qcom/a630_gmu.bin"); -MODULE_FIRMWARE("qcom/a630_zap.mbn"); -MODULE_FIRMWARE("qcom/a640_gmu.bin"); -MODULE_FIRMWARE("qcom/a650_gmu.bin"); -MODULE_FIRMWARE("qcom/a650_sqe.fw"); -MODULE_FIRMWARE("qcom/a660_gmu.bin"); -MODULE_FIRMWARE("qcom/a660_sqe.fw"); - static const struct adreno_reglist a702_hwcg[] = { { REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222 }, { REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220 }, From 90957ca46abe41f61b318a18852eaed1aa828f11 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 5 May 2025 03:14:45 +0300 Subject: [PATCH 58/84] dt-bindings: display/msm/hdmi: drop obsolete GPIOs from schema The commit 68e674b13b17 ("drm/msm/hdmi: drop unused GPIO support") dropped support for obsolete qcom,hdmi-tx-mux-* gpios. They were not used by any of the upstream platforms. Drop them from the bindings too. Signed-off-by: Dmitry Baryshkov Reviewed-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/651708/ Link: https://lore.kernel.org/r/20250505-fd-hdmi-hpd-v5-1-48541f76318c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- .../devicetree/bindings/display/msm/hdmi.yaml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/hdmi.yaml b/Documentation/devicetree/bindings/display/msm/hdmi.yaml index d4a2033afea8..7e6f776a047a 100644 --- a/Documentation/devicetree/bindings/display/msm/hdmi.yaml +++ b/Documentation/devicetree/bindings/display/msm/hdmi.yaml @@ -66,21 +66,6 @@ properties: maxItems: 1 description: hpd pin - qcom,hdmi-tx-mux-en-gpios: - maxItems: 1 - deprecated: true - description: HDMI mux enable pin - - qcom,hdmi-tx-mux-sel-gpios: - maxItems: 1 - deprecated: true - description: HDMI mux select pin - - qcom,hdmi-tx-mux-lpm-gpios: - maxItems: 1 - deprecated: true - description: HDMI mux lpm pin - '#sound-dai-cells': const: 1 From 72dff0b04e40ca2fd28b07e8f237b1145e60de8d Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 5 May 2025 03:14:46 +0300 Subject: [PATCH 59/84] drm/msm/hdmi: convert clock and regulator arrays to const arrays As a preparation to the next patches convert 'static const char *' arrays to 'static const char * const', as required by the checkpatch.pl Signed-off-by: Dmitry Baryshkov Reviewed-by: Jessica Zhang Patchwork: https://patchwork.freedesktop.org/patch/651705/ Link: https://lore.kernel.org/r/20250505-fd-hdmi-hpd-v5-2-48541f76318c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.c | 10 +++++----- drivers/gpu/drm/msm/hdmi/hdmi.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 248541ff4492..9e9900882687 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -224,17 +224,17 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, .item ## _names = item ##_names_ ## entry, \ .item ## _cnt = ARRAY_SIZE(item ## _names_ ## entry) -static const char *hpd_reg_names_8960[] = {"core-vdda"}; -static const char *hpd_clk_names_8960[] = {"core", "master_iface", "slave_iface"}; +static const char * const hpd_reg_names_8960[] = {"core-vdda"}; +static const char * const hpd_clk_names_8960[] = {"core", "master_iface", "slave_iface"}; static const struct hdmi_platform_config hdmi_tx_8960_config = { HDMI_CFG(hpd_reg, 8960), HDMI_CFG(hpd_clk, 8960), }; -static const char *pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"}; -static const char *pwr_clk_names_8x74[] = {"extp", "alt_iface"}; -static const char *hpd_clk_names_8x74[] = {"iface", "core", "mdp_core"}; +static const char * const pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"}; +static const char * const pwr_clk_names_8x74[] = {"extp", "alt_iface"}; +static const char * const hpd_clk_names_8x74[] = {"iface", "core", "mdp_core"}; static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0}; static const struct hdmi_platform_config hdmi_tx_8974_config = { diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index a5f481c39277..381f957b3430 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -84,20 +84,20 @@ struct hdmi { /* platform config data (ie. from DT, or pdata) */ struct hdmi_platform_config { /* regulators that need to be on for hpd: */ - const char **hpd_reg_names; + const char * const *hpd_reg_names; int hpd_reg_cnt; /* regulators that need to be on for screen pwr: */ - const char **pwr_reg_names; + const char * const *pwr_reg_names; int pwr_reg_cnt; /* clks that need to be on for hpd: */ - const char **hpd_clk_names; + const char * const *hpd_clk_names; const long unsigned *hpd_freq; int hpd_clk_cnt; /* clks that need to be on for screen pwr (ie pixel clk): */ - const char **pwr_clk_names; + const char * const *pwr_clk_names; int pwr_clk_cnt; }; From e300f26b7e10cb4553352daebfc8a67ca12441e9 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 5 May 2025 03:14:47 +0300 Subject: [PATCH 60/84] drm/msm/hdmi: move the alt_iface clock to the hpd list According to the vendor kernel [1] , the alt_iface clock should be enabled together with the rest of HPD clocks, to make HPD to work properly. [1] https://git.codelinaro.org/clo/la/kernel/msm-3.18/-/commit/e07a5487e521e57f76083c0a6e2f995414ac6d03 Reviewed-by: Jessica Zhang Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/651709/ Link: https://lore.kernel.org/r/20250505-fd-hdmi-hpd-v5-3-48541f76318c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 9e9900882687..ebf9d8162c6e 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -233,9 +233,9 @@ static const struct hdmi_platform_config hdmi_tx_8960_config = { }; static const char * const pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"}; -static const char * const pwr_clk_names_8x74[] = {"extp", "alt_iface"}; -static const char * const hpd_clk_names_8x74[] = {"iface", "core", "mdp_core"}; -static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0}; +static const char * const pwr_clk_names_8x74[] = {"extp"}; +static const char * const hpd_clk_names_8x74[] = {"iface", "core", "mdp_core", "alt_iface"}; +static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0, 0}; static const struct hdmi_platform_config hdmi_tx_8974_config = { HDMI_CFG(pwr_reg, 8x74), From 7e53b0a98f1d425b48a10434efccbe9018536f4f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 5 May 2025 03:14:48 +0300 Subject: [PATCH 61/84] drm/msm/hdmi: simplify extp clock handling With the extp being the only "power" clock left, remove the surrounding loops and handle the extp clock directly. Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/651710/ Link: https://lore.kernel.org/r/20250505-fd-hdmi-hpd-v5-4-48541f76318c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.c | 24 ++++--------------- drivers/gpu/drm/msm/hdmi/hdmi.h | 6 +---- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 33 ++++++++++---------------- 3 files changed, 18 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index ebf9d8162c6e..104f9cefa148 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -233,13 +233,11 @@ static const struct hdmi_platform_config hdmi_tx_8960_config = { }; static const char * const pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"}; -static const char * const pwr_clk_names_8x74[] = {"extp"}; static const char * const hpd_clk_names_8x74[] = {"iface", "core", "mdp_core", "alt_iface"}; static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0, 0}; static const struct hdmi_platform_config hdmi_tx_8974_config = { HDMI_CFG(pwr_reg, 8x74), - HDMI_CFG(pwr_clk, 8x74), HDMI_CFG(hpd_clk, 8x74), .hpd_freq = hpd_clk_freq_8x74, }; @@ -369,24 +367,10 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev) hdmi->hpd_clks[i] = clk; } - hdmi->pwr_clks = devm_kcalloc(&pdev->dev, - config->pwr_clk_cnt, - sizeof(hdmi->pwr_clks[0]), - GFP_KERNEL); - if (!hdmi->pwr_clks) - return -ENOMEM; - - for (i = 0; i < config->pwr_clk_cnt; i++) { - struct clk *clk; - - clk = msm_clk_get(pdev, config->pwr_clk_names[i]); - if (IS_ERR(clk)) - return dev_err_probe(dev, PTR_ERR(clk), - "failed to get pwr clk: %s\n", - config->pwr_clk_names[i]); - - hdmi->pwr_clks[i] = clk; - } + hdmi->extp_clk = devm_clk_get_optional(&pdev->dev, "extp"); + if (IS_ERR(hdmi->extp_clk)) + return dev_err_probe(dev, PTR_ERR(hdmi->extp_clk), + "failed to get extp clock\n"); hdmi->hpd_gpiod = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN); /* This will catch e.g. -EPROBE_DEFER */ diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index 381f957b3430..3314bb8a09d6 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -50,7 +50,7 @@ struct hdmi { struct regulator_bulk_data *hpd_regs; struct regulator_bulk_data *pwr_regs; struct clk **hpd_clks; - struct clk **pwr_clks; + struct clk *extp_clk; struct gpio_desc *hpd_gpiod; @@ -95,10 +95,6 @@ struct hdmi_platform_config { const char * const *hpd_clk_names; const long unsigned *hpd_freq; int hpd_clk_cnt; - - /* clks that need to be on for screen pwr (ie pixel clk): */ - const char * const *pwr_clk_names; - int pwr_clk_cnt; }; struct hdmi_bridge { diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 9f1191e4c020..e7997e4a741c 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -19,7 +19,7 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; const struct hdmi_platform_config *config = hdmi->config; - int i, ret; + int ret; pm_runtime_get_sync(&hdmi->pdev->dev); @@ -27,21 +27,15 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) if (ret) DRM_DEV_ERROR(dev->dev, "failed to enable pwr regulator: %d\n", ret); - if (config->pwr_clk_cnt > 0) { + if (hdmi->extp_clk) { DBG("pixclock: %lu", hdmi->pixclock); - ret = clk_set_rate(hdmi->pwr_clks[0], hdmi->pixclock); - if (ret) { - DRM_DEV_ERROR(dev->dev, "failed to set pixel clk: %s (%d)\n", - config->pwr_clk_names[0], ret); - } - } + ret = clk_set_rate(hdmi->extp_clk, hdmi->pixclock); + if (ret) + DRM_DEV_ERROR(dev->dev, "failed to set extp clk rate: %d\n", ret); - for (i = 0; i < config->pwr_clk_cnt; i++) { - ret = clk_prepare_enable(hdmi->pwr_clks[i]); - if (ret) { - DRM_DEV_ERROR(dev->dev, "failed to enable pwr clk: %s (%d)\n", - config->pwr_clk_names[i], ret); - } + ret = clk_prepare_enable(hdmi->extp_clk); + if (ret) + DRM_DEV_ERROR(dev->dev, "failed to enable extp clk: %d\n", ret); } } @@ -51,15 +45,15 @@ static void power_off(struct drm_bridge *bridge) struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; const struct hdmi_platform_config *config = hdmi->config; - int i, ret; + int ret; /* TODO do we need to wait for final vblank somewhere before * cutting the clocks? */ mdelay(16 + 4); - for (i = 0; i < config->pwr_clk_cnt; i++) - clk_disable_unprepare(hdmi->pwr_clks[i]); + if (hdmi->extp_clk) + clk_disable_unprepare(hdmi->extp_clk); ret = regulator_bulk_disable(config->pwr_reg_cnt, hdmi->pwr_regs); if (ret) @@ -438,7 +432,6 @@ static enum drm_mode_status msm_hdmi_bridge_tmds_char_rate_valid(const struct dr { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; - const struct hdmi_platform_config *config = hdmi->config; struct msm_drm_private *priv = bridge->dev->dev_private; struct msm_kms *kms = priv->kms; long actual; @@ -451,8 +444,8 @@ static enum drm_mode_status msm_hdmi_bridge_tmds_char_rate_valid(const struct dr actual = kms->funcs->round_pixclk(kms, tmds_rate, hdmi_bridge->hdmi->encoder); - else if (config->pwr_clk_cnt > 0) - actual = clk_round_rate(hdmi->pwr_clks[0], tmds_rate); + else if (hdmi->extp_clk) + actual = clk_round_rate(hdmi->extp_clk, tmds_rate); else actual = tmds_rate; From a6984a3f9a5aef20c0bb17922c6e9a404ca9ef3a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 5 May 2025 03:14:49 +0300 Subject: [PATCH 62/84] drm/msm/hdmi: drop clock frequency assignment The only clock which has frequency being set through hpd_freqs is the "core" aka MDSS_HDMI_CLK clock. It always has the specified frequency, so we can drop corresponding clk_set_rate() call together with the hpd_freq infrastructure. Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/651717/ Link: https://lore.kernel.org/r/20250505-fd-hdmi-hpd-v5-5-48541f76318c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.c | 2 -- drivers/gpu/drm/msm/hdmi/hdmi.h | 1 - drivers/gpu/drm/msm/hdmi/hdmi_hpd.c | 9 --------- 3 files changed, 12 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 104f9cefa148..6f09920c5819 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -234,12 +234,10 @@ static const struct hdmi_platform_config hdmi_tx_8960_config = { static const char * const pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"}; static const char * const hpd_clk_names_8x74[] = {"iface", "core", "mdp_core", "alt_iface"}; -static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0, 0}; static const struct hdmi_platform_config hdmi_tx_8974_config = { HDMI_CFG(pwr_reg, 8x74), HDMI_CFG(hpd_clk, 8x74), - .hpd_freq = hpd_clk_freq_8x74, }; static int msm_hdmi_bind(struct device *dev, struct device *master, void *data) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index 3314bb8a09d6..e93d49d9e869 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -93,7 +93,6 @@ struct hdmi_platform_config { /* clks that need to be on for hpd: */ const char * const *hpd_clk_names; - const long unsigned *hpd_freq; int hpd_clk_cnt; }; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c index 9ce0ffa35417..7ae69b14e953 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c @@ -68,15 +68,6 @@ static void enable_hpd_clocks(struct hdmi *hdmi, bool enable) if (enable) { for (i = 0; i < config->hpd_clk_cnt; i++) { - if (config->hpd_freq && config->hpd_freq[i]) { - ret = clk_set_rate(hdmi->hpd_clks[i], - config->hpd_freq[i]); - if (ret) - dev_warn(dev, - "failed to set clk %s (%d)\n", - config->hpd_clk_names[i], ret); - } - ret = clk_prepare_enable(hdmi->hpd_clks[i]); if (ret) { DRM_DEV_ERROR(dev, From 15a5223dc6553c583a00e4f4afb106fa80b15f01 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 5 May 2025 03:14:50 +0300 Subject: [PATCH 63/84] drm/msm/hdmi: switch to clk_bulk API The last platform using legacy clock names for HDMI block (APQ8064) switched to new clock names in 5.16. It's time to stop caring about old DT, drop hand-coded helpers and switch to clk_bulk_* API. Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/651716/ Link: https://lore.kernel.org/r/20250505-fd-hdmi-hpd-v5-6-48541f76318c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.c | 15 ++++------- drivers/gpu/drm/msm/hdmi/hdmi.h | 2 +- drivers/gpu/drm/msm/hdmi/hdmi_hpd.c | 39 ++++++++++------------------- 3 files changed, 19 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 6f09920c5819..69e337d55179 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -353,17 +353,12 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev) if (!hdmi->hpd_clks) return -ENOMEM; - for (i = 0; i < config->hpd_clk_cnt; i++) { - struct clk *clk; + for (i = 0; i < config->hpd_clk_cnt; i++) + hdmi->hpd_clks[i].id = config->hpd_clk_names[i]; - clk = msm_clk_get(pdev, config->hpd_clk_names[i]); - if (IS_ERR(clk)) - return dev_err_probe(dev, PTR_ERR(clk), - "failed to get hpd clk: %s\n", - config->hpd_clk_names[i]); - - hdmi->hpd_clks[i] = clk; - } + ret = devm_clk_bulk_get(&pdev->dev, config->hpd_clk_cnt, hdmi->hpd_clks); + if (ret) + return ret; hdmi->extp_clk = devm_clk_get_optional(&pdev->dev, "extp"); if (IS_ERR(hdmi->extp_clk)) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index e93d49d9e869..3f87535bcf43 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -49,7 +49,7 @@ struct hdmi { struct regulator_bulk_data *hpd_regs; struct regulator_bulk_data *pwr_regs; - struct clk **hpd_clks; + struct clk_bulk_data *hpd_clks; struct clk *extp_clk; struct gpio_desc *hpd_gpiod; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c index 7ae69b14e953..e253c1408dd1 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c @@ -60,27 +60,6 @@ static void msm_hdmi_phy_reset(struct hdmi *hdmi) } } -static void enable_hpd_clocks(struct hdmi *hdmi, bool enable) -{ - const struct hdmi_platform_config *config = hdmi->config; - struct device *dev = &hdmi->pdev->dev; - int i, ret; - - if (enable) { - for (i = 0; i < config->hpd_clk_cnt; i++) { - ret = clk_prepare_enable(hdmi->hpd_clks[i]); - if (ret) { - DRM_DEV_ERROR(dev, - "failed to enable hpd clk: %s (%d)\n", - config->hpd_clk_names[i], ret); - } - } - } else { - for (i = config->hpd_clk_cnt - 1; i >= 0; i--) - clk_disable_unprepare(hdmi->hpd_clks[i]); - } -} - int msm_hdmi_hpd_enable(struct drm_bridge *bridge) { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); @@ -107,7 +86,9 @@ int msm_hdmi_hpd_enable(struct drm_bridge *bridge) gpiod_set_value_cansleep(hdmi->hpd_gpiod, 1); pm_runtime_get_sync(dev); - enable_hpd_clocks(hdmi, true); + ret = clk_bulk_prepare_enable(config->hpd_clk_cnt, hdmi->hpd_clks); + if (ret) + goto fail; msm_hdmi_set_mode(hdmi, false); msm_hdmi_phy_reset(hdmi); @@ -149,7 +130,7 @@ void msm_hdmi_hpd_disable(struct hdmi *hdmi) msm_hdmi_set_mode(hdmi, false); - enable_hpd_clocks(hdmi, false); + clk_bulk_disable_unprepare(config->hpd_clk_cnt, hdmi->hpd_clks); pm_runtime_put(dev); ret = pinctrl_pm_select_sleep_state(dev); @@ -193,14 +174,20 @@ void msm_hdmi_hpd_irq(struct drm_bridge *bridge) static enum drm_connector_status detect_reg(struct hdmi *hdmi) { - uint32_t hpd_int_status; + const struct hdmi_platform_config *config = hdmi->config; + u32 hpd_int_status = 0; + int ret; pm_runtime_get_sync(&hdmi->pdev->dev); - enable_hpd_clocks(hdmi, true); + ret = clk_bulk_prepare_enable(config->hpd_clk_cnt, hdmi->hpd_clks); + if (ret) + goto out; hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS); - enable_hpd_clocks(hdmi, false); + clk_bulk_disable_unprepare(config->hpd_clk_cnt, hdmi->hpd_clks); + +out: pm_runtime_put(&hdmi->pdev->dev); return (hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED) ? From 81aa83419706e74ad150a229cd3ada28a1afc35a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 5 May 2025 03:14:51 +0300 Subject: [PATCH 64/84] drm/msm/hdmi: switch to pm_runtime_resume_and_get() The pm_runtime_get_sync() function is a bad choise for runtime power management. Switch HDMI driver to pm_runtime_resume_and_get() and add proper error handling, while we are at it. Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/651713/ Link: https://lore.kernel.org/r/20250505-fd-hdmi-hpd-v5-7-48541f76318c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 2 +- drivers/gpu/drm/msm/hdmi/hdmi_hpd.c | 12 ++++++++++-- drivers/gpu/drm/msm/hdmi/hdmi_phy.c | 6 +++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index e7997e4a741c..3ae305e868a5 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -21,7 +21,7 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) const struct hdmi_platform_config *config = hdmi->config; int ret; - pm_runtime_get_sync(&hdmi->pdev->dev); + pm_runtime_resume_and_get(&hdmi->pdev->dev); ret = regulator_bulk_enable(config->pwr_reg_cnt, hdmi->pwr_regs); if (ret) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c index e253c1408dd1..d77c68914c5f 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c @@ -85,7 +85,12 @@ int msm_hdmi_hpd_enable(struct drm_bridge *bridge) if (hdmi->hpd_gpiod) gpiod_set_value_cansleep(hdmi->hpd_gpiod, 1); - pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) { + DRM_DEV_ERROR(dev, "runtime resume failed: %d\n", ret); + goto fail; + } + ret = clk_bulk_prepare_enable(config->hpd_clk_cnt, hdmi->hpd_clks); if (ret) goto fail; @@ -178,7 +183,10 @@ static enum drm_connector_status detect_reg(struct hdmi *hdmi) u32 hpd_int_status = 0; int ret; - pm_runtime_get_sync(&hdmi->pdev->dev); + ret = pm_runtime_resume_and_get(&hdmi->pdev->dev); + if (ret) + goto out; + ret = clk_bulk_prepare_enable(config->hpd_clk_cnt, hdmi->hpd_clks); if (ret) goto out; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c index 03120c54ced6..667573f1db7c 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c @@ -58,7 +58,11 @@ int msm_hdmi_phy_resource_enable(struct hdmi_phy *phy) struct device *dev = &phy->pdev->dev; int i, ret = 0; - pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) { + DRM_DEV_ERROR(dev, "runtime resume failed: %d\n", ret); + return ret; + } ret = regulator_bulk_enable(cfg->num_regs, phy->regs); if (ret) { From 531b4e2c206e5f7dead04d9da84dfa693ac57481 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 5 May 2025 03:14:52 +0300 Subject: [PATCH 65/84] drm/msm/hdmi: add runtime PM calls to DDC transfer function We must be sure that the HDMI controller is powered on, while performing the DDC transfer. Add corresponding runtime PM calls to msm_hdmi_i2c_xfer(). Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/651727/ Link: https://lore.kernel.org/r/20250505-fd-hdmi-hpd-v5-8-48541f76318c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi_i2c.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_i2c.c b/drivers/gpu/drm/msm/hdmi/hdmi_i2c.c index 7aa500d24240..ebefea4fb408 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_i2c.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_i2c.c @@ -107,11 +107,15 @@ static int msm_hdmi_i2c_xfer(struct i2c_adapter *i2c, if (num == 0) return num; + ret = pm_runtime_resume_and_get(&hdmi->pdev->dev); + if (ret) + return ret; + init_ddc(hdmi_i2c); ret = ddc_clear_irq(hdmi_i2c); if (ret) - return ret; + goto fail; for (i = 0; i < num; i++) { struct i2c_msg *p = &msgs[i]; @@ -169,7 +173,7 @@ static int msm_hdmi_i2c_xfer(struct i2c_adapter *i2c, hdmi_read(hdmi, REG_HDMI_DDC_SW_STATUS), hdmi_read(hdmi, REG_HDMI_DDC_HW_STATUS), hdmi_read(hdmi, REG_HDMI_DDC_INT_CTRL)); - return ret; + goto fail; } ddc_status = hdmi_read(hdmi, REG_HDMI_DDC_SW_STATUS); @@ -202,7 +206,13 @@ static int msm_hdmi_i2c_xfer(struct i2c_adapter *i2c, } } + pm_runtime_put(&hdmi->pdev->dev); + return i; + +fail: + pm_runtime_put(&hdmi->pdev->dev); + return ret; } static u32 msm_hdmi_i2c_func(struct i2c_adapter *adapter) From 0c5ec818cc166b4633c5f12e26abfddb57f6af9f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 5 May 2025 03:14:53 +0300 Subject: [PATCH 66/84] drm/msm/hdmi: implement proper runtime PM handling It is completely not obvious, but the so-called 'hpd' clocks and regulators are required for the HDMI host to function properly. Merge pwr and hpd regulators. Use regulators, clocks and pinctrl to implement proper runtime PM callbacks. Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/651715/ Link: https://lore.kernel.org/r/20250505-fd-hdmi-hpd-v5-9-48541f76318c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.c | 62 +++++++++++++++++++------- drivers/gpu/drm/msm/hdmi/hdmi.h | 5 --- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 12 ----- drivers/gpu/drm/msm/hdmi/hdmi_hpd.c | 42 +---------------- 4 files changed, 47 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 69e337d55179..ded20176aa80 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -224,11 +225,11 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, .item ## _names = item ##_names_ ## entry, \ .item ## _cnt = ARRAY_SIZE(item ## _names_ ## entry) -static const char * const hpd_reg_names_8960[] = {"core-vdda"}; +static const char * const pwr_reg_names_8960[] = {"core-vdda"}; static const char * const hpd_clk_names_8960[] = {"core", "master_iface", "slave_iface"}; static const struct hdmi_platform_config hdmi_tx_8960_config = { - HDMI_CFG(hpd_reg, 8960), + HDMI_CFG(pwr_reg, 8960), HDMI_CFG(hpd_clk, 8960), }; @@ -318,20 +319,6 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev) if (hdmi->irq < 0) return hdmi->irq; - hdmi->hpd_regs = devm_kcalloc(&pdev->dev, - config->hpd_reg_cnt, - sizeof(hdmi->hpd_regs[0]), - GFP_KERNEL); - if (!hdmi->hpd_regs) - return -ENOMEM; - - for (i = 0; i < config->hpd_reg_cnt; i++) - hdmi->hpd_regs[i].supply = config->hpd_reg_names[i]; - - ret = devm_regulator_bulk_get(&pdev->dev, config->hpd_reg_cnt, hdmi->hpd_regs); - if (ret) - return dev_err_probe(dev, ret, "failed to get hpd regulators\n"); - hdmi->pwr_regs = devm_kcalloc(&pdev->dev, config->pwr_reg_cnt, sizeof(hdmi->pwr_regs[0]), @@ -409,6 +396,48 @@ static void msm_hdmi_dev_remove(struct platform_device *pdev) msm_hdmi_put_phy(hdmi); } +static int msm_hdmi_runtime_suspend(struct device *dev) +{ + struct hdmi *hdmi = dev_get_drvdata(dev); + const struct hdmi_platform_config *config = hdmi->config; + + clk_bulk_disable_unprepare(config->hpd_clk_cnt, hdmi->hpd_clks); + + pinctrl_pm_select_sleep_state(dev); + + regulator_bulk_disable(config->pwr_reg_cnt, hdmi->pwr_regs); + + return 0; +} + +static int msm_hdmi_runtime_resume(struct device *dev) +{ + struct hdmi *hdmi = dev_get_drvdata(dev); + const struct hdmi_platform_config *config = hdmi->config; + int ret; + + ret = regulator_bulk_enable(config->pwr_reg_cnt, hdmi->pwr_regs); + if (ret) + return ret; + + ret = pinctrl_pm_select_default_state(dev); + if (ret) + goto fail; + + ret = clk_bulk_prepare_enable(config->hpd_clk_cnt, hdmi->hpd_clks); + if (ret) + goto fail; + + return 0; + +fail: + pinctrl_pm_select_sleep_state(dev); + + return ret; +} + +DEFINE_RUNTIME_DEV_PM_OPS(msm_hdmi_pm_ops, msm_hdmi_runtime_suspend, msm_hdmi_runtime_resume, NULL); + static const struct of_device_id msm_hdmi_dt_match[] = { { .compatible = "qcom,hdmi-tx-8998", .data = &hdmi_tx_8974_config }, { .compatible = "qcom,hdmi-tx-8996", .data = &hdmi_tx_8974_config }, @@ -426,6 +455,7 @@ static struct platform_driver msm_hdmi_driver = { .driver = { .name = "hdmi_msm", .of_match_table = msm_hdmi_dt_match, + .pm = &msm_hdmi_pm_ops, }, }; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index 3f87535bcf43..7e3c035cf913 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -47,7 +47,6 @@ struct hdmi { void __iomem *qfprom_mmio; phys_addr_t mmio_phy_addr; - struct regulator_bulk_data *hpd_regs; struct regulator_bulk_data *pwr_regs; struct clk_bulk_data *hpd_clks; struct clk *extp_clk; @@ -83,10 +82,6 @@ struct hdmi { /* platform config data (ie. from DT, or pdata) */ struct hdmi_platform_config { - /* regulators that need to be on for hpd: */ - const char * const *hpd_reg_names; - int hpd_reg_cnt; - /* regulators that need to be on for screen pwr: */ const char * const *pwr_reg_names; int pwr_reg_cnt; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 3ae305e868a5..665c5e1323d0 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -18,15 +18,10 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) struct drm_device *dev = bridge->dev; struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; - const struct hdmi_platform_config *config = hdmi->config; int ret; pm_runtime_resume_and_get(&hdmi->pdev->dev); - ret = regulator_bulk_enable(config->pwr_reg_cnt, hdmi->pwr_regs); - if (ret) - DRM_DEV_ERROR(dev->dev, "failed to enable pwr regulator: %d\n", ret); - if (hdmi->extp_clk) { DBG("pixclock: %lu", hdmi->pixclock); ret = clk_set_rate(hdmi->extp_clk, hdmi->pixclock); @@ -41,11 +36,8 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) static void power_off(struct drm_bridge *bridge) { - struct drm_device *dev = bridge->dev; struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; - const struct hdmi_platform_config *config = hdmi->config; - int ret; /* TODO do we need to wait for final vblank somewhere before * cutting the clocks? @@ -55,10 +47,6 @@ static void power_off(struct drm_bridge *bridge) if (hdmi->extp_clk) clk_disable_unprepare(hdmi->extp_clk); - ret = regulator_bulk_disable(config->pwr_reg_cnt, hdmi->pwr_regs); - if (ret) - DRM_DEV_ERROR(dev->dev, "failed to disable pwr regulator: %d\n", ret); - pm_runtime_put(&hdmi->pdev->dev); } diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c index d77c68914c5f..a42ed26a5b7c 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c @@ -64,36 +64,17 @@ int msm_hdmi_hpd_enable(struct drm_bridge *bridge) { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; - const struct hdmi_platform_config *config = hdmi->config; struct device *dev = &hdmi->pdev->dev; uint32_t hpd_ctrl; int ret; unsigned long flags; - ret = regulator_bulk_enable(config->hpd_reg_cnt, hdmi->hpd_regs); - if (ret) { - DRM_DEV_ERROR(dev, "failed to enable hpd regulators: %d\n", ret); - goto fail; - } - - ret = pinctrl_pm_select_default_state(dev); - if (ret) { - DRM_DEV_ERROR(dev, "pinctrl state chg failed: %d\n", ret); - goto fail; - } - if (hdmi->hpd_gpiod) gpiod_set_value_cansleep(hdmi->hpd_gpiod, 1); ret = pm_runtime_resume_and_get(dev); - if (ret) { - DRM_DEV_ERROR(dev, "runtime resume failed: %d\n", ret); - goto fail; - } - - ret = clk_bulk_prepare_enable(config->hpd_clk_cnt, hdmi->hpd_clks); if (ret) - goto fail; + return ret; msm_hdmi_set_mode(hdmi, false); msm_hdmi_phy_reset(hdmi); @@ -119,32 +100,18 @@ int msm_hdmi_hpd_enable(struct drm_bridge *bridge) spin_unlock_irqrestore(&hdmi->reg_lock, flags); return 0; - -fail: - return ret; } void msm_hdmi_hpd_disable(struct hdmi *hdmi) { - const struct hdmi_platform_config *config = hdmi->config; struct device *dev = &hdmi->pdev->dev; - int ret; /* Disable HPD interrupt */ hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0); msm_hdmi_set_mode(hdmi, false); - clk_bulk_disable_unprepare(config->hpd_clk_cnt, hdmi->hpd_clks); pm_runtime_put(dev); - - ret = pinctrl_pm_select_sleep_state(dev); - if (ret) - dev_warn(dev, "pinctrl state chg failed: %d\n", ret); - - ret = regulator_bulk_disable(config->hpd_reg_cnt, hdmi->hpd_regs); - if (ret) - dev_warn(dev, "failed to disable hpd regulator: %d\n", ret); } void msm_hdmi_hpd_irq(struct drm_bridge *bridge) @@ -179,7 +146,6 @@ void msm_hdmi_hpd_irq(struct drm_bridge *bridge) static enum drm_connector_status detect_reg(struct hdmi *hdmi) { - const struct hdmi_platform_config *config = hdmi->config; u32 hpd_int_status = 0; int ret; @@ -187,14 +153,8 @@ static enum drm_connector_status detect_reg(struct hdmi *hdmi) if (ret) goto out; - ret = clk_bulk_prepare_enable(config->hpd_clk_cnt, hdmi->hpd_clks); - if (ret) - goto out; - hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS); - clk_bulk_disable_unprepare(config->hpd_clk_cnt, hdmi->hpd_clks); - out: pm_runtime_put(&hdmi->pdev->dev); From a7a1550d04e90a66bf6a9875aaaba392fc426e30 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 5 May 2025 03:14:54 +0300 Subject: [PATCH 67/84] drm/msm/hdmi: rename hpd_clks to pwr_clks As these clocks are now used in the runtime PM callbacks, they have no connection to 'HPD'. Rename corresponding fields to follow clocks purpose, to power up the HDMI controller. Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/651720/ Link: https://lore.kernel.org/r/20250505-fd-hdmi-hpd-v5-10-48541f76318c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.c | 26 +++++++++++++------------- drivers/gpu/drm/msm/hdmi/hdmi.h | 6 +++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index ded20176aa80..8e6e3e6a04bd 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -226,19 +226,19 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, .item ## _cnt = ARRAY_SIZE(item ## _names_ ## entry) static const char * const pwr_reg_names_8960[] = {"core-vdda"}; -static const char * const hpd_clk_names_8960[] = {"core", "master_iface", "slave_iface"}; +static const char * const pwr_clk_names_8960[] = {"core", "master_iface", "slave_iface"}; static const struct hdmi_platform_config hdmi_tx_8960_config = { HDMI_CFG(pwr_reg, 8960), - HDMI_CFG(hpd_clk, 8960), + HDMI_CFG(pwr_clk, 8960), }; static const char * const pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"}; -static const char * const hpd_clk_names_8x74[] = {"iface", "core", "mdp_core", "alt_iface"}; +static const char * const pwr_clk_names_8x74[] = {"iface", "core", "mdp_core", "alt_iface"}; static const struct hdmi_platform_config hdmi_tx_8974_config = { HDMI_CFG(pwr_reg, 8x74), - HDMI_CFG(hpd_clk, 8x74), + HDMI_CFG(pwr_clk, 8x74), }; static int msm_hdmi_bind(struct device *dev, struct device *master, void *data) @@ -333,17 +333,17 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev) if (ret) return dev_err_probe(dev, ret, "failed to get pwr regulators\n"); - hdmi->hpd_clks = devm_kcalloc(&pdev->dev, - config->hpd_clk_cnt, - sizeof(hdmi->hpd_clks[0]), + hdmi->pwr_clks = devm_kcalloc(&pdev->dev, + config->pwr_clk_cnt, + sizeof(hdmi->pwr_clks[0]), GFP_KERNEL); - if (!hdmi->hpd_clks) + if (!hdmi->pwr_clks) return -ENOMEM; - for (i = 0; i < config->hpd_clk_cnt; i++) - hdmi->hpd_clks[i].id = config->hpd_clk_names[i]; + for (i = 0; i < config->pwr_clk_cnt; i++) + hdmi->pwr_clks[i].id = config->pwr_clk_names[i]; - ret = devm_clk_bulk_get(&pdev->dev, config->hpd_clk_cnt, hdmi->hpd_clks); + ret = devm_clk_bulk_get(&pdev->dev, config->pwr_clk_cnt, hdmi->pwr_clks); if (ret) return ret; @@ -401,7 +401,7 @@ static int msm_hdmi_runtime_suspend(struct device *dev) struct hdmi *hdmi = dev_get_drvdata(dev); const struct hdmi_platform_config *config = hdmi->config; - clk_bulk_disable_unprepare(config->hpd_clk_cnt, hdmi->hpd_clks); + clk_bulk_disable_unprepare(config->pwr_clk_cnt, hdmi->pwr_clks); pinctrl_pm_select_sleep_state(dev); @@ -424,7 +424,7 @@ static int msm_hdmi_runtime_resume(struct device *dev) if (ret) goto fail; - ret = clk_bulk_prepare_enable(config->hpd_clk_cnt, hdmi->hpd_clks); + ret = clk_bulk_prepare_enable(config->pwr_clk_cnt, hdmi->pwr_clks); if (ret) goto fail; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index 7e3c035cf913..a28437beb157 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -48,7 +48,7 @@ struct hdmi { phys_addr_t mmio_phy_addr; struct regulator_bulk_data *pwr_regs; - struct clk_bulk_data *hpd_clks; + struct clk_bulk_data *pwr_clks; struct clk *extp_clk; struct gpio_desc *hpd_gpiod; @@ -87,8 +87,8 @@ struct hdmi_platform_config { int pwr_reg_cnt; /* clks that need to be on for hpd: */ - const char * const *hpd_clk_names; - int hpd_clk_cnt; + const char * const *pwr_clk_names; + int pwr_clk_cnt; }; struct hdmi_bridge { From 969bbbf7fba2ae09f97df773dc764de11abdb902 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 5 May 2025 03:14:55 +0300 Subject: [PATCH 68/84] drm/msm/hdmi: expand the HDMI_CFG macro Expand the HDMI_CFG() macro in HDMI config description. It has no added value other than hiding some boilerplate declarations. Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/651724/ Link: https://lore.kernel.org/r/20250505-fd-hdmi-hpd-v5-11-48541f76318c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.c | 16 ++++++++-------- drivers/gpu/drm/msm/hdmi/hdmi.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 8e6e3e6a04bd..3d10fe6f8545 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -221,24 +221,24 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, * The hdmi device: */ -#define HDMI_CFG(item, entry) \ - .item ## _names = item ##_names_ ## entry, \ - .item ## _cnt = ARRAY_SIZE(item ## _names_ ## entry) - static const char * const pwr_reg_names_8960[] = {"core-vdda"}; static const char * const pwr_clk_names_8960[] = {"core", "master_iface", "slave_iface"}; static const struct hdmi_platform_config hdmi_tx_8960_config = { - HDMI_CFG(pwr_reg, 8960), - HDMI_CFG(pwr_clk, 8960), + .pwr_reg_names = pwr_reg_names_8960, + .pwr_reg_cnt = ARRAY_SIZE(pwr_reg_names_8960), + .pwr_clk_names = pwr_clk_names_8960, + .pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names_8960), }; static const char * const pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"}; static const char * const pwr_clk_names_8x74[] = {"iface", "core", "mdp_core", "alt_iface"}; static const struct hdmi_platform_config hdmi_tx_8974_config = { - HDMI_CFG(pwr_reg, 8x74), - HDMI_CFG(pwr_clk, 8x74), + .pwr_reg_names = pwr_reg_names_8x74, + .pwr_reg_cnt = ARRAY_SIZE(pwr_reg_names_8x74), + .pwr_clk_names = pwr_clk_names_8x74, + .pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names_8x74), }; static int msm_hdmi_bind(struct device *dev, struct device *master, void *data) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index a28437beb157..fb64652162b6 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -86,7 +86,7 @@ struct hdmi_platform_config { const char * const *pwr_reg_names; int pwr_reg_cnt; - /* clks that need to be on for hpd: */ + /* clks that need to be on: */ const char * const *pwr_clk_names; int pwr_clk_cnt; }; From b93f19d8d03a9455aef88664c649e86140fe1430 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 5 May 2025 03:14:56 +0300 Subject: [PATCH 69/84] drm/msm/hdmi: ensure that HDMI is up if HPD is requested The HDMI block needs to be enabled to properly generate HPD events. Make sure it is not turned off in the disable paths if HPD delivery is enabled. Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/651722/ Link: https://lore.kernel.org/r/20250505-fd-hdmi-hpd-v5-12-48541f76318c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.c | 1 + drivers/gpu/drm/msm/hdmi/hdmi.h | 2 ++ drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 8 +++++++- drivers/gpu/drm/msm/hdmi/hdmi_hpd.c | 9 ++++++++- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 3d10fe6f8545..5355cfd391c5 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -293,6 +293,7 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev) hdmi->pdev = pdev; hdmi->config = config; spin_lock_init(&hdmi->reg_lock); + mutex_init(&hdmi->state_mutex); ret = drm_of_find_panel_or_bridge(pdev->dev.of_node, 1, 0, NULL, &hdmi->next_bridge); if (ret && ret != -ENODEV) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index fb64652162b6..e488ee31cc86 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -41,6 +41,8 @@ struct hdmi { /* video state: */ bool power_on; + bool hpd_enabled; + struct mutex state_mutex; /* protects two booleans */ unsigned long int pixclock; void __iomem *mmio; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 665c5e1323d0..8ff0079abc80 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -302,11 +302,13 @@ static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge, msm_hdmi_set_timings(hdmi, &crtc_state->adjusted_mode); + mutex_lock(&hdmi->state_mutex); if (!hdmi->power_on) { msm_hdmi_phy_resource_enable(phy); msm_hdmi_power_on(bridge); hdmi->power_on = true; } + mutex_unlock(&hdmi->state_mutex); if (connector->display_info.is_hdmi) msm_hdmi_audio_update(hdmi); @@ -332,7 +334,10 @@ static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge, msm_hdmi_hdcp_off(hdmi->hdcp_ctrl); DBG("power down"); - msm_hdmi_set_mode(hdmi, false); + + /* Keep the HDMI enabled if the HPD is enabled */ + mutex_lock(&hdmi->state_mutex); + msm_hdmi_set_mode(hdmi, hdmi->hpd_enabled); msm_hdmi_phy_powerdown(phy); @@ -343,6 +348,7 @@ static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge, msm_hdmi_audio_update(hdmi); msm_hdmi_phy_resource_disable(phy); } + mutex_unlock(&hdmi->state_mutex); } static void msm_hdmi_set_timings(struct hdmi *hdmi, diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c index a42ed26a5b7c..e03d0ca230e6 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c @@ -76,10 +76,14 @@ int msm_hdmi_hpd_enable(struct drm_bridge *bridge) if (ret) return ret; + mutex_lock(&hdmi->state_mutex); msm_hdmi_set_mode(hdmi, false); msm_hdmi_phy_reset(hdmi); msm_hdmi_set_mode(hdmi, true); + hdmi->hpd_enabled = true; + mutex_unlock(&hdmi->state_mutex); + hdmi_write(hdmi, REG_HDMI_USEC_REFTIMER, 0x0001001b); /* enable HPD events: */ @@ -109,7 +113,10 @@ void msm_hdmi_hpd_disable(struct hdmi *hdmi) /* Disable HPD interrupt */ hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0); - msm_hdmi_set_mode(hdmi, false); + mutex_lock(&hdmi->state_mutex); + hdmi->hpd_enabled = false; + msm_hdmi_set_mode(hdmi, hdmi->power_on); + mutex_unlock(&hdmi->state_mutex); pm_runtime_put(dev); } From 666832f7c2612345c0c15546f3e0bf3d86ee325a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 5 May 2025 03:55:47 +0300 Subject: [PATCH 70/84] drm/msm/hdmi: wire in hpd_enable/hpd_disable bridge ops The HDMI driver already has msm_hdmi_hpd_enable() and msm_hdmi_hpd_disable() functions. Wire them into the msm_hdmi_bridge_funcs, so that HPD can be enabled and disabled dynamically rather than always having HPD events generation enabled. Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250505-fd-hdmi-hpd-v5-13-48541f76318c@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.c | 9 --------- drivers/gpu/drm/msm/hdmi/hdmi.h | 4 ++-- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 2 ++ drivers/gpu/drm/msm/hdmi/hdmi_hpd.c | 12 ++++++------ 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 5355cfd391c5..2fd388b892dc 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -200,12 +200,6 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, goto fail; } - ret = msm_hdmi_hpd_enable(hdmi->bridge); - if (ret < 0) { - DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret); - goto fail; - } - return 0; fail: @@ -261,9 +255,6 @@ static void msm_hdmi_unbind(struct device *dev, struct device *master, struct msm_drm_private *priv = dev_get_drvdata(master); if (priv->hdmi) { - if (priv->hdmi->bridge) - msm_hdmi_hpd_disable(priv->hdmi); - msm_hdmi_destroy(priv->hdmi); priv->hdmi = NULL; } diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index e488ee31cc86..d5e572d10d6a 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -216,8 +216,8 @@ int msm_hdmi_bridge_init(struct hdmi *hdmi); void msm_hdmi_hpd_irq(struct drm_bridge *bridge); enum drm_connector_status msm_hdmi_bridge_detect( struct drm_bridge *bridge); -int msm_hdmi_hpd_enable(struct drm_bridge *bridge); -void msm_hdmi_hpd_disable(struct hdmi *hdmi); +void msm_hdmi_hpd_enable(struct drm_bridge *bridge); +void msm_hdmi_hpd_disable(struct drm_bridge *bridge); /* * i2c adapter for ddc: diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 8ff0079abc80..53a7ce8cc7bc 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -459,6 +459,8 @@ static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = { .atomic_post_disable = msm_hdmi_bridge_atomic_post_disable, .edid_read = msm_hdmi_bridge_edid_read, .detect = msm_hdmi_bridge_detect, + .hpd_enable = msm_hdmi_hpd_enable, + .hpd_disable = msm_hdmi_hpd_disable, .hdmi_tmds_char_rate_valid = msm_hdmi_bridge_tmds_char_rate_valid, .hdmi_clear_infoframe = msm_hdmi_bridge_clear_infoframe, .hdmi_write_infoframe = msm_hdmi_bridge_write_infoframe, diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c index e03d0ca230e6..407e6c449ee0 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c @@ -60,7 +60,7 @@ static void msm_hdmi_phy_reset(struct hdmi *hdmi) } } -int msm_hdmi_hpd_enable(struct drm_bridge *bridge) +void msm_hdmi_hpd_enable(struct drm_bridge *bridge) { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; @@ -73,8 +73,8 @@ int msm_hdmi_hpd_enable(struct drm_bridge *bridge) gpiod_set_value_cansleep(hdmi->hpd_gpiod, 1); ret = pm_runtime_resume_and_get(dev); - if (ret) - return ret; + if (WARN_ON(ret)) + return; mutex_lock(&hdmi->state_mutex); msm_hdmi_set_mode(hdmi, false); @@ -102,12 +102,12 @@ int msm_hdmi_hpd_enable(struct drm_bridge *bridge) hdmi_write(hdmi, REG_HDMI_HPD_CTRL, HDMI_HPD_CTRL_ENABLE | hpd_ctrl); spin_unlock_irqrestore(&hdmi->reg_lock, flags); - - return 0; } -void msm_hdmi_hpd_disable(struct hdmi *hdmi) +void msm_hdmi_hpd_disable(struct drm_bridge *bridge) { + struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = hdmi_bridge->hdmi; struct device *dev = &hdmi->pdev->dev; /* Disable HPD interrupt */ From 1d0a6c9e3b0d2efb6274d50e706b9bdbc8ba0aaa Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 30 Apr 2025 15:00:37 +0200 Subject: [PATCH 71/84] drm/msm/dpu: Add missing "fetch" name to set_active_pipes() The set_active_pipes() callback configures CTL_FETCH_PIPE_ACTIVE and newer DPU v12.0 comes with CTL_PIPE_ACTIVE, thus rename it to set_active_fetch_pipes() to better match the purpose. Reviewed-by: Dmitry Baryshkov Reviewed-by: Jessica Zhang Signed-off-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/651261/ Link: https://lore.kernel.org/r/20250430-b4-sm8750-display-v5-7-8cab30c3e4df@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 12 ++++++------ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 6 +++--- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 0714936d8835..2d7af6fff270 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -445,9 +445,9 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, uint32_t lm_idx; bool bg_alpha_enable = false; - DECLARE_BITMAP(fetch_active, SSPP_MAX); + DECLARE_BITMAP(active_fetch, SSPP_MAX); - memset(fetch_active, 0, sizeof(fetch_active)); + memset(active_fetch, 0, sizeof(active_fetch)); drm_atomic_crtc_for_each_plane(plane, crtc) { state = plane->state; if (!state) @@ -464,7 +464,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, if (pstate->stage == DPU_STAGE_BASE && format->alpha_enable) bg_alpha_enable = true; - set_bit(pstate->pipe.sspp->idx, fetch_active); + set_bit(pstate->pipe.sspp->idx, active_fetch); _dpu_crtc_blend_setup_pipe(crtc, plane, mixer, cstate->num_mixers, pstate->stage, @@ -472,7 +472,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, &pstate->pipe, 0, stage_cfg); if (pstate->r_pipe.sspp) { - set_bit(pstate->r_pipe.sspp->idx, fetch_active); + set_bit(pstate->r_pipe.sspp->idx, active_fetch); _dpu_crtc_blend_setup_pipe(crtc, plane, mixer, cstate->num_mixers, pstate->stage, @@ -492,8 +492,8 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, } } - if (ctl->ops.set_active_pipes) - ctl->ops.set_active_pipes(ctl, fetch_active); + if (ctl->ops.set_active_fetch_pipes) + ctl->ops.set_active_fetch_pipes(ctl, active_fetch); _dpu_crtc_program_lm_output_roi(crtc); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index 21f4d403e3c2..65ec632a2294 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -711,8 +711,8 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx, } } -static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx, - unsigned long *fetch_active) +static void dpu_hw_ctl_set_active_fetch_pipes(struct dpu_hw_ctl *ctx, + unsigned long *fetch_active) { int i; u32 val = 0; @@ -775,7 +775,7 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops, ops->update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp; if (cap & BIT(DPU_CTL_FETCH_ACTIVE)) - ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active; + ops->set_active_fetch_pipes = dpu_hw_ctl_set_active_fetch_pipes; }; /** diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h index cea23436fc80..feb09590bc8f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h @@ -256,7 +256,7 @@ struct dpu_hw_ctl_ops { void (*setup_blendstage)(struct dpu_hw_ctl *ctx, enum dpu_lm lm, struct dpu_hw_stage_cfg *cfg); - void (*set_active_pipes)(struct dpu_hw_ctl *ctx, + void (*set_active_fetch_pipes)(struct dpu_hw_ctl *ctx, unsigned long *fetch_active); }; From 164e00a9e6fbb8045e1a199972a5215c88a935fa Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 30 Apr 2025 15:00:38 +0200 Subject: [PATCH 72/84] drm/msm/dpu: Clear CTL_FETCH_PIPE_ACTIVE on mixer reset Resetting mixers should also include resetting active fetch pipes. Fixes: ae4d721ce100 ("drm/msm/dpu: add an API to reset the encoder related hw blocks") Reviewed-by: Dmitry Baryshkov Signed-off-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/651246/ Link: https://lore.kernel.org/r/20250430-b4-sm8750-display-v5-8-8cab30c3e4df@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index f9c46180b8f7..7020098360e4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2194,6 +2194,9 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc) /* clear all blendstages */ if (ctl->ops.setup_blendstage) ctl->ops.setup_blendstage(ctl, hw_mixer[i]->idx, NULL); + + if (ctl->ops.set_active_fetch_pipes) + ctl->ops.set_active_fetch_pipes(ctl, NULL); } } From 3c072d50aed6fb354d593606b5424c8d1fc30fb7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 30 Apr 2025 15:00:39 +0200 Subject: [PATCH 73/84] drm/msm/dpu: Clear CTL_FETCH_PIPE_ACTIVE on ctl_path reset Resetting entire CTL path should also include resetting active fetch pipes. Fixes: e1a950eec256 ("drm/msm/dpu: add reset_intf_cfg operation for dpu_hw_ctl") Reviewed-by: Dmitry Baryshkov Signed-off-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/651252/ Link: https://lore.kernel.org/r/20250430-b4-sm8750-display-v5-9-8cab30c3e4df@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index 65ec632a2294..6e6143865621 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -672,6 +672,9 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx, dpu_hw_ctl_clear_all_blendstages(ctx); + if (ctx->ops.set_active_fetch_pipes) + ctx->ops.set_active_fetch_pipes(ctx, NULL); + if (cfg->intf) { intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE); intf_active &= ~BIT(cfg->intf - INTF_0); From 2e162df9f66f280eb614e65be506017fe3ab39b9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 30 Apr 2025 15:00:40 +0200 Subject: [PATCH 74/84] drm/msm/dpu: Clear CTL_FETCH_PIPE_ACTIVE before blend setup Before blend setup, all existing blend stages are cleared, so shall be active fetch pipes. Fixes: b3652e87c03c ("drm/msm/disp/dpu1: add support to program fetch active in ctl path") Reviewed-by: Dmitry Baryshkov Signed-off-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/651263/ Link: https://lore.kernel.org/r/20250430-b4-sm8750-display-v5-10-8cab30c3e4df@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 2d7af6fff270..a4b0fe0d9899 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -519,6 +519,8 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc) if (mixer[i].lm_ctl->ops.clear_all_blendstages) mixer[i].lm_ctl->ops.clear_all_blendstages( mixer[i].lm_ctl); + if (mixer[i].lm_ctl->ops.set_active_fetch_pipes) + mixer[i].lm_ctl->ops.set_active_fetch_pipes(mixer[i].lm_ctl, NULL); } /* initialize stage cfg */ From b82dd6d2583c1ab6bb7342ee14cfe52107bca99a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 30 Apr 2025 15:00:41 +0200 Subject: [PATCH 75/84] drm/msm/dpu: Drop useless comments Drop comments about SoC before each 'struct dpu_lm_sub_blks' for given SoC because it's duplicating the actual name of structure. Reviewed-by: Dmitry Baryshkov Reviewed-by: Jessica Zhang Signed-off-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/651251/ Link: https://lore.kernel.org/r/20250430-b4-sm8750-display-v5-11-8cab30c3e4df@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 338fdec761d4..c878fe196aeb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -370,8 +370,6 @@ static const struct dpu_sspp_sub_blks dpu_dma_sblk = _DMA_SBLK(); * MIXER sub blocks config *************************************************************/ -/* MSM8998 */ - static const struct dpu_lm_sub_blks msm8998_lm_sblk = { .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .maxblendstages = 7, /* excluding base layer */ @@ -381,8 +379,6 @@ static const struct dpu_lm_sub_blks msm8998_lm_sblk = { }, }; -/* SDM845 */ - static const struct dpu_lm_sub_blks sdm845_lm_sblk = { .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .maxblendstages = 11, /* excluding base layer */ @@ -392,8 +388,6 @@ static const struct dpu_lm_sub_blks sdm845_lm_sblk = { }, }; -/* SC7180 */ - static const struct dpu_lm_sub_blks sc7180_lm_sblk = { .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .maxblendstages = 7, /* excluding base layer */ @@ -402,8 +396,6 @@ static const struct dpu_lm_sub_blks sc7180_lm_sblk = { }, }; -/* QCM2290 */ - static const struct dpu_lm_sub_blks qcm2290_lm_sblk = { .maxwidth = DEFAULT_DPU_LINE_WIDTH, .maxblendstages = 4, /* excluding base layer */ From a5539d0fbbe7bf3e3cbb96e813946b0d5c150711 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 30 Apr 2025 15:00:42 +0200 Subject: [PATCH 76/84] drm/msm/dpu: Add LM_7, DSC_[67], PP_[67] and MERGE_3D_5 Add IDs for new blocks present in MDSS/MDP v12 for LM, DSC, PINGPONG and MERGE_3D blocks. Reviewed-by: Dmitry Baryshkov Reviewed-by: Jessica Zhang Signed-off-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/651262/ Link: https://lore.kernel.org/r/20250430-b4-sm8750-display-v5-12-8cab30c3e4df@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h index 8d820cd1b554..175639c8bfbb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h @@ -125,6 +125,7 @@ enum dpu_lm { LM_4, LM_5, LM_6, + LM_7, LM_MAX }; @@ -169,6 +170,8 @@ enum dpu_dsc { DSC_3, DSC_4, DSC_5, + DSC_6, + DSC_7, DSC_MAX }; @@ -185,6 +188,8 @@ enum dpu_pingpong { PINGPONG_3, PINGPONG_4, PINGPONG_5, + PINGPONG_6, + PINGPONG_7, PINGPONG_CWB_0, PINGPONG_CWB_1, PINGPONG_CWB_2, @@ -199,6 +204,7 @@ enum dpu_merge_3d { MERGE_3D_2, MERGE_3D_3, MERGE_3D_4, + MERGE_3D_5, MERGE_3D_MAX }; From 7520803bb9aa6754d1300f7c3d319f484df3a54e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 30 Apr 2025 15:00:43 +0200 Subject: [PATCH 77/84] drm/msm/dpu: Add handling of LM_6 and LM_7 bits in pending flush mask MDSS/MDP v12 comes with new bits in flush registers (e.g. MDP_CTL_0_FLUSH) for Layer Mixer 6 and 7. Reviewed-by: Dmitry Baryshkov Reviewed-by: Jessica Zhang Signed-off-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/651260/ Link: https://lore.kernel.org/r/20250430-b4-sm8750-display-v5-13-8cab30c3e4df@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index 6e6143865621..573e42b06ad0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -261,6 +261,12 @@ static void dpu_hw_ctl_update_pending_flush_mixer(struct dpu_hw_ctl *ctx, case LM_5: ctx->pending_flush_mask |= BIT(20); break; + case LM_6: + ctx->pending_flush_mask |= BIT(21); + break; + case LM_7: + ctx->pending_flush_mask |= BIT(27); + break; default: break; } From de01fc9fa1753f958cf127a0695aa777fee108c7 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 7 May 2025 16:29:06 +0300 Subject: [PATCH 78/84] drm/msm/dpu: remove DPU_CTL_SPLIT_DISPLAY from SAR2130P CTL blocks Follow the changes in the commit a2649952f66e ("drm/msm/dpu: remove DPU_CTL_SPLIT_DISPLAY from CTL blocks on DPU >= 5.0") and remove DPU_CTL_SPLIT_DISPLAY from the CTL blocks on the SAR2130P platform. Single CTL is used for all interfaces used by a single path Fixes: 178575173472 ("drm/msm/dpu: add catalog entry for SAR2130P") Reviewed-by: Marijn Suijten Reviewed-by: Jessica Zhang Patchwork: https://patchwork.freedesktop.org/patch/651883/ Link: https://lore.kernel.org/r/20250506-dpu-sar2130p-no-split-display-v1-1-b619c0fddea5@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h index 22dd16c6e210..5667d055fbd1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h @@ -27,17 +27,16 @@ static const struct dpu_mdp_cfg sar2130p_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sar2130p_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x290, - .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x290, - .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), + .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, From 9351d3d302060d114de2f0c648579c0aadbd8f72 Mon Sep 17 00:00:00 2001 From: Aleksandrs Vinarskis Date: Thu, 8 May 2025 00:58:59 +0200 Subject: [PATCH 79/84] drm/msm/dp: Fix support of LTTPR initialization Initialize LTTPR before msm_dp_panel_read_sink_caps, as DPTX shall (re)read DPRX caps after LTTPR detection, as required by DP 2.1a, Section 3.6.7.6.1. Fixes: 72d0af4accd9 ("drm/msm/dp: Add support for LTTPR handling") Reviewed-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Signed-off-by: Aleksandrs Vinarskis Tested-by: Jessica Zhang # SA8775P Tested-by: Johan Hovold Tested-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/652301/ Link: https://lore.kernel.org/r/20250507230113.14270-2-alex.vinarskis@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_display.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index ece184d20c0f..c39c1669c74c 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -360,12 +360,12 @@ static int msm_dp_display_send_hpd_notification(struct msm_dp_display_private *d return 0; } -static void msm_dp_display_lttpr_init(struct msm_dp_display_private *dp) +static void msm_dp_display_lttpr_init(struct msm_dp_display_private *dp, u8 *dpcd) { u8 lttpr_caps[DP_LTTPR_COMMON_CAP_SIZE]; int rc; - if (drm_dp_read_lttpr_common_caps(dp->aux, dp->panel->dpcd, lttpr_caps)) + if (drm_dp_read_lttpr_common_caps(dp->aux, dpcd, lttpr_caps)) return; rc = drm_dp_lttpr_init(dp->aux, drm_dp_lttpr_count(lttpr_caps)); @@ -378,13 +378,18 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) struct drm_connector *connector = dp->msm_dp_display.connector; const struct drm_display_info *info = &connector->display_info; int rc = 0; + u8 dpcd[DP_RECEIVER_CAP_SIZE]; + + rc = drm_dp_read_dpcd_caps(dp->aux, dpcd); + if (rc) + goto end; + + msm_dp_display_lttpr_init(dp, dpcd); rc = msm_dp_panel_read_sink_caps(dp->panel, connector); if (rc) goto end; - msm_dp_display_lttpr_init(dp); - msm_dp_link_process_request(dp->link); if (!dp->msm_dp_display.is_edp) From c156fe2dd46774321c8eaaff9a6f04b64e6b9742 Mon Sep 17 00:00:00 2001 From: Aleksandrs Vinarskis Date: Thu, 8 May 2025 00:59:00 +0200 Subject: [PATCH 80/84] drm/msm/dp: Account for LTTPRs capabilities Take into account LTTPR capabilities when selecting maximum allowed link rate, number of data lines. Fixes: 72d0af4accd9 ("drm/msm/dp: Add support for LTTPR handling") Reviewed-by: Abel Vesa Reviewed-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Signed-off-by: Aleksandrs Vinarskis Tested-by: Jessica Zhang # SA8775P Tested-by: Johan Hovold Tested-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/652302/ Link: https://lore.kernel.org/r/20250507230113.14270-3-alex.vinarskis@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_display.c | 5 ++--- drivers/gpu/drm/msm/dp/dp_link.h | 3 +++ drivers/gpu/drm/msm/dp/dp_panel.c | 12 +++++++++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index c39c1669c74c..ba08350cd9c5 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -362,13 +362,12 @@ static int msm_dp_display_send_hpd_notification(struct msm_dp_display_private *d static void msm_dp_display_lttpr_init(struct msm_dp_display_private *dp, u8 *dpcd) { - u8 lttpr_caps[DP_LTTPR_COMMON_CAP_SIZE]; int rc; - if (drm_dp_read_lttpr_common_caps(dp->aux, dpcd, lttpr_caps)) + if (drm_dp_read_lttpr_common_caps(dp->aux, dpcd, dp->link->lttpr_common_caps)) return; - rc = drm_dp_lttpr_init(dp->aux, drm_dp_lttpr_count(lttpr_caps)); + rc = drm_dp_lttpr_init(dp->aux, drm_dp_lttpr_count(dp->link->lttpr_common_caps)); if (rc) DRM_ERROR("failed to set LTTPRs transparency mode, rc=%d\n", rc); } diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h index 8db5d5698a97..c47d75cfc720 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -7,6 +7,7 @@ #define _DP_LINK_H_ #include "dp_aux.h" +#include #define DS_PORT_STATUS_CHANGED 0x200 #define DP_TEST_BIT_DEPTH_UNKNOWN 0xFFFFFFFF @@ -60,6 +61,8 @@ struct msm_dp_link_phy_params { }; struct msm_dp_link { + u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE]; + u32 sink_request; u32 test_response; diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 92415bf8aa16..4e8ab75c771b 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -47,7 +47,7 @@ static void msm_dp_panel_read_psr_cap(struct msm_dp_panel_private *panel) static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel) { - int rc; + int rc, max_lttpr_lanes, max_lttpr_rate; struct msm_dp_panel_private *panel; struct msm_dp_link_info *link_info; u8 *dpcd, major, minor; @@ -75,6 +75,16 @@ static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel) if (link_info->rate > msm_dp_panel->max_dp_link_rate) link_info->rate = msm_dp_panel->max_dp_link_rate; + /* Limit data lanes from LTTPR capabilities, if any */ + max_lttpr_lanes = drm_dp_lttpr_max_lane_count(panel->link->lttpr_common_caps); + if (max_lttpr_lanes && max_lttpr_lanes < link_info->num_lanes) + link_info->num_lanes = max_lttpr_lanes; + + /* Limit link rate from LTTPR capabilities, if any */ + max_lttpr_rate = drm_dp_lttpr_max_link_rate(panel->link->lttpr_common_caps); + if (max_lttpr_rate && max_lttpr_rate < link_info->rate) + link_info->rate = max_lttpr_rate; + drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", major, minor); drm_dbg_dp(panel->drm_dev, "link_rate=%d\n", link_info->rate); drm_dbg_dp(panel->drm_dev, "lane_count=%d\n", link_info->num_lanes); From 7513ccb8840b54e35579f3c2cce08c3443a6e2d4 Mon Sep 17 00:00:00 2001 From: Aleksandrs Vinarskis Date: Thu, 8 May 2025 00:59:01 +0200 Subject: [PATCH 81/84] drm/msm/dp: Prepare for link training per-segment for LTTPRs Per-segment link training requires knowing the number of LTTPRs (if any) present. Store the count during LTTPRs' initialization. Fixes: 72d0af4accd9 ("drm/msm/dp: Add support for LTTPR handling") Reviewed-by: Abel Vesa Reviewed-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Signed-off-by: Aleksandrs Vinarskis Tested-by: Jessica Zhang # SA8775P Tested-by: Johan Hovold Tested-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/652306/ Link: https://lore.kernel.org/r/20250507230113.14270-4-alex.vinarskis@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_display.c | 17 +++++++++++------ drivers/gpu/drm/msm/dp/dp_link.h | 1 + 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index ba08350cd9c5..386c4669c831 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -360,16 +360,21 @@ static int msm_dp_display_send_hpd_notification(struct msm_dp_display_private *d return 0; } -static void msm_dp_display_lttpr_init(struct msm_dp_display_private *dp, u8 *dpcd) +static int msm_dp_display_lttpr_init(struct msm_dp_display_private *dp, u8 *dpcd) { - int rc; + int rc, lttpr_count; if (drm_dp_read_lttpr_common_caps(dp->aux, dpcd, dp->link->lttpr_common_caps)) - return; + return 0; - rc = drm_dp_lttpr_init(dp->aux, drm_dp_lttpr_count(dp->link->lttpr_common_caps)); - if (rc) + lttpr_count = drm_dp_lttpr_count(dp->link->lttpr_common_caps); + rc = drm_dp_lttpr_init(dp->aux, lttpr_count); + if (rc) { DRM_ERROR("failed to set LTTPRs transparency mode, rc=%d\n", rc); + return 0; + } + + return lttpr_count; } static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) @@ -383,7 +388,7 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) if (rc) goto end; - msm_dp_display_lttpr_init(dp, dpcd); + dp->link->lttpr_count = msm_dp_display_lttpr_init(dp, dpcd); rc = msm_dp_panel_read_sink_caps(dp->panel, connector); if (rc) diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h index c47d75cfc720..ba47c6d19fbf 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -62,6 +62,7 @@ struct msm_dp_link_phy_params { struct msm_dp_link { u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE]; + int lttpr_count; u32 sink_request; u32 test_response; From 5a0436e92aa76d6314bb66b0072e2ae397fe816c Mon Sep 17 00:00:00 2001 From: Aleksandrs Vinarskis Date: Thu, 8 May 2025 00:59:02 +0200 Subject: [PATCH 82/84] drm/msm/dp: Introduce link training per-segment for LTTPRs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DisplayPort requires per-segment link training when LTTPR are switched to non-transparent mode, starting with LTTPR closest to the source. Only when each segment is trained individually, source can link train to sink. Implement per-segment link traning when LTTPR(s) are detected, to support external docking stations. On higher level, changes are: * Pass phy being trained down to all required helpers * Run CR, EQ link training per phy * Set voltage swing, pre-emphasis levels per phy Since at least some LTTPRs (eg. Parade PS8830) do not correctly report voltage-swing, pre-emphasis level 3 support, always assume level 3 is supported. This is permitted under DP 2.1(a) section 3.6.7.2 stating that LTTPR shall set its transmitter levels as close as possible to those requested by the DPTX, if the DPTX sets the voltage swing or pre-emphasis to a level that the LTTPR does not support. It shall be noted that LTTPR’s level choosing is implementation-specific. This ensures successful link training both when connected directly to the monitor (single LTTPR onboard most X1E laptops) and via the docking station (at least two LTTPRs). Fixes: 72d0af4accd9 ("drm/msm/dp: Add support for LTTPR handling") Tested-by: Jessica Zhang # SA8775P Tested-by: Johan Hovold Tested-by: Rob Clark Tested-by: Stefan Schmidt Signed-off-by: Aleksandrs Vinarskis Reviewed-by: Abel Vesa Reviewed-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/652305/ Link: https://lore.kernel.org/r/20250507230113.14270-5-alex.vinarskis@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 126 ++++++++++++++++++++++--------- 1 file changed, 89 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 69a26bb5fabd..a50bfafbb4ea 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1034,10 +1034,12 @@ static int msm_dp_ctrl_set_vx_px(struct msm_dp_ctrl_private *ctrl, return 0; } -static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_update_phy_vx_px(struct msm_dp_ctrl_private *ctrl, + enum drm_dp_phy dp_phy) { struct msm_dp_link *link = ctrl->link; - int ret = 0, lane, lane_cnt; + int lane, lane_cnt, reg; + int ret = 0; u8 buf[4]; u32 max_level_reached = 0; u32 voltage_swing_level = link->phy_params.v_level; @@ -1075,8 +1077,13 @@ static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl) drm_dbg_dp(ctrl->drm_dev, "sink: p|v=0x%x\n", voltage_swing_level | pre_emphasis_level); - ret = drm_dp_dpcd_write(ctrl->aux, DP_TRAINING_LANE0_SET, - buf, lane_cnt); + + if (dp_phy == DP_PHY_DPRX) + reg = DP_TRAINING_LANE0_SET; + else + reg = DP_TRAINING_LANE0_SET_PHY_REPEATER(dp_phy); + + ret = drm_dp_dpcd_write(ctrl->aux, reg, buf, lane_cnt); if (ret == lane_cnt) ret = 0; @@ -1084,9 +1091,10 @@ static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl) } static bool msm_dp_ctrl_train_pattern_set(struct msm_dp_ctrl_private *ctrl, - u8 pattern) + u8 pattern, enum drm_dp_phy dp_phy) { u8 buf; + int reg; int ret = 0; drm_dbg_dp(ctrl->drm_dev, "sink: pattern=%x\n", pattern); @@ -1096,17 +1104,26 @@ static bool msm_dp_ctrl_train_pattern_set(struct msm_dp_ctrl_private *ctrl, if (pattern && pattern != DP_TRAINING_PATTERN_4) buf |= DP_LINK_SCRAMBLING_DISABLE; - ret = drm_dp_dpcd_writeb(ctrl->aux, DP_TRAINING_PATTERN_SET, buf); + if (dp_phy == DP_PHY_DPRX) + reg = DP_TRAINING_PATTERN_SET; + else + reg = DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy); + + ret = drm_dp_dpcd_writeb(ctrl->aux, reg, buf); return ret == 1; } static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, - int *training_step) + int *training_step, enum drm_dp_phy dp_phy) { + int delay_us; int tries, old_v_level, ret = 0; u8 link_status[DP_LINK_STATUS_SIZE]; int const maximum_retries = 4; + delay_us = drm_dp_read_clock_recovery_delay(ctrl->aux, + ctrl->panel->dpcd, dp_phy, false); + msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); *training_step = DP_TRAINING_1; @@ -1115,18 +1132,19 @@ static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, if (ret) return ret; msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 | - DP_LINK_SCRAMBLING_DISABLE); + DP_LINK_SCRAMBLING_DISABLE, dp_phy); - ret = msm_dp_ctrl_update_vx_px(ctrl); + msm_dp_link_reset_phy_params_vx_px(ctrl->link); + ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy); if (ret) return ret; tries = 0; old_v_level = ctrl->link->phy_params.v_level; for (tries = 0; tries < maximum_retries; tries++) { - drm_dp_link_train_clock_recovery_delay(ctrl->aux, ctrl->panel->dpcd); + fsleep(delay_us); - ret = drm_dp_dpcd_read_link_status(ctrl->aux, link_status); + ret = drm_dp_dpcd_read_phy_link_status(ctrl->aux, dp_phy, link_status); if (ret) return ret; @@ -1147,7 +1165,7 @@ static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, } msm_dp_link_adjust_levels(ctrl->link, link_status); - ret = msm_dp_ctrl_update_vx_px(ctrl); + ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy); if (ret) return ret; } @@ -1199,21 +1217,31 @@ static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl) return 0; } -static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl) +static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl, + enum drm_dp_phy dp_phy) { - msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE); - drm_dp_link_train_channel_eq_delay(ctrl->aux, ctrl->panel->dpcd); + int delay_us; + + msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE, dp_phy); + + delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, + ctrl->panel->dpcd, dp_phy, false); + fsleep(delay_us); } static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, - int *training_step) + int *training_step, enum drm_dp_phy dp_phy) { + int delay_us; int tries = 0, ret = 0; u8 pattern; u32 state_ctrl_bit; int const maximum_retries = 5; u8 link_status[DP_LINK_STATUS_SIZE]; + delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, + ctrl->panel->dpcd, dp_phy, false); + msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); *training_step = DP_TRAINING_2; @@ -1233,12 +1261,12 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, if (ret) return ret; - msm_dp_ctrl_train_pattern_set(ctrl, pattern); + msm_dp_ctrl_train_pattern_set(ctrl, pattern, dp_phy); for (tries = 0; tries <= maximum_retries; tries++) { - drm_dp_link_train_channel_eq_delay(ctrl->aux, ctrl->panel->dpcd); + fsleep(delay_us); - ret = drm_dp_dpcd_read_link_status(ctrl->aux, link_status); + ret = drm_dp_dpcd_read_phy_link_status(ctrl->aux, dp_phy, link_status); if (ret) return ret; @@ -1248,7 +1276,7 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, } msm_dp_link_adjust_levels(ctrl->link, link_status); - ret = msm_dp_ctrl_update_vx_px(ctrl); + ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy); if (ret) return ret; @@ -1257,9 +1285,32 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, return -ETIMEDOUT; } +static int msm_dp_ctrl_link_train_1_2(struct msm_dp_ctrl_private *ctrl, + int *training_step, enum drm_dp_phy dp_phy) +{ + int ret; + + ret = msm_dp_ctrl_link_train_1(ctrl, training_step, dp_phy); + if (ret) { + DRM_ERROR("link training #1 on phy %d failed. ret=%d\n", dp_phy, ret); + return ret; + } + drm_dbg_dp(ctrl->drm_dev, "link training #1 on phy %d successful\n", dp_phy); + + ret = msm_dp_ctrl_link_train_2(ctrl, training_step, dp_phy); + if (ret) { + DRM_ERROR("link training #2 on phy %d failed. ret=%d\n", dp_phy, ret); + return ret; + } + drm_dbg_dp(ctrl->drm_dev, "link training #2 on phy %d successful\n", dp_phy); + + return 0; +} + static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, int *training_step) { + int i; int ret = 0; const u8 *dpcd = ctrl->panel->dpcd; u8 encoding[] = { 0, DP_SET_ANSI_8B10B }; @@ -1272,8 +1323,6 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, link_info.rate = ctrl->link->link_params.rate; link_info.capabilities = DP_LINK_CAP_ENHANCED_FRAMING; - msm_dp_link_reset_phy_params_vx_px(ctrl->link); - msm_dp_aux_link_configure(ctrl->aux, &link_info); if (drm_dp_max_downspread(dpcd)) @@ -1288,24 +1337,27 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, &assr, 1); } - ret = msm_dp_ctrl_link_train_1(ctrl, training_step); + for (i = ctrl->link->lttpr_count - 1; i >= 0; i--) { + enum drm_dp_phy dp_phy = DP_PHY_LTTPR(i); + + ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, dp_phy); + msm_dp_ctrl_clear_training_pattern(ctrl, dp_phy); + + if (ret) + break; + } + if (ret) { - DRM_ERROR("link training #1 failed. ret=%d\n", ret); + DRM_ERROR("link training of LTTPR(s) failed. ret=%d\n", ret); goto end; } - /* print success info as this is a result of user initiated action */ - drm_dbg_dp(ctrl->drm_dev, "link training #1 successful\n"); - - ret = msm_dp_ctrl_link_train_2(ctrl, training_step); + ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, DP_PHY_DPRX); if (ret) { - DRM_ERROR("link training #2 failed. ret=%d\n", ret); + DRM_ERROR("link training on sink failed. ret=%d\n", ret); goto end; } - /* print success info as this is a result of user initiated action */ - drm_dbg_dp(ctrl->drm_dev, "link training #2 successful\n"); - end: msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); @@ -1622,7 +1674,7 @@ static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl) if (ret) goto end; - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO); @@ -1646,7 +1698,7 @@ static bool msm_dp_ctrl_send_phy_test_pattern(struct msm_dp_ctrl_private *ctrl) return false; } msm_dp_catalog_ctrl_send_phy_pattern(ctrl->catalog, pattern_requested); - msm_dp_ctrl_update_vx_px(ctrl); + msm_dp_ctrl_update_phy_vx_px(ctrl, DP_PHY_DPRX); msm_dp_link_send_test_response(ctrl->link); pattern_sent = msm_dp_catalog_ctrl_read_phy_pattern(ctrl->catalog); @@ -1888,7 +1940,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) } /* stop link training before start re training */ - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); } rc = msm_dp_ctrl_reinitialize_mainlink(ctrl); @@ -1912,7 +1964,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) * link training failed * end txing train pattern here */ - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); msm_dp_ctrl_deinitialize_mainlink(ctrl); rc = -ECONNRESET; @@ -1983,7 +2035,7 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train msm_dp_ctrl_link_retrain(ctrl); /* stop txing train pattern to end link training */ - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); /* * Set up transfer unit values and set controller state to send From d92801d8e6b43887ca5acc1713e89e26bbc64643 Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Wed, 7 May 2025 16:59:12 -0500 Subject: [PATCH 83/84] dt-bindings: display/msm: hdmi: Fix constraints on additional 'port' properties The MSM HDMI port nodes are missing any restrictions on additional properties. The $ref should be to "/properties/port" rather than "/$defs/port-base" as there are not additional properties in the nodes to define. Signed-off-by: Rob Herring (Arm) Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/652299/ Link: https://lore.kernel.org/r/20250507215912.2748964-1-robh@kernel.org Signed-off-by: Dmitry Baryshkov --- Documentation/devicetree/bindings/display/msm/hdmi.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/hdmi.yaml b/Documentation/devicetree/bindings/display/msm/hdmi.yaml index 7e6f776a047a..dfec6c3480f3 100644 --- a/Documentation/devicetree/bindings/display/msm/hdmi.yaml +++ b/Documentation/devicetree/bindings/display/msm/hdmi.yaml @@ -74,12 +74,12 @@ properties: $ref: /schemas/graph.yaml#/properties/ports properties: port@0: - $ref: /schemas/graph.yaml#/$defs/port-base + $ref: /schemas/graph.yaml#/properties/port description: | Input endpoints of the controller. port@1: - $ref: /schemas/graph.yaml#/$defs/port-base + $ref: /schemas/graph.yaml#/properties/port description: | Output endpoints of the controller. From fc5c669c902c3039aa41731b6c58c0960d0b1bbf Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 5 May 2025 15:56:26 +0300 Subject: [PATCH 84/84] dt-bindings: display: msm: correct example in SM8350 MDSS schema Fix the interconnects in the example to follow the schema changes. Fixes: 60b8d3a2365a ("dt-bindings: display: msm: sm8350-mdss: Describe the CPU-CFG icc path") Reported-by: Rob Herring Closes: http://lore.kernel.org/r/CAL_JsqKr8Xd8uxFzE0YJTyD+V6N++VV8SX-GB5Xt0_BKkeoGUQ@mail.gmail.com Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/651775/ Link: https://lore.kernel.org/r/20250505-sm8350-fix-example-v1-1-36d5d9ccba66@oss.qualcomm.com --- .../devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml index 3733d8cd2ae0..68176de854b3 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml @@ -92,6 +92,7 @@ examples: #include #include #include + #include #include #include @@ -101,8 +102,10 @@ examples: reg-names = "mdss"; interconnects = <&mmss_noc MASTER_MDP0 0 &mc_virt SLAVE_EBI1 0>, - <&mmss_noc MASTER_MDP1 0 &mc_virt SLAVE_EBI1 0>; - interconnect-names = "mdp0-mem", "mdp1-mem"; + <&mmss_noc MASTER_MDP1 0 &mc_virt SLAVE_EBI1 0>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_DISPLAY_CFG QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "mdp0-mem", "mdp1-mem", "cpu-cfg"; power-domains = <&dispcc MDSS_GDSC>; resets = <&dispcc DISP_CC_MDSS_CORE_BCR>;