diff options
author | Petri Gynther <pgynther@google.com> | 2024-02-09 12:23:04 -0800 |
---|---|---|
committer | Petri Gynther <pgynther@google.com> | 2024-02-09 13:55:15 -0800 |
commit | 5fde3d56bd7507ea84affdf41b172f086faadc70 (patch) | |
tree | 956c7cbf16e18281d27154ec2ded3f0e8e28165d | |
parent | 2fad53a51fea745f744a22d0ef53cae2245a0df3 (diff) | |
download | display-5fde3d56bd7507ea84affdf41b172f086faadc70.tar.gz |
drm: samsung: handle USBDP PHY init failures
Handle unexpected timeout failures in:
dpphytca_reg_wait_mode_change()
dp_reg_wait_phy_pll_lock()
properly in dp_hw_init() and dp_hw_reinit().
Bug: 306144368
Signed-off-by: Petri Gynther <pgynther@google.com>
Change-Id: Ia69c2ac92df3320947806f99a54633dbec676fe0
-rw-r--r-- | samsung/cal_9855/dp_reg.c | 8 | ||||
-rw-r--r-- | samsung/cal_9865/dp_reg.c | 51 | ||||
-rw-r--r-- | samsung/cal_common/dp_cal.h | 4 | ||||
-rw-r--r-- | samsung/exynos_drm_dp.c | 31 |
4 files changed, 69 insertions, 25 deletions
diff --git a/samsung/cal_9855/dp_reg.c b/samsung/cal_9855/dp_reg.c index b940c61..fffbe3d 100644 --- a/samsung/cal_9855/dp_reg.c +++ b/samsung/cal_9855/dp_reg.c @@ -1530,7 +1530,7 @@ int dp_hw_read_edid(u8 block_cnt, u32 length, u8 *data) } /* DP Hardware Control Interfaces */ -void dp_hw_init(struct dp_hw_config *hw_config) +int dp_hw_init(struct dp_hw_config *hw_config) { cal_log_info(0, "DP Link Version = 0x%X\n", dp_reg_get_version()); @@ -1583,9 +1583,11 @@ void dp_hw_init(struct dp_hw_config *hw_config) /* Set Interrupts */ dp_hw_set_common_interrupt(1); cal_log_debug(0, "set interrupts\n"); + + return 0; } -void dp_hw_reinit(struct dp_hw_config *hw_config) +int dp_hw_reinit(struct dp_hw_config *hw_config) { /* Set system clock to OSC */ dp_reg_set_txclk_osc(); @@ -1619,6 +1621,8 @@ void dp_hw_reinit(struct dp_hw_config *hw_config) dp_reg_set_enhanced_mode(hw_config->enhanced_mode ? 1 : 0); dp_reg_set_sst1_video_func_en(1); cal_log_debug(0, "set sst function\n"); + + return 0; } void dp_hw_deinit(struct dp_hw_config *hw_config) diff --git a/samsung/cal_9865/dp_reg.c b/samsung/cal_9865/dp_reg.c index 8f179dd..0182370 100644 --- a/samsung/cal_9865/dp_reg.c +++ b/samsung/cal_9865/dp_reg.c @@ -179,7 +179,7 @@ static u32 audio_sync_m_n[2][4][7] = { */ /* USBDP PHY TCA Registers */ -static void dpphytca_reg_wait_mode_change(enum lane_usage lane) +static int dpphytca_reg_wait_mode_change(enum lane_usage lane) { unsigned int cnt = 0; unsigned int val = 0; @@ -202,9 +202,11 @@ static void dpphytca_reg_wait_mode_change(enum lane_usage lane) TCA_REG_TCA_INTR_STS)); cal_log_err(0, "Fail to change mode from USB to DP%d\n", lane); - } else - cal_log_debug(0, "Success to change mode from USB to DP%d\n", - lane); + return -ETIME; + } + + cal_log_debug(0, "Success to change mode from USB to DP%d\n", lane); + return 0; } static void dpphytca_reg_set_tcpc(u32 mux_control, u32 orientation, @@ -886,7 +888,7 @@ static enum lane_usage dp_get_and_inform_lanes(struct dp_hw_config *hw_config) return num_lane; } -static void dpphy_reg_switch_to_dp(enum lane_usage num_lane) +static int dpphy_reg_switch_to_dp(enum lane_usage num_lane) { u32 tcpc_mux_con = NO_CONNECTION, tcpc_orientation = NORMAL; u32 tcpc_low_pwr_en = STANDARD_OPERATION, tcpc_valid = VALID_I; @@ -908,7 +910,7 @@ static void dpphy_reg_switch_to_dp(enum lane_usage num_lane) cal_log_debug(0, "Start USB to DP%d\n", num_lane); dpphytca_reg_set_tcpc(tcpc_mux_con, tcpc_orientation, tcpc_low_pwr_en, tcpc_valid); - dpphytca_reg_wait_mode_change(num_lane); + return dpphytca_reg_wait_mode_change(num_lane); } static void dpphy_reg_set_lanes(struct dp_hw_config *hw_config, enum lane_usage num_lane) @@ -933,8 +935,9 @@ static void dpphy_reg_set_lanes(struct dp_hw_config *hw_config, enum lane_usage cal_log_debug(0, "enable %d lanes.\n", num_lane); } -static void dpphy_reg_init(struct dp_hw_config *hw_config, bool reconfig) +static int dpphy_reg_init(struct dp_hw_config *hw_config, bool reconfig) { + int ret; enum lane_usage num_lane = DP_USE_0_LANES; //dpphy_reg_usbdrd_qch_en(1); @@ -963,7 +966,9 @@ static void dpphy_reg_init(struct dp_hw_config *hw_config, bool reconfig) num_lane = dp_get_and_inform_lanes(hw_config); /* Switch from USB to DP */ - dpphy_reg_switch_to_dp(num_lane); + ret = dpphy_reg_switch_to_dp(num_lane); + if (ret) + return ret; cal_log_debug(0, "switch from USB to DP.\n"); /* Set DP TX lanes */ @@ -972,6 +977,8 @@ static void dpphy_reg_init(struct dp_hw_config *hw_config, bool reconfig) /* De-assert DP Alt-mode Disable ACK */ dpphy_reg_set_config19_dpalt_disable_ack(0); + + return 0; } /* @@ -2355,8 +2362,10 @@ int dp_hw_read_edid(u8 block_cnt, u32 length, u8 *data) } /* DP Hardware Control Interfaces */ -void dp_hw_init(struct dp_hw_config *hw_config) +int dp_hw_init(struct dp_hw_config *hw_config) { + int ret; + cal_log_debug(0, "DP Link Version = 0x%X\n", dp_reg_get_version()); /* Apply Soft Reset */ @@ -2376,11 +2385,15 @@ void dp_hw_init(struct dp_hw_config *hw_config) dwc3_exynos_phy_enable(1, 1); atomic_inc(&hw_config->usbdp_phy_en_cnt); - dpphy_reg_init(hw_config, false); + ret = dpphy_reg_init(hw_config, false); + if (ret) + return ret; cal_log_debug(0, "init USBDP Combo PHY\n"); /* Wait for PHY PLL Lock */ - dp_reg_wait_phy_pll_lock(); + ret = dp_reg_wait_phy_pll_lock(); + if (ret) + return ret; cal_log_debug(0, "locked PHY PLL\n"); /* Set system clock to TXCLK */ @@ -2412,21 +2425,29 @@ void dp_hw_init(struct dp_hw_config *hw_config) /* Set Interrupts */ dp_hw_set_common_interrupt(1); cal_log_debug(0, "set interrupts\n"); + + return 0; } -void dp_hw_reinit(struct dp_hw_config *hw_config) +int dp_hw_reinit(struct dp_hw_config *hw_config) { + int ret; + /* Set system clock to OSC */ dp_reg_set_txclk_osc(); cal_log_debug(0, "set system clk to OSC: Mux(%u)\n", dp_reg_get_gfmux_status()); /* USBDP PHY Re-initialization */ - dpphy_reg_init(hw_config, true); + ret = dpphy_reg_init(hw_config, true); + if (ret) + return ret; cal_log_debug(0, "reconfig USBDP Combo PHY\n"); /* Wait for PHY PLL Lock */ - dp_reg_wait_phy_pll_lock(); + ret = dp_reg_wait_phy_pll_lock(); + if (ret) + return ret; cal_log_debug(0, "locked PHY PLL\n"); /* Set system clock to TXCLK */ @@ -2448,6 +2469,8 @@ void dp_hw_reinit(struct dp_hw_config *hw_config) dp_reg_set_enhanced_mode(hw_config->enhanced_mode ? 1 : 0); dp_reg_set_sst1_video_func_en(1); cal_log_debug(0, "set sst function\n"); + + return 0; } void dp_hw_deinit(struct dp_hw_config *hw_config) diff --git a/samsung/cal_common/dp_cal.h b/samsung/cal_common/dp_cal.h index 225616e..37f82f6 100644 --- a/samsung/cal_common/dp_cal.h +++ b/samsung/cal_common/dp_cal.h @@ -317,8 +317,8 @@ int dp_hw_read_dpcd_burst(u32 address, u32 length, u8 *data); int dp_hw_read_edid(u8 block_cnt, u32 length, u8 *data); /* DP Hardware Control Interfaces */ -void dp_hw_init(struct dp_hw_config *hw_config); -void dp_hw_reinit(struct dp_hw_config *hw_config); +int dp_hw_init(struct dp_hw_config *hw_config); +int dp_hw_reinit(struct dp_hw_config *hw_config); void dp_hw_deinit(struct dp_hw_config *hw_config); void dp_hw_start(void); void dp_hw_stop(void); diff --git a/samsung/exynos_drm_dp.c b/samsung/exynos_drm_dp.c index 1ff6623..02d5e01 100644 --- a/samsung/exynos_drm_dp.c +++ b/samsung/exynos_drm_dp.c @@ -571,8 +571,10 @@ static int dp_link_configure(struct dp_device *dp) return 0; } -static void dp_init_link_training_cr(struct dp_device *dp) +static int dp_init_link_training_cr(struct dp_device *dp) { + int ret; + /* Disable DP Training Pattern */ drm_dp_dpcd_writeb(&dp->dp_aux, DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE); @@ -580,7 +582,12 @@ static void dp_init_link_training_cr(struct dp_device *dp) /* Reconfigure DP HW */ dp_set_hwconfig_dplink(dp); dp_set_hwconfig_video(dp); - dp_hw_reinit(&dp->hw_config); + ret = dp_hw_reinit(&dp->hw_config); + if (ret) { + dp_err(dp, "dp_hw_reinit() failed\n"); + return ret; + } + dp_info(dp, "HW configured with Rate(%d) and Lanes(%u)\n", dp->hw_config.link_rate, dp->hw_config.num_lanes); @@ -597,6 +604,8 @@ static void dp_init_link_training_cr(struct dp_device *dp) /* Enable DP Training Pattern */ drm_dp_dpcd_writeb(&dp->dp_aux, DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_1 | DP_LINK_SCRAMBLING_DISABLE); + + return 0; } static bool dp_do_link_training_cr(struct dp_device *dp, u32 interval_us) @@ -621,7 +630,8 @@ static bool dp_do_link_training_cr(struct dp_device *dp, u32 interval_us) max_reach_value[i] = 0; } - dp_init_link_training_cr(dp); + if (dp_init_link_training_cr(dp)) + goto err; // Voltage Swing do { @@ -914,9 +924,12 @@ static int dp_link_up(struct dp_device *dp) dp_set_hwconfig_video(dp); dp->hw_config.dp_emul = true; - dp_hw_reinit(&dp->hw_config); - dp_info(dp, "HW configured with Rate(%d) and Lanes(%u)\n", - dp->hw_config.link_rate, dp->hw_config.num_lanes); + if (!dp_hw_reinit(&dp->hw_config)) { + dp_info(dp, "HW configured with Rate(%d) and Lanes(%u)\n", + dp->hw_config.link_rate, dp->hw_config.num_lanes); + } else { + dp_err(dp, "dp_hw_reinit() failed\n"); + } mutex_unlock(&dp->training_lock); return 0; @@ -1724,7 +1737,11 @@ static void dp_work_hpd(struct work_struct *work) /* PHY power on */ usleep_range(10000, 10030); - dp_hw_init(&dp->hw_config); /* for AUX ch read/write. */ + ret = dp_hw_init(&dp->hw_config); /* for AUX ch read/write. */ + if (ret) { + dp_err(dp, "dp_hw_init() failed\n"); + goto HPD_FAIL; + } usleep_range(10000, 11000); ret = dp_link_up(dp); |