From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752081AbeEGL3o (ORCPT ); Mon, 7 May 2018 07:29:44 -0400 Received: from mail-qk0-f195.google.com ([209.85.220.195]:39118 "EHLO mail-qk0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751980AbeEGL3k (ORCPT ); Mon, 7 May 2018 07:29:40 -0400 X-Google-Smtp-Source: AB8JxZoGUgP9o0DW9GtodQBX1rCMvamg/WKCZYyKG9Kx9COGSkosNudy5dm8QT/sXea8GIc8zV974QUnbHeB430AFew= MIME-Version: 1.0 In-Reply-To: <1525421338-1021-4-git-send-email-hl@rock-chips.com> References: <1525421338-1021-1-git-send-email-hl@rock-chips.com> <1525421338-1021-4-git-send-email-hl@rock-chips.com> From: Enric Balletbo Serra Date: Mon, 7 May 2018 13:29:39 +0200 Message-ID: Subject: Re: [PATCH 4/4] drm/rockchip: support dp training outside dp firmware To: Lin Huang Cc: Sean Paul , David Airlie , Chris Zhong , Doug Anderson , Brian Norris , "open list:ARM/Rockchip SoC..." , =?UTF-8?Q?Heiko_St=C3=BCbner?= , daniel.vetter@intel.com, jani.nikula@linux.intel.com, dri-devel , Linux ARM , linux-kernel Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Lin, Thanks for the patch. 2018-05-04 10:08 GMT+02:00 Lin Huang : > DP firware use fix phy config value to do training, but some s/fiware/firmware/ > board need to adjust these value to fit for their hardware design, > so we use new phy config to do training outside firmware to meet > this situation, if there have new phy config pass from dts, it will > use training outside firmware. > maybe you can rewrite all this in a better way. ooi, which boards needs this? > Signed-off-by: Chris Zhong > Signed-off-by: Lin Huang > --- > drivers/gpu/drm/rockchip/Makefile | 3 +- > drivers/gpu/drm/rockchip/cdn-dp-core.c | 23 +- > drivers/gpu/drm/rockchip/cdn-dp-core.h | 2 + > drivers/gpu/drm/rockchip/cdn-dp-link-training.c | 398 ++++++++++++++++++++++++ > drivers/gpu/drm/rockchip/cdn-dp-reg.c | 33 +- > drivers/gpu/drm/rockchip/cdn-dp-reg.h | 38 ++- > 6 files changed, 480 insertions(+), 17 deletions(-) > create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-link-training.c > > diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile > index a314e21..b932f62 100644 > --- a/drivers/gpu/drm/rockchip/Makefile > +++ b/drivers/gpu/drm/rockchip/Makefile > @@ -9,7 +9,8 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ > rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o > > rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o > -rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o > +rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o \ > + cdn-dp-link-training.o > rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o > rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o > rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o > diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c > index 268c190..a2a4208 100644 > --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c > +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c > @@ -629,11 +629,13 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder) > goto out; > } > } > - > - ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE); > - if (ret) { > - DRM_DEV_ERROR(dp->dev, "Failed to idle video %d\n", ret); > - goto out; > + if (dp->sw_training_success == false) { > + ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE); > + if (ret) { > + DRM_DEV_ERROR(dp->dev, > + "Failed to idle video %d\n", ret); > + goto out; > + } > } > > ret = cdn_dp_config_video(dp); > @@ -642,11 +644,14 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder) > goto out; > } > > - ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID); > - if (ret) { > - DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret); > - goto out; > + if (dp->sw_training_success == false) { > + ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID); > + if (ret) { > + DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret); > + goto out; > + } > } > + > out: > mutex_unlock(&dp->lock); > } > diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h > index 46159b2..c6050ab 100644 > --- a/drivers/gpu/drm/rockchip/cdn-dp-core.h > +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h > @@ -84,6 +84,7 @@ struct cdn_dp_device { > bool connected; > bool active; > bool suspended; > + bool sw_training_success; > > const struct firmware *fw; /* cdn dp firmware */ > unsigned int fw_version; /* cdn fw version */ > @@ -106,6 +107,7 @@ struct cdn_dp_device { > u8 ports; > u8 lanes; > int active_port; > + u8 train_set[4]; > > u8 dpcd[DP_RECEIVER_CAP_SIZE]; > bool sink_has_audio; > diff --git a/drivers/gpu/drm/rockchip/cdn-dp-link-training.c b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c > new file mode 100644 > index 0000000..558c945 > --- /dev/null > +++ b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c > @@ -0,0 +1,398 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ For a C source file the format is: (https://www.kernel.org/doc/html/latest/process/license-rules.html) // SPDX-License-Identifier: > +/* > + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd > + * Author: Chris Zhong > + */ > + > +#include Why you need this include? > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + In fact, I think that there are other includes that can be removed, please review. > +#include "cdn-dp-core.h" > +#include "cdn-dp-reg.h" > + > +static void cdn_dp_set_signal_levels(struct cdn_dp_device *dp) > +{ > + struct cdn_dp_port *port = dp->port[dp->active_port]; > + struct rockchip_typec_phy *tcphy = phy_get_drvdata(port->phy); > + > + int rate = drm_dp_bw_code_to_link_rate(dp->link.rate); > + u8 swing = (dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) >> > + DP_TRAIN_VOLTAGE_SWING_SHIFT; > + u8 pre_emphasis = (dp->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) > + >> DP_TRAIN_PRE_EMPHASIS_SHIFT; > + > + tcphy->typec_phy_config(port->phy, rate, dp->link.num_lanes, > + swing, pre_emphasis); > +} > + > +static int cdn_dp_set_pattern(struct cdn_dp_device *dp, uint8_t dp_train_pat) > +{ > + u32 phy_config, global_config; > + int ret; > + uint8_t pattern = dp_train_pat & DP_TRAINING_PATTERN_MASK; > + > + global_config = NUM_LANES(dp->link.num_lanes - 1) | SST_MODE | > + GLOBAL_EN | RG_EN | ENC_RST_DIS | WR_VHSYNC_FALL; > + > + phy_config = DP_TX_PHY_ENCODER_BYPASS(0) | > + DP_TX_PHY_SKEW_BYPASS(0) | > + DP_TX_PHY_DISPARITY_RST(0) | > + DP_TX_PHY_LANE0_SKEW(0) | > + DP_TX_PHY_LANE1_SKEW(1) | > + DP_TX_PHY_LANE2_SKEW(2) | > + DP_TX_PHY_LANE3_SKEW(3) | > + DP_TX_PHY_10BIT_ENABLE(0); > + > + if (pattern != DP_TRAINING_PATTERN_DISABLE) { > + global_config |= NO_VIDEO; > + phy_config |= DP_TX_PHY_TRAINING_ENABLE(1) | > + DP_TX_PHY_SCRAMBLER_BYPASS(1) | > + DP_TX_PHY_TRAINING_PATTERN(pattern); > + } > + > + ret = cdn_dp_reg_write(dp, DP_FRAMER_GLOBAL_CONFIG, global_config); > + if (ret) { > + DRM_ERROR("fail to set DP_FRAMER_GLOBAL_CONFIG, error: %d\n", > + ret); > + return ret; > + } > + > + ret = cdn_dp_reg_write(dp, DP_TX_PHY_CONFIG_REG, phy_config); > + if (ret) { > + DRM_ERROR("fail to set DP_TX_PHY_CONFIG_REG, error: %d\n", > + ret); > + return ret; > + } > + > + ret = cdn_dp_reg_write(dp, DPTX_LANE_EN, BIT(dp->link.num_lanes) - 1); > + if (ret) { > + DRM_ERROR("fail to set DPTX_LANE_EN, error: %d\n", ret); > + return ret; > + } > + > + if (drm_dp_enhanced_frame_cap(dp->dpcd)) > + ret = cdn_dp_reg_write(dp, DPTX_ENHNCD, 1); > + else > + ret = cdn_dp_reg_write(dp, DPTX_ENHNCD, 0); > + if (ret) > + DRM_ERROR("failed to set DPTX_ENHNCD, error: %x\n", ret); > + > + return ret; > +} > + > +static u8 cdn_dp_pre_emphasis_max(u8 voltage_swing) > +{ > + switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: > + return DP_TRAIN_PRE_EMPH_LEVEL_3; > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: > + return DP_TRAIN_PRE_EMPH_LEVEL_2; > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: > + return DP_TRAIN_PRE_EMPH_LEVEL_1; > + default: > + return DP_TRAIN_PRE_EMPH_LEVEL_0; > + } > +} > + > +static void cdn_dp_get_adjust_train(struct cdn_dp_device *dp, > + uint8_t link_status[DP_LINK_STATUS_SIZE]) > +{ > + int i; > + uint8_t v = 0, p = 0; > + uint8_t preemph_max; > + > + for (i = 0; i < dp->link.num_lanes; i++) { > + v = max(v, drm_dp_get_adjust_request_voltage(link_status, i)); > + p = max(p, drm_dp_get_adjust_request_pre_emphasis(link_status, > + i)); > + } > + > + if (v >= VOLTAGE_LEVEL_2) > + v = VOLTAGE_LEVEL_2 | DP_TRAIN_MAX_SWING_REACHED; > + > + preemph_max = cdn_dp_pre_emphasis_max(v); > + if (p >= preemph_max) > + p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; > + > + for (i = 0; i < dp->link.num_lanes; i++) > + dp->train_set[i] = v | p; > +} > + > +/* > + * Pick training pattern for channel equalization. Training Pattern 3 for HBR2 > + * or 1.2 devices that support it, Training Pattern 2 otherwise. > + */ > +static u32 cdn_dp_select_chaneq_pattern(struct cdn_dp_device *dp) > +{ > + u32 training_pattern = DP_TRAINING_PATTERN_2; > + > + /* > + * cdn dp support HBR2 also support TPS3. TPS3 support is also mandatory > + * for downstream devices that support HBR2. However, not all sinks > + * follow the spec. > + */ > + if (drm_dp_tps3_supported(dp->dpcd)) > + training_pattern = DP_TRAINING_PATTERN_3; > + else > + DRM_DEBUG_KMS("5.4 Gbps link rate without sink TPS3 support\n"); > + > + return training_pattern; > +} > + > + > +static bool cdn_dp_link_max_vswing_reached(struct cdn_dp_device *dp) > +{ > + int lane; > + > + for (lane = 0; lane < dp->link.num_lanes; lane++) > + if ((dp->train_set[lane] & DP_TRAIN_MAX_SWING_REACHED) == 0) > + return false; > + > + return true; > +} > + > +static int cdn_dp_update_link_train(struct cdn_dp_device *dp) > +{ > + int ret; > + > + cdn_dp_set_signal_levels(dp); > + > + ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, > + dp->train_set, dp->link.num_lanes); > + if (ret != dp->link.num_lanes) > + return -EINVAL; > + > + return 0; > +} > + > +static int cdn_dp_set_link_train(struct cdn_dp_device *dp, > + uint8_t dp_train_pat) > +{ > + uint8_t buf[sizeof(dp->train_set) + 1]; > + int ret, len; > + > + buf[0] = dp_train_pat; > + if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) == > + DP_TRAINING_PATTERN_DISABLE) { > + /* don't write DP_TRAINING_LANEx_SET on disable */ > + len = 1; > + } else { > + /* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */ > + memcpy(buf + 1, dp->train_set, dp->link.num_lanes); > + len = dp->link.num_lanes + 1; > + } > + > + ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_PATTERN_SET, > + buf, len); > + if (ret != len) > + return -EINVAL; > + > + return 0; > +} > + > +static int cdn_dp_reset_link_train(struct cdn_dp_device *dp, > + uint8_t dp_train_pat) > +{ > + int ret; > + > + memset(dp->train_set, 0, sizeof(dp->train_set)); > + > + cdn_dp_set_signal_levels(dp); > + > + ret = cdn_dp_set_pattern(dp, dp_train_pat); > + if (ret) > + return ret; > + > + return cdn_dp_set_link_train(dp, dp_train_pat); > +} > + > +/* Enable corresponding port and start training pattern 1 */ > +static int cdn_dp_link_training_clock_recovery(struct cdn_dp_device *dp) > +{ > + u8 voltage, link_config[2]; > + u8 link_status[DP_LINK_STATUS_SIZE]; > + u32 voltage_tries, max_vswing_tries; > + u32 rate, sink_max, source_max; > + int ret; > + > + source_max = dp->lanes; > + sink_max = drm_dp_max_lane_count(dp->dpcd); > + dp->link.num_lanes = min(source_max, sink_max); > + > + source_max = drm_dp_bw_code_to_link_rate(CDN_DP_MAX_LINK_RATE); > + sink_max = drm_dp_max_link_rate(dp->dpcd); > + rate = min(source_max, sink_max); > + dp->link.rate = drm_dp_link_rate_to_bw_code(rate); > + > + /* Write the link configuration data */ > + link_config[0] = dp->link.rate; > + link_config[1] = dp->link.num_lanes; > + if (drm_dp_enhanced_frame_cap(dp->dpcd)) > + link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; > + drm_dp_dpcd_write(&dp->aux, DP_LINK_BW_SET, link_config, 2); > + > + link_config[0] = 0; > + link_config[1] = 0; > + if (dp->dpcd[DP_MAIN_LINK_CHANNEL_CODING] & 0x01) > + link_config[1] = DP_SET_ANSI_8B10B; > + > + drm_dp_dpcd_write(&dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2); > + > + /* clock recovery */ > + ret = cdn_dp_reset_link_train(dp, DP_TRAINING_PATTERN_1 | > + DP_LINK_SCRAMBLING_DISABLE); > + if (ret) { > + DRM_ERROR("failed to start link train\n"); > + return ret; > + } > + > + voltage_tries = 1; > + max_vswing_tries = 0; > + for (;;) { > + drm_dp_link_train_clock_recovery_delay(dp->dpcd); > + if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) != > + DP_LINK_STATUS_SIZE) { > + DRM_ERROR("failed to get link status\n"); > + return -EINVAL; > + } > + > + if (drm_dp_clock_recovery_ok(link_status, dp->link.num_lanes)) { > + DRM_DEBUG_KMS("clock recovery OK\n"); > + return 0; > + } > + > + if (voltage_tries >= 5) { > + DRM_DEBUG_KMS("Same voltage tried 5 times\n"); > + return -EINVAL; > + } > + > + if (max_vswing_tries >= 1) { > + DRM_DEBUG_KMS("Max Voltage Swing reached\n"); > + return -EINVAL; > + } > + > + voltage = dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; > + > + /* Update training set as requested by target */ > + cdn_dp_get_adjust_train(dp, link_status); > + if (cdn_dp_update_link_train(dp)) { > + DRM_ERROR("failed to update link training\n"); > + return -EINVAL; > + } > + > + if ((dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == > + voltage) > + ++voltage_tries; > + else > + voltage_tries = 1; > + > + if (cdn_dp_link_max_vswing_reached(dp)) > + ++max_vswing_tries; > + } > +} > + > +static int cdn_dp_link_training_channel_equalization(struct cdn_dp_device *dp) > +{ > + int tries, ret; > + u32 training_pattern; > + uint8_t link_status[DP_LINK_STATUS_SIZE]; > + > + training_pattern = cdn_dp_select_chaneq_pattern(dp); > + training_pattern |= DP_LINK_SCRAMBLING_DISABLE; > + > + ret = cdn_dp_set_pattern(dp, training_pattern); > + if (ret) > + return ret; > + > + ret = cdn_dp_set_link_train(dp, training_pattern); > + if (ret) { > + DRM_ERROR("failed to start channel equalization\n"); > + return ret; > + } > + > + for (tries = 0; tries < 5; tries++) { > + drm_dp_link_train_channel_eq_delay(dp->dpcd); > + if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) != > + DP_LINK_STATUS_SIZE) { > + DRM_ERROR("failed to get link status\n"); > + break; > + } > + > + /* Make sure clock is still ok */ > + if (!drm_dp_clock_recovery_ok(link_status, dp->link.num_lanes)) { > + DRM_DEBUG_KMS("Clock recovery check failed, cannot " > + "continue channel equalization\n"); > + break; > + } > + > + if (drm_dp_channel_eq_ok(link_status, dp->link.num_lanes)) { > + DRM_DEBUG_KMS("Channel EQ done. DP Training " > + "successful\n"); > + return 0; > + } > + > + /* Update training set as requested by target */ > + cdn_dp_get_adjust_train(dp, link_status); > + if (cdn_dp_update_link_train(dp)) { > + DRM_ERROR("failed to update link training\n"); > + break; > + } > + } > + > + /* Try 5 times, else fail and try at lower BW */ > + if (tries == 5) > + DRM_DEBUG_KMS("Channel equalization failed 5 times\n"); > + > + return -EINVAL; > + > +} > + > +static int cdn_dp_stop_link_train(struct cdn_dp_device *dp) > +{ > + int ret = cdn_dp_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE); > + > + if (ret) > + return ret; > + > + return cdn_dp_set_link_train(dp, DP_TRAINING_PATTERN_DISABLE); > +} > + > +int cdn_dp_software_train_link(struct cdn_dp_device *dp) > +{ > + int ret, stop_err; > + > + ret = drm_dp_dpcd_read(&dp->aux, DP_DPCD_REV, dp->dpcd, > + sizeof(dp->dpcd)); > + if (ret < 0) { > + DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret); > + return ret; > + } > + > + ret = cdn_dp_link_training_clock_recovery(dp); > + if (ret) { > + DRM_ERROR("training clock recovery fail, error: %d\n", ret); > + goto out; > + } > + > + ret = cdn_dp_link_training_channel_equalization(dp); > + if (ret) { > + DRM_ERROR("training channel equalization fail, error: %d\n", > + ret); > + goto out; > + } > +out: > + stop_err = cdn_dp_stop_link_train(dp); > + if (stop_err) { > + DRM_ERROR("stop training fail, error: %d\n", stop_err); > + return stop_err; > + } > + > + return ret; > +} > diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c > index b2f532a..72780f1 100644 > --- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c > +++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c > @@ -17,7 +17,9 @@ > #include > #include > #include > +#include > #include > +#include > > #include "cdn-dp-core.h" > #include "cdn-dp-reg.h" > @@ -189,7 +191,7 @@ static int cdn_dp_mailbox_send(struct cdn_dp_device *dp, u8 module_id, > return 0; > } > > -static int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val) > +int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val) > { > u8 msg[6]; > > @@ -605,22 +607,41 @@ static int cdn_dp_get_training_status(struct cdn_dp_device *dp) > int cdn_dp_train_link(struct cdn_dp_device *dp) > { > int ret; > + struct cdn_dp_port *port = dp->port[dp->active_port]; > + struct rockchip_typec_phy *tcphy = phy_get_drvdata(port->phy); > > + /* > + * DP firmware uses fixed phy config values to do training, but some > + * boards need to adjust these values to fit for their unique hardware > + * design. So if the phy is using custom config values, do software > + * link training instead of relying on firmware, if software training > + * fail, keep firmware training as a fallback if sw training fails. > + */ > + if (tcphy->need_software_training) { > + ret = cdn_dp_software_train_link(dp); > + if (ret) { > + DRM_DEV_ERROR(dp->dev, > + "Failed to do software training %d\n", ret); > + goto do_fw_training; > + } > + cdn_dp_reg_write(dp, SOURCE_HDTX_CAR, 0xf); Check for an error here and act accordingly? Or doesn't matter? > + dp->sw_training_success = true; > + return 0; > + } > + nit: Personally I don't like this goto. Maybe you can refactor this. if (tcphy->need_software_training) { ret = cdn_dp_software_train_link(dp); if (!ret) { cdn_dp_reg_write(dp, SOURCE_HDTX_CAR, 0xf); dp->sw_training_success = true; return 0; } DRM_DEV_ERROR(dp->dev, "Failed to do software training %d\n", ret); } > +do_fw_training: Then remove the goto label. > + dp->sw_training_success = false; > ret = cdn_dp_training_start(dp); > if (ret) { > DRM_DEV_ERROR(dp->dev, "Failed to start training %d\n", ret); > return ret; > } > - Do not remove the new line. > ret = cdn_dp_get_training_status(dp); > if (ret) { > DRM_DEV_ERROR(dp->dev, "Failed to get training stat %d\n", ret); > return ret; > } > - > - DRM_DEV_DEBUG_KMS(dp->dev, "rate:0x%x, lanes:%d\n", dp->link.rate, > - dp->link.num_lanes); Why you remove this debug message? > - return ret; > + return 0; > } > > int cdn_dp_set_video_status(struct cdn_dp_device *dp, int active) > diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h b/drivers/gpu/drm/rockchip/cdn-dp-reg.h > index aedf2dc..b60a6b2 100644 > --- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h > +++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h > @@ -137,7 +137,7 @@ > #define HPD_EVENT_MASK 0x211c > #define HPD_EVENT_DET 0x2120 > > -/* dpyx framer addr */ > +/* dptx framer addr */ > #define DP_FRAMER_GLOBAL_CONFIG 0x2200 > #define DP_SW_RESET 0x2204 > #define DP_FRAMER_TU 0x2208 > @@ -431,6 +431,40 @@ > /* Reference cycles when using lane clock as reference */ > #define LANE_REF_CYC 0x8000 > > +/* register CM_VID_CTRL */ > +#define LANE_VID_REF_CYC(x) (((x) & (BIT(24) - 1)) << 0) > +#define NMVID_MEAS_TOLERANCE(x) (((x) & 0xf) << 24) > + > +/* register DP_TX_PHY_CONFIG_REG */ > +#define DP_TX_PHY_TRAINING_ENABLE(x) ((x) & 1) > +#define DP_TX_PHY_TRAINING_TYPE_PRBS7 (0 << 1) > +#define DP_TX_PHY_TRAINING_TYPE_TPS1 (1 << 1) > +#define DP_TX_PHY_TRAINING_TYPE_TPS2 (2 << 1) > +#define DP_TX_PHY_TRAINING_TYPE_TPS3 (3 << 1) > +#define DP_TX_PHY_TRAINING_TYPE_TPS4 (4 << 1) > +#define DP_TX_PHY_TRAINING_TYPE_PLTPAT (5 << 1) > +#define DP_TX_PHY_TRAINING_TYPE_D10_2 (6 << 1) > +#define DP_TX_PHY_TRAINING_TYPE_HBR2CPAT (8 << 1) > +#define DP_TX_PHY_TRAINING_PATTERN(x) ((x) << 1) > +#define DP_TX_PHY_SCRAMBLER_BYPASS(x) (((x) & 1) << 5) > +#define DP_TX_PHY_ENCODER_BYPASS(x) (((x) & 1) << 6) > +#define DP_TX_PHY_SKEW_BYPASS(x) (((x) & 1) << 7) > +#define DP_TX_PHY_DISPARITY_RST(x) (((x) & 1) << 8) > +#define DP_TX_PHY_LANE0_SKEW(x) (((x) & 7) << 9) > +#define DP_TX_PHY_LANE1_SKEW(x) (((x) & 7) << 12) > +#define DP_TX_PHY_LANE2_SKEW(x) (((x) & 7) << 15) > +#define DP_TX_PHY_LANE3_SKEW(x) (((x) & 7) << 18) > +#define DP_TX_PHY_10BIT_ENABLE(x) (((x) & 1) << 21) > + > +/* register DP_FRAMER_GLOBAL_CONFIG */ > +#define NUM_LANES(x) ((x) & 3) > +#define SST_MODE (0 << 2) > +#define GLOBAL_EN (1 << 3) > +#define RG_EN (0 << 4) > +#define NO_VIDEO (1 << 5) > +#define ENC_RST_DIS (1 << 6) > +#define WR_VHSYNC_FALL (1 << 7) > + Use the BIT() macros for these. > enum voltage_swing_level { > VOLTAGE_LEVEL_0, > VOLTAGE_LEVEL_1, > @@ -476,6 +510,7 @@ int cdn_dp_set_host_cap(struct cdn_dp_device *dp, u8 lanes, bool flip); > int cdn_dp_event_config(struct cdn_dp_device *dp); > u32 cdn_dp_get_event(struct cdn_dp_device *dp); > int cdn_dp_get_hpd_status(struct cdn_dp_device *dp); > +int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val); > ssize_t cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, > u8 *data, u16 len); > ssize_t cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, > @@ -489,4 +524,5 @@ int cdn_dp_config_video(struct cdn_dp_device *dp); > int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio); > int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable); > int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio); > +int cdn_dp_software_train_link(struct cdn_dp_device *dp); > #endif /* _CDN_DP_REG_H */ > -- > 2.7.4 > From mboxrd@z Thu Jan 1 00:00:00 1970 From: Enric Balletbo Serra Subject: Re: [PATCH 4/4] drm/rockchip: support dp training outside dp firmware Date: Mon, 7 May 2018 13:29:39 +0200 Message-ID: References: <1525421338-1021-1-git-send-email-hl@rock-chips.com> <1525421338-1021-4-git-send-email-hl@rock-chips.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <1525421338-1021-4-git-send-email-hl@rock-chips.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Lin Huang Cc: David Airlie , Brian Norris , Doug Anderson , linux-kernel , "open list:ARM/Rockchip SoC..." , dri-devel , Chris Zhong , daniel.vetter@intel.com, Linux ARM List-Id: linux-rockchip.vger.kernel.org SGkgTGluLAoKVGhhbmtzIGZvciB0aGUgcGF0Y2guCgoyMDE4LTA1LTA0IDEwOjA4IEdNVCswMjow MCBMaW4gSHVhbmcgPGhsQHJvY2stY2hpcHMuY29tPjoKPiBEUCBmaXJ3YXJlIHVzZSBmaXggcGh5 IGNvbmZpZyB2YWx1ZSB0byBkbyB0cmFpbmluZywgYnV0IHNvbWUKCnMvZml3YXJlL2Zpcm13YXJl LwoKPiBib2FyZCBuZWVkIHRvIGFkanVzdCB0aGVzZSB2YWx1ZSB0byBmaXQgZm9yIHRoZWlyIGhh cmR3YXJlIGRlc2lnbiwKPiBzbyB3ZSB1c2UgbmV3IHBoeSBjb25maWcgdG8gZG8gdHJhaW5pbmcg b3V0c2lkZSBmaXJtd2FyZSB0byBtZWV0Cj4gdGhpcyBzaXR1YXRpb24sIGlmIHRoZXJlIGhhdmUg bmV3IHBoeSBjb25maWcgcGFzcyBmcm9tIGR0cywgaXQgd2lsbAo+IHVzZSB0cmFpbmluZyBvdXRz aWRlIGZpcm13YXJlLgo+CgptYXliZSB5b3UgY2FuIHJld3JpdGUgYWxsIHRoaXMgaW4gYSBiZXR0 ZXIgd2F5LgoKb29pLCB3aGljaCBib2FyZHMgbmVlZHMgdGhpcz8KCgo+IFNpZ25lZC1vZmYtYnk6 IENocmlzIFpob25nIDx6eXdAcm9jay1jaGlwcy5jb20+Cj4gU2lnbmVkLW9mZi1ieTogTGluIEh1 YW5nIDxobEByb2NrLWNoaXBzLmNvbT4KPiAtLS0KPiAgZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlw L01ha2VmaWxlICAgICAgICAgICAgICAgfCAgIDMgKy0KPiAgZHJpdmVycy9ncHUvZHJtL3JvY2tj aGlwL2Nkbi1kcC1jb3JlLmMgICAgICAgICAgfCAgMjMgKy0KPiAgZHJpdmVycy9ncHUvZHJtL3Jv Y2tjaGlwL2Nkbi1kcC1jb3JlLmggICAgICAgICAgfCAgIDIgKwo+ICBkcml2ZXJzL2dwdS9kcm0v cm9ja2NoaXAvY2RuLWRwLWxpbmstdHJhaW5pbmcuYyB8IDM5OCArKysrKysrKysrKysrKysrKysr KysrKysKPiAgZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlwL2Nkbi1kcC1yZWcuYyAgICAgICAgICAg fCAgMzMgKy0KPiAgZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlwL2Nkbi1kcC1yZWcuaCAgICAgICAg ICAgfCAgMzggKystCj4gIDYgZmlsZXMgY2hhbmdlZCwgNDgwIGluc2VydGlvbnMoKyksIDE3IGRl bGV0aW9ucygtKQo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlw L2Nkbi1kcC1saW5rLXRyYWluaW5nLmMKPgo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0v cm9ja2NoaXAvTWFrZWZpbGUgYi9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvTWFrZWZpbGUKPiBp bmRleCBhMzE0ZTIxLi5iOTMyZjYyIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvZ3B1L2RybS9yb2Nr Y2hpcC9NYWtlZmlsZQo+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9yb2NrY2hpcC9NYWtlZmlsZQo+ IEBAIC05LDcgKzksOCBAQCByb2NrY2hpcGRybS15IDo9IHJvY2tjaGlwX2RybV9kcnYubyByb2Nr Y2hpcF9kcm1fZmIubyBcCj4gIHJvY2tjaGlwZHJtLSQoQ09ORklHX0RSTV9GQkRFVl9FTVVMQVRJ T04pICs9IHJvY2tjaGlwX2RybV9mYmRldi5vCj4KPiAgcm9ja2NoaXBkcm0tJChDT05GSUdfUk9D S0NISVBfQU5BTE9HSVhfRFApICs9IGFuYWxvZ2l4X2RwLXJvY2tjaGlwLm8KPiAtcm9ja2NoaXBk cm0tJChDT05GSUdfUk9DS0NISVBfQ0ROX0RQKSArPSBjZG4tZHAtY29yZS5vIGNkbi1kcC1yZWcu bwo+ICtyb2NrY2hpcGRybS0kKENPTkZJR19ST0NLQ0hJUF9DRE5fRFApICs9IGNkbi1kcC1jb3Jl Lm8gY2RuLWRwLXJlZy5vIFwKPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgY2RuLWRwLWxpbmstdHJhaW5pbmcubwo+ICByb2NrY2hpcGRybS0kKENPTkZJR19ST0NLQ0hJ UF9EV19IRE1JKSArPSBkd19oZG1pLXJvY2tjaGlwLm8KPiAgcm9ja2NoaXBkcm0tJChDT05GSUdf Uk9DS0NISVBfRFdfTUlQSV9EU0kpICs9IGR3LW1pcGktZHNpLm8KPiAgcm9ja2NoaXBkcm0tJChD T05GSUdfUk9DS0NISVBfSU5OT19IRE1JKSArPSBpbm5vX2hkbWkubwo+IGRpZmYgLS1naXQgYS9k cml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvY2RuLWRwLWNvcmUuYyBiL2RyaXZlcnMvZ3B1L2RybS9y b2NrY2hpcC9jZG4tZHAtY29yZS5jCj4gaW5kZXggMjY4YzE5MC4uYTJhNDIwOCAxMDA2NDQKPiAt LS0gYS9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvY2RuLWRwLWNvcmUuYwo+ICsrKyBiL2RyaXZl cnMvZ3B1L2RybS9yb2NrY2hpcC9jZG4tZHAtY29yZS5jCj4gQEAgLTYyOSwxMSArNjI5LDEzIEBA IHN0YXRpYyB2b2lkIGNkbl9kcF9lbmNvZGVyX2VuYWJsZShzdHJ1Y3QgZHJtX2VuY29kZXIgKmVu Y29kZXIpCj4gICAgICAgICAgICAgICAgICAgICAgICAgZ290byBvdXQ7Cj4gICAgICAgICAgICAg ICAgIH0KPiAgICAgICAgIH0KPiAtCj4gLSAgICAgICByZXQgPSBjZG5fZHBfc2V0X3ZpZGVvX3N0 YXR1cyhkcCwgQ09OVFJPTF9WSURFT19JRExFKTsKPiAtICAgICAgIGlmIChyZXQpIHsKPiAtICAg ICAgICAgICAgICAgRFJNX0RFVl9FUlJPUihkcC0+ZGV2LCAiRmFpbGVkIHRvIGlkbGUgdmlkZW8g JWRcbiIsIHJldCk7Cj4gLSAgICAgICAgICAgICAgIGdvdG8gb3V0Owo+ICsgICAgICAgaWYgKGRw LT5zd190cmFpbmluZ19zdWNjZXNzID09IGZhbHNlKSB7Cj4gKyAgICAgICAgICAgICAgIHJldCA9 IGNkbl9kcF9zZXRfdmlkZW9fc3RhdHVzKGRwLCBDT05UUk9MX1ZJREVPX0lETEUpOwo+ICsgICAg ICAgICAgICAgICBpZiAocmV0KSB7Cj4gKyAgICAgICAgICAgICAgICAgICAgICAgRFJNX0RFVl9F UlJPUihkcC0+ZGV2LAo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkZh aWxlZCB0byBpZGxlIHZpZGVvICVkXG4iLCByZXQpOwo+ICsgICAgICAgICAgICAgICAgICAgICAg IGdvdG8gb3V0Owo+ICsgICAgICAgICAgICAgICB9Cj4gICAgICAgICB9Cj4KPiAgICAgICAgIHJl dCA9IGNkbl9kcF9jb25maWdfdmlkZW8oZHApOwo+IEBAIC02NDIsMTEgKzY0NCwxNCBAQCBzdGF0 aWMgdm9pZCBjZG5fZHBfZW5jb2Rlcl9lbmFibGUoc3RydWN0IGRybV9lbmNvZGVyICplbmNvZGVy KQo+ICAgICAgICAgICAgICAgICBnb3RvIG91dDsKPiAgICAgICAgIH0KPgo+IC0gICAgICAgcmV0 ID0gY2RuX2RwX3NldF92aWRlb19zdGF0dXMoZHAsIENPTlRST0xfVklERU9fVkFMSUQpOwo+IC0g ICAgICAgaWYgKHJldCkgewo+IC0gICAgICAgICAgICAgICBEUk1fREVWX0VSUk9SKGRwLT5kZXYs ICJGYWlsZWQgdG8gdmFsaWQgdmlkZW8gJWRcbiIsIHJldCk7Cj4gLSAgICAgICAgICAgICAgIGdv dG8gb3V0Owo+ICsgICAgICAgaWYgKGRwLT5zd190cmFpbmluZ19zdWNjZXNzID09IGZhbHNlKSB7 Cj4gKyAgICAgICAgICAgICAgIHJldCA9IGNkbl9kcF9zZXRfdmlkZW9fc3RhdHVzKGRwLCBDT05U Uk9MX1ZJREVPX1ZBTElEKTsKPiArICAgICAgICAgICAgICAgaWYgKHJldCkgewo+ICsgICAgICAg ICAgICAgICAgICAgICAgIERSTV9ERVZfRVJST1IoZHAtPmRldiwgIkZhaWxlZCB0byB2YWxpZCB2 aWRlbyAlZFxuIiwgcmV0KTsKPiArICAgICAgICAgICAgICAgICAgICAgICBnb3RvIG91dDsKPiAr ICAgICAgICAgICAgICAgfQo+ICAgICAgICAgfQo+ICsKPiAgb3V0Ogo+ICAgICAgICAgbXV0ZXhf dW5sb2NrKCZkcC0+bG9jayk7Cj4gIH0KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL3Jv Y2tjaGlwL2Nkbi1kcC1jb3JlLmggYi9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvY2RuLWRwLWNv cmUuaAo+IGluZGV4IDQ2MTU5YjIuLmM2MDUwYWIgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy9ncHUv ZHJtL3JvY2tjaGlwL2Nkbi1kcC1jb3JlLmgKPiArKysgYi9kcml2ZXJzL2dwdS9kcm0vcm9ja2No aXAvY2RuLWRwLWNvcmUuaAo+IEBAIC04NCw2ICs4NCw3IEBAIHN0cnVjdCBjZG5fZHBfZGV2aWNl IHsKPiAgICAgICAgIGJvb2wgY29ubmVjdGVkOwo+ICAgICAgICAgYm9vbCBhY3RpdmU7Cj4gICAg ICAgICBib29sIHN1c3BlbmRlZDsKPiArICAgICAgIGJvb2wgc3dfdHJhaW5pbmdfc3VjY2VzczsK Pgo+ICAgICAgICAgY29uc3Qgc3RydWN0IGZpcm13YXJlICpmdzsgICAgICAvKiBjZG4gZHAgZmly bXdhcmUgKi8KPiAgICAgICAgIHVuc2lnbmVkIGludCBmd192ZXJzaW9uOyAgICAgICAgLyogY2Ru IGZ3IHZlcnNpb24gKi8KPiBAQCAtMTA2LDYgKzEwNyw3IEBAIHN0cnVjdCBjZG5fZHBfZGV2aWNl IHsKPiAgICAgICAgIHU4IHBvcnRzOwo+ICAgICAgICAgdTggbGFuZXM7Cj4gICAgICAgICBpbnQg YWN0aXZlX3BvcnQ7Cj4gKyAgICAgICB1OCB0cmFpbl9zZXRbNF07Cj4KPiAgICAgICAgIHU4IGRw Y2RbRFBfUkVDRUlWRVJfQ0FQX1NJWkVdOwo+ICAgICAgICAgYm9vbCBzaW5rX2hhc19hdWRpbzsK PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlwL2Nkbi1kcC1saW5rLXRyYWlu aW5nLmMgYi9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvY2RuLWRwLWxpbmstdHJhaW5pbmcuYwo+ IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uNTU4Yzk0NQo+IC0tLSAvZGV2 L251bGwKPiArKysgYi9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvY2RuLWRwLWxpbmstdHJhaW5p bmcuYwo+IEBAIC0wLDAgKzEsMzk4IEBACj4gKy8qIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBH UEwtMi4wICovCgpGb3IgYSBDIHNvdXJjZSBmaWxlIHRoZSBmb3JtYXQgaXM6CihodHRwczovL3d3 dy5rZXJuZWwub3JnL2RvYy9odG1sL2xhdGVzdC9wcm9jZXNzL2xpY2Vuc2UtcnVsZXMuaHRtbCkK Ci8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiA8U1BEWCBMaWNlbnNlIEV4cHJlc3Npb24+Cgo+ ICsvKgo+ICsgKiBDb3B5cmlnaHQgKEMpIEZ1emhvdSBSb2NrY2hpcCBFbGVjdHJvbmljcyBDby5M dGQKPiArICogQXV0aG9yOiBDaHJpcyBaaG9uZyA8enl3QHJvY2stY2hpcHMuY29tPgo+ICsgKi8K PiArCj4gKyNpbmNsdWRlIDxsaW51eC9hcm0tc21jY2MuaD4KCldoeSB5b3UgbmVlZCB0aGlzIGlu Y2x1ZGU/Cgo+ICsjaW5jbHVkZSA8bGludXgvY2xrLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9kZXZp Y2UuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2RlbGF5Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9pby5o Pgo+ICsjaW5jbHVkZSA8bGludXgvaW9wb2xsLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9waHkvcGh5 Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9yZXNldC5oPgo+ICsjaW5jbHVkZSA8c29jL3JvY2tjaGlw L3JvY2tjaGlwX3BoeV90eXBlYy5oPgo+ICsKCkluIGZhY3QsIEkgdGhpbmsgdGhhdCB0aGVyZSBh cmUgb3RoZXIgaW5jbHVkZXMgdGhhdCBjYW4gYmUgcmVtb3ZlZCwKcGxlYXNlIHJldmlldy4KCj4g KyNpbmNsdWRlICJjZG4tZHAtY29yZS5oIgo+ICsjaW5jbHVkZSAiY2RuLWRwLXJlZy5oIgo+ICsK PiArc3RhdGljIHZvaWQgY2RuX2RwX3NldF9zaWduYWxfbGV2ZWxzKHN0cnVjdCBjZG5fZHBfZGV2 aWNlICpkcCkKPiArewo+ICsgICAgICAgc3RydWN0IGNkbl9kcF9wb3J0ICpwb3J0ID0gZHAtPnBv cnRbZHAtPmFjdGl2ZV9wb3J0XTsKPiArICAgICAgIHN0cnVjdCByb2NrY2hpcF90eXBlY19waHkg KnRjcGh5ID0gcGh5X2dldF9kcnZkYXRhKHBvcnQtPnBoeSk7Cj4gKwo+ICsgICAgICAgaW50IHJh dGUgPSBkcm1fZHBfYndfY29kZV90b19saW5rX3JhdGUoZHAtPmxpbmsucmF0ZSk7Cj4gKyAgICAg ICB1OCBzd2luZyA9IChkcC0+dHJhaW5fc2V0WzBdICYgRFBfVFJBSU5fVk9MVEFHRV9TV0lOR19N QVNLKSA+Pgo+ICsgICAgICAgICAgICAgICAgICBEUF9UUkFJTl9WT0xUQUdFX1NXSU5HX1NISUZU Owo+ICsgICAgICAgdTggcHJlX2VtcGhhc2lzID0gKGRwLT50cmFpbl9zZXRbMF0gJiBEUF9UUkFJ Tl9QUkVfRU1QSEFTSVNfTUFTSykKPiArICAgICAgICAgICAgICAgICAgICAgICAgID4+IERQX1RS QUlOX1BSRV9FTVBIQVNJU19TSElGVDsKPiArCj4gKyAgICAgICB0Y3BoeS0+dHlwZWNfcGh5X2Nv bmZpZyhwb3J0LT5waHksIHJhdGUsIGRwLT5saW5rLm51bV9sYW5lcywKPiArICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIHN3aW5nLCBwcmVfZW1waGFzaXMpOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgaW50IGNkbl9kcF9zZXRfcGF0dGVybihzdHJ1Y3QgY2RuX2RwX2RldmljZSAqZHAsIHVpbnQ4 X3QgZHBfdHJhaW5fcGF0KQo+ICt7Cj4gKyAgICAgICB1MzIgcGh5X2NvbmZpZywgZ2xvYmFsX2Nv bmZpZzsKPiArICAgICAgIGludCByZXQ7Cj4gKyAgICAgICB1aW50OF90IHBhdHRlcm4gPSBkcF90 cmFpbl9wYXQgJiBEUF9UUkFJTklOR19QQVRURVJOX01BU0s7Cj4gKwo+ICsgICAgICAgZ2xvYmFs X2NvbmZpZyA9IE5VTV9MQU5FUyhkcC0+bGluay5udW1fbGFuZXMgLSAxKSB8IFNTVF9NT0RFIHwK PiArICAgICAgICAgICAgICAgICAgICAgICBHTE9CQUxfRU4gfCBSR19FTiB8IEVOQ19SU1RfRElT IHwgV1JfVkhTWU5DX0ZBTEw7Cj4gKwo+ICsgICAgICAgcGh5X2NvbmZpZyA9IERQX1RYX1BIWV9F TkNPREVSX0JZUEFTUygwKSB8Cj4gKyAgICAgICAgICAgICAgICAgICAgRFBfVFhfUEhZX1NLRVdf QllQQVNTKDApIHwKPiArICAgICAgICAgICAgICAgICAgICBEUF9UWF9QSFlfRElTUEFSSVRZX1JT VCgwKSB8Cj4gKyAgICAgICAgICAgICAgICAgICAgRFBfVFhfUEhZX0xBTkUwX1NLRVcoMCkgfAo+ ICsgICAgICAgICAgICAgICAgICAgIERQX1RYX1BIWV9MQU5FMV9TS0VXKDEpIHwKPiArICAgICAg ICAgICAgICAgICAgICBEUF9UWF9QSFlfTEFORTJfU0tFVygyKSB8Cj4gKyAgICAgICAgICAgICAg ICAgICAgRFBfVFhfUEhZX0xBTkUzX1NLRVcoMykgfAo+ICsgICAgICAgICAgICAgICAgICAgIERQ X1RYX1BIWV8xMEJJVF9FTkFCTEUoMCk7Cj4gKwo+ICsgICAgICAgaWYgKHBhdHRlcm4gIT0gRFBf VFJBSU5JTkdfUEFUVEVSTl9ESVNBQkxFKSB7Cj4gKyAgICAgICAgICAgICAgIGdsb2JhbF9jb25m aWcgfD0gTk9fVklERU87Cj4gKyAgICAgICAgICAgICAgIHBoeV9jb25maWcgfD0gRFBfVFhfUEhZ X1RSQUlOSU5HX0VOQUJMRSgxKSB8Cj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRFBf VFhfUEhZX1NDUkFNQkxFUl9CWVBBU1MoMSkgfAo+ICsgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIERQX1RYX1BIWV9UUkFJTklOR19QQVRURVJOKHBhdHRlcm4pOwo+ICsgICAgICAgfQo+ICsK PiArICAgICAgIHJldCA9IGNkbl9kcF9yZWdfd3JpdGUoZHAsIERQX0ZSQU1FUl9HTE9CQUxfQ09O RklHLCBnbG9iYWxfY29uZmlnKTsKPiArICAgICAgIGlmIChyZXQpIHsKPiArICAgICAgICAgICAg ICAgRFJNX0VSUk9SKCJmYWlsIHRvIHNldCBEUF9GUkFNRVJfR0xPQkFMX0NPTkZJRywgZXJyb3I6 ICVkXG4iLAo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgcmV0KTsKPiArICAgICAgICAgICAg ICAgcmV0dXJuIHJldDsKPiArICAgICAgIH0KPiArCj4gKyAgICAgICByZXQgPSBjZG5fZHBfcmVn X3dyaXRlKGRwLCBEUF9UWF9QSFlfQ09ORklHX1JFRywgcGh5X2NvbmZpZyk7Cj4gKyAgICAgICBp ZiAocmV0KSB7Cj4gKyAgICAgICAgICAgICAgIERSTV9FUlJPUigiZmFpbCB0byBzZXQgRFBfVFhf UEhZX0NPTkZJR19SRUcsIGVycm9yOiAlZFxuIiwKPiArICAgICAgICAgICAgICAgICAgICAgICAg IHJldCk7Cj4gKyAgICAgICAgICAgICAgIHJldHVybiByZXQ7Cj4gKyAgICAgICB9Cj4gKwo+ICsg ICAgICAgcmV0ID0gY2RuX2RwX3JlZ193cml0ZShkcCwgRFBUWF9MQU5FX0VOLCBCSVQoZHAtPmxp bmsubnVtX2xhbmVzKSAtIDEpOwo+ICsgICAgICAgaWYgKHJldCkgewo+ICsgICAgICAgICAgICAg ICBEUk1fRVJST1IoImZhaWwgdG8gc2V0IERQVFhfTEFORV9FTiwgZXJyb3I6ICVkXG4iLCByZXQp Owo+ICsgICAgICAgICAgICAgICByZXR1cm4gcmV0Owo+ICsgICAgICAgfQo+ICsKPiArICAgICAg IGlmIChkcm1fZHBfZW5oYW5jZWRfZnJhbWVfY2FwKGRwLT5kcGNkKSkKPiArICAgICAgICAgICAg ICAgcmV0ID0gY2RuX2RwX3JlZ193cml0ZShkcCwgRFBUWF9FTkhOQ0QsIDEpOwo+ICsgICAgICAg ZWxzZQo+ICsgICAgICAgICAgICAgICByZXQgPSBjZG5fZHBfcmVnX3dyaXRlKGRwLCBEUFRYX0VO SE5DRCwgMCk7Cj4gKyAgICAgICBpZiAocmV0KQo+ICsgICAgICAgICAgICAgICBEUk1fRVJST1Io ImZhaWxlZCB0byBzZXQgRFBUWF9FTkhOQ0QsIGVycm9yOiAleFxuIiwgcmV0KTsKPiArCj4gKyAg ICAgICByZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgdTggY2RuX2RwX3ByZV9lbXBoYXNp c19tYXgodTggdm9sdGFnZV9zd2luZykKPiArewo+ICsgICAgICAgc3dpdGNoICh2b2x0YWdlX3N3 aW5nICYgRFBfVFJBSU5fVk9MVEFHRV9TV0lOR19NQVNLKSB7Cj4gKyAgICAgICBjYXNlIERQX1RS QUlOX1ZPTFRBR0VfU1dJTkdfTEVWRUxfMDoKPiArICAgICAgICAgICAgICAgcmV0dXJuIERQX1RS QUlOX1BSRV9FTVBIX0xFVkVMXzM7Cj4gKyAgICAgICBjYXNlIERQX1RSQUlOX1ZPTFRBR0VfU1dJ TkdfTEVWRUxfMToKPiArICAgICAgICAgICAgICAgcmV0dXJuIERQX1RSQUlOX1BSRV9FTVBIX0xF VkVMXzI7Cj4gKyAgICAgICBjYXNlIERQX1RSQUlOX1ZPTFRBR0VfU1dJTkdfTEVWRUxfMjoKPiAr ICAgICAgICAgICAgICAgcmV0dXJuIERQX1RSQUlOX1BSRV9FTVBIX0xFVkVMXzE7Cj4gKyAgICAg ICBkZWZhdWx0Ogo+ICsgICAgICAgICAgICAgICByZXR1cm4gRFBfVFJBSU5fUFJFX0VNUEhfTEVW RUxfMDsKPiArICAgICAgIH0KPiArfQo+ICsKPiArc3RhdGljIHZvaWQgY2RuX2RwX2dldF9hZGp1 c3RfdHJhaW4oc3RydWN0IGNkbl9kcF9kZXZpY2UgKmRwLAo+ICsgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIHVpbnQ4X3QgbGlua19zdGF0dXNbRFBfTElOS19TVEFUVVNfU0laRV0p Cj4gK3sKPiArICAgICAgIGludCBpOwo+ICsgICAgICAgdWludDhfdCB2ID0gMCwgcCA9IDA7Cj4g KyAgICAgICB1aW50OF90IHByZWVtcGhfbWF4Owo+ICsKPiArICAgICAgIGZvciAoaSA9IDA7IGkg PCBkcC0+bGluay5udW1fbGFuZXM7IGkrKykgewo+ICsgICAgICAgICAgICAgICB2ID0gbWF4KHYs IGRybV9kcF9nZXRfYWRqdXN0X3JlcXVlc3Rfdm9sdGFnZShsaW5rX3N0YXR1cywgaSkpOwo+ICsg ICAgICAgICAgICAgICBwID0gbWF4KHAsIGRybV9kcF9nZXRfYWRqdXN0X3JlcXVlc3RfcHJlX2Vt cGhhc2lzKGxpbmtfc3RhdHVzLAo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGkpKTsKPiArICAgICAgIH0KPiArCj4gKyAg ICAgICBpZiAodiA+PSBWT0xUQUdFX0xFVkVMXzIpCj4gKyAgICAgICAgICAgICAgIHYgPSBWT0xU QUdFX0xFVkVMXzIgfCBEUF9UUkFJTl9NQVhfU1dJTkdfUkVBQ0hFRDsKPiArCj4gKyAgICAgICBw cmVlbXBoX21heCA9IGNkbl9kcF9wcmVfZW1waGFzaXNfbWF4KHYpOwo+ICsgICAgICAgaWYgKHAg Pj0gcHJlZW1waF9tYXgpCj4gKyAgICAgICAgICAgICAgIHAgPSBwcmVlbXBoX21heCB8IERQX1RS QUlOX01BWF9QUkVfRU1QSEFTSVNfUkVBQ0hFRDsKPiArCj4gKyAgICAgICBmb3IgKGkgPSAwOyBp IDwgZHAtPmxpbmsubnVtX2xhbmVzOyBpKyspCj4gKyAgICAgICAgICAgICAgIGRwLT50cmFpbl9z ZXRbaV0gPSB2IHwgcDsKPiArfQo+ICsKPiArLyoKPiArICogUGljayB0cmFpbmluZyBwYXR0ZXJu IGZvciBjaGFubmVsIGVxdWFsaXphdGlvbi4gVHJhaW5pbmcgUGF0dGVybiAzIGZvciBIQlIyCj4g KyAqIG9yIDEuMiBkZXZpY2VzIHRoYXQgc3VwcG9ydCBpdCwgVHJhaW5pbmcgUGF0dGVybiAyIG90 aGVyd2lzZS4KPiArICovCj4gK3N0YXRpYyB1MzIgY2RuX2RwX3NlbGVjdF9jaGFuZXFfcGF0dGVy bihzdHJ1Y3QgY2RuX2RwX2RldmljZSAqZHApCj4gK3sKPiArICAgICAgIHUzMiB0cmFpbmluZ19w YXR0ZXJuID0gRFBfVFJBSU5JTkdfUEFUVEVSTl8yOwo+ICsKPiArICAgICAgIC8qCj4gKyAgICAg ICAgKiBjZG4gZHAgc3VwcG9ydCBIQlIyIGFsc28gc3VwcG9ydCBUUFMzLiBUUFMzIHN1cHBvcnQg aXMgYWxzbyBtYW5kYXRvcnkKPiArICAgICAgICAqIGZvciBkb3duc3RyZWFtIGRldmljZXMgdGhh dCBzdXBwb3J0IEhCUjIuIEhvd2V2ZXIsIG5vdCBhbGwgc2lua3MKPiArICAgICAgICAqIGZvbGxv dyB0aGUgc3BlYy4KPiArICAgICAgICAqLwo+ICsgICAgICAgaWYgKGRybV9kcF90cHMzX3N1cHBv cnRlZChkcC0+ZHBjZCkpCj4gKyAgICAgICAgICAgICAgIHRyYWluaW5nX3BhdHRlcm4gPSBEUF9U UkFJTklOR19QQVRURVJOXzM7Cj4gKyAgICAgICBlbHNlCj4gKyAgICAgICAgICAgICAgIERSTV9E RUJVR19LTVMoIjUuNCBHYnBzIGxpbmsgcmF0ZSB3aXRob3V0IHNpbmsgVFBTMyBzdXBwb3J0XG4i KTsKPiArCj4gKyAgICAgICByZXR1cm4gdHJhaW5pbmdfcGF0dGVybjsKPiArfQo+ICsKPiArCj4g K3N0YXRpYyBib29sIGNkbl9kcF9saW5rX21heF92c3dpbmdfcmVhY2hlZChzdHJ1Y3QgY2RuX2Rw X2RldmljZSAqZHApCj4gK3sKPiArICAgICAgIGludCBsYW5lOwo+ICsKPiArICAgICAgIGZvciAo bGFuZSA9IDA7IGxhbmUgPCBkcC0+bGluay5udW1fbGFuZXM7IGxhbmUrKykKPiArICAgICAgICAg ICAgICAgaWYgKChkcC0+dHJhaW5fc2V0W2xhbmVdICYgRFBfVFJBSU5fTUFYX1NXSU5HX1JFQUNI RUQpID09IDApCj4gKyAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwo+ICsKPiAr ICAgICAgIHJldHVybiB0cnVlOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGNkbl9kcF91cGRhdGVf bGlua190cmFpbihzdHJ1Y3QgY2RuX2RwX2RldmljZSAqZHApCj4gK3sKPiArICAgICAgIGludCBy ZXQ7Cj4gKwo+ICsgICAgICAgY2RuX2RwX3NldF9zaWduYWxfbGV2ZWxzKGRwKTsKPiArCj4gKyAg ICAgICByZXQgPSBkcm1fZHBfZHBjZF93cml0ZSgmZHAtPmF1eCwgRFBfVFJBSU5JTkdfTEFORTBf U0VULAo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHAtPnRyYWluX3NldCwgZHAt PmxpbmsubnVtX2xhbmVzKTsKPiArICAgICAgIGlmIChyZXQgIT0gZHAtPmxpbmsubnVtX2xhbmVz KQo+ICsgICAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsKPiArCj4gKyAgICAgICByZXR1cm4g MDsKPiArfQo+ICsKPiArc3RhdGljIGludCBjZG5fZHBfc2V0X2xpbmtfdHJhaW4oc3RydWN0IGNk bl9kcF9kZXZpY2UgKmRwLAo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1aW50 OF90IGRwX3RyYWluX3BhdCkKPiArewo+ICsgICAgICAgdWludDhfdCBidWZbc2l6ZW9mKGRwLT50 cmFpbl9zZXQpICsgMV07Cj4gKyAgICAgICBpbnQgcmV0LCBsZW47Cj4gKwo+ICsgICAgICAgYnVm WzBdID0gZHBfdHJhaW5fcGF0Owo+ICsgICAgICAgaWYgKChkcF90cmFpbl9wYXQgJiBEUF9UUkFJ TklOR19QQVRURVJOX01BU0spID09Cj4gKyAgICAgICAgICAgRFBfVFJBSU5JTkdfUEFUVEVSTl9E SVNBQkxFKSB7Cj4gKyAgICAgICAgICAgICAgIC8qIGRvbid0IHdyaXRlIERQX1RSQUlOSU5HX0xB TkV4X1NFVCBvbiBkaXNhYmxlICovCj4gKyAgICAgICAgICAgICAgIGxlbiA9IDE7Cj4gKyAgICAg ICB9IGVsc2Ugewo+ICsgICAgICAgICAgICAgICAvKiBEUF9UUkFJTklOR19MQU5FeF9TRVQgZm9s bG93IERQX1RSQUlOSU5HX1BBVFRFUk5fU0VUICovCj4gKyAgICAgICAgICAgICAgIG1lbWNweShi dWYgKyAxLCBkcC0+dHJhaW5fc2V0LCBkcC0+bGluay5udW1fbGFuZXMpOwo+ICsgICAgICAgICAg ICAgICBsZW4gPSBkcC0+bGluay5udW1fbGFuZXMgKyAxOwo+ICsgICAgICAgfQo+ICsKPiArICAg ICAgIHJldCA9IGRybV9kcF9kcGNkX3dyaXRlKCZkcC0+YXV4LCBEUF9UUkFJTklOR19QQVRURVJO X1NFVCwKPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZiwgbGVuKTsKPiArICAg ICAgIGlmIChyZXQgIT0gbGVuKQo+ICsgICAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsKPiAr Cj4gKyAgICAgICByZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBjZG5fZHBfcmVzZXRf bGlua190cmFpbihzdHJ1Y3QgY2RuX2RwX2RldmljZSAqZHAsCj4gKyAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgdWludDhfdCBkcF90cmFpbl9wYXQpCj4gK3sKPiArICAgICAgIGlu dCByZXQ7Cj4gKwo+ICsgICAgICAgbWVtc2V0KGRwLT50cmFpbl9zZXQsIDAsIHNpemVvZihkcC0+ dHJhaW5fc2V0KSk7Cj4gKwo+ICsgICAgICAgY2RuX2RwX3NldF9zaWduYWxfbGV2ZWxzKGRwKTsK PiArCj4gKyAgICAgICByZXQgPSBjZG5fZHBfc2V0X3BhdHRlcm4oZHAsIGRwX3RyYWluX3BhdCk7 Cj4gKyAgICAgICBpZiAocmV0KQo+ICsgICAgICAgICAgICAgICByZXR1cm4gcmV0Owo+ICsKPiAr ICAgICAgIHJldHVybiBjZG5fZHBfc2V0X2xpbmtfdHJhaW4oZHAsIGRwX3RyYWluX3BhdCk7Cj4g K30KPiArCj4gKy8qIEVuYWJsZSBjb3JyZXNwb25kaW5nIHBvcnQgYW5kIHN0YXJ0IHRyYWluaW5n IHBhdHRlcm4gMSAqLwo+ICtzdGF0aWMgaW50IGNkbl9kcF9saW5rX3RyYWluaW5nX2Nsb2NrX3Jl Y292ZXJ5KHN0cnVjdCBjZG5fZHBfZGV2aWNlICpkcCkKPiArewo+ICsgICAgICAgdTggdm9sdGFn ZSwgbGlua19jb25maWdbMl07Cj4gKyAgICAgICB1OCBsaW5rX3N0YXR1c1tEUF9MSU5LX1NUQVRV U19TSVpFXTsKPiArICAgICAgIHUzMiB2b2x0YWdlX3RyaWVzLCBtYXhfdnN3aW5nX3RyaWVzOwo+ ICsgICAgICAgdTMyIHJhdGUsIHNpbmtfbWF4LCBzb3VyY2VfbWF4Owo+ICsgICAgICAgaW50IHJl dDsKPiArCj4gKyAgICAgICBzb3VyY2VfbWF4ID0gZHAtPmxhbmVzOwo+ICsgICAgICAgc2lua19t YXggPSBkcm1fZHBfbWF4X2xhbmVfY291bnQoZHAtPmRwY2QpOwo+ICsgICAgICAgZHAtPmxpbmsu bnVtX2xhbmVzID0gbWluKHNvdXJjZV9tYXgsIHNpbmtfbWF4KTsKPiArCj4gKyAgICAgICBzb3Vy Y2VfbWF4ID0gZHJtX2RwX2J3X2NvZGVfdG9fbGlua19yYXRlKENETl9EUF9NQVhfTElOS19SQVRF KTsKPiArICAgICAgIHNpbmtfbWF4ID0gZHJtX2RwX21heF9saW5rX3JhdGUoZHAtPmRwY2QpOwo+ ICsgICAgICAgcmF0ZSA9IG1pbihzb3VyY2VfbWF4LCBzaW5rX21heCk7Cj4gKyAgICAgICBkcC0+ bGluay5yYXRlID0gZHJtX2RwX2xpbmtfcmF0ZV90b19id19jb2RlKHJhdGUpOwo+ICsKPiArICAg ICAgIC8qIFdyaXRlIHRoZSBsaW5rIGNvbmZpZ3VyYXRpb24gZGF0YSAqLwo+ICsgICAgICAgbGlu a19jb25maWdbMF0gPSBkcC0+bGluay5yYXRlOwo+ICsgICAgICAgbGlua19jb25maWdbMV0gPSBk cC0+bGluay5udW1fbGFuZXM7Cj4gKyAgICAgICBpZiAoZHJtX2RwX2VuaGFuY2VkX2ZyYW1lX2Nh cChkcC0+ZHBjZCkpCj4gKyAgICAgICAgICAgICAgIGxpbmtfY29uZmlnWzFdIHw9IERQX0xBTkVf Q09VTlRfRU5IQU5DRURfRlJBTUVfRU47Cj4gKyAgICAgICBkcm1fZHBfZHBjZF93cml0ZSgmZHAt PmF1eCwgRFBfTElOS19CV19TRVQsIGxpbmtfY29uZmlnLCAyKTsKPiArCj4gKyAgICAgICBsaW5r X2NvbmZpZ1swXSA9IDA7Cj4gKyAgICAgICBsaW5rX2NvbmZpZ1sxXSA9IDA7Cj4gKyAgICAgICBp ZiAoZHAtPmRwY2RbRFBfTUFJTl9MSU5LX0NIQU5ORUxfQ09ESU5HXSAmIDB4MDEpCj4gKyAgICAg ICAgICAgICAgIGxpbmtfY29uZmlnWzFdID0gRFBfU0VUX0FOU0lfOEIxMEI7Cj4gKwo+ICsgICAg ICAgZHJtX2RwX2RwY2Rfd3JpdGUoJmRwLT5hdXgsIERQX0RPV05TUFJFQURfQ1RSTCwgbGlua19j b25maWcsIDIpOwo+ICsKPiArICAgICAgIC8qIGNsb2NrIHJlY292ZXJ5ICovCj4gKyAgICAgICBy ZXQgPSBjZG5fZHBfcmVzZXRfbGlua190cmFpbihkcCwgRFBfVFJBSU5JTkdfUEFUVEVSTl8xIHwK PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEUF9MSU5LX1NDUkFN QkxJTkdfRElTQUJMRSk7Cj4gKyAgICAgICBpZiAocmV0KSB7Cj4gKyAgICAgICAgICAgICAgIERS TV9FUlJPUigiZmFpbGVkIHRvIHN0YXJ0IGxpbmsgdHJhaW5cbiIpOwo+ICsgICAgICAgICAgICAg ICByZXR1cm4gcmV0Owo+ICsgICAgICAgfQo+ICsKPiArICAgICAgIHZvbHRhZ2VfdHJpZXMgPSAx Owo+ICsgICAgICAgbWF4X3Zzd2luZ190cmllcyA9IDA7Cj4gKyAgICAgICBmb3IgKDs7KSB7Cj4g KyAgICAgICAgICAgICAgIGRybV9kcF9saW5rX3RyYWluX2Nsb2NrX3JlY292ZXJ5X2RlbGF5KGRw LT5kcGNkKTsKPiArICAgICAgICAgICAgICAgaWYgKGRybV9kcF9kcGNkX3JlYWRfbGlua19zdGF0 dXMoJmRwLT5hdXgsIGxpbmtfc3RhdHVzKSAhPQo+ICsgICAgICAgICAgICAgICAgICAgRFBfTElO S19TVEFUVVNfU0laRSkgewo+ICsgICAgICAgICAgICAgICAgICAgICAgIERSTV9FUlJPUigiZmFp bGVkIHRvIGdldCBsaW5rIHN0YXR1c1xuIik7Cj4gKyAgICAgICAgICAgICAgICAgICAgICAgcmV0 dXJuIC1FSU5WQUw7Cj4gKyAgICAgICAgICAgICAgIH0KPiArCj4gKyAgICAgICAgICAgICAgIGlm IChkcm1fZHBfY2xvY2tfcmVjb3Zlcnlfb2sobGlua19zdGF0dXMsIGRwLT5saW5rLm51bV9sYW5l cykpIHsKPiArICAgICAgICAgICAgICAgICAgICAgICBEUk1fREVCVUdfS01TKCJjbG9jayByZWNv dmVyeSBPS1xuIik7Cj4gKyAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDA7Cj4gKyAgICAg ICAgICAgICAgIH0KPiArCj4gKyAgICAgICAgICAgICAgIGlmICh2b2x0YWdlX3RyaWVzID49IDUp IHsKPiArICAgICAgICAgICAgICAgICAgICAgICBEUk1fREVCVUdfS01TKCJTYW1lIHZvbHRhZ2Ug dHJpZWQgNSB0aW1lc1xuIik7Cj4gKyAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIC1FSU5W QUw7Cj4gKyAgICAgICAgICAgICAgIH0KPiArCj4gKyAgICAgICAgICAgICAgIGlmIChtYXhfdnN3 aW5nX3RyaWVzID49IDEpIHsKPiArICAgICAgICAgICAgICAgICAgICAgICBEUk1fREVCVUdfS01T KCJNYXggVm9sdGFnZSBTd2luZyByZWFjaGVkXG4iKTsKPiArICAgICAgICAgICAgICAgICAgICAg ICByZXR1cm4gLUVJTlZBTDsKPiArICAgICAgICAgICAgICAgfQo+ICsKPiArICAgICAgICAgICAg ICAgdm9sdGFnZSA9IGRwLT50cmFpbl9zZXRbMF0gJiBEUF9UUkFJTl9WT0xUQUdFX1NXSU5HX01B U0s7Cj4gKwo+ICsgICAgICAgICAgICAgICAvKiBVcGRhdGUgdHJhaW5pbmcgc2V0IGFzIHJlcXVl c3RlZCBieSB0YXJnZXQgKi8KPiArICAgICAgICAgICAgICAgY2RuX2RwX2dldF9hZGp1c3RfdHJh aW4oZHAsIGxpbmtfc3RhdHVzKTsKPiArICAgICAgICAgICAgICAgaWYgKGNkbl9kcF91cGRhdGVf bGlua190cmFpbihkcCkpIHsKPiArICAgICAgICAgICAgICAgICAgICAgICBEUk1fRVJST1IoImZh aWxlZCB0byB1cGRhdGUgbGluayB0cmFpbmluZ1xuIik7Cj4gKyAgICAgICAgICAgICAgICAgICAg ICAgcmV0dXJuIC1FSU5WQUw7Cj4gKyAgICAgICAgICAgICAgIH0KPiArCj4gKyAgICAgICAgICAg ICAgIGlmICgoZHAtPnRyYWluX3NldFswXSAmIERQX1RSQUlOX1ZPTFRBR0VfU1dJTkdfTUFTSykg PT0KPiArICAgICAgICAgICAgICAgICAgIHZvbHRhZ2UpCj4gKyAgICAgICAgICAgICAgICAgICAg ICAgKyt2b2x0YWdlX3RyaWVzOwo+ICsgICAgICAgICAgICAgICBlbHNlCj4gKyAgICAgICAgICAg ICAgICAgICAgICAgdm9sdGFnZV90cmllcyA9IDE7Cj4gKwo+ICsgICAgICAgICAgICAgICBpZiAo Y2RuX2RwX2xpbmtfbWF4X3Zzd2luZ19yZWFjaGVkKGRwKSkKPiArICAgICAgICAgICAgICAgICAg ICAgICArK21heF92c3dpbmdfdHJpZXM7Cj4gKyAgICAgICB9Cj4gK30KPiArCj4gK3N0YXRpYyBp bnQgY2RuX2RwX2xpbmtfdHJhaW5pbmdfY2hhbm5lbF9lcXVhbGl6YXRpb24oc3RydWN0IGNkbl9k cF9kZXZpY2UgKmRwKQo+ICt7Cj4gKyAgICAgICBpbnQgdHJpZXMsIHJldDsKPiArICAgICAgIHUz MiB0cmFpbmluZ19wYXR0ZXJuOwo+ICsgICAgICAgdWludDhfdCBsaW5rX3N0YXR1c1tEUF9MSU5L X1NUQVRVU19TSVpFXTsKPiArCj4gKyAgICAgICB0cmFpbmluZ19wYXR0ZXJuID0gY2RuX2RwX3Nl bGVjdF9jaGFuZXFfcGF0dGVybihkcCk7Cj4gKyAgICAgICB0cmFpbmluZ19wYXR0ZXJuIHw9IERQ X0xJTktfU0NSQU1CTElOR19ESVNBQkxFOwo+ICsKPiArICAgICAgIHJldCA9IGNkbl9kcF9zZXRf cGF0dGVybihkcCwgdHJhaW5pbmdfcGF0dGVybik7Cj4gKyAgICAgICBpZiAocmV0KQo+ICsgICAg ICAgICAgICAgICByZXR1cm4gcmV0Owo+ICsKPiArICAgICAgIHJldCA9IGNkbl9kcF9zZXRfbGlu a190cmFpbihkcCwgdHJhaW5pbmdfcGF0dGVybik7Cj4gKyAgICAgICBpZiAocmV0KSB7Cj4gKyAg ICAgICAgICAgICAgIERSTV9FUlJPUigiZmFpbGVkIHRvIHN0YXJ0IGNoYW5uZWwgZXF1YWxpemF0 aW9uXG4iKTsKPiArICAgICAgICAgICAgICAgcmV0dXJuIHJldDsKPiArICAgICAgIH0KPiArCj4g KyAgICAgICBmb3IgKHRyaWVzID0gMDsgdHJpZXMgPCA1OyB0cmllcysrKSB7Cj4gKyAgICAgICAg ICAgICAgIGRybV9kcF9saW5rX3RyYWluX2NoYW5uZWxfZXFfZGVsYXkoZHAtPmRwY2QpOwo+ICsg ICAgICAgICAgICAgICBpZiAoZHJtX2RwX2RwY2RfcmVhZF9saW5rX3N0YXR1cygmZHAtPmF1eCwg bGlua19zdGF0dXMpICE9Cj4gKyAgICAgICAgICAgICAgICAgICBEUF9MSU5LX1NUQVRVU19TSVpF KSB7Cj4gKyAgICAgICAgICAgICAgICAgICAgICAgRFJNX0VSUk9SKCJmYWlsZWQgdG8gZ2V0IGxp bmsgc3RhdHVzXG4iKTsKPiArICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKPiArICAgICAg ICAgICAgICAgfQo+ICsKPiArICAgICAgICAgICAgICAgLyogTWFrZSBzdXJlIGNsb2NrIGlzIHN0 aWxsIG9rICovCj4gKyAgICAgICAgICAgICAgIGlmICghZHJtX2RwX2Nsb2NrX3JlY292ZXJ5X29r KGxpbmtfc3RhdHVzLCBkcC0+bGluay5udW1fbGFuZXMpKSB7Cj4gKyAgICAgICAgICAgICAgICAg ICAgICAgRFJNX0RFQlVHX0tNUygiQ2xvY2sgcmVjb3ZlcnkgY2hlY2sgZmFpbGVkLCBjYW5ub3Qg Igo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImNvbnRpbnVlIGNoYW5u ZWwgZXF1YWxpemF0aW9uXG4iKTsKPiArICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKPiAr ICAgICAgICAgICAgICAgfQo+ICsKPiArICAgICAgICAgICAgICAgaWYgKGRybV9kcF9jaGFubmVs X2VxX29rKGxpbmtfc3RhdHVzLCAgZHAtPmxpbmsubnVtX2xhbmVzKSkgewo+ICsgICAgICAgICAg ICAgICAgICAgICAgIERSTV9ERUJVR19LTVMoIkNoYW5uZWwgRVEgZG9uZS4gRFAgVHJhaW5pbmcg Igo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInN1Y2Nlc3NmdWxcbiIp Owo+ICsgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAwOwo+ICsgICAgICAgICAgICAgICB9 Cj4gKwo+ICsgICAgICAgICAgICAgICAvKiBVcGRhdGUgdHJhaW5pbmcgc2V0IGFzIHJlcXVlc3Rl ZCBieSB0YXJnZXQgKi8KPiArICAgICAgICAgICAgICAgY2RuX2RwX2dldF9hZGp1c3RfdHJhaW4o ZHAsIGxpbmtfc3RhdHVzKTsKPiArICAgICAgICAgICAgICAgaWYgKGNkbl9kcF91cGRhdGVfbGlu a190cmFpbihkcCkpIHsKPiArICAgICAgICAgICAgICAgICAgICAgICBEUk1fRVJST1IoImZhaWxl ZCB0byB1cGRhdGUgbGluayB0cmFpbmluZ1xuIik7Cj4gKyAgICAgICAgICAgICAgICAgICAgICAg YnJlYWs7Cj4gKyAgICAgICAgICAgICAgIH0KPiArICAgICAgIH0KPiArCj4gKyAgICAgICAvKiBU cnkgNSB0aW1lcywgZWxzZSBmYWlsIGFuZCB0cnkgYXQgbG93ZXIgQlcgKi8KPiArICAgICAgIGlm ICh0cmllcyA9PSA1KQo+ICsgICAgICAgICAgICAgICBEUk1fREVCVUdfS01TKCJDaGFubmVsIGVx dWFsaXphdGlvbiBmYWlsZWQgNSB0aW1lc1xuIik7Cj4gKwo+ICsgICAgICAgcmV0dXJuIC1FSU5W QUw7Cj4gKwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGNkbl9kcF9zdG9wX2xpbmtfdHJhaW4oc3Ry dWN0IGNkbl9kcF9kZXZpY2UgKmRwKQo+ICt7Cj4gKyAgICAgICBpbnQgcmV0ID0gY2RuX2RwX3Nl dF9wYXR0ZXJuKGRwLCBEUF9UUkFJTklOR19QQVRURVJOX0RJU0FCTEUpOwo+ICsKPiArICAgICAg IGlmIChyZXQpCj4gKyAgICAgICAgICAgICAgIHJldHVybiByZXQ7Cj4gKwo+ICsgICAgICAgcmV0 dXJuIGNkbl9kcF9zZXRfbGlua190cmFpbihkcCwgRFBfVFJBSU5JTkdfUEFUVEVSTl9ESVNBQkxF KTsKPiArfQo+ICsKPiAraW50IGNkbl9kcF9zb2Z0d2FyZV90cmFpbl9saW5rKHN0cnVjdCBjZG5f ZHBfZGV2aWNlICpkcCkKPiArewo+ICsgICAgICAgaW50IHJldCwgc3RvcF9lcnI7Cj4gKwo+ICsg ICAgICAgcmV0ID0gZHJtX2RwX2RwY2RfcmVhZCgmZHAtPmF1eCwgRFBfRFBDRF9SRVYsIGRwLT5k cGNkLAo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplb2YoZHAtPmRwY2QpKTsK PiArICAgICAgIGlmIChyZXQgPCAwKSB7Cj4gKyAgICAgICAgICAgICAgIERSTV9ERVZfRVJST1Io ZHAtPmRldiwgIkZhaWxlZCB0byBnZXQgY2FwcyAlZFxuIiwgcmV0KTsKPiArICAgICAgICAgICAg ICAgcmV0dXJuIHJldDsKPiArICAgICAgIH0KPiArCj4gKyAgICAgICByZXQgPSBjZG5fZHBfbGlu a190cmFpbmluZ19jbG9ja19yZWNvdmVyeShkcCk7Cj4gKyAgICAgICBpZiAocmV0KSB7Cj4gKyAg ICAgICAgICAgICAgIERSTV9FUlJPUigidHJhaW5pbmcgY2xvY2sgcmVjb3ZlcnkgZmFpbCwgZXJy b3I6ICVkXG4iLCByZXQpOwo+ICsgICAgICAgICAgICAgICBnb3RvIG91dDsKPiArICAgICAgIH0K PiArCj4gKyAgICAgICByZXQgPSBjZG5fZHBfbGlua190cmFpbmluZ19jaGFubmVsX2VxdWFsaXph dGlvbihkcCk7Cj4gKyAgICAgICBpZiAocmV0KSB7Cj4gKyAgICAgICAgICAgICAgIERSTV9FUlJP UigidHJhaW5pbmcgY2hhbm5lbCBlcXVhbGl6YXRpb24gZmFpbCwgZXJyb3I6ICVkXG4iLAo+ICsg ICAgICAgICAgICAgICAgICAgICAgICAgcmV0KTsKPiArICAgICAgICAgICAgICAgZ290byBvdXQ7 Cj4gKyAgICAgICB9Cj4gK291dDoKPiArICAgICAgIHN0b3BfZXJyID0gY2RuX2RwX3N0b3BfbGlu a190cmFpbihkcCk7Cj4gKyAgICAgICBpZiAoc3RvcF9lcnIpIHsKPiArICAgICAgICAgICAgICAg RFJNX0VSUk9SKCJzdG9wIHRyYWluaW5nIGZhaWwsIGVycm9yOiAlZFxuIiwgc3RvcF9lcnIpOwo+ ICsgICAgICAgICAgICAgICByZXR1cm4gc3RvcF9lcnI7Cj4gKyAgICAgICB9Cj4gKwo+ICsgICAg ICAgcmV0dXJuIHJldDsKPiArfQo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vcm9ja2No aXAvY2RuLWRwLXJlZy5jIGIvZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlwL2Nkbi1kcC1yZWcuYwo+ IGluZGV4IGIyZjUzMmEuLjcyNzgwZjEgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy9ncHUvZHJtL3Jv Y2tjaGlwL2Nkbi1kcC1yZWcuYwo+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9yb2NrY2hpcC9jZG4t ZHAtcmVnLmMKPiBAQCAtMTcsNyArMTcsOSBAQAo+ICAjaW5jbHVkZSA8bGludXgvZGVsYXkuaD4K PiAgI2luY2x1ZGUgPGxpbnV4L2lvLmg+Cj4gICNpbmNsdWRlIDxsaW51eC9pb3BvbGwuaD4KPiAr I2luY2x1ZGUgPGxpbnV4L3BoeS9waHkuaD4KPiAgI2luY2x1ZGUgPGxpbnV4L3Jlc2V0Lmg+Cj4g KyNpbmNsdWRlIDxzb2Mvcm9ja2NoaXAvcm9ja2NoaXBfcGh5X3R5cGVjLmg+Cj4KPiAgI2luY2x1 ZGUgImNkbi1kcC1jb3JlLmgiCj4gICNpbmNsdWRlICJjZG4tZHAtcmVnLmgiCj4gQEAgLTE4OSw3 ICsxOTEsNyBAQCBzdGF0aWMgaW50IGNkbl9kcF9tYWlsYm94X3NlbmQoc3RydWN0IGNkbl9kcF9k ZXZpY2UgKmRwLCB1OCBtb2R1bGVfaWQsCj4gICAgICAgICByZXR1cm4gMDsKPiAgfQo+Cj4gLXN0 YXRpYyBpbnQgY2RuX2RwX3JlZ193cml0ZShzdHJ1Y3QgY2RuX2RwX2RldmljZSAqZHAsIHUxNiBh ZGRyLCB1MzIgdmFsKQo+ICtpbnQgY2RuX2RwX3JlZ193cml0ZShzdHJ1Y3QgY2RuX2RwX2Rldmlj ZSAqZHAsIHUxNiBhZGRyLCB1MzIgdmFsKQo+ICB7Cj4gICAgICAgICB1OCBtc2dbNl07Cj4KPiBA QCAtNjA1LDIyICs2MDcsNDEgQEAgc3RhdGljIGludCBjZG5fZHBfZ2V0X3RyYWluaW5nX3N0YXR1 cyhzdHJ1Y3QgY2RuX2RwX2RldmljZSAqZHApCj4gIGludCBjZG5fZHBfdHJhaW5fbGluayhzdHJ1 Y3QgY2RuX2RwX2RldmljZSAqZHApCj4gIHsKPiAgICAgICAgIGludCByZXQ7Cj4gKyAgICAgICBz dHJ1Y3QgY2RuX2RwX3BvcnQgKnBvcnQgPSBkcC0+cG9ydFtkcC0+YWN0aXZlX3BvcnRdOwo+ICsg ICAgICAgc3RydWN0IHJvY2tjaGlwX3R5cGVjX3BoeSAqdGNwaHkgPSBwaHlfZ2V0X2RydmRhdGEo cG9ydC0+cGh5KTsKPgo+ICsgICAgICAgLyoKPiArICAgICAgICAqIERQIGZpcm13YXJlIHVzZXMg Zml4ZWQgcGh5IGNvbmZpZyB2YWx1ZXMgdG8gZG8gdHJhaW5pbmcsIGJ1dCBzb21lCj4gKyAgICAg ICAgKiBib2FyZHMgbmVlZCB0byBhZGp1c3QgdGhlc2UgdmFsdWVzIHRvIGZpdCBmb3IgdGhlaXIg dW5pcXVlIGhhcmR3YXJlCj4gKyAgICAgICAgKiBkZXNpZ24uIFNvIGlmIHRoZSBwaHkgaXMgdXNp bmcgY3VzdG9tIGNvbmZpZyB2YWx1ZXMsIGRvIHNvZnR3YXJlCj4gKyAgICAgICAgKiBsaW5rIHRy YWluaW5nIGluc3RlYWQgb2YgcmVseWluZyBvbiBmaXJtd2FyZSwgaWYgc29mdHdhcmUgdHJhaW5p bmcKPiArICAgICAgICAqIGZhaWwsIGtlZXAgZmlybXdhcmUgdHJhaW5pbmcgYXMgYSBmYWxsYmFj ayBpZiBzdyB0cmFpbmluZyBmYWlscy4KPiArICAgICAgICAqLwo+ICsgICAgICAgaWYgKHRjcGh5 LT5uZWVkX3NvZnR3YXJlX3RyYWluaW5nKSB7Cj4gKyAgICAgICAgICAgICAgIHJldCA9IGNkbl9k cF9zb2Z0d2FyZV90cmFpbl9saW5rKGRwKTsKPiArICAgICAgICAgICAgICAgaWYgKHJldCkgewo+ ICsgICAgICAgICAgICAgICAgICAgICAgIERSTV9ERVZfRVJST1IoZHAtPmRldiwKPiArICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICJGYWlsZWQgdG8gZG8gc29mdHdhcmUgdHJhaW5pbmcg JWRcbiIsIHJldCk7Cj4gKyAgICAgICAgICAgICAgICAgICAgICAgZ290byBkb19md190cmFpbmlu ZzsKPiArICAgICAgICAgICAgICAgfQo+ICsgICAgICAgICAgICAgICBjZG5fZHBfcmVnX3dyaXRl KGRwLCBTT1VSQ0VfSERUWF9DQVIsIDB4Zik7CgpDaGVjayBmb3IgYW4gZXJyb3IgaGVyZSBhbmQg YWN0IGFjY29yZGluZ2x5PyBPciBkb2Vzbid0IG1hdHRlcj8KCj4gKyAgICAgICAgICAgICAgIGRw LT5zd190cmFpbmluZ19zdWNjZXNzID0gdHJ1ZTsKPiArICAgICAgICAgICAgICAgcmV0dXJuIDA7 Cj4gKyAgICAgICB9Cj4gKwoKbml0OiBQZXJzb25hbGx5IEkgZG9uJ3QgbGlrZSB0aGlzIGdvdG8u IE1heWJlIHlvdSBjYW4gcmVmYWN0b3IgdGhpcy4KCiAgICAgICBpZiAodGNwaHktPm5lZWRfc29m dHdhcmVfdHJhaW5pbmcpIHsKICAgICAgICAgICAgICAgcmV0ID0gY2RuX2RwX3NvZnR3YXJlX3Ry YWluX2xpbmsoZHApOwogICAgICAgICAgICAgICBpZiAoIXJldCkgewogICAgICAgICAgICAgICAg ICAgICAgIGNkbl9kcF9yZWdfd3JpdGUoZHAsIFNPVVJDRV9IRFRYX0NBUiwgMHhmKTsKICAgICAg ICAgICAgICAgICAgICAgICBkcC0+c3dfdHJhaW5pbmdfc3VjY2VzcyA9IHRydWU7CiAgICAgICAg ICAgICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAg RFJNX0RFVl9FUlJPUihkcC0+ZGV2LCAiRmFpbGVkIHRvIGRvIHNvZnR3YXJlIHRyYWluaW5nCiVk XG4iLCByZXQpOwogICAgICAgfQoKPiArZG9fZndfdHJhaW5pbmc6CgpUaGVuIHJlbW92ZSB0aGUg Z290byBsYWJlbC4KCj4gKyAgICAgICBkcC0+c3dfdHJhaW5pbmdfc3VjY2VzcyA9IGZhbHNlOwo+ ICAgICAgICAgcmV0ID0gY2RuX2RwX3RyYWluaW5nX3N0YXJ0KGRwKTsKPiAgICAgICAgIGlmIChy ZXQpIHsKPiAgICAgICAgICAgICAgICAgRFJNX0RFVl9FUlJPUihkcC0+ZGV2LCAiRmFpbGVkIHRv IHN0YXJ0IHRyYWluaW5nICVkXG4iLCByZXQpOwo+ICAgICAgICAgICAgICAgICByZXR1cm4gcmV0 Owo+ICAgICAgICAgfQo+IC0KCkRvIG5vdCByZW1vdmUgdGhlIG5ldyBsaW5lLgoKPiAgICAgICAg IHJldCA9IGNkbl9kcF9nZXRfdHJhaW5pbmdfc3RhdHVzKGRwKTsKPiAgICAgICAgIGlmIChyZXQp IHsKPiAgICAgICAgICAgICAgICAgRFJNX0RFVl9FUlJPUihkcC0+ZGV2LCAiRmFpbGVkIHRvIGdl dCB0cmFpbmluZyBzdGF0ICVkXG4iLCByZXQpOwo+ICAgICAgICAgICAgICAgICByZXR1cm4gcmV0 Owo+ICAgICAgICAgfQo+IC0KPiAtICAgICAgIERSTV9ERVZfREVCVUdfS01TKGRwLT5kZXYsICJy YXRlOjB4JXgsIGxhbmVzOiVkXG4iLCBkcC0+bGluay5yYXRlLAo+IC0gICAgICAgICAgICAgICAg ICAgICAgICAgZHAtPmxpbmsubnVtX2xhbmVzKTsKCldoeSB5b3UgcmVtb3ZlIHRoaXMgZGVidWcg bWVzc2FnZT8KCj4gLSAgICAgICByZXR1cm4gcmV0Owo+ICsgICAgICAgcmV0dXJuIDA7Cj4gIH0K Pgo+ICBpbnQgY2RuX2RwX3NldF92aWRlb19zdGF0dXMoc3RydWN0IGNkbl9kcF9kZXZpY2UgKmRw LCBpbnQgYWN0aXZlKQo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvY2Ru LWRwLXJlZy5oIGIvZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlwL2Nkbi1kcC1yZWcuaAo+IGluZGV4 IGFlZGYyZGMuLmI2MGE2YjIgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlw L2Nkbi1kcC1yZWcuaAo+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9yb2NrY2hpcC9jZG4tZHAtcmVn LmgKPiBAQCAtMTM3LDcgKzEzNyw3IEBACj4gICNkZWZpbmUgSFBEX0VWRU5UX01BU0sgICAgICAg ICAgICAgICAgIDB4MjExYwo+ICAjZGVmaW5lIEhQRF9FVkVOVF9ERVQgICAgICAgICAgICAgICAg ICAweDIxMjAKPgo+IC0vKiBkcHl4IGZyYW1lciBhZGRyICovCj4gKy8qIGRwdHggZnJhbWVyIGFk ZHIgKi8KPiAgI2RlZmluZSBEUF9GUkFNRVJfR0xPQkFMX0NPTkZJRyAgICAgICAgICAgICAgICAw eDIyMDAKPiAgI2RlZmluZSBEUF9TV19SRVNFVCAgICAgICAgICAgICAgICAgICAgMHgyMjA0Cj4g ICNkZWZpbmUgRFBfRlJBTUVSX1RVICAgICAgICAgICAgICAgICAgIDB4MjIwOAo+IEBAIC00MzEs NiArNDMxLDQwIEBACj4gIC8qIFJlZmVyZW5jZSBjeWNsZXMgd2hlbiB1c2luZyBsYW5lIGNsb2Nr IGFzIHJlZmVyZW5jZSAqLwo+ICAjZGVmaW5lIExBTkVfUkVGX0NZQyAgICAgICAgICAgICAgICAg ICAgICAgICAgIDB4ODAwMAo+Cj4gKy8qIHJlZ2lzdGVyIENNX1ZJRF9DVFJMICovCj4gKyNkZWZp bmUgTEFORV9WSURfUkVGX0NZQyh4KSAgICAgICAgICAgICAgICAgICAgKCgoeCkgJiAoQklUKDI0 KSAtIDEpKSA8PCAwKQo+ICsjZGVmaW5lIE5NVklEX01FQVNfVE9MRVJBTkNFKHgpICAgICAgICAg ICAgICAgICAgICAgICAgKCgoeCkgJiAweGYpIDw8IDI0KQo+ICsKPiArLyogcmVnaXN0ZXIgRFBf VFhfUEhZX0NPTkZJR19SRUcgKi8KPiArI2RlZmluZSBEUF9UWF9QSFlfVFJBSU5JTkdfRU5BQkxF KHgpICAgICAgICAgICAoKHgpICYgMSkKPiArI2RlZmluZSBEUF9UWF9QSFlfVFJBSU5JTkdfVFlQ RV9QUkJTNyAgICAgICAgICAoMCA8PCAxKQo+ICsjZGVmaW5lIERQX1RYX1BIWV9UUkFJTklOR19U WVBFX1RQUzEgICAgICAgICAgICgxIDw8IDEpCj4gKyNkZWZpbmUgRFBfVFhfUEhZX1RSQUlOSU5H X1RZUEVfVFBTMiAgICAgICAgICAgKDIgPDwgMSkKPiArI2RlZmluZSBEUF9UWF9QSFlfVFJBSU5J TkdfVFlQRV9UUFMzICAgICAgICAgICAoMyA8PCAxKQo+ICsjZGVmaW5lIERQX1RYX1BIWV9UUkFJ TklOR19UWVBFX1RQUzQgICAgICAgICAgICg0IDw8IDEpCj4gKyNkZWZpbmUgRFBfVFhfUEhZX1RS QUlOSU5HX1RZUEVfUExUUEFUICAgICAgICAgKDUgPDwgMSkKPiArI2RlZmluZSBEUF9UWF9QSFlf VFJBSU5JTkdfVFlQRV9EMTBfMiAgICAgICAgICAoNiA8PCAxKQo+ICsjZGVmaW5lIERQX1RYX1BI WV9UUkFJTklOR19UWVBFX0hCUjJDUEFUICAgICAgICg4IDw8IDEpCj4gKyNkZWZpbmUgRFBfVFhf UEhZX1RSQUlOSU5HX1BBVFRFUk4oeCkgICAgICAgICAgKCh4KSA8PCAxKQo+ICsjZGVmaW5lIERQ X1RYX1BIWV9TQ1JBTUJMRVJfQllQQVNTKHgpICAgICAgICAgICgoKHgpICYgMSkgPDwgNSkKPiAr I2RlZmluZSBEUF9UWF9QSFlfRU5DT0RFUl9CWVBBU1MoeCkgICAgICAgICAgICAoKCh4KSAmIDEp IDw8IDYpCj4gKyNkZWZpbmUgRFBfVFhfUEhZX1NLRVdfQllQQVNTKHgpICAgICAgICAgICAgICAg KCgoeCkgJiAxKSA8PCA3KQo+ICsjZGVmaW5lIERQX1RYX1BIWV9ESVNQQVJJVFlfUlNUKHgpICAg ICAgICAgICAgICgoKHgpICYgMSkgPDwgOCkKPiArI2RlZmluZSBEUF9UWF9QSFlfTEFORTBfU0tF Vyh4KSAgICAgICAgICAgICAgICAoKCh4KSAmIDcpIDw8IDkpCj4gKyNkZWZpbmUgRFBfVFhfUEhZ X0xBTkUxX1NLRVcoeCkgICAgICAgICAgICAgICAgKCgoeCkgJiA3KSA8PCAxMikKPiArI2RlZmlu ZSBEUF9UWF9QSFlfTEFORTJfU0tFVyh4KSAgICAgICAgICAgICAgICAoKCh4KSAmIDcpIDw8IDE1 KQo+ICsjZGVmaW5lIERQX1RYX1BIWV9MQU5FM19TS0VXKHgpICAgICAgICAgICAgICAgICgoKHgp ICYgNykgPDwgMTgpCj4gKyNkZWZpbmUgRFBfVFhfUEhZXzEwQklUX0VOQUJMRSh4KSAgICAgICAg ICAgICAgKCgoeCkgJiAxKSA8PCAyMSkKPiArCj4gKy8qIHJlZ2lzdGVyIERQX0ZSQU1FUl9HTE9C QUxfQ09ORklHICovCj4gKyNkZWZpbmUgTlVNX0xBTkVTKHgpICAgICAgICAgICAoKHgpICYgMykK PiArI2RlZmluZSBTU1RfTU9ERSAgICAgICAgICAgICAgICgwIDw8IDIpCj4gKyNkZWZpbmUgR0xP QkFMX0VOICAgICAgICAgICAgICAoMSA8PCAzKQo+ICsjZGVmaW5lIFJHX0VOICAgICAgICAgICAg ICAgICAgKDAgPDwgNCkKPiArI2RlZmluZSBOT19WSURFTyAgICAgICAgICAgICAgICgxIDw8IDUp Cj4gKyNkZWZpbmUgRU5DX1JTVF9ESVMgICAgICAgICAgICAoMSA8PCA2KQo+ICsjZGVmaW5lIFdS X1ZIU1lOQ19GQUxMICAgICAgICAgKDEgPDwgNykKPiArCgpVc2UgdGhlIEJJVCgpIG1hY3JvcyBm b3IgdGhlc2UuCgo+ICBlbnVtIHZvbHRhZ2Vfc3dpbmdfbGV2ZWwgewo+ICAgICAgICAgVk9MVEFH RV9MRVZFTF8wLAo+ICAgICAgICAgVk9MVEFHRV9MRVZFTF8xLAo+IEBAIC00NzYsNiArNTEwLDcg QEAgaW50IGNkbl9kcF9zZXRfaG9zdF9jYXAoc3RydWN0IGNkbl9kcF9kZXZpY2UgKmRwLCB1OCBs YW5lcywgYm9vbCBmbGlwKTsKPiAgaW50IGNkbl9kcF9ldmVudF9jb25maWcoc3RydWN0IGNkbl9k cF9kZXZpY2UgKmRwKTsKPiAgdTMyIGNkbl9kcF9nZXRfZXZlbnQoc3RydWN0IGNkbl9kcF9kZXZp Y2UgKmRwKTsKPiAgaW50IGNkbl9kcF9nZXRfaHBkX3N0YXR1cyhzdHJ1Y3QgY2RuX2RwX2Rldmlj ZSAqZHApOwo+ICtpbnQgY2RuX2RwX3JlZ193cml0ZShzdHJ1Y3QgY2RuX2RwX2RldmljZSAqZHAs IHUxNiBhZGRyLCB1MzIgdmFsKTsKPiAgc3NpemVfdCBjZG5fZHBfZHBjZF93cml0ZShzdHJ1Y3Qg Y2RuX2RwX2RldmljZSAqZHAsIHUzMiBhZGRyLAo+ICAgICAgICAgICAgICAgICAgICAgICAgICAg dTggKmRhdGEsIHUxNiBsZW4pOwo+ICBzc2l6ZV90IGNkbl9kcF9kcGNkX3JlYWQoc3RydWN0IGNk bl9kcF9kZXZpY2UgKmRwLCB1MzIgYWRkciwKPiBAQCAtNDg5LDQgKzUyNCw1IEBAIGludCBjZG5f ZHBfY29uZmlnX3ZpZGVvKHN0cnVjdCBjZG5fZHBfZGV2aWNlICpkcCk7Cj4gIGludCBjZG5fZHBf YXVkaW9fc3RvcChzdHJ1Y3QgY2RuX2RwX2RldmljZSAqZHAsIHN0cnVjdCBhdWRpb19pbmZvICph dWRpbyk7Cj4gIGludCBjZG5fZHBfYXVkaW9fbXV0ZShzdHJ1Y3QgY2RuX2RwX2RldmljZSAqZHAs IGJvb2wgZW5hYmxlKTsKPiAgaW50IGNkbl9kcF9hdWRpb19jb25maWcoc3RydWN0IGNkbl9kcF9k ZXZpY2UgKmRwLCBzdHJ1Y3QgYXVkaW9faW5mbyAqYXVkaW8pOwo+ICtpbnQgY2RuX2RwX3NvZnR3 YXJlX3RyYWluX2xpbmsoc3RydWN0IGNkbl9kcF9kZXZpY2UgKmRwKTsKPiAgI2VuZGlmIC8qIF9D RE5fRFBfUkVHX0ggKi8KPiAtLQo+IDIuNy40Cj4KX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX18KZHJpLWRldmVsIG1haWxpbmcgbGlzdApkcmktZGV2ZWxAbGlz dHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4v bGlzdGluZm8vZHJpLWRldmVsCg== From mboxrd@z Thu Jan 1 00:00:00 1970 From: eballetbo@gmail.com (Enric Balletbo Serra) Date: Mon, 7 May 2018 13:29:39 +0200 Subject: [PATCH 4/4] drm/rockchip: support dp training outside dp firmware In-Reply-To: <1525421338-1021-4-git-send-email-hl@rock-chips.com> References: <1525421338-1021-1-git-send-email-hl@rock-chips.com> <1525421338-1021-4-git-send-email-hl@rock-chips.com> Message-ID: To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Hi Lin, Thanks for the patch. 2018-05-04 10:08 GMT+02:00 Lin Huang : > DP firware use fix phy config value to do training, but some s/fiware/firmware/ > board need to adjust these value to fit for their hardware design, > so we use new phy config to do training outside firmware to meet > this situation, if there have new phy config pass from dts, it will > use training outside firmware. > maybe you can rewrite all this in a better way. ooi, which boards needs this? > Signed-off-by: Chris Zhong > Signed-off-by: Lin Huang > --- > drivers/gpu/drm/rockchip/Makefile | 3 +- > drivers/gpu/drm/rockchip/cdn-dp-core.c | 23 +- > drivers/gpu/drm/rockchip/cdn-dp-core.h | 2 + > drivers/gpu/drm/rockchip/cdn-dp-link-training.c | 398 ++++++++++++++++++++++++ > drivers/gpu/drm/rockchip/cdn-dp-reg.c | 33 +- > drivers/gpu/drm/rockchip/cdn-dp-reg.h | 38 ++- > 6 files changed, 480 insertions(+), 17 deletions(-) > create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-link-training.c > > diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile > index a314e21..b932f62 100644 > --- a/drivers/gpu/drm/rockchip/Makefile > +++ b/drivers/gpu/drm/rockchip/Makefile > @@ -9,7 +9,8 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ > rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o > > rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o > -rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o > +rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o \ > + cdn-dp-link-training.o > rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o > rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o > rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o > diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c > index 268c190..a2a4208 100644 > --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c > +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c > @@ -629,11 +629,13 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder) > goto out; > } > } > - > - ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE); > - if (ret) { > - DRM_DEV_ERROR(dp->dev, "Failed to idle video %d\n", ret); > - goto out; > + if (dp->sw_training_success == false) { > + ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE); > + if (ret) { > + DRM_DEV_ERROR(dp->dev, > + "Failed to idle video %d\n", ret); > + goto out; > + } > } > > ret = cdn_dp_config_video(dp); > @@ -642,11 +644,14 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder) > goto out; > } > > - ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID); > - if (ret) { > - DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret); > - goto out; > + if (dp->sw_training_success == false) { > + ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID); > + if (ret) { > + DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret); > + goto out; > + } > } > + > out: > mutex_unlock(&dp->lock); > } > diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h > index 46159b2..c6050ab 100644 > --- a/drivers/gpu/drm/rockchip/cdn-dp-core.h > +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h > @@ -84,6 +84,7 @@ struct cdn_dp_device { > bool connected; > bool active; > bool suspended; > + bool sw_training_success; > > const struct firmware *fw; /* cdn dp firmware */ > unsigned int fw_version; /* cdn fw version */ > @@ -106,6 +107,7 @@ struct cdn_dp_device { > u8 ports; > u8 lanes; > int active_port; > + u8 train_set[4]; > > u8 dpcd[DP_RECEIVER_CAP_SIZE]; > bool sink_has_audio; > diff --git a/drivers/gpu/drm/rockchip/cdn-dp-link-training.c b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c > new file mode 100644 > index 0000000..558c945 > --- /dev/null > +++ b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c > @@ -0,0 +1,398 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ For a C source file the format is: (https://www.kernel.org/doc/html/latest/process/license-rules.html) // SPDX-License-Identifier: > +/* > + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd > + * Author: Chris Zhong > + */ > + > +#include Why you need this include? > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + In fact, I think that there are other includes that can be removed, please review. > +#include "cdn-dp-core.h" > +#include "cdn-dp-reg.h" > + > +static void cdn_dp_set_signal_levels(struct cdn_dp_device *dp) > +{ > + struct cdn_dp_port *port = dp->port[dp->active_port]; > + struct rockchip_typec_phy *tcphy = phy_get_drvdata(port->phy); > + > + int rate = drm_dp_bw_code_to_link_rate(dp->link.rate); > + u8 swing = (dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) >> > + DP_TRAIN_VOLTAGE_SWING_SHIFT; > + u8 pre_emphasis = (dp->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) > + >> DP_TRAIN_PRE_EMPHASIS_SHIFT; > + > + tcphy->typec_phy_config(port->phy, rate, dp->link.num_lanes, > + swing, pre_emphasis); > +} > + > +static int cdn_dp_set_pattern(struct cdn_dp_device *dp, uint8_t dp_train_pat) > +{ > + u32 phy_config, global_config; > + int ret; > + uint8_t pattern = dp_train_pat & DP_TRAINING_PATTERN_MASK; > + > + global_config = NUM_LANES(dp->link.num_lanes - 1) | SST_MODE | > + GLOBAL_EN | RG_EN | ENC_RST_DIS | WR_VHSYNC_FALL; > + > + phy_config = DP_TX_PHY_ENCODER_BYPASS(0) | > + DP_TX_PHY_SKEW_BYPASS(0) | > + DP_TX_PHY_DISPARITY_RST(0) | > + DP_TX_PHY_LANE0_SKEW(0) | > + DP_TX_PHY_LANE1_SKEW(1) | > + DP_TX_PHY_LANE2_SKEW(2) | > + DP_TX_PHY_LANE3_SKEW(3) | > + DP_TX_PHY_10BIT_ENABLE(0); > + > + if (pattern != DP_TRAINING_PATTERN_DISABLE) { > + global_config |= NO_VIDEO; > + phy_config |= DP_TX_PHY_TRAINING_ENABLE(1) | > + DP_TX_PHY_SCRAMBLER_BYPASS(1) | > + DP_TX_PHY_TRAINING_PATTERN(pattern); > + } > + > + ret = cdn_dp_reg_write(dp, DP_FRAMER_GLOBAL_CONFIG, global_config); > + if (ret) { > + DRM_ERROR("fail to set DP_FRAMER_GLOBAL_CONFIG, error: %d\n", > + ret); > + return ret; > + } > + > + ret = cdn_dp_reg_write(dp, DP_TX_PHY_CONFIG_REG, phy_config); > + if (ret) { > + DRM_ERROR("fail to set DP_TX_PHY_CONFIG_REG, error: %d\n", > + ret); > + return ret; > + } > + > + ret = cdn_dp_reg_write(dp, DPTX_LANE_EN, BIT(dp->link.num_lanes) - 1); > + if (ret) { > + DRM_ERROR("fail to set DPTX_LANE_EN, error: %d\n", ret); > + return ret; > + } > + > + if (drm_dp_enhanced_frame_cap(dp->dpcd)) > + ret = cdn_dp_reg_write(dp, DPTX_ENHNCD, 1); > + else > + ret = cdn_dp_reg_write(dp, DPTX_ENHNCD, 0); > + if (ret) > + DRM_ERROR("failed to set DPTX_ENHNCD, error: %x\n", ret); > + > + return ret; > +} > + > +static u8 cdn_dp_pre_emphasis_max(u8 voltage_swing) > +{ > + switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: > + return DP_TRAIN_PRE_EMPH_LEVEL_3; > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: > + return DP_TRAIN_PRE_EMPH_LEVEL_2; > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: > + return DP_TRAIN_PRE_EMPH_LEVEL_1; > + default: > + return DP_TRAIN_PRE_EMPH_LEVEL_0; > + } > +} > + > +static void cdn_dp_get_adjust_train(struct cdn_dp_device *dp, > + uint8_t link_status[DP_LINK_STATUS_SIZE]) > +{ > + int i; > + uint8_t v = 0, p = 0; > + uint8_t preemph_max; > + > + for (i = 0; i < dp->link.num_lanes; i++) { > + v = max(v, drm_dp_get_adjust_request_voltage(link_status, i)); > + p = max(p, drm_dp_get_adjust_request_pre_emphasis(link_status, > + i)); > + } > + > + if (v >= VOLTAGE_LEVEL_2) > + v = VOLTAGE_LEVEL_2 | DP_TRAIN_MAX_SWING_REACHED; > + > + preemph_max = cdn_dp_pre_emphasis_max(v); > + if (p >= preemph_max) > + p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; > + > + for (i = 0; i < dp->link.num_lanes; i++) > + dp->train_set[i] = v | p; > +} > + > +/* > + * Pick training pattern for channel equalization. Training Pattern 3 for HBR2 > + * or 1.2 devices that support it, Training Pattern 2 otherwise. > + */ > +static u32 cdn_dp_select_chaneq_pattern(struct cdn_dp_device *dp) > +{ > + u32 training_pattern = DP_TRAINING_PATTERN_2; > + > + /* > + * cdn dp support HBR2 also support TPS3. TPS3 support is also mandatory > + * for downstream devices that support HBR2. However, not all sinks > + * follow the spec. > + */ > + if (drm_dp_tps3_supported(dp->dpcd)) > + training_pattern = DP_TRAINING_PATTERN_3; > + else > + DRM_DEBUG_KMS("5.4 Gbps link rate without sink TPS3 support\n"); > + > + return training_pattern; > +} > + > + > +static bool cdn_dp_link_max_vswing_reached(struct cdn_dp_device *dp) > +{ > + int lane; > + > + for (lane = 0; lane < dp->link.num_lanes; lane++) > + if ((dp->train_set[lane] & DP_TRAIN_MAX_SWING_REACHED) == 0) > + return false; > + > + return true; > +} > + > +static int cdn_dp_update_link_train(struct cdn_dp_device *dp) > +{ > + int ret; > + > + cdn_dp_set_signal_levels(dp); > + > + ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, > + dp->train_set, dp->link.num_lanes); > + if (ret != dp->link.num_lanes) > + return -EINVAL; > + > + return 0; > +} > + > +static int cdn_dp_set_link_train(struct cdn_dp_device *dp, > + uint8_t dp_train_pat) > +{ > + uint8_t buf[sizeof(dp->train_set) + 1]; > + int ret, len; > + > + buf[0] = dp_train_pat; > + if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) == > + DP_TRAINING_PATTERN_DISABLE) { > + /* don't write DP_TRAINING_LANEx_SET on disable */ > + len = 1; > + } else { > + /* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */ > + memcpy(buf + 1, dp->train_set, dp->link.num_lanes); > + len = dp->link.num_lanes + 1; > + } > + > + ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_PATTERN_SET, > + buf, len); > + if (ret != len) > + return -EINVAL; > + > + return 0; > +} > + > +static int cdn_dp_reset_link_train(struct cdn_dp_device *dp, > + uint8_t dp_train_pat) > +{ > + int ret; > + > + memset(dp->train_set, 0, sizeof(dp->train_set)); > + > + cdn_dp_set_signal_levels(dp); > + > + ret = cdn_dp_set_pattern(dp, dp_train_pat); > + if (ret) > + return ret; > + > + return cdn_dp_set_link_train(dp, dp_train_pat); > +} > + > +/* Enable corresponding port and start training pattern 1 */ > +static int cdn_dp_link_training_clock_recovery(struct cdn_dp_device *dp) > +{ > + u8 voltage, link_config[2]; > + u8 link_status[DP_LINK_STATUS_SIZE]; > + u32 voltage_tries, max_vswing_tries; > + u32 rate, sink_max, source_max; > + int ret; > + > + source_max = dp->lanes; > + sink_max = drm_dp_max_lane_count(dp->dpcd); > + dp->link.num_lanes = min(source_max, sink_max); > + > + source_max = drm_dp_bw_code_to_link_rate(CDN_DP_MAX_LINK_RATE); > + sink_max = drm_dp_max_link_rate(dp->dpcd); > + rate = min(source_max, sink_max); > + dp->link.rate = drm_dp_link_rate_to_bw_code(rate); > + > + /* Write the link configuration data */ > + link_config[0] = dp->link.rate; > + link_config[1] = dp->link.num_lanes; > + if (drm_dp_enhanced_frame_cap(dp->dpcd)) > + link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; > + drm_dp_dpcd_write(&dp->aux, DP_LINK_BW_SET, link_config, 2); > + > + link_config[0] = 0; > + link_config[1] = 0; > + if (dp->dpcd[DP_MAIN_LINK_CHANNEL_CODING] & 0x01) > + link_config[1] = DP_SET_ANSI_8B10B; > + > + drm_dp_dpcd_write(&dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2); > + > + /* clock recovery */ > + ret = cdn_dp_reset_link_train(dp, DP_TRAINING_PATTERN_1 | > + DP_LINK_SCRAMBLING_DISABLE); > + if (ret) { > + DRM_ERROR("failed to start link train\n"); > + return ret; > + } > + > + voltage_tries = 1; > + max_vswing_tries = 0; > + for (;;) { > + drm_dp_link_train_clock_recovery_delay(dp->dpcd); > + if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) != > + DP_LINK_STATUS_SIZE) { > + DRM_ERROR("failed to get link status\n"); > + return -EINVAL; > + } > + > + if (drm_dp_clock_recovery_ok(link_status, dp->link.num_lanes)) { > + DRM_DEBUG_KMS("clock recovery OK\n"); > + return 0; > + } > + > + if (voltage_tries >= 5) { > + DRM_DEBUG_KMS("Same voltage tried 5 times\n"); > + return -EINVAL; > + } > + > + if (max_vswing_tries >= 1) { > + DRM_DEBUG_KMS("Max Voltage Swing reached\n"); > + return -EINVAL; > + } > + > + voltage = dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; > + > + /* Update training set as requested by target */ > + cdn_dp_get_adjust_train(dp, link_status); > + if (cdn_dp_update_link_train(dp)) { > + DRM_ERROR("failed to update link training\n"); > + return -EINVAL; > + } > + > + if ((dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == > + voltage) > + ++voltage_tries; > + else > + voltage_tries = 1; > + > + if (cdn_dp_link_max_vswing_reached(dp)) > + ++max_vswing_tries; > + } > +} > + > +static int cdn_dp_link_training_channel_equalization(struct cdn_dp_device *dp) > +{ > + int tries, ret; > + u32 training_pattern; > + uint8_t link_status[DP_LINK_STATUS_SIZE]; > + > + training_pattern = cdn_dp_select_chaneq_pattern(dp); > + training_pattern |= DP_LINK_SCRAMBLING_DISABLE; > + > + ret = cdn_dp_set_pattern(dp, training_pattern); > + if (ret) > + return ret; > + > + ret = cdn_dp_set_link_train(dp, training_pattern); > + if (ret) { > + DRM_ERROR("failed to start channel equalization\n"); > + return ret; > + } > + > + for (tries = 0; tries < 5; tries++) { > + drm_dp_link_train_channel_eq_delay(dp->dpcd); > + if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) != > + DP_LINK_STATUS_SIZE) { > + DRM_ERROR("failed to get link status\n"); > + break; > + } > + > + /* Make sure clock is still ok */ > + if (!drm_dp_clock_recovery_ok(link_status, dp->link.num_lanes)) { > + DRM_DEBUG_KMS("Clock recovery check failed, cannot " > + "continue channel equalization\n"); > + break; > + } > + > + if (drm_dp_channel_eq_ok(link_status, dp->link.num_lanes)) { > + DRM_DEBUG_KMS("Channel EQ done. DP Training " > + "successful\n"); > + return 0; > + } > + > + /* Update training set as requested by target */ > + cdn_dp_get_adjust_train(dp, link_status); > + if (cdn_dp_update_link_train(dp)) { > + DRM_ERROR("failed to update link training\n"); > + break; > + } > + } > + > + /* Try 5 times, else fail and try at lower BW */ > + if (tries == 5) > + DRM_DEBUG_KMS("Channel equalization failed 5 times\n"); > + > + return -EINVAL; > + > +} > + > +static int cdn_dp_stop_link_train(struct cdn_dp_device *dp) > +{ > + int ret = cdn_dp_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE); > + > + if (ret) > + return ret; > + > + return cdn_dp_set_link_train(dp, DP_TRAINING_PATTERN_DISABLE); > +} > + > +int cdn_dp_software_train_link(struct cdn_dp_device *dp) > +{ > + int ret, stop_err; > + > + ret = drm_dp_dpcd_read(&dp->aux, DP_DPCD_REV, dp->dpcd, > + sizeof(dp->dpcd)); > + if (ret < 0) { > + DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret); > + return ret; > + } > + > + ret = cdn_dp_link_training_clock_recovery(dp); > + if (ret) { > + DRM_ERROR("training clock recovery fail, error: %d\n", ret); > + goto out; > + } > + > + ret = cdn_dp_link_training_channel_equalization(dp); > + if (ret) { > + DRM_ERROR("training channel equalization fail, error: %d\n", > + ret); > + goto out; > + } > +out: > + stop_err = cdn_dp_stop_link_train(dp); > + if (stop_err) { > + DRM_ERROR("stop training fail, error: %d\n", stop_err); > + return stop_err; > + } > + > + return ret; > +} > diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c > index b2f532a..72780f1 100644 > --- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c > +++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c > @@ -17,7 +17,9 @@ > #include > #include > #include > +#include > #include > +#include > > #include "cdn-dp-core.h" > #include "cdn-dp-reg.h" > @@ -189,7 +191,7 @@ static int cdn_dp_mailbox_send(struct cdn_dp_device *dp, u8 module_id, > return 0; > } > > -static int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val) > +int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val) > { > u8 msg[6]; > > @@ -605,22 +607,41 @@ static int cdn_dp_get_training_status(struct cdn_dp_device *dp) > int cdn_dp_train_link(struct cdn_dp_device *dp) > { > int ret; > + struct cdn_dp_port *port = dp->port[dp->active_port]; > + struct rockchip_typec_phy *tcphy = phy_get_drvdata(port->phy); > > + /* > + * DP firmware uses fixed phy config values to do training, but some > + * boards need to adjust these values to fit for their unique hardware > + * design. So if the phy is using custom config values, do software > + * link training instead of relying on firmware, if software training > + * fail, keep firmware training as a fallback if sw training fails. > + */ > + if (tcphy->need_software_training) { > + ret = cdn_dp_software_train_link(dp); > + if (ret) { > + DRM_DEV_ERROR(dp->dev, > + "Failed to do software training %d\n", ret); > + goto do_fw_training; > + } > + cdn_dp_reg_write(dp, SOURCE_HDTX_CAR, 0xf); Check for an error here and act accordingly? Or doesn't matter? > + dp->sw_training_success = true; > + return 0; > + } > + nit: Personally I don't like this goto. Maybe you can refactor this. if (tcphy->need_software_training) { ret = cdn_dp_software_train_link(dp); if (!ret) { cdn_dp_reg_write(dp, SOURCE_HDTX_CAR, 0xf); dp->sw_training_success = true; return 0; } DRM_DEV_ERROR(dp->dev, "Failed to do software training %d\n", ret); } > +do_fw_training: Then remove the goto label. > + dp->sw_training_success = false; > ret = cdn_dp_training_start(dp); > if (ret) { > DRM_DEV_ERROR(dp->dev, "Failed to start training %d\n", ret); > return ret; > } > - Do not remove the new line. > ret = cdn_dp_get_training_status(dp); > if (ret) { > DRM_DEV_ERROR(dp->dev, "Failed to get training stat %d\n", ret); > return ret; > } > - > - DRM_DEV_DEBUG_KMS(dp->dev, "rate:0x%x, lanes:%d\n", dp->link.rate, > - dp->link.num_lanes); Why you remove this debug message? > - return ret; > + return 0; > } > > int cdn_dp_set_video_status(struct cdn_dp_device *dp, int active) > diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h b/drivers/gpu/drm/rockchip/cdn-dp-reg.h > index aedf2dc..b60a6b2 100644 > --- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h > +++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h > @@ -137,7 +137,7 @@ > #define HPD_EVENT_MASK 0x211c > #define HPD_EVENT_DET 0x2120 > > -/* dpyx framer addr */ > +/* dptx framer addr */ > #define DP_FRAMER_GLOBAL_CONFIG 0x2200 > #define DP_SW_RESET 0x2204 > #define DP_FRAMER_TU 0x2208 > @@ -431,6 +431,40 @@ > /* Reference cycles when using lane clock as reference */ > #define LANE_REF_CYC 0x8000 > > +/* register CM_VID_CTRL */ > +#define LANE_VID_REF_CYC(x) (((x) & (BIT(24) - 1)) << 0) > +#define NMVID_MEAS_TOLERANCE(x) (((x) & 0xf) << 24) > + > +/* register DP_TX_PHY_CONFIG_REG */ > +#define DP_TX_PHY_TRAINING_ENABLE(x) ((x) & 1) > +#define DP_TX_PHY_TRAINING_TYPE_PRBS7 (0 << 1) > +#define DP_TX_PHY_TRAINING_TYPE_TPS1 (1 << 1) > +#define DP_TX_PHY_TRAINING_TYPE_TPS2 (2 << 1) > +#define DP_TX_PHY_TRAINING_TYPE_TPS3 (3 << 1) > +#define DP_TX_PHY_TRAINING_TYPE_TPS4 (4 << 1) > +#define DP_TX_PHY_TRAINING_TYPE_PLTPAT (5 << 1) > +#define DP_TX_PHY_TRAINING_TYPE_D10_2 (6 << 1) > +#define DP_TX_PHY_TRAINING_TYPE_HBR2CPAT (8 << 1) > +#define DP_TX_PHY_TRAINING_PATTERN(x) ((x) << 1) > +#define DP_TX_PHY_SCRAMBLER_BYPASS(x) (((x) & 1) << 5) > +#define DP_TX_PHY_ENCODER_BYPASS(x) (((x) & 1) << 6) > +#define DP_TX_PHY_SKEW_BYPASS(x) (((x) & 1) << 7) > +#define DP_TX_PHY_DISPARITY_RST(x) (((x) & 1) << 8) > +#define DP_TX_PHY_LANE0_SKEW(x) (((x) & 7) << 9) > +#define DP_TX_PHY_LANE1_SKEW(x) (((x) & 7) << 12) > +#define DP_TX_PHY_LANE2_SKEW(x) (((x) & 7) << 15) > +#define DP_TX_PHY_LANE3_SKEW(x) (((x) & 7) << 18) > +#define DP_TX_PHY_10BIT_ENABLE(x) (((x) & 1) << 21) > + > +/* register DP_FRAMER_GLOBAL_CONFIG */ > +#define NUM_LANES(x) ((x) & 3) > +#define SST_MODE (0 << 2) > +#define GLOBAL_EN (1 << 3) > +#define RG_EN (0 << 4) > +#define NO_VIDEO (1 << 5) > +#define ENC_RST_DIS (1 << 6) > +#define WR_VHSYNC_FALL (1 << 7) > + Use the BIT() macros for these. > enum voltage_swing_level { > VOLTAGE_LEVEL_0, > VOLTAGE_LEVEL_1, > @@ -476,6 +510,7 @@ int cdn_dp_set_host_cap(struct cdn_dp_device *dp, u8 lanes, bool flip); > int cdn_dp_event_config(struct cdn_dp_device *dp); > u32 cdn_dp_get_event(struct cdn_dp_device *dp); > int cdn_dp_get_hpd_status(struct cdn_dp_device *dp); > +int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val); > ssize_t cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, > u8 *data, u16 len); > ssize_t cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, > @@ -489,4 +524,5 @@ int cdn_dp_config_video(struct cdn_dp_device *dp); > int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio); > int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable); > int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio); > +int cdn_dp_software_train_link(struct cdn_dp_device *dp); > #endif /* _CDN_DP_REG_H */ > -- > 2.7.4 >