Hi, Liankun: Liankun Yang <[email protected]> 於 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 <[email protected]> > --- > 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/[email protected]/ > > Change in V7: > - Separate the edp part. > Per suggestion from the previous thread: > https://patchwork.kernel.org/project/linux-mediatek/patch/[email protected]/ > > Change in V6: > - Fixed power on in atomic enable. > Per suggestion from the previous thread: > https://patchwork.kernel.org/project/linux-mediatek/patch/[email protected]/ > > 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/[email protected]/ > > 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/[email protected]/ > > 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/[email protected]/ > > 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/[email protected]/ > --- > 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 >
