Loading drivers/gpu/drm/msm/dp/dp_aux.c +6 −5 Original line number Diff line number Diff line Loading @@ -131,13 +131,14 @@ static int dp_aux_cmd_fifo_tx(struct dp_aux_private *aux, return -ETIMEDOUT; } pr_debug("aux status %s\n", if (aux->aux_error_num == DP_AUX_ERR_NONE) { ret = len; } else { pr_err_ratelimited("aux err: %s\n", dp_aux_get_error(aux->aux_error_num)); if (aux->aux_error_num == DP_AUX_ERR_NONE) ret = len; else ret = -EINVAL; } return ret; } Loading drivers/gpu/drm/msm/dp/dp_catalog.c +20 −10 Original line number Diff line number Diff line Loading @@ -471,6 +471,8 @@ static void dp_catalog_ctrl_config_ctrl(struct dp_catalog_ctrl *ctrl, u32 cfg) dp_catalog_get_priv(ctrl); base = catalog->io->ctrl_io.base; pr_debug("DP_CONFIGURATION_CTRL=0x%x\n", cfg); dp_write(base + DP_CONFIGURATION_CTRL, cfg); dp_write(base + DP_MAINLINK_LEVELS, 0xa08); dp_write(base + MMSS_DP_ASYNC_FIFO_CONFIG, 0x1); Loading Loading @@ -507,10 +509,7 @@ static void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog_ctrl *ctrl, dp_catalog_get_priv(ctrl); base = catalog->io->ctrl_io.base; mainlink_ctrl = dp_read(base + DP_MAINLINK_CTRL); if (enable) { mainlink_ctrl |= BIT(0); dp_write(base + DP_MAINLINK_CTRL, 0x02000000); wmb(); /* make sure mainlink is turned off before reset */ dp_write(base + DP_MAINLINK_CTRL, 0x02000002); Loading @@ -520,8 +519,9 @@ static void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog_ctrl *ctrl, dp_write(base + DP_MAINLINK_CTRL, 0x02000001); wmb(); /* make sure mainlink turned on */ } else { mainlink_ctrl = dp_read(base + DP_MAINLINK_CTRL); mainlink_ctrl &= ~BIT(0); dp_write(base + DP_MAINLINK_CTRL, 0x0); dp_write(base + DP_MAINLINK_CTRL, mainlink_ctrl); } } Loading @@ -543,14 +543,16 @@ static void dp_catalog_ctrl_config_misc(struct dp_catalog_ctrl *ctrl, misc_val |= (tb << 5); misc_val |= BIT(0); /* Configure clock to synchronous mode */ pr_debug("isc settings = 0x%x\n", misc_val); pr_debug("misc settings = 0x%x\n", misc_val); dp_write(base + DP_MISC1_MISC0, misc_val); } static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl) static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl, u32 rate) { u32 pixel_m, pixel_n; u32 mvid, nvid; u32 const link_rate = 540000; struct dp_catalog_private *catalog; void __iomem *base_cc, *base_ctrl; Loading @@ -570,6 +572,11 @@ static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl) mvid = (pixel_m & 0xFFFF) * 5; nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF); pr_debug("rate = %d\n", rate); if (link_rate == rate) nvid *= 2; pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid); dp_write(base_ctrl + DP_SOFTWARE_MVID, mvid); dp_write(base_ctrl + DP_SOFTWARE_NVID, nvid); Loading @@ -593,7 +600,7 @@ static void dp_catalog_ctrl_set_pattern(struct dp_catalog_ctrl *ctrl, bit = 1; bit <<= (pattern - 1); pr_debug("bit=%d train=%d\n", bit, pattern); pr_debug("hw: bit=%d train=%d\n", bit, pattern); dp_write(base + DP_STATE_CTRL, bit); bit = 8; Loading Loading @@ -792,7 +799,7 @@ static void dp_catalog_ctrl_update_vx_px(struct dp_catalog_ctrl *ctrl, base0 = catalog->io->ln_tx0_io.base; base1 = catalog->io->ln_tx1_io.base; pr_debug("v=%d p=%d\n", v_level, p_level); pr_debug("hw: v=%d p=%d\n", v_level, p_level); value0 = vm_voltage_swing[v_level][p_level]; value1 = vm_pre_emphasis[v_level][p_level]; Loading @@ -814,8 +821,11 @@ static void dp_catalog_ctrl_update_vx_px(struct dp_catalog_ctrl *ctrl, dp_write(base0 + TXn_TX_EMP_POST1_LVL, value1); dp_write(base1 + TXn_TX_EMP_POST1_LVL, value1); pr_debug("host PHY settings: value0=0x%x value1=0x%x", pr_debug("hw: vx_value=0x%x px_value=0x%x\n", value0, value1); } else { pr_err("invalid vx (0x%x=0x%x), px (0x%x=0x%x\n", v_level, value0, p_level, value1); } } Loading drivers/gpu/drm/msm/dp/dp_catalog.h +1 −1 Original line number Diff line number Diff line Loading @@ -58,7 +58,7 @@ struct dp_catalog_ctrl { void (*lane_mapping)(struct dp_catalog_ctrl *ctrl); void (*mainlink_ctrl)(struct dp_catalog_ctrl *ctrl, bool enable); void (*config_misc)(struct dp_catalog_ctrl *ctrl, u32 cc, u32 tb); void (*config_msa)(struct dp_catalog_ctrl *ctrl); void (*config_msa)(struct dp_catalog_ctrl *ctrl, u32 rate); void (*set_pattern)(struct dp_catalog_ctrl *ctrl, u32 pattern); void (*reset)(struct dp_catalog_ctrl *ctrl); bool (*mainlink_ready)(struct dp_catalog_ctrl *ctrl); Loading drivers/gpu/drm/msm/dp/dp_ctrl.c +143 −89 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ struct dp_ctrl_private { bool psm_enabled; bool orientation; atomic_t aborted; u32 pixel_rate; u32 vic; Loading @@ -92,6 +93,20 @@ static void dp_ctrl_video_ready(struct dp_ctrl_private *ctrl) complete(&ctrl->video_comp); } static void dp_ctrl_abort(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; if (!dp_ctrl) { pr_err("Invalid input data\n"); return; } ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); atomic_set(&ctrl->aborted, 1); } static void dp_ctrl_state_ctrl(struct dp_ctrl_private *ctrl, u32 state) { ctrl->catalog->state_ctrl(ctrl->catalog, state); Loading @@ -109,8 +124,6 @@ static void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl) ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); drm_dp_link_power_down(ctrl->aux->drm_aux, &ctrl->panel->dp_link); reinit_completion(&ctrl->idle_comp); dp_ctrl_state_ctrl(ctrl, ST_PUSH_IDLE); Loading @@ -135,6 +148,10 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl) tbd = ctrl->link->get_test_bits_depth(ctrl->link, ctrl->panel->pinfo.bpp); if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN) tbd = DP_TEST_BIT_DEPTH_8; config |= tbd << 8; /* Num of Lanes */ Loading Loading @@ -170,9 +187,6 @@ static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl) ctrl->panel->pinfo.bpp); cc = ctrl->link->get_colorimetry_config(ctrl->link); ctrl->catalog->config_misc(ctrl->catalog, cc, tb); ctrl->catalog->config_msa(ctrl->catalog); ctrl->panel->timing_cfg(ctrl->panel); } Loading Loading @@ -226,7 +240,7 @@ static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl, { u32 const multiplier = 1000000; u64 pclk, lclk; u8 bpp, ln_cnt, link_rate; u8 bpp, ln_cnt; int run_idx = 0; u32 lwidth, h_blank; u32 fifo_empty = 0; Loading Loading @@ -289,7 +303,6 @@ static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl, u64 brute_force_threshold = 10; u64 diff_abs; link_rate = ctrl->link->link_rate; ln_cnt = ctrl->link->lane_count; bpp = pinfo->bpp; Loading @@ -309,7 +322,7 @@ static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl, even_distribution = 0; min_hblank = 0; lclk = drm_dp_bw_code_to_link_rate(link_rate) * DP_KHZ_TO_HZ; lclk = drm_dp_bw_code_to_link_rate(ctrl->link->bw_code) * DP_KHZ_TO_HZ; pr_debug("pclk=%lld, active_width=%d, h_blank=%d\n", pclk, lwidth, h_blank); Loading Loading @@ -734,14 +747,12 @@ static int dp_ctrl_update_sink_vx_px(struct dp_ctrl_private *ctrl, max_level_reached |= BIT(5); } pr_debug("max_level_reached = 0x%x\n", max_level_reached); pre_emphasis_level <<= 3; for (i = 0; i < 4; i++) buf[i] = voltage_level | pre_emphasis_level | max_level_reached; pr_debug("p|v=0x%x\n", voltage_level | pre_emphasis_level); pr_debug("sink: p|v=0x%x\n", voltage_level | pre_emphasis_level); return drm_dp_dpcd_write(ctrl->aux->drm_aux, 0x103, buf, 4); } Loading @@ -749,8 +760,6 @@ static void dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl) { struct dp_link *link = ctrl->link; pr_debug("v=%d p=%d\n", link->v_level, link->p_level); ctrl->catalog->update_vx_px(ctrl->catalog, link->v_level, link->p_level); Loading @@ -762,15 +771,38 @@ static void dp_ctrl_train_pattern_set(struct dp_ctrl_private *ctrl, { u8 buf[4]; pr_debug("pattern=%x\n", pattern); pr_debug("sink: pattern=%x\n", pattern); buf[0] = pattern; drm_dp_dpcd_write(ctrl->aux->drm_aux, DP_TRAINING_PATTERN_SET, buf, 1); } static int dp_ctrl_read_link_status(struct dp_ctrl_private *ctrl, u8 *link_status) { int ret = 0, len; u32 const offset = DP_LANE_ALIGN_STATUS_UPDATED - DP_LANE0_1_STATUS; u32 link_status_read_max_retries = 100; while (--link_status_read_max_retries) { len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux, link_status); if (len != DP_LINK_STATUS_SIZE) { pr_err("DP link status read failed, err: %d\n", len); ret = len; break; } if (!(link_status[offset] & DP_LINK_STATUS_UPDATED)) break; } return ret; } static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) { int tries, old_v_level, ret = 0, len = 0; int tries, old_v_level, ret = 0; u8 link_status[DP_LINK_STATUS_SIZE]; int const maximum_retries = 5; Loading @@ -780,7 +812,7 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) ctrl->catalog->set_pattern(ctrl->catalog, 0x01); dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 | DP_RECOVERED_CLOCK_OUT_EN); /* train_1 */ DP_LINK_SCRAMBLING_DISABLE); /* train_1 */ dp_ctrl_update_vx_px(ctrl); tries = 0; Loading @@ -788,36 +820,35 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) while (1) { drm_dp_link_train_clock_recovery_delay(ctrl->panel->dpcd); len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux, link_status); if (len < DP_LINK_STATUS_SIZE) { pr_err("[%s]: DP link status read failed\n", __func__); ret = -1; ret = dp_ctrl_read_link_status(ctrl, link_status); if (ret) break; } if (drm_dp_clock_recovery_ok(link_status, ctrl->link->lane_count)) { ret = 0; break; } if (ctrl->link->v_level == DP_LINK_VOLTAGE_MAX) { ret = -1; break; /* quit */ pr_err_ratelimited("max v_level reached\n"); ret = -EAGAIN; break; } if (old_v_level == ctrl->link->v_level) { tries++; if (tries >= maximum_retries) { ret = -1; break; /* quit */ pr_err("max tries reached\n"); ret = -EAGAIN; break; } } else { tries = 0; old_v_level = ctrl->link->v_level; } pr_debug("clock recovery not done, adjusting vx px\n"); ctrl->link->adjust_levels(ctrl->link, link_status); dp_ctrl_update_vx_px(ctrl); } Loading @@ -828,27 +859,41 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) static int dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl) { int ret = 0; u32 min_req_link_rate_khz; u32 new_proposed_link_bw_code; u32 new_proposed_link_rate_khz; if (!ctrl) return -EINVAL; switch (ctrl->link->link_rate) { min_req_link_rate_khz = ctrl->panel->get_min_req_link_rate(ctrl->panel); switch (ctrl->link->bw_code) { case DP_LINK_RATE_810: ctrl->link->link_rate = DP_LINK_BW_5_4; new_proposed_link_bw_code = DP_LINK_BW_5_4; break; case DP_LINK_BW_5_4: ctrl->link->link_rate = DP_LINK_BW_2_7; new_proposed_link_bw_code = DP_LINK_BW_2_7; break; case DP_LINK_BW_2_7: ctrl->link->link_rate = DP_LINK_BW_1_62; break; case DP_LINK_BW_1_62: default: ret = -EINVAL; new_proposed_link_bw_code = DP_LINK_BW_1_62; break; }; pr_debug("new rate=%d\n", ctrl->link->link_rate); new_proposed_link_rate_khz = drm_dp_bw_code_to_link_rate( new_proposed_link_bw_code); pr_debug("new proposed link rate=%d khz\n", new_proposed_link_rate_khz); pr_debug("min required link rate=%d khz\n", min_req_link_rate_khz); if (new_proposed_link_rate_khz >= min_req_link_rate_khz) ctrl->link->bw_code = new_proposed_link_bw_code; else pr_debug("can't go below min required link rate\n"); pr_debug("new bw code=0x%x\n", ctrl->link->bw_code); return ret; } Loading @@ -861,11 +906,15 @@ static void dp_ctrl_clear_training_pattern(struct dp_ctrl_private *ctrl) static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl) { int tries = 0, ret = 0, len = 0; int tries = 0, ret = 0; char pattern; int const maximum_retries = 5; u8 link_status[DP_LINK_STATUS_SIZE]; dp_ctrl_state_ctrl(ctrl, 0); /* Make sure to clear the current pattern before starting a new one */ wmb(); if (drm_dp_tps3_supported(ctrl->panel->dpcd)) pattern = DP_TRAINING_PATTERN_3; else Loading @@ -878,21 +927,15 @@ static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl) do { drm_dp_link_train_channel_eq_delay(ctrl->panel->dpcd); len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux, link_status); if (len < DP_LINK_STATUS_SIZE) { pr_err("[%s]: DP link status read failed\n", __func__); ret = -1; ret = dp_ctrl_read_link_status(ctrl, link_status); if (ret) break; } if (drm_dp_channel_eq_ok(link_status, ctrl->link->lane_count)) { ret = 0; if (drm_dp_channel_eq_ok(link_status, ctrl->link->lane_count)) break; } if (tries > maximum_retries) { ret = -1; ret = -EAGAIN; break; } tries++; Loading @@ -907,61 +950,45 @@ static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl) static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl) { int ret = 0; struct drm_dp_link dp_link; u8 encoding = 0x1; struct drm_dp_link link_info = {0}; ctrl->link->p_level = 0; ctrl->link->v_level = 0; dp_ctrl_config_ctrl(ctrl); dp_ctrl_state_ctrl(ctrl, 0); dp_link.num_lanes = ctrl->link->lane_count; dp_link.rate = ctrl->link->link_rate; dp_link.capabilities = ctrl->panel->dp_link.capabilities; drm_dp_link_configure(ctrl->aux->drm_aux, &dp_link); link_info.num_lanes = ctrl->link->lane_count; link_info.rate = drm_dp_bw_code_to_link_rate(ctrl->link->bw_code); link_info.capabilities = ctrl->panel->link_info.capabilities; ret = dp_ctrl_link_train_1(ctrl); if (ret < 0) { if (!dp_ctrl_link_rate_down_shift(ctrl)) { pr_debug("retry with lower rate\n"); dp_ctrl_clear_training_pattern(ctrl); return -EAGAIN; } drm_dp_link_configure(ctrl->aux->drm_aux, &link_info); drm_dp_dpcd_write(ctrl->aux->drm_aux, DP_MAIN_LINK_CHANNEL_CODING_SET, &encoding, 1); pr_err("Training 1 failed\n"); ret = -EINVAL; goto clear; ret = dp_ctrl_link_train_1(ctrl); if (ret) { pr_err("link training #1 failed\n"); goto end; } pr_debug("Training 1 completed successfully\n"); dp_ctrl_state_ctrl(ctrl, 0); /* Make sure to clear the current pattern before starting a new one */ wmb(); /* print success info as this is a result of user initiated action */ pr_info("link training #1 successful\n"); ret = dp_ctrl_link_training_2(ctrl); if (ret < 0) { if (!dp_ctrl_link_rate_down_shift(ctrl)) { pr_debug("retry with lower rate\n"); dp_ctrl_clear_training_pattern(ctrl); return -EAGAIN; } pr_err("Training 2 failed\n"); ret = -EINVAL; goto clear; if (ret) { pr_err("link training #2 failed\n"); goto end; } pr_debug("Training 2 completed successfully\n"); /* print success info as this is a result of user initiated action */ pr_debug("link training #2 successful\n"); end: dp_ctrl_state_ctrl(ctrl, 0); /* Make sure to clear the current pattern before starting a new one */ wmb(); clear: dp_ctrl_clear_training_pattern(ctrl); return ret; } Loading @@ -973,7 +1000,7 @@ static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl, bool train) ctrl->catalog->mainlink_ctrl(ctrl->catalog, true); drm_dp_link_power_up(ctrl->aux->drm_aux, &ctrl->panel->dp_link); drm_dp_link_power_up(ctrl->aux->drm_aux, &ctrl->panel->link_info); if (ctrl->link->phy_pattern_requested(ctrl->link)) goto end; Loading Loading @@ -1018,6 +1045,8 @@ static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl, cfg++; } pr_debug("setting rate=%d on clk=%s\n", rate, name); if (num) cfg->rate = rate; else Loading @@ -1031,7 +1060,7 @@ static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) ctrl->power->set_pixel_clk_parent(ctrl->power); dp_ctrl_set_clock_rate(ctrl, "ctrl_link_clk", drm_dp_bw_code_to_link_rate(ctrl->link->link_rate)); drm_dp_bw_code_to_link_rate(ctrl->link->bw_code)); dp_ctrl_set_clock_rate(ctrl, "ctrl_pixel_clk", ctrl->pixel_rate); Loading Loading @@ -1128,6 +1157,9 @@ static int dp_ctrl_on_irq(struct dp_ctrl_private *ctrl, bool lt_needed) dp_ctrl_configure_source_params(ctrl); ctrl->catalog->config_msa(ctrl->catalog, drm_dp_bw_code_to_link_rate(ctrl->link->bw_code)); reinit_completion(&ctrl->idle_comp); if (ctrl->psm_enabled) { Loading @@ -1148,16 +1180,20 @@ static int dp_ctrl_on_irq(struct dp_ctrl_private *ctrl, bool lt_needed) static int dp_ctrl_on_hpd(struct dp_ctrl_private *ctrl) { int ret = 0; u32 rate = ctrl->panel->link_info.rate; u32 link_train_max_retries = 100; atomic_set(&ctrl->aborted, 0); ctrl->power->clk_enable(ctrl->power, DP_CORE_PM, true); ctrl->catalog->hpd_config(ctrl->catalog, true); ctrl->link->link_rate = ctrl->panel->get_link_rate(ctrl->panel); ctrl->link->lane_count = ctrl->panel->dp_link.num_lanes; ctrl->link->bw_code = drm_dp_link_rate_to_bw_code(rate); ctrl->link->lane_count = ctrl->panel->link_info.num_lanes; ctrl->pixel_rate = ctrl->panel->pinfo.pixel_clk_khz; pr_debug("link_rate=%d, lane_count=%d, pixel_rate=%d\n", ctrl->link->link_rate, ctrl->link->lane_count, pr_debug("bw_code=%d, lane_count=%d, pixel_rate=%d\n", ctrl->link->bw_code, ctrl->link->lane_count, ctrl->pixel_rate); ctrl->catalog->phy_lane_cfg(ctrl->catalog, Loading @@ -1174,8 +1210,25 @@ static int dp_ctrl_on_hpd(struct dp_ctrl_private *ctrl) if (ctrl->psm_enabled) ret = ctrl->link->send_psm_request(ctrl->link, false); while (-EAGAIN == dp_ctrl_setup_main_link(ctrl, true)) pr_debug("MAIN LINK TRAINING RETRY\n"); while (--link_train_max_retries && !atomic_read(&ctrl->aborted)) { ctrl->catalog->config_msa(ctrl->catalog, drm_dp_bw_code_to_link_rate(ctrl->link->bw_code)); ret = dp_ctrl_setup_main_link(ctrl, true); if (!ret) break; /* try with lower link rate */ dp_ctrl_link_rate_down_shift(ctrl); ctrl->catalog->mainlink_ctrl(ctrl->catalog, false); dp_ctrl_disable_mainlink_clocks(ctrl); /* hw recommended delay before re-enabling clocks */ msleep(20); dp_ctrl_enable_mainlink_clocks(ctrl); } pr_debug("End-\n"); Loading Loading @@ -1292,6 +1345,7 @@ struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in) dp_ctrl->on = dp_ctrl_on; dp_ctrl->off = dp_ctrl_off; dp_ctrl->push_idle = dp_ctrl_push_idle; dp_ctrl->abort = dp_ctrl_abort; dp_ctrl->isr = dp_ctrl_isr; return dp_ctrl; Loading drivers/gpu/drm/msm/dp/dp_ctrl.h +1 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ struct dp_ctrl { int (*on)(struct dp_ctrl *dp_ctrl, bool hpd_irq); void (*off)(struct dp_ctrl *dp_ctrl, bool hpd_irq); void (*push_idle)(struct dp_ctrl *dp_ctrl); void (*abort)(struct dp_ctrl *dp_ctrl); void (*isr)(struct dp_ctrl *dp_ctrl); }; Loading Loading
drivers/gpu/drm/msm/dp/dp_aux.c +6 −5 Original line number Diff line number Diff line Loading @@ -131,13 +131,14 @@ static int dp_aux_cmd_fifo_tx(struct dp_aux_private *aux, return -ETIMEDOUT; } pr_debug("aux status %s\n", if (aux->aux_error_num == DP_AUX_ERR_NONE) { ret = len; } else { pr_err_ratelimited("aux err: %s\n", dp_aux_get_error(aux->aux_error_num)); if (aux->aux_error_num == DP_AUX_ERR_NONE) ret = len; else ret = -EINVAL; } return ret; } Loading
drivers/gpu/drm/msm/dp/dp_catalog.c +20 −10 Original line number Diff line number Diff line Loading @@ -471,6 +471,8 @@ static void dp_catalog_ctrl_config_ctrl(struct dp_catalog_ctrl *ctrl, u32 cfg) dp_catalog_get_priv(ctrl); base = catalog->io->ctrl_io.base; pr_debug("DP_CONFIGURATION_CTRL=0x%x\n", cfg); dp_write(base + DP_CONFIGURATION_CTRL, cfg); dp_write(base + DP_MAINLINK_LEVELS, 0xa08); dp_write(base + MMSS_DP_ASYNC_FIFO_CONFIG, 0x1); Loading Loading @@ -507,10 +509,7 @@ static void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog_ctrl *ctrl, dp_catalog_get_priv(ctrl); base = catalog->io->ctrl_io.base; mainlink_ctrl = dp_read(base + DP_MAINLINK_CTRL); if (enable) { mainlink_ctrl |= BIT(0); dp_write(base + DP_MAINLINK_CTRL, 0x02000000); wmb(); /* make sure mainlink is turned off before reset */ dp_write(base + DP_MAINLINK_CTRL, 0x02000002); Loading @@ -520,8 +519,9 @@ static void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog_ctrl *ctrl, dp_write(base + DP_MAINLINK_CTRL, 0x02000001); wmb(); /* make sure mainlink turned on */ } else { mainlink_ctrl = dp_read(base + DP_MAINLINK_CTRL); mainlink_ctrl &= ~BIT(0); dp_write(base + DP_MAINLINK_CTRL, 0x0); dp_write(base + DP_MAINLINK_CTRL, mainlink_ctrl); } } Loading @@ -543,14 +543,16 @@ static void dp_catalog_ctrl_config_misc(struct dp_catalog_ctrl *ctrl, misc_val |= (tb << 5); misc_val |= BIT(0); /* Configure clock to synchronous mode */ pr_debug("isc settings = 0x%x\n", misc_val); pr_debug("misc settings = 0x%x\n", misc_val); dp_write(base + DP_MISC1_MISC0, misc_val); } static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl) static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl, u32 rate) { u32 pixel_m, pixel_n; u32 mvid, nvid; u32 const link_rate = 540000; struct dp_catalog_private *catalog; void __iomem *base_cc, *base_ctrl; Loading @@ -570,6 +572,11 @@ static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl) mvid = (pixel_m & 0xFFFF) * 5; nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF); pr_debug("rate = %d\n", rate); if (link_rate == rate) nvid *= 2; pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid); dp_write(base_ctrl + DP_SOFTWARE_MVID, mvid); dp_write(base_ctrl + DP_SOFTWARE_NVID, nvid); Loading @@ -593,7 +600,7 @@ static void dp_catalog_ctrl_set_pattern(struct dp_catalog_ctrl *ctrl, bit = 1; bit <<= (pattern - 1); pr_debug("bit=%d train=%d\n", bit, pattern); pr_debug("hw: bit=%d train=%d\n", bit, pattern); dp_write(base + DP_STATE_CTRL, bit); bit = 8; Loading Loading @@ -792,7 +799,7 @@ static void dp_catalog_ctrl_update_vx_px(struct dp_catalog_ctrl *ctrl, base0 = catalog->io->ln_tx0_io.base; base1 = catalog->io->ln_tx1_io.base; pr_debug("v=%d p=%d\n", v_level, p_level); pr_debug("hw: v=%d p=%d\n", v_level, p_level); value0 = vm_voltage_swing[v_level][p_level]; value1 = vm_pre_emphasis[v_level][p_level]; Loading @@ -814,8 +821,11 @@ static void dp_catalog_ctrl_update_vx_px(struct dp_catalog_ctrl *ctrl, dp_write(base0 + TXn_TX_EMP_POST1_LVL, value1); dp_write(base1 + TXn_TX_EMP_POST1_LVL, value1); pr_debug("host PHY settings: value0=0x%x value1=0x%x", pr_debug("hw: vx_value=0x%x px_value=0x%x\n", value0, value1); } else { pr_err("invalid vx (0x%x=0x%x), px (0x%x=0x%x\n", v_level, value0, p_level, value1); } } Loading
drivers/gpu/drm/msm/dp/dp_catalog.h +1 −1 Original line number Diff line number Diff line Loading @@ -58,7 +58,7 @@ struct dp_catalog_ctrl { void (*lane_mapping)(struct dp_catalog_ctrl *ctrl); void (*mainlink_ctrl)(struct dp_catalog_ctrl *ctrl, bool enable); void (*config_misc)(struct dp_catalog_ctrl *ctrl, u32 cc, u32 tb); void (*config_msa)(struct dp_catalog_ctrl *ctrl); void (*config_msa)(struct dp_catalog_ctrl *ctrl, u32 rate); void (*set_pattern)(struct dp_catalog_ctrl *ctrl, u32 pattern); void (*reset)(struct dp_catalog_ctrl *ctrl); bool (*mainlink_ready)(struct dp_catalog_ctrl *ctrl); Loading
drivers/gpu/drm/msm/dp/dp_ctrl.c +143 −89 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ struct dp_ctrl_private { bool psm_enabled; bool orientation; atomic_t aborted; u32 pixel_rate; u32 vic; Loading @@ -92,6 +93,20 @@ static void dp_ctrl_video_ready(struct dp_ctrl_private *ctrl) complete(&ctrl->video_comp); } static void dp_ctrl_abort(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; if (!dp_ctrl) { pr_err("Invalid input data\n"); return; } ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); atomic_set(&ctrl->aborted, 1); } static void dp_ctrl_state_ctrl(struct dp_ctrl_private *ctrl, u32 state) { ctrl->catalog->state_ctrl(ctrl->catalog, state); Loading @@ -109,8 +124,6 @@ static void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl) ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); drm_dp_link_power_down(ctrl->aux->drm_aux, &ctrl->panel->dp_link); reinit_completion(&ctrl->idle_comp); dp_ctrl_state_ctrl(ctrl, ST_PUSH_IDLE); Loading @@ -135,6 +148,10 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl) tbd = ctrl->link->get_test_bits_depth(ctrl->link, ctrl->panel->pinfo.bpp); if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN) tbd = DP_TEST_BIT_DEPTH_8; config |= tbd << 8; /* Num of Lanes */ Loading Loading @@ -170,9 +187,6 @@ static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl) ctrl->panel->pinfo.bpp); cc = ctrl->link->get_colorimetry_config(ctrl->link); ctrl->catalog->config_misc(ctrl->catalog, cc, tb); ctrl->catalog->config_msa(ctrl->catalog); ctrl->panel->timing_cfg(ctrl->panel); } Loading Loading @@ -226,7 +240,7 @@ static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl, { u32 const multiplier = 1000000; u64 pclk, lclk; u8 bpp, ln_cnt, link_rate; u8 bpp, ln_cnt; int run_idx = 0; u32 lwidth, h_blank; u32 fifo_empty = 0; Loading Loading @@ -289,7 +303,6 @@ static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl, u64 brute_force_threshold = 10; u64 diff_abs; link_rate = ctrl->link->link_rate; ln_cnt = ctrl->link->lane_count; bpp = pinfo->bpp; Loading @@ -309,7 +322,7 @@ static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl, even_distribution = 0; min_hblank = 0; lclk = drm_dp_bw_code_to_link_rate(link_rate) * DP_KHZ_TO_HZ; lclk = drm_dp_bw_code_to_link_rate(ctrl->link->bw_code) * DP_KHZ_TO_HZ; pr_debug("pclk=%lld, active_width=%d, h_blank=%d\n", pclk, lwidth, h_blank); Loading Loading @@ -734,14 +747,12 @@ static int dp_ctrl_update_sink_vx_px(struct dp_ctrl_private *ctrl, max_level_reached |= BIT(5); } pr_debug("max_level_reached = 0x%x\n", max_level_reached); pre_emphasis_level <<= 3; for (i = 0; i < 4; i++) buf[i] = voltage_level | pre_emphasis_level | max_level_reached; pr_debug("p|v=0x%x\n", voltage_level | pre_emphasis_level); pr_debug("sink: p|v=0x%x\n", voltage_level | pre_emphasis_level); return drm_dp_dpcd_write(ctrl->aux->drm_aux, 0x103, buf, 4); } Loading @@ -749,8 +760,6 @@ static void dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl) { struct dp_link *link = ctrl->link; pr_debug("v=%d p=%d\n", link->v_level, link->p_level); ctrl->catalog->update_vx_px(ctrl->catalog, link->v_level, link->p_level); Loading @@ -762,15 +771,38 @@ static void dp_ctrl_train_pattern_set(struct dp_ctrl_private *ctrl, { u8 buf[4]; pr_debug("pattern=%x\n", pattern); pr_debug("sink: pattern=%x\n", pattern); buf[0] = pattern; drm_dp_dpcd_write(ctrl->aux->drm_aux, DP_TRAINING_PATTERN_SET, buf, 1); } static int dp_ctrl_read_link_status(struct dp_ctrl_private *ctrl, u8 *link_status) { int ret = 0, len; u32 const offset = DP_LANE_ALIGN_STATUS_UPDATED - DP_LANE0_1_STATUS; u32 link_status_read_max_retries = 100; while (--link_status_read_max_retries) { len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux, link_status); if (len != DP_LINK_STATUS_SIZE) { pr_err("DP link status read failed, err: %d\n", len); ret = len; break; } if (!(link_status[offset] & DP_LINK_STATUS_UPDATED)) break; } return ret; } static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) { int tries, old_v_level, ret = 0, len = 0; int tries, old_v_level, ret = 0; u8 link_status[DP_LINK_STATUS_SIZE]; int const maximum_retries = 5; Loading @@ -780,7 +812,7 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) ctrl->catalog->set_pattern(ctrl->catalog, 0x01); dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 | DP_RECOVERED_CLOCK_OUT_EN); /* train_1 */ DP_LINK_SCRAMBLING_DISABLE); /* train_1 */ dp_ctrl_update_vx_px(ctrl); tries = 0; Loading @@ -788,36 +820,35 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) while (1) { drm_dp_link_train_clock_recovery_delay(ctrl->panel->dpcd); len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux, link_status); if (len < DP_LINK_STATUS_SIZE) { pr_err("[%s]: DP link status read failed\n", __func__); ret = -1; ret = dp_ctrl_read_link_status(ctrl, link_status); if (ret) break; } if (drm_dp_clock_recovery_ok(link_status, ctrl->link->lane_count)) { ret = 0; break; } if (ctrl->link->v_level == DP_LINK_VOLTAGE_MAX) { ret = -1; break; /* quit */ pr_err_ratelimited("max v_level reached\n"); ret = -EAGAIN; break; } if (old_v_level == ctrl->link->v_level) { tries++; if (tries >= maximum_retries) { ret = -1; break; /* quit */ pr_err("max tries reached\n"); ret = -EAGAIN; break; } } else { tries = 0; old_v_level = ctrl->link->v_level; } pr_debug("clock recovery not done, adjusting vx px\n"); ctrl->link->adjust_levels(ctrl->link, link_status); dp_ctrl_update_vx_px(ctrl); } Loading @@ -828,27 +859,41 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) static int dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl) { int ret = 0; u32 min_req_link_rate_khz; u32 new_proposed_link_bw_code; u32 new_proposed_link_rate_khz; if (!ctrl) return -EINVAL; switch (ctrl->link->link_rate) { min_req_link_rate_khz = ctrl->panel->get_min_req_link_rate(ctrl->panel); switch (ctrl->link->bw_code) { case DP_LINK_RATE_810: ctrl->link->link_rate = DP_LINK_BW_5_4; new_proposed_link_bw_code = DP_LINK_BW_5_4; break; case DP_LINK_BW_5_4: ctrl->link->link_rate = DP_LINK_BW_2_7; new_proposed_link_bw_code = DP_LINK_BW_2_7; break; case DP_LINK_BW_2_7: ctrl->link->link_rate = DP_LINK_BW_1_62; break; case DP_LINK_BW_1_62: default: ret = -EINVAL; new_proposed_link_bw_code = DP_LINK_BW_1_62; break; }; pr_debug("new rate=%d\n", ctrl->link->link_rate); new_proposed_link_rate_khz = drm_dp_bw_code_to_link_rate( new_proposed_link_bw_code); pr_debug("new proposed link rate=%d khz\n", new_proposed_link_rate_khz); pr_debug("min required link rate=%d khz\n", min_req_link_rate_khz); if (new_proposed_link_rate_khz >= min_req_link_rate_khz) ctrl->link->bw_code = new_proposed_link_bw_code; else pr_debug("can't go below min required link rate\n"); pr_debug("new bw code=0x%x\n", ctrl->link->bw_code); return ret; } Loading @@ -861,11 +906,15 @@ static void dp_ctrl_clear_training_pattern(struct dp_ctrl_private *ctrl) static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl) { int tries = 0, ret = 0, len = 0; int tries = 0, ret = 0; char pattern; int const maximum_retries = 5; u8 link_status[DP_LINK_STATUS_SIZE]; dp_ctrl_state_ctrl(ctrl, 0); /* Make sure to clear the current pattern before starting a new one */ wmb(); if (drm_dp_tps3_supported(ctrl->panel->dpcd)) pattern = DP_TRAINING_PATTERN_3; else Loading @@ -878,21 +927,15 @@ static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl) do { drm_dp_link_train_channel_eq_delay(ctrl->panel->dpcd); len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux, link_status); if (len < DP_LINK_STATUS_SIZE) { pr_err("[%s]: DP link status read failed\n", __func__); ret = -1; ret = dp_ctrl_read_link_status(ctrl, link_status); if (ret) break; } if (drm_dp_channel_eq_ok(link_status, ctrl->link->lane_count)) { ret = 0; if (drm_dp_channel_eq_ok(link_status, ctrl->link->lane_count)) break; } if (tries > maximum_retries) { ret = -1; ret = -EAGAIN; break; } tries++; Loading @@ -907,61 +950,45 @@ static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl) static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl) { int ret = 0; struct drm_dp_link dp_link; u8 encoding = 0x1; struct drm_dp_link link_info = {0}; ctrl->link->p_level = 0; ctrl->link->v_level = 0; dp_ctrl_config_ctrl(ctrl); dp_ctrl_state_ctrl(ctrl, 0); dp_link.num_lanes = ctrl->link->lane_count; dp_link.rate = ctrl->link->link_rate; dp_link.capabilities = ctrl->panel->dp_link.capabilities; drm_dp_link_configure(ctrl->aux->drm_aux, &dp_link); link_info.num_lanes = ctrl->link->lane_count; link_info.rate = drm_dp_bw_code_to_link_rate(ctrl->link->bw_code); link_info.capabilities = ctrl->panel->link_info.capabilities; ret = dp_ctrl_link_train_1(ctrl); if (ret < 0) { if (!dp_ctrl_link_rate_down_shift(ctrl)) { pr_debug("retry with lower rate\n"); dp_ctrl_clear_training_pattern(ctrl); return -EAGAIN; } drm_dp_link_configure(ctrl->aux->drm_aux, &link_info); drm_dp_dpcd_write(ctrl->aux->drm_aux, DP_MAIN_LINK_CHANNEL_CODING_SET, &encoding, 1); pr_err("Training 1 failed\n"); ret = -EINVAL; goto clear; ret = dp_ctrl_link_train_1(ctrl); if (ret) { pr_err("link training #1 failed\n"); goto end; } pr_debug("Training 1 completed successfully\n"); dp_ctrl_state_ctrl(ctrl, 0); /* Make sure to clear the current pattern before starting a new one */ wmb(); /* print success info as this is a result of user initiated action */ pr_info("link training #1 successful\n"); ret = dp_ctrl_link_training_2(ctrl); if (ret < 0) { if (!dp_ctrl_link_rate_down_shift(ctrl)) { pr_debug("retry with lower rate\n"); dp_ctrl_clear_training_pattern(ctrl); return -EAGAIN; } pr_err("Training 2 failed\n"); ret = -EINVAL; goto clear; if (ret) { pr_err("link training #2 failed\n"); goto end; } pr_debug("Training 2 completed successfully\n"); /* print success info as this is a result of user initiated action */ pr_debug("link training #2 successful\n"); end: dp_ctrl_state_ctrl(ctrl, 0); /* Make sure to clear the current pattern before starting a new one */ wmb(); clear: dp_ctrl_clear_training_pattern(ctrl); return ret; } Loading @@ -973,7 +1000,7 @@ static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl, bool train) ctrl->catalog->mainlink_ctrl(ctrl->catalog, true); drm_dp_link_power_up(ctrl->aux->drm_aux, &ctrl->panel->dp_link); drm_dp_link_power_up(ctrl->aux->drm_aux, &ctrl->panel->link_info); if (ctrl->link->phy_pattern_requested(ctrl->link)) goto end; Loading Loading @@ -1018,6 +1045,8 @@ static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl, cfg++; } pr_debug("setting rate=%d on clk=%s\n", rate, name); if (num) cfg->rate = rate; else Loading @@ -1031,7 +1060,7 @@ static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) ctrl->power->set_pixel_clk_parent(ctrl->power); dp_ctrl_set_clock_rate(ctrl, "ctrl_link_clk", drm_dp_bw_code_to_link_rate(ctrl->link->link_rate)); drm_dp_bw_code_to_link_rate(ctrl->link->bw_code)); dp_ctrl_set_clock_rate(ctrl, "ctrl_pixel_clk", ctrl->pixel_rate); Loading Loading @@ -1128,6 +1157,9 @@ static int dp_ctrl_on_irq(struct dp_ctrl_private *ctrl, bool lt_needed) dp_ctrl_configure_source_params(ctrl); ctrl->catalog->config_msa(ctrl->catalog, drm_dp_bw_code_to_link_rate(ctrl->link->bw_code)); reinit_completion(&ctrl->idle_comp); if (ctrl->psm_enabled) { Loading @@ -1148,16 +1180,20 @@ static int dp_ctrl_on_irq(struct dp_ctrl_private *ctrl, bool lt_needed) static int dp_ctrl_on_hpd(struct dp_ctrl_private *ctrl) { int ret = 0; u32 rate = ctrl->panel->link_info.rate; u32 link_train_max_retries = 100; atomic_set(&ctrl->aborted, 0); ctrl->power->clk_enable(ctrl->power, DP_CORE_PM, true); ctrl->catalog->hpd_config(ctrl->catalog, true); ctrl->link->link_rate = ctrl->panel->get_link_rate(ctrl->panel); ctrl->link->lane_count = ctrl->panel->dp_link.num_lanes; ctrl->link->bw_code = drm_dp_link_rate_to_bw_code(rate); ctrl->link->lane_count = ctrl->panel->link_info.num_lanes; ctrl->pixel_rate = ctrl->panel->pinfo.pixel_clk_khz; pr_debug("link_rate=%d, lane_count=%d, pixel_rate=%d\n", ctrl->link->link_rate, ctrl->link->lane_count, pr_debug("bw_code=%d, lane_count=%d, pixel_rate=%d\n", ctrl->link->bw_code, ctrl->link->lane_count, ctrl->pixel_rate); ctrl->catalog->phy_lane_cfg(ctrl->catalog, Loading @@ -1174,8 +1210,25 @@ static int dp_ctrl_on_hpd(struct dp_ctrl_private *ctrl) if (ctrl->psm_enabled) ret = ctrl->link->send_psm_request(ctrl->link, false); while (-EAGAIN == dp_ctrl_setup_main_link(ctrl, true)) pr_debug("MAIN LINK TRAINING RETRY\n"); while (--link_train_max_retries && !atomic_read(&ctrl->aborted)) { ctrl->catalog->config_msa(ctrl->catalog, drm_dp_bw_code_to_link_rate(ctrl->link->bw_code)); ret = dp_ctrl_setup_main_link(ctrl, true); if (!ret) break; /* try with lower link rate */ dp_ctrl_link_rate_down_shift(ctrl); ctrl->catalog->mainlink_ctrl(ctrl->catalog, false); dp_ctrl_disable_mainlink_clocks(ctrl); /* hw recommended delay before re-enabling clocks */ msleep(20); dp_ctrl_enable_mainlink_clocks(ctrl); } pr_debug("End-\n"); Loading Loading @@ -1292,6 +1345,7 @@ struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in) dp_ctrl->on = dp_ctrl_on; dp_ctrl->off = dp_ctrl_off; dp_ctrl->push_idle = dp_ctrl_push_idle; dp_ctrl->abort = dp_ctrl_abort; dp_ctrl->isr = dp_ctrl_isr; return dp_ctrl; Loading
drivers/gpu/drm/msm/dp/dp_ctrl.h +1 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ struct dp_ctrl { int (*on)(struct dp_ctrl *dp_ctrl, bool hpd_irq); void (*off)(struct dp_ctrl *dp_ctrl, bool hpd_irq); void (*push_idle)(struct dp_ctrl *dp_ctrl); void (*abort)(struct dp_ctrl *dp_ctrl); void (*isr)(struct dp_ctrl *dp_ctrl); }; Loading