lkml.org 
[lkml]   [2022]   [Aug]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    SubjectRe: [PATCH v16 3/8] drm/mediatek: Add MT8195 Embedded DisplayPort driver
    From
    Date
    Hi, Bo-Chen:

    On Fri, 2022-08-05 at 18:14 +0800, Bo-Chen Chen wrote:
    > From: Markus Schneider-Pargmann <msp@baylibre.com>
    >
    > This patch adds a embedded displayport driver for the MediaTek mt8195
    > SoC.
    >
    > It supports the MT8195, the embedded DisplayPort units. It offers
    > DisplayPort 1.4 with up to 4 lanes.
    >
    > The driver creates a child device for the phy. The child device will
    > never exist without the parent being active. As they are sharing a
    > register range, the parent passes a regmap pointer to the child so
    > that
    > both can work with the same register range. The phy driver sets
    > device
    > data that is read by the parent to get the phy device that can be
    > used
    > to control the phy properties.
    >
    > This driver is based on an initial version by
    > Jitao shi <jitao.shi@mediatek.com>
    >
    > Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
    > Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
    > Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
    > Tested-by: AngeloGioacchino Del Regno <
    > angelogioacchino.delregno@collabora.com>
    > Reviewed-by: AngeloGioacchino Del Regno <
    > angelogioacchino.delregno@collabora.com>
    > ---

    [snip]

    > +
    > +static int mtk_dp_train_tps_1(struct mtk_dp *mtk_dp, u8
    > target_lane_count,
    > + u8 *lane_adjust, int *status_control,
    > + u8 *prev_lane_adjust)
    > +{
    > + u8 link_status[DP_LINK_STATUS_SIZE] = {};
    > +
    > + mtk_dp_training_set_scramble(mtk_dp, false);

    I think this statement could be moved to mtk_dp_train_flow() before the
    training loop. After this moving, mtk_dp_train_tps_1() is almost the
    same as mtk_dp_train_tps_2_3(), so try to merge these two function.

    > +
    > + if (*status_control == 0) {
    > + mtk_dp_pattern(mtk_dp, true, target_lane_count,
    > lane_adjust);
    > + *status_control = 1;

    if calling mtk_dp_pattern() directly from mtk_dp_train_flow(), we could
    drop status_control.

    Regards,
    CK

    > + }
    > +
    > + drm_dp_link_train_clock_recovery_delay(&mtk_dp->aux, mtk_dp-
    > >rx_cap);
    > + drm_dp_dpcd_read_link_status(&mtk_dp->aux, link_status);
    > +
    > + if (drm_dp_clock_recovery_ok(link_status,
    > + target_lane_count)) {
    > + mtk_dp->train_info.cr_done = true;
    > + dev_dbg(mtk_dp->dev, "Link train CR pass\n");
    > + return 0;
    > + } else if (*prev_lane_adjust == link_status[4]) {
    > + if (*prev_lane_adjust &
    > DP_ADJUST_VOLTAGE_SWING_LANE0_MASK) {
    > + dev_dbg(mtk_dp->dev, "Link train CQ fail\n");
    > + return -EINVAL;
    > + }
    > + } else {
    > + *prev_lane_adjust = link_status[4];
    > + }
    > + return -EAGAIN;
    > +}
    > +
    > +static int mtk_dp_train_tps_2_3(struct mtk_dp *mtk_dp, u8
    > target_linkrate,
    > + u8 target_lane_count, u8 *lane_adjust,
    > + int *status_control, u8
    > *prev_lane_adjust)
    > +{
    > + u8 link_status[DP_LINK_STATUS_SIZE] = {};
    > +
    > + if (*status_control == 1) {
    > + mtk_dp_pattern(mtk_dp, false, target_lane_count,
    > lane_adjust);
    > + *status_control = 2;
    > + }
    > +
    > + drm_dp_link_train_channel_eq_delay(&mtk_dp->aux, mtk_dp-
    > >rx_cap);
    > +
    > + drm_dp_dpcd_read_link_status(&mtk_dp->aux, link_status);
    > +
    > + if (drm_dp_channel_eq_ok(link_status, target_lane_count)) {
    > + mtk_dp->train_info.eq_done = true;
    > + dev_dbg(mtk_dp->dev, "Link train EQ pass\n");
    > + return 0;
    > + }
    > +
    > + dev_dbg(mtk_dp->dev, "Link train EQ fail\n");
    > +
    > + if (*prev_lane_adjust != link_status[4])
    > + *prev_lane_adjust = link_status[4];
    > +
    > + return -EAGAIN;
    > +}
    > +
    > +static int mtk_dp_train_flow(struct mtk_dp *mtk_dp, u8
    > target_link_rate,
    > + u8 target_lane_count)
    > +{
    > + u8 lane_adjust[2] = {};
    > + bool pass_tps1 = false;
    > + bool pass_tps2_3 = false;
    > + int train_retries;
    > + int status_control;
    > + int ret;
    > + u8 prev_lane_adjust;
    > +
    > + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_LINK_BW_SET,
    > target_link_rate);
    > + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_LANE_COUNT_SET,
    > + target_lane_count |
    > DP_LANE_COUNT_ENHANCED_FRAME_EN);
    > +
    > + if (mtk_dp->train_info.sink_ssc)
    > + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_DOWNSPREAD_CTRL,
    > + DP_SPREAD_AMP_0_5);
    > +
    > + train_retries = 0;
    > + status_control = 0;
    > + prev_lane_adjust = 0xFF;
    > +
    > + mtk_dp_set_lanes(mtk_dp, target_lane_count / 2);
    > + ret = mtk_dp_phy_configure(mtk_dp, target_link_rate,
    > target_lane_count);
    > + if (ret)
    > + return ret;
    > +
    > + dev_dbg(mtk_dp->dev,
    > + "Link train target_link_rate = 0x%x, target_lane_count
    > = 0x%x\n",
    > + target_link_rate, target_lane_count);
    > +
    > + do {
    > + train_retries++;
    > + if (!mtk_dp->train_info.cable_plugged_in)
    > + return -ENODEV;
    > +
    > + if (!pass_tps1) {
    > + ret = mtk_dp_train_tps_1(mtk_dp,
    > target_lane_count,
    > + lane_adjust,
    > &status_control,
    > + &prev_lane_adjust);
    > + if (!ret) {
    > + pass_tps1 = true;
    > + train_retries = 0;
    > + } else if (ret == -EINVAL) {
    > + break;
    > + }
    > + } else {
    > + ret = mtk_dp_train_tps_2_3(mtk_dp,
    > target_link_rate,
    > + target_lane_count,
    > + lane_adjust,
    > &status_control,
    > + &prev_lane_adjust);
    > + if (!ret) {
    > + pass_tps2_3 = true;
    > + break;
    > + }
    > + }
    > +
    > + drm_dp_dpcd_read(&mtk_dp->aux,
    > DP_ADJUST_REQUEST_LANE0_1,
    > + lane_adjust, sizeof(lane_adjust));
    > + mtk_dp_train_update_swing_pre(mtk_dp,
    > target_lane_count,
    > + lane_adjust);
    > + } while (train_retries < MTK_DP_TRAIN_DOWNSCALE_RETRY);
    > +
    > + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_TRAINING_PATTERN_SET,
    > + DP_TRAINING_PATTERN_DISABLE);
    > + mtk_dp_train_set_pattern(mtk_dp, 0);
    > +
    > + if (!pass_tps2_3)
    > + return -ETIMEDOUT;
    > +
    > + mtk_dp->train_info.link_rate = target_link_rate;
    > + mtk_dp->train_info.lane_count = target_lane_count;
    > +
    > + mtk_dp_training_set_scramble(mtk_dp, true);
    > +
    > + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_LANE_COUNT_SET,
    > + target_lane_count |
    > + DP_LANE_COUNT_ENHANCED_FRAME_EN);
    > + mtk_dp_set_enhanced_frame_mode(mtk_dp, true);
    > +
    > + return ret;
    > +}
    > +

    \
     
     \ /
      Last update: 2022-08-08 07:17    [W:4.185 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site