1 // SPDX-License-Identifier: GPL-2.0-or-later 2 // Copyright (c) 2024 Hisilicon Limited. 3 4 #include <linux/delay.h> 5 #include <drm/drm_device.h> 6 #include <drm/drm_print.h> 7 #include "dp_comm.h" 8 #include "dp_reg.h" 9 10 #define HIBMC_EQ_MAX_RETRY 5 11 12 static inline int hibmc_dp_get_serdes_rate_cfg(struct hibmc_dp_dev *dp) 13 { 14 switch (dp->link.cap.link_rate) { 15 case DP_LINK_BW_1_62: 16 return DP_SERDES_BW_1_62; 17 case DP_LINK_BW_2_7: 18 return DP_SERDES_BW_2_7; 19 case DP_LINK_BW_5_4: 20 return DP_SERDES_BW_5_4; 21 case DP_LINK_BW_8_1: 22 return DP_SERDES_BW_8_1; 23 default: 24 return -EINVAL; 25 } 26 } 27 28 static int hibmc_dp_link_training_configure(struct hibmc_dp_dev *dp) 29 { 30 u8 buf[2]; 31 int ret; 32 33 /* DP 2 lane */ 34 hibmc_dp_reg_write_field(dp, HIBMC_DP_PHYIF_CTRL0, HIBMC_DP_CFG_LANE_DATA_EN, 35 dp->link.cap.lanes == 0x2 ? 0x3 : 0x1); 36 hibmc_dp_reg_write_field(dp, HIBMC_DP_DPTX_GCTL0, HIBMC_DP_CFG_PHY_LANE_NUM, 37 dp->link.cap.lanes == 0x2 ? 0x1 : 0); 38 39 /* enhanced frame */ 40 hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CTRL, HIBMC_DP_CFG_STREAM_FRAME_MODE, 0x1); 41 42 /* set rate and lane count */ 43 buf[0] = dp->link.cap.link_rate; 44 buf[1] = DP_LANE_COUNT_ENHANCED_FRAME_EN | dp->link.cap.lanes; 45 ret = drm_dp_dpcd_write(dp->aux, DP_LINK_BW_SET, buf, sizeof(buf)); 46 if (ret != sizeof(buf)) { 47 drm_dbg_dp(dp->dev, "dp aux write link rate and lanes failed, ret: %d\n", ret); 48 return ret >= 0 ? -EIO : ret; 49 } 50 51 /* set 8b/10b and downspread */ 52 buf[0] = DP_SPREAD_AMP_0_5; 53 buf[1] = DP_SET_ANSI_8B10B; 54 ret = drm_dp_dpcd_write(dp->aux, DP_DOWNSPREAD_CTRL, buf, sizeof(buf)); 55 if (ret != sizeof(buf)) { 56 drm_dbg_dp(dp->dev, "dp aux write 8b/10b and downspread failed, ret: %d\n", ret); 57 return ret >= 0 ? -EIO : ret; 58 } 59 60 return 0; 61 } 62 63 static int hibmc_dp_link_set_pattern(struct hibmc_dp_dev *dp, int pattern) 64 { 65 int ret; 66 u8 val; 67 u8 buf; 68 69 buf = (u8)pattern; 70 if (pattern != DP_TRAINING_PATTERN_DISABLE && pattern != DP_TRAINING_PATTERN_4) { 71 buf |= DP_LINK_SCRAMBLING_DISABLE; 72 hibmc_dp_reg_write_field(dp, HIBMC_DP_PHYIF_CTRL0, HIBMC_DP_CFG_SCRAMBLE_EN, 0x1); 73 } else { 74 hibmc_dp_reg_write_field(dp, HIBMC_DP_PHYIF_CTRL0, HIBMC_DP_CFG_SCRAMBLE_EN, 0); 75 } 76 77 switch (pattern) { 78 case DP_TRAINING_PATTERN_DISABLE: 79 val = 0; 80 break; 81 case DP_TRAINING_PATTERN_1: 82 val = 1; 83 break; 84 case DP_TRAINING_PATTERN_2: 85 val = 2; 86 break; 87 case DP_TRAINING_PATTERN_3: 88 val = 3; 89 break; 90 case DP_TRAINING_PATTERN_4: 91 val = 4; 92 break; 93 default: 94 return -EINVAL; 95 } 96 97 hibmc_dp_reg_write_field(dp, HIBMC_DP_PHYIF_CTRL0, HIBMC_DP_CFG_PAT_SEL, val); 98 99 ret = drm_dp_dpcd_write(dp->aux, DP_TRAINING_PATTERN_SET, &buf, sizeof(buf)); 100 if (ret != sizeof(buf)) { 101 drm_dbg_dp(dp->dev, "dp aux write training pattern set failed\n"); 102 return ret >= 0 ? -EIO : ret; 103 } 104 105 return 0; 106 } 107 108 static int hibmc_dp_link_training_cr_pre(struct hibmc_dp_dev *dp) 109 { 110 u8 *train_set = dp->link.train_set; 111 int ret; 112 u8 i; 113 114 ret = hibmc_dp_link_training_configure(dp); 115 if (ret) 116 return ret; 117 118 ret = hibmc_dp_link_set_pattern(dp, DP_TRAINING_PATTERN_1); 119 if (ret) 120 return ret; 121 122 for (i = 0; i < dp->link.cap.lanes; i++) 123 train_set[i] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0; 124 125 ret = hibmc_dp_serdes_set_tx_cfg(dp, dp->link.train_set); 126 if (ret) 127 return ret; 128 129 ret = drm_dp_dpcd_write(dp->aux, DP_TRAINING_LANE0_SET, train_set, dp->link.cap.lanes); 130 if (ret != dp->link.cap.lanes) { 131 drm_dbg_dp(dp->dev, "dp aux write training lane set failed\n"); 132 return ret >= 0 ? -EIO : ret; 133 } 134 135 return 0; 136 } 137 138 static bool hibmc_dp_link_get_adjust_train(struct hibmc_dp_dev *dp, 139 u8 lane_status[DP_LINK_STATUS_SIZE]) 140 { 141 u8 train_set[HIBMC_DP_LANE_NUM_MAX] = {0}; 142 u8 lane; 143 144 for (lane = 0; lane < dp->link.cap.lanes; lane++) 145 train_set[lane] = drm_dp_get_adjust_request_voltage(lane_status, lane) | 146 drm_dp_get_adjust_request_pre_emphasis(lane_status, lane); 147 148 if (memcmp(dp->link.train_set, train_set, HIBMC_DP_LANE_NUM_MAX)) { 149 memcpy(dp->link.train_set, train_set, HIBMC_DP_LANE_NUM_MAX); 150 return true; 151 } 152 153 return false; 154 } 155 156 static int hibmc_dp_link_reduce_rate(struct hibmc_dp_dev *dp) 157 { 158 int ret; 159 160 switch (dp->link.cap.link_rate) { 161 case DP_LINK_BW_2_7: 162 dp->link.cap.link_rate = DP_LINK_BW_1_62; 163 break; 164 case DP_LINK_BW_5_4: 165 dp->link.cap.link_rate = DP_LINK_BW_2_7; 166 break; 167 case DP_LINK_BW_8_1: 168 dp->link.cap.link_rate = DP_LINK_BW_5_4; 169 break; 170 default: 171 return -EINVAL; 172 } 173 174 ret = hibmc_dp_get_serdes_rate_cfg(dp); 175 if (ret < 0) 176 return ret; 177 178 return hibmc_dp_serdes_rate_switch(ret, dp); 179 } 180 181 static inline int hibmc_dp_link_reduce_lane(struct hibmc_dp_dev *dp) 182 { 183 switch (dp->link.cap.lanes) { 184 case 0x2: 185 dp->link.cap.lanes--; 186 drm_dbg_dp(dp->dev, "dp link training reduce to 1 lane\n"); 187 break; 188 case 0x1: 189 drm_err(dp->dev, "dp link training reduce lane failed, already reach minimum\n"); 190 return -EIO; 191 default: 192 return -EINVAL; 193 } 194 195 return 0; 196 } 197 198 static int hibmc_dp_link_training_cr(struct hibmc_dp_dev *dp) 199 { 200 u8 lane_status[DP_LINK_STATUS_SIZE] = {0}; 201 bool level_changed; 202 u32 voltage_tries; 203 u32 cr_tries; 204 int ret; 205 206 /* 207 * DP 1.4 spec define 10 for maxtries value, for pre DP 1.4 version set a limit of 80 208 * (4 voltage levels x 4 preemphasis levels x 5 identical voltage retries) 209 */ 210 211 voltage_tries = 1; 212 for (cr_tries = 0; cr_tries < 80; cr_tries++) { 213 drm_dp_link_train_clock_recovery_delay(dp->aux, dp->dpcd); 214 215 ret = drm_dp_dpcd_read_link_status(dp->aux, lane_status); 216 if (ret) { 217 drm_err(dp->dev, "Get lane status failed\n"); 218 return ret; 219 } 220 221 if (drm_dp_clock_recovery_ok(lane_status, dp->link.cap.lanes)) { 222 drm_dbg_dp(dp->dev, "dp link training cr done\n"); 223 dp->link.status.clock_recovered = true; 224 return 0; 225 } 226 227 if (voltage_tries == 5) { 228 drm_dbg_dp(dp->dev, "same voltage tries 5 times\n"); 229 dp->link.status.clock_recovered = false; 230 return 0; 231 } 232 233 level_changed = hibmc_dp_link_get_adjust_train(dp, lane_status); 234 235 ret = hibmc_dp_serdes_set_tx_cfg(dp, dp->link.train_set); 236 if (ret) 237 return ret; 238 239 ret = drm_dp_dpcd_write(dp->aux, DP_TRAINING_LANE0_SET, dp->link.train_set, 240 dp->link.cap.lanes); 241 if (ret != dp->link.cap.lanes) { 242 drm_dbg_dp(dp->dev, "Update link training failed\n"); 243 return ret >= 0 ? -EIO : ret; 244 } 245 246 voltage_tries = level_changed ? 1 : voltage_tries + 1; 247 } 248 249 drm_err(dp->dev, "dp link training clock recovery 80 times failed\n"); 250 dp->link.status.clock_recovered = false; 251 252 return 0; 253 } 254 255 static int hibmc_dp_link_training_channel_eq(struct hibmc_dp_dev *dp) 256 { 257 u8 lane_status[DP_LINK_STATUS_SIZE] = {0}; 258 u8 eq_tries; 259 int ret; 260 261 ret = hibmc_dp_link_set_pattern(dp, DP_TRAINING_PATTERN_2); 262 if (ret) 263 return ret; 264 265 for (eq_tries = 0; eq_tries < HIBMC_EQ_MAX_RETRY; eq_tries++) { 266 drm_dp_link_train_channel_eq_delay(dp->aux, dp->dpcd); 267 268 ret = drm_dp_dpcd_read_link_status(dp->aux, lane_status); 269 if (ret) { 270 drm_err(dp->dev, "get lane status failed\n"); 271 break; 272 } 273 274 if (!drm_dp_clock_recovery_ok(lane_status, dp->link.cap.lanes)) { 275 drm_dbg_dp(dp->dev, "clock recovery check failed\n"); 276 drm_dbg_dp(dp->dev, "cannot continue channel equalization\n"); 277 dp->link.status.clock_recovered = false; 278 break; 279 } 280 281 if (drm_dp_channel_eq_ok(lane_status, dp->link.cap.lanes)) { 282 dp->link.status.channel_equalized = true; 283 drm_dbg_dp(dp->dev, "dp link training eq done\n"); 284 break; 285 } 286 287 hibmc_dp_link_get_adjust_train(dp, lane_status); 288 289 ret = hibmc_dp_serdes_set_tx_cfg(dp, dp->link.train_set); 290 if (ret) 291 return ret; 292 293 ret = drm_dp_dpcd_write(dp->aux, DP_TRAINING_LANE0_SET, 294 dp->link.train_set, dp->link.cap.lanes); 295 if (ret != dp->link.cap.lanes) { 296 drm_dbg_dp(dp->dev, "Update link training failed\n"); 297 ret = (ret >= 0) ? -EIO : ret; 298 break; 299 } 300 } 301 302 if (eq_tries == HIBMC_EQ_MAX_RETRY) 303 drm_err(dp->dev, "channel equalization failed %u times\n", eq_tries); 304 305 hibmc_dp_link_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE); 306 307 return ret < 0 ? ret : 0; 308 } 309 310 static int hibmc_dp_link_downgrade_training_cr(struct hibmc_dp_dev *dp) 311 { 312 if (hibmc_dp_link_reduce_rate(dp)) 313 return hibmc_dp_link_reduce_lane(dp); 314 315 return 0; 316 } 317 318 static int hibmc_dp_link_downgrade_training_eq(struct hibmc_dp_dev *dp) 319 { 320 if ((dp->link.status.clock_recovered && !dp->link.status.channel_equalized)) { 321 if (!hibmc_dp_link_reduce_lane(dp)) 322 return 0; 323 } 324 325 return hibmc_dp_link_reduce_rate(dp); 326 } 327 328 int hibmc_dp_link_training(struct hibmc_dp_dev *dp) 329 { 330 struct hibmc_dp_link *link = &dp->link; 331 int ret; 332 333 ret = drm_dp_read_dpcd_caps(dp->aux, dp->dpcd); 334 if (ret) 335 drm_err(dp->dev, "dp aux read dpcd failed, ret: %d\n", ret); 336 337 dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE]; 338 dp->link.cap.lanes = 0x2; 339 340 ret = hibmc_dp_get_serdes_rate_cfg(dp); 341 if (ret < 0) 342 return ret; 343 344 ret = hibmc_dp_serdes_rate_switch(ret, dp); 345 if (ret) 346 return ret; 347 348 while (true) { 349 ret = hibmc_dp_link_training_cr_pre(dp); 350 if (ret) 351 goto err; 352 353 ret = hibmc_dp_link_training_cr(dp); 354 if (ret) 355 goto err; 356 357 if (!link->status.clock_recovered) { 358 ret = hibmc_dp_link_downgrade_training_cr(dp); 359 if (ret) 360 goto err; 361 continue; 362 } 363 364 ret = hibmc_dp_link_training_channel_eq(dp); 365 if (ret) 366 goto err; 367 368 if (!link->status.channel_equalized) { 369 ret = hibmc_dp_link_downgrade_training_eq(dp); 370 if (ret) 371 goto err; 372 continue; 373 } 374 375 return 0; 376 } 377 378 err: 379 hibmc_dp_link_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE); 380 381 return ret; 382 } 383