[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CAAOTY_9VL6U5TM6hnMZ8sJKO5rDUHuMPtNwOs_B7LwJQt7_-VQ@mail.gmail.com>
Date: Tue, 30 Dec 2025 16:13:30 +0000
From: Chun-Kuang Hu <chunkuang.hu@...nel.org>
To: Liankun Yang <liankun.yang@...iatek.com>
Cc: chunkuang.hu@...nel.org, p.zabel@...gutronix.de, airlied@...il.com,
simona@...ll.ch, matthias.bgg@...il.com,
angelogioacchino.delregno@...labora.com, mac.shen@...iatek.com,
peng.liu@...iatek.com, Project_Global_Chrome_Upstream_Group@...iatek.com,
dri-devel@...ts.freedesktop.org, linux-mediatek@...ts.infradead.org,
linux-arm-kernel@...ts.infradead.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH v8 1/1] drm/mediatek: Move DP training to hotplug thread
Hi, Liankun:
Liankun Yang <liankun.yang@...iatek.com> 於 2025年12月23日週二 上午6:34寫道:
>
> By adjusting the order of link training and relocating it to HPD,
> link training can identify the usability of each lane in the current link.
>
> It also supports handling signal instability and weakness due to
> environmental issues, enabling the acquisition of a stable bandwidth
> for the current link. Subsequently, DP work can proceed based on
> the actual maximum bandwidth.
>
> It should training in the hpd event thread.
> Check the mode with lane count and link rate of training.
>
> If we're eDP and capabilities were already parsed we can skip
> reading again because eDP panels aren't hotpluggable hence the
> caps and training information won't ever change in a boot life
>
> Therefore, bridge typec judgment is required for edp training in
> atomic_enable function.
>
> `mtk_dp_parse_capabilities` is related to DP training, it is
> used in `mtk_dp_hpd_event_thread` before DP training, and then only
> used by eDP when read edid.
>
> -Modify part of in `mtk_dp_bridge_atomic_disable`
> if (mtk_dp->train_info.cable_plugged_in) {
> drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3);
> usleep_range(2000, 3000);
> }
>
> /* power off aux */
> mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
> DP_PWR_STATE_BANDGAP_TPLL,
> DP_PWR_STATE_MASK);
>
> -Modify part of in `mtk_dp_aux_panel_poweron(mtk_dp, false);`
> if (pwron) {
> ....
> } else {
> /* power off panel */
> drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3);
> usleep_range(2000, 3000);
>
> /* power off aux */
> mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
> DP_PWR_STATE_BANDGAP_TPLL,
> DP_PWR_STATE_MASK);
> }
>
> The `mtk_dp_aux_panel_poweron` function fails to align.
> Within the `mtk_dp_hpd_event_thread`, if DP is disconnected,
> the `mtk_dp_aux_panel_poweron` function will write from `aux`
> to `DPRX`, causing a failure and thus preventing symmetry.
>
> This shows the current timings after the DP cable is plugged in,
> as well as the modified timings.
>
> current timings: Fix timings:
>
> mtk_dp_hpd_event_thread() mtk_dp_hpd_event_thread()
> (including DP link training)
> | |
> ... ...
> mtk_dp_bridge_mode_valid() mtk_dp_bridge_mode_valid()
> |
> ... ...
> mtk_dp_bridge_atomic_check() mtk_dp_bridge_atomic_check()
> |
> ... ...
> mtk_dp_bridge_atomic_enable() mtk_dp_bridge_atomic_enable()
> (including DP link training)
>
> PS:
> 1. "..." represents ommited steps;
>
> 2. `mtk_dp_bridge_mode_valid()` calculates the bandwidth using the
> current lane count and link rate, and then filters each mode to
> determine if it supports returning a status.
>
> 3. In the `drm_display_mode_to_videomode(&crtc_state->adjusted_mode,
> &mtk_dp->info.vm);` function, within the `mtk_dp_bridge_atomic_check()`
> function, `adjusted_mode` sets the currently selected display mode for
> the DRM.
>
> 4. DP link training tests the signal conditions of the link between
> DPTX and DPRX, and selects the lane count and link rate that meet
> the signal conditions.
>
> 5. For example, the platform support DP 4lane 5.4G,
> but panel A support DP 2lane 5.4G.
>
> This is a time sequence:
>
> a).Plug in panel A. According to the platform, it can output 4K60Hz.
> b).Timing mode set 4K 60Hz(Including in mtk_dp_bridge_atomic_check
> function).
> c).Atomic enable(Based on panel A ability, training pass 2lane
> 5.4G).
> d).Finally, due to 2lane 5.4G bandwidth limitation, the platform
> cannot output 4K 60Hz, resulting in a black sreen.
>
> If apply this patch.
>
> a).Plug in panel A.
> b).Training pass 2lane 5.4G
> c).Timing mode set 2K 60Hz(Based on the 2lane 5.4G bandwidth limit
> and including in mtk_dp_bridge_atomic_che
Applied to mediatek-drm-next [1], thanks.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next
Regards,
Chun-Kuang.
>
> Signed-off-by: Liankun Yang <liankun.yang@...iatek.com>
> ---
> Change in V8:
> - Update the commit message.
> - Update the commit title.
> Per suggestion from the previous thread:
> https://patchwork.kernel.org/project/linux-mediatek/patch/20251104085957.1175-2-liankun.yang@mediatek.com/
>
> Change in V7:
> - Separate the edp part.
> Per suggestion from the previous thread:
> https://patchwork.kernel.org/project/linux-mediatek/patch/20250822120506.15486-1-liankun.yang@mediatek.com/
>
> Change in V6:
> - Fixed power on in atomic enable.
> Per suggestion from the previous thread:
> https://patchwork.kernel.org/project/linux-mediatek/patch/20250630080824.7107-1-liankun.yang@mediatek.com/
>
> Change in V5:
> - Fixed the issue that the 4th version of the patch caused DP to have no screen.
> Per suggestion from the previous thread:
> https://patchwork.kernel.org/project/linux-mediatek/patch/20250625095446.31726-1-liankun.yang@mediatek.com/
>
> Change in V4:
> - Tested the internal eDP display on MT8195 Tomato and it is fine.
> Per suggestion from the previous thread:
> https://patchwork.kernel.org/project/linux-mediatek/patch/20250318140236.13650-2-liankun.yang@mediatek.com/
>
> Change in V3:
> - Remove 'mtk_dp->enabled = false" in atomic disable.
> - Remove 'mtk_dp->enabled = true" in atomic enable.
> Per suggestion from the previous thread:
> https://patchwork.kernel.org/project/linux-mediatek/patch/20241025083036.8829-4-liankun.yang@mediatek.com/
>
> Change in V2:
> - Adjust DP training timing.
> - Adjust parse capabilities timing.
> - Add power on/off for connect/disconnect.
> Per suggestion from the previous thread:
> https://patchwork.kernel.org/project/linux-mediatek/patch/20240315015233.2023-1-liankun.yang@mediatek.com/
> ---
> drivers/gpu/drm/mediatek/mtk_dp.c | 57 ++++++++++++++++++++-----------
> 1 file changed, 38 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c
> index b0b1e158600f..5e67dab6e2e9 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dp.c
> @@ -1976,6 +1976,7 @@ static irqreturn_t mtk_dp_hpd_event_thread(int hpd, void *dev)
> struct mtk_dp *mtk_dp = dev;
> unsigned long flags;
> u32 status;
> + int ret;
>
> if (mtk_dp->need_debounce && mtk_dp->train_info.cable_plugged_in)
> msleep(100);
> @@ -1994,9 +1995,28 @@ static irqreturn_t mtk_dp_hpd_event_thread(int hpd, void *dev)
> memset(&mtk_dp->info.audio_cur_cfg, 0,
> sizeof(mtk_dp->info.audio_cur_cfg));
>
> + mtk_dp->enabled = false;
> + /* power off aux */
> + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
> + DP_PWR_STATE_BANDGAP_TPLL,
> + DP_PWR_STATE_MASK);
> +
> mtk_dp->need_debounce = false;
> mod_timer(&mtk_dp->debounce_timer,
> jiffies + msecs_to_jiffies(100) - 1);
> + } else {
> + mtk_dp_aux_panel_poweron(mtk_dp, true);
> +
> + ret = mtk_dp_parse_capabilities(mtk_dp);
> + if (ret)
> + drm_err(mtk_dp->drm_dev, "Can't parse capabilities\n");
> +
> + /* Training */
> + ret = mtk_dp_training(mtk_dp);
> + if (ret)
> + drm_err(mtk_dp->drm_dev, "Training failed, %d\n", ret);
> +
> + mtk_dp->enabled = true;
> }
> }
>
> @@ -2168,7 +2188,8 @@ static const struct drm_edid *mtk_dp_edid_read(struct drm_bridge *bridge,
> * Parse capability here to let atomic_get_input_bus_fmts and
> * mode_valid use the capability to calculate sink bitrates.
> */
> - if (mtk_dp_parse_capabilities(mtk_dp)) {
> + if (mtk_dp->bridge.type == DRM_MODE_CONNECTOR_eDP &&
> + mtk_dp_parse_capabilities(mtk_dp)) {
> drm_err(mtk_dp->drm_dev, "Can't parse capabilities\n");
> drm_edid_free(drm_edid);
> drm_edid = NULL;
> @@ -2366,13 +2387,15 @@ static void mtk_dp_bridge_atomic_enable(struct drm_bridge *bridge,
> return;
> }
>
> - mtk_dp_aux_panel_poweron(mtk_dp, true);
> + if (mtk_dp->data->bridge_type == DRM_MODE_CONNECTOR_eDP) {
> + mtk_dp_aux_panel_poweron(mtk_dp, true);
>
> - /* Training */
> - ret = mtk_dp_training(mtk_dp);
> - if (ret) {
> - drm_err(mtk_dp->drm_dev, "Training failed, %d\n", ret);
> - goto power_off_aux;
> + /* Training */
> + ret = mtk_dp_training(mtk_dp);
> + if (ret) {
> + drm_err(mtk_dp->drm_dev, "Training failed, %d\n", ret);
> + goto power_off_aux;
> + }
> }
>
> ret = mtk_dp_video_config(mtk_dp);
> @@ -2392,7 +2415,9 @@ static void mtk_dp_bridge_atomic_enable(struct drm_bridge *bridge,
> sizeof(mtk_dp->info.audio_cur_cfg));
> }
>
> - mtk_dp->enabled = true;
> + if (mtk_dp->data->bridge_type == DRM_MODE_CONNECTOR_eDP)
> + mtk_dp->enabled = true;
> +
> mtk_dp_update_plugged_status(mtk_dp);
>
> return;
> @@ -2407,21 +2432,15 @@ static void mtk_dp_bridge_atomic_disable(struct drm_bridge *bridge,
> {
> struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge);
>
> - mtk_dp->enabled = false;
> + if (mtk_dp->data->bridge_type == DRM_MODE_CONNECTOR_eDP) {
> + mtk_dp->enabled = false;
> + mtk_dp_aux_panel_poweron(mtk_dp, false);
> + }
> +
> mtk_dp_update_plugged_status(mtk_dp);
> mtk_dp_video_enable(mtk_dp, false);
> mtk_dp_audio_mute(mtk_dp, true);
>
> - if (mtk_dp->train_info.cable_plugged_in) {
> - drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3);
> - usleep_range(2000, 3000);
> - }
> -
> - /* power off aux */
> - mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
> - DP_PWR_STATE_BANDGAP_TPLL,
> - DP_PWR_STATE_MASK);
> -
> /* SDP path reset sw*/
> mtk_dp_sdp_path_reset(mtk_dp);
>
> --
> 2.45.2
>
Powered by blists - more mailing lists