1 /* 2 * Copyright 2014 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Ben Skeggs 23 */ 24 #include "dp.h" 25 #include "conn.h" 26 #include "head.h" 27 #include "ior.h" 28 29 #include <subdev/bios.h> 30 #include <subdev/bios/init.h> 31 #include <subdev/gpio.h> 32 #include <subdev/i2c.h> 33 34 #include <nvif/event.h> 35 36 /* IED scripts are no longer used by UEFI/RM from Ampere, but have been updated for 37 * the x86 option ROM. However, the relevant VBIOS table versions weren't modified, 38 * so we're unable to detect this in a nice way. 39 */ 40 #define AMPERE_IED_HACK(disp) ((disp)->engine.subdev.device->card_type >= GA100) 41 42 struct lt_state { 43 struct nvkm_outp *outp; 44 45 int repeaters; 46 int repeater; 47 48 u8 stat[6]; 49 u8 conf[4]; 50 bool pc2; 51 u8 pc2stat; 52 u8 pc2conf[2]; 53 }; 54 55 static int 56 nvkm_dp_train_sense(struct lt_state *lt, bool pc, u32 delay) 57 { 58 struct nvkm_outp *outp = lt->outp; 59 u32 addr; 60 int ret; 61 62 usleep_range(delay, delay * 2); 63 64 if (lt->repeater) 65 addr = DPCD_LTTPR_LANE0_1_STATUS(lt->repeater); 66 else 67 addr = DPCD_LS02; 68 69 ret = nvkm_rdaux(outp->dp.aux, addr, <->stat[0], 3); 70 if (ret) 71 return ret; 72 73 if (lt->repeater) 74 addr = DPCD_LTTPR_LANE0_1_ADJUST(lt->repeater); 75 else 76 addr = DPCD_LS06; 77 78 ret = nvkm_rdaux(outp->dp.aux, addr, <->stat[4], 2); 79 if (ret) 80 return ret; 81 82 if (pc) { 83 ret = nvkm_rdaux(outp->dp.aux, DPCD_LS0C, <->pc2stat, 1); 84 if (ret) 85 lt->pc2stat = 0x00; 86 87 OUTP_TRACE(outp, "status %6ph pc2 %02x", lt->stat, lt->pc2stat); 88 } else { 89 OUTP_TRACE(outp, "status %6ph", lt->stat); 90 } 91 92 return 0; 93 } 94 95 static int 96 nvkm_dp_train_drive(struct lt_state *lt, bool pc) 97 { 98 struct nvkm_outp *outp = lt->outp; 99 struct nvkm_ior *ior = outp->ior; 100 struct nvkm_bios *bios = ior->disp->engine.subdev.device->bios; 101 struct nvbios_dpout info; 102 struct nvbios_dpcfg ocfg; 103 u8 ver, hdr, cnt, len; 104 u32 addr; 105 u32 data; 106 int ret, i; 107 108 for (i = 0; i < ior->dp.nr; i++) { 109 u8 lane = (lt->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; 110 u8 lpc2 = (lt->pc2stat >> (i * 2)) & 0x3; 111 u8 lpre = (lane & 0x0c) >> 2; 112 u8 lvsw = (lane & 0x03) >> 0; 113 u8 hivs = 3 - lpre; 114 u8 hipe = 3; 115 u8 hipc = 3; 116 117 if (lpc2 >= hipc) 118 lpc2 = hipc | DPCD_LC0F_LANE0_MAX_POST_CURSOR2_REACHED; 119 if (lpre >= hipe) { 120 lpre = hipe | DPCD_LC03_MAX_SWING_REACHED; /* yes. */ 121 lvsw = hivs = 3 - (lpre & 3); 122 } else 123 if (lvsw >= hivs) { 124 lvsw = hivs | DPCD_LC03_MAX_SWING_REACHED; 125 } 126 127 lt->conf[i] = (lpre << 3) | lvsw; 128 lt->pc2conf[i >> 1] |= lpc2 << ((i & 1) * 4); 129 130 OUTP_TRACE(outp, "config lane %d %02x %02x", i, lt->conf[i], lpc2); 131 132 if (lt->repeater != lt->repeaters) 133 continue; 134 135 data = nvbios_dpout_match(bios, outp->info.hasht, outp->info.hashm, 136 &ver, &hdr, &cnt, &len, &info); 137 if (!data) 138 continue; 139 140 data = nvbios_dpcfg_match(bios, data, lpc2 & 3, lvsw & 3, lpre & 3, 141 &ver, &hdr, &cnt, &len, &ocfg); 142 if (!data) 143 continue; 144 145 ior->func->dp->drive(ior, i, ocfg.pc, ocfg.dc, ocfg.pe, ocfg.tx_pu); 146 } 147 148 if (lt->repeater) 149 addr = DPCD_LTTPR_LANE0_SET(lt->repeater); 150 else 151 addr = DPCD_LC03(0); 152 153 ret = nvkm_wraux(outp->dp.aux, addr, lt->conf, 4); 154 if (ret) 155 return ret; 156 157 if (pc) { 158 ret = nvkm_wraux(outp->dp.aux, DPCD_LC0F, lt->pc2conf, 2); 159 if (ret) 160 return ret; 161 } 162 163 return 0; 164 } 165 166 static void 167 nvkm_dp_train_pattern(struct lt_state *lt, u8 pattern) 168 { 169 struct nvkm_outp *outp = lt->outp; 170 u32 addr; 171 u8 sink_tp; 172 173 OUTP_TRACE(outp, "training pattern %d", pattern); 174 outp->ior->func->dp->pattern(outp->ior, pattern); 175 176 if (lt->repeater) 177 addr = DPCD_LTTPR_PATTERN_SET(lt->repeater); 178 else 179 addr = DPCD_LC02; 180 181 nvkm_rdaux(outp->dp.aux, addr, &sink_tp, 1); 182 sink_tp &= ~DPCD_LC02_TRAINING_PATTERN_SET; 183 sink_tp |= (pattern != 4) ? pattern : 7; 184 185 if (pattern != 0) 186 sink_tp |= DPCD_LC02_SCRAMBLING_DISABLE; 187 else 188 sink_tp &= ~DPCD_LC02_SCRAMBLING_DISABLE; 189 nvkm_wraux(outp->dp.aux, addr, &sink_tp, 1); 190 } 191 192 static int 193 nvkm_dp_train_eq(struct lt_state *lt) 194 { 195 struct nvkm_i2c_aux *aux = lt->outp->dp.aux; 196 bool eq_done = false, cr_done = true; 197 int tries = 0, usec = 0, i; 198 u8 data; 199 200 if (lt->repeater) { 201 if (!nvkm_rdaux(aux, DPCD_LTTPR_AUX_RD_INTERVAL(lt->repeater), &data, sizeof(data))) 202 usec = (data & DPCD_RC0E_AUX_RD_INTERVAL) * 4000; 203 204 nvkm_dp_train_pattern(lt, 4); 205 } else { 206 if (lt->outp->dp.dpcd[DPCD_RC00_DPCD_REV] >= 0x14 && 207 lt->outp->dp.dpcd[DPCD_RC03] & DPCD_RC03_TPS4_SUPPORTED) 208 nvkm_dp_train_pattern(lt, 4); 209 else 210 if (lt->outp->dp.dpcd[DPCD_RC00_DPCD_REV] >= 0x12 && 211 lt->outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED) 212 nvkm_dp_train_pattern(lt, 3); 213 else 214 nvkm_dp_train_pattern(lt, 2); 215 216 usec = (lt->outp->dp.dpcd[DPCD_RC0E] & DPCD_RC0E_AUX_RD_INTERVAL) * 4000; 217 } 218 219 do { 220 if ((tries && 221 nvkm_dp_train_drive(lt, lt->pc2)) || 222 nvkm_dp_train_sense(lt, lt->pc2, usec ? usec : 400)) 223 break; 224 225 eq_done = !!(lt->stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE); 226 for (i = 0; i < lt->outp->ior->dp.nr && eq_done; i++) { 227 u8 lane = (lt->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; 228 if (!(lane & DPCD_LS02_LANE0_CR_DONE)) 229 cr_done = false; 230 if (!(lane & DPCD_LS02_LANE0_CHANNEL_EQ_DONE) || 231 !(lane & DPCD_LS02_LANE0_SYMBOL_LOCKED)) 232 eq_done = false; 233 } 234 } while (!eq_done && cr_done && ++tries <= 5); 235 236 return eq_done ? 0 : -1; 237 } 238 239 static int 240 nvkm_dp_train_cr(struct lt_state *lt) 241 { 242 bool cr_done = false, abort = false; 243 int voltage = lt->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET; 244 int tries = 0, usec = 0, i; 245 246 nvkm_dp_train_pattern(lt, 1); 247 248 if (lt->outp->dp.dpcd[DPCD_RC00_DPCD_REV] < 0x14 && !lt->repeater) 249 usec = (lt->outp->dp.dpcd[DPCD_RC0E] & DPCD_RC0E_AUX_RD_INTERVAL) * 4000; 250 251 do { 252 if (nvkm_dp_train_drive(lt, false) || 253 nvkm_dp_train_sense(lt, false, usec ? usec : 100)) 254 break; 255 256 cr_done = true; 257 for (i = 0; i < lt->outp->ior->dp.nr; i++) { 258 u8 lane = (lt->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; 259 if (!(lane & DPCD_LS02_LANE0_CR_DONE)) { 260 cr_done = false; 261 if (lt->conf[i] & DPCD_LC03_MAX_SWING_REACHED) 262 abort = true; 263 break; 264 } 265 } 266 267 if ((lt->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET) != voltage) { 268 voltage = lt->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET; 269 tries = 0; 270 } 271 } while (!cr_done && !abort && ++tries < 5); 272 273 return cr_done ? 0 : -1; 274 } 275 276 static int 277 nvkm_dp_train_link(struct nvkm_outp *outp, int rate) 278 { 279 struct nvkm_ior *ior = outp->ior; 280 struct lt_state lt = { 281 .outp = outp, 282 .pc2 = outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED, 283 }; 284 u8 sink[2], data; 285 int ret; 286 287 OUTP_DBG(outp, "training %dx%02x", ior->dp.nr, ior->dp.bw); 288 289 /* Select LTTPR non-transparent mode if we have a valid configuration, 290 * use transparent mode otherwise. 291 */ 292 if (outp->dp.lttpr[0] >= 0x14) { 293 data = DPCD_LTTPR_MODE_TRANSPARENT; 294 nvkm_wraux(outp->dp.aux, DPCD_LTTPR_MODE, &data, sizeof(data)); 295 296 if (outp->dp.lttprs) { 297 data = DPCD_LTTPR_MODE_NON_TRANSPARENT; 298 nvkm_wraux(outp->dp.aux, DPCD_LTTPR_MODE, &data, sizeof(data)); 299 lt.repeaters = outp->dp.lttprs; 300 } 301 } 302 303 /* Set desired link configuration on the sink. */ 304 sink[0] = (outp->dp.rate[rate].dpcd < 0) ? ior->dp.bw : 0; 305 sink[1] = ior->dp.nr; 306 if (ior->dp.ef) 307 sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN; 308 309 ret = nvkm_wraux(outp->dp.aux, DPCD_LC00_LINK_BW_SET, sink, 2); 310 if (ret) 311 return ret; 312 313 if (outp->dp.rate[rate].dpcd >= 0) { 314 ret = nvkm_rdaux(outp->dp.aux, DPCD_LC15_LINK_RATE_SET, &sink[0], sizeof(sink[0])); 315 if (ret) 316 return ret; 317 318 sink[0] &= ~DPCD_LC15_LINK_RATE_SET_MASK; 319 sink[0] |= outp->dp.rate[rate].dpcd; 320 321 ret = nvkm_wraux(outp->dp.aux, DPCD_LC15_LINK_RATE_SET, &sink[0], sizeof(sink[0])); 322 if (ret) 323 return ret; 324 } 325 326 /* Attempt to train the link in this configuration. */ 327 for (lt.repeater = lt.repeaters; lt.repeater >= 0; lt.repeater--) { 328 if (lt.repeater) 329 OUTP_DBG(outp, "training LTTPR%d", lt.repeater); 330 else 331 OUTP_DBG(outp, "training sink"); 332 333 memset(lt.stat, 0x00, sizeof(lt.stat)); 334 ret = nvkm_dp_train_cr(<); 335 if (ret == 0) 336 ret = nvkm_dp_train_eq(<); 337 nvkm_dp_train_pattern(<, 0); 338 } 339 340 return ret; 341 } 342 343 static int 344 nvkm_dp_train_links(struct nvkm_outp *outp, int rate) 345 { 346 struct nvkm_ior *ior = outp->ior; 347 struct nvkm_disp *disp = outp->disp; 348 struct nvkm_subdev *subdev = &disp->engine.subdev; 349 struct nvkm_bios *bios = subdev->device->bios; 350 u32 lnkcmp; 351 int ret; 352 353 OUTP_DBG(outp, "programming link for %dx%02x", ior->dp.nr, ior->dp.bw); 354 355 /* Intersect misc. capabilities of the OR and sink. */ 356 if (disp->engine.subdev.device->chipset < 0x110) 357 outp->dp.dpcd[DPCD_RC03] &= ~DPCD_RC03_TPS4_SUPPORTED; 358 if (disp->engine.subdev.device->chipset < 0xd0) 359 outp->dp.dpcd[DPCD_RC02] &= ~DPCD_RC02_TPS3_SUPPORTED; 360 361 if (AMPERE_IED_HACK(disp) && (lnkcmp = outp->dp.info.script[0])) { 362 /* Execute BeforeLinkTraining script from DP Info table. */ 363 while (ior->dp.bw < nvbios_rd08(bios, lnkcmp)) 364 lnkcmp += 3; 365 lnkcmp = nvbios_rd16(bios, lnkcmp + 1); 366 367 nvbios_init(&outp->disp->engine.subdev, lnkcmp, 368 init.outp = &outp->info; 369 init.or = ior->id; 370 init.link = ior->asy.link; 371 ); 372 } 373 374 /* Set desired link configuration on the source. */ 375 if ((lnkcmp = outp->dp.info.lnkcmp)) { 376 if (outp->dp.version < 0x30) { 377 while ((ior->dp.bw * 2700) < nvbios_rd16(bios, lnkcmp)) 378 lnkcmp += 4; 379 lnkcmp = nvbios_rd16(bios, lnkcmp + 2); 380 } else { 381 while (ior->dp.bw < nvbios_rd08(bios, lnkcmp)) 382 lnkcmp += 3; 383 lnkcmp = nvbios_rd16(bios, lnkcmp + 1); 384 } 385 386 nvbios_init(subdev, lnkcmp, 387 init.outp = &outp->info; 388 init.or = ior->id; 389 init.link = ior->asy.link; 390 ); 391 } 392 393 ret = ior->func->dp->links(ior, outp->dp.aux); 394 if (ret) { 395 if (ret < 0) { 396 OUTP_ERR(outp, "train failed with %d", ret); 397 return ret; 398 } 399 return 0; 400 } 401 402 ior->func->dp->power(ior, ior->dp.nr); 403 404 /* Attempt to train the link in this configuration. */ 405 return nvkm_dp_train_link(outp, rate); 406 } 407 408 static void 409 nvkm_dp_train_fini(struct nvkm_outp *outp) 410 { 411 /* Execute AfterLinkTraining script from DP Info table. */ 412 nvbios_init(&outp->disp->engine.subdev, outp->dp.info.script[1], 413 init.outp = &outp->info; 414 init.or = outp->ior->id; 415 init.link = outp->ior->asy.link; 416 ); 417 } 418 419 static void 420 nvkm_dp_train_init(struct nvkm_outp *outp) 421 { 422 /* Execute EnableSpread/DisableSpread script from DP Info table. */ 423 if (outp->dp.dpcd[DPCD_RC03] & DPCD_RC03_MAX_DOWNSPREAD) { 424 nvbios_init(&outp->disp->engine.subdev, outp->dp.info.script[2], 425 init.outp = &outp->info; 426 init.or = outp->ior->id; 427 init.link = outp->ior->asy.link; 428 ); 429 } else { 430 nvbios_init(&outp->disp->engine.subdev, outp->dp.info.script[3], 431 init.outp = &outp->info; 432 init.or = outp->ior->id; 433 init.link = outp->ior->asy.link; 434 ); 435 } 436 437 if (!AMPERE_IED_HACK(outp->disp)) { 438 /* Execute BeforeLinkTraining script from DP Info table. */ 439 nvbios_init(&outp->disp->engine.subdev, outp->dp.info.script[0], 440 init.outp = &outp->info; 441 init.or = outp->ior->id; 442 init.link = outp->ior->asy.link; 443 ); 444 } 445 } 446 447 static int 448 nvkm_dp_train(struct nvkm_outp *outp, u32 dataKBps) 449 { 450 struct nvkm_ior *ior = outp->ior; 451 int ret = -EINVAL, nr, rate; 452 u8 pwr; 453 454 /* Retraining link? Skip source configuration, it can mess up the active modeset. */ 455 if (atomic_read(&outp->dp.lt.done)) { 456 for (rate = 0; rate < outp->dp.rates; rate++) { 457 if (outp->dp.rate[rate].rate == ior->dp.bw * 27000) 458 return nvkm_dp_train_link(outp, ret); 459 } 460 WARN_ON(1); 461 return -EINVAL; 462 } 463 464 /* Ensure sink is not in a low-power state. */ 465 if (!nvkm_rdaux(outp->dp.aux, DPCD_SC00, &pwr, 1)) { 466 if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) { 467 pwr &= ~DPCD_SC00_SET_POWER; 468 pwr |= DPCD_SC00_SET_POWER_D0; 469 nvkm_wraux(outp->dp.aux, DPCD_SC00, &pwr, 1); 470 } 471 } 472 473 ior->dp.mst = outp->dp.lt.mst; 474 ior->dp.ef = outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP; 475 ior->dp.nr = 0; 476 477 /* Link training. */ 478 OUTP_DBG(outp, "training"); 479 nvkm_dp_train_init(outp); 480 481 /* Validate and train at configuration requested (if any) on ACQUIRE. */ 482 if (outp->dp.lt.nr) { 483 for (nr = outp->dp.links; ret < 0 && nr; nr >>= 1) { 484 for (rate = 0; nr == outp->dp.lt.nr && rate < outp->dp.rates; rate++) { 485 if (outp->dp.rate[rate].rate / 27000 == outp->dp.lt.bw) { 486 ior->dp.bw = outp->dp.rate[rate].rate / 27000; 487 ior->dp.nr = nr; 488 ret = nvkm_dp_train_links(outp, rate); 489 } 490 } 491 } 492 } 493 494 /* Otherwise, loop through all valid link configurations that support the data rate. */ 495 for (nr = outp->dp.links; ret < 0 && nr; nr >>= 1) { 496 for (rate = 0; ret < 0 && rate < outp->dp.rates; rate++) { 497 if (outp->dp.rate[rate].rate * nr >= dataKBps || WARN_ON(!ior->dp.nr)) { 498 /* Program selected link configuration. */ 499 ior->dp.bw = outp->dp.rate[rate].rate / 27000; 500 ior->dp.nr = nr; 501 ret = nvkm_dp_train_links(outp, rate); 502 } 503 } 504 } 505 506 /* Finish up. */ 507 nvkm_dp_train_fini(outp); 508 if (ret < 0) 509 OUTP_ERR(outp, "training failed"); 510 else 511 OUTP_DBG(outp, "training done"); 512 atomic_set(&outp->dp.lt.done, 1); 513 return ret; 514 } 515 516 void 517 nvkm_dp_disable(struct nvkm_outp *outp, struct nvkm_ior *ior) 518 { 519 /* Execute DisableLT script from DP Info Table. */ 520 nvbios_init(&ior->disp->engine.subdev, outp->dp.info.script[4], 521 init.outp = &outp->info; 522 init.or = ior->id; 523 init.link = ior->arm.link; 524 ); 525 } 526 527 static void 528 nvkm_dp_release(struct nvkm_outp *outp) 529 { 530 /* Prevent link from being retrained if sink sends an IRQ. */ 531 atomic_set(&outp->dp.lt.done, 0); 532 outp->ior->dp.nr = 0; 533 } 534 535 static int 536 nvkm_dp_acquire(struct nvkm_outp *outp) 537 { 538 struct nvkm_ior *ior = outp->ior; 539 struct nvkm_head *head; 540 bool retrain = true; 541 u32 datakbps = 0; 542 u32 dataKBps; 543 u32 linkKBps; 544 u8 stat[3]; 545 int ret, i; 546 547 mutex_lock(&outp->dp.mutex); 548 549 /* Check that link configuration meets current requirements. */ 550 list_for_each_entry(head, &outp->disp->heads, head) { 551 if (ior->asy.head & (1 << head->id)) { 552 u32 khz = (head->asy.hz >> ior->asy.rgdiv) / 1000; 553 datakbps += khz * head->asy.or.depth; 554 } 555 } 556 557 linkKBps = ior->dp.bw * 27000 * ior->dp.nr; 558 dataKBps = DIV_ROUND_UP(datakbps, 8); 559 OUTP_DBG(outp, "data %d KB/s link %d KB/s mst %d->%d", 560 dataKBps, linkKBps, ior->dp.mst, outp->dp.lt.mst); 561 if (linkKBps < dataKBps || ior->dp.mst != outp->dp.lt.mst) { 562 OUTP_DBG(outp, "link requirements changed"); 563 goto done; 564 } 565 566 /* Check that link is still trained. */ 567 ret = nvkm_rdaux(outp->dp.aux, DPCD_LS02, stat, 3); 568 if (ret) { 569 OUTP_DBG(outp, "failed to read link status, assuming no sink"); 570 goto done; 571 } 572 573 if (stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE) { 574 for (i = 0; i < ior->dp.nr; i++) { 575 u8 lane = (stat[i >> 1] >> ((i & 1) * 4)) & 0x0f; 576 if (!(lane & DPCD_LS02_LANE0_CR_DONE) || 577 !(lane & DPCD_LS02_LANE0_CHANNEL_EQ_DONE) || 578 !(lane & DPCD_LS02_LANE0_SYMBOL_LOCKED)) { 579 OUTP_DBG(outp, "lane %d not equalised", lane); 580 goto done; 581 } 582 } 583 retrain = false; 584 } else { 585 OUTP_DBG(outp, "no inter-lane alignment"); 586 } 587 588 done: 589 if (retrain || !atomic_read(&outp->dp.lt.done)) 590 ret = nvkm_dp_train(outp, dataKBps); 591 mutex_unlock(&outp->dp.mutex); 592 return ret; 593 } 594 595 static bool 596 nvkm_dp_enable_supported_link_rates(struct nvkm_outp *outp) 597 { 598 u8 sink_rates[DPCD_RC10_SUPPORTED_LINK_RATES__SIZE]; 599 int i, j, k; 600 601 if (outp->conn->info.type != DCB_CONNECTOR_eDP || 602 outp->dp.dpcd[DPCD_RC00_DPCD_REV] < 0x13 || 603 nvkm_rdaux(outp->dp.aux, DPCD_RC10_SUPPORTED_LINK_RATES(0), 604 sink_rates, sizeof(sink_rates))) 605 return false; 606 607 for (i = 0; i < ARRAY_SIZE(sink_rates); i += 2) { 608 const u32 rate = ((sink_rates[i + 1] << 8) | sink_rates[i]) * 200 / 10; 609 610 if (!rate || WARN_ON(outp->dp.rates == ARRAY_SIZE(outp->dp.rate))) 611 break; 612 613 if (rate > outp->info.dpconf.link_bw * 27000) { 614 OUTP_DBG(outp, "rate %d !outp", rate); 615 continue; 616 } 617 618 for (j = 0; j < outp->dp.rates; j++) { 619 if (rate > outp->dp.rate[j].rate) { 620 for (k = outp->dp.rates; k > j; k--) 621 outp->dp.rate[k] = outp->dp.rate[k - 1]; 622 break; 623 } 624 } 625 626 outp->dp.rate[j].dpcd = i / 2; 627 outp->dp.rate[j].rate = rate; 628 outp->dp.rates++; 629 } 630 631 for (i = 0; i < outp->dp.rates; i++) 632 OUTP_DBG(outp, "link_rate[%d] = %d", outp->dp.rate[i].dpcd, outp->dp.rate[i].rate); 633 634 return outp->dp.rates != 0; 635 } 636 637 void 638 nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr) 639 { 640 struct nvkm_gpio *gpio = outp->disp->engine.subdev.device->gpio; 641 struct nvkm_i2c_aux *aux = outp->dp.aux; 642 643 if (auxpwr && !outp->dp.aux_pwr) { 644 /* eDP panels need powering on by us (if the VBIOS doesn't default it 645 * to on) before doing any AUX channel transactions. LVDS panel power 646 * is handled by the SOR itself, and not required for LVDS DDC. 647 */ 648 if (outp->conn->info.type == DCB_CONNECTOR_eDP) { 649 int power = nvkm_gpio_get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff); 650 if (power == 0) { 651 nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); 652 outp->dp.aux_pwr_pu = true; 653 } 654 655 /* We delay here unconditionally, even if already powered, 656 * because some laptop panels having a significant resume 657 * delay before the panel begins responding. 658 * 659 * This is likely a bit of a hack, but no better idea for 660 * handling this at the moment. 661 */ 662 msleep(300); 663 } 664 665 OUTP_DBG(outp, "aux power -> always"); 666 nvkm_i2c_aux_monitor(aux, true); 667 outp->dp.aux_pwr = true; 668 669 /* Detect any LTTPRs before reading DPCD receiver caps. */ 670 if (!nvkm_rdaux(aux, DPCD_LTTPR_REV, outp->dp.lttpr, sizeof(outp->dp.lttpr)) && 671 outp->dp.lttpr[0] >= 0x14 && outp->dp.lttpr[2]) { 672 switch (outp->dp.lttpr[2]) { 673 case 0x80: outp->dp.lttprs = 1; break; 674 case 0x40: outp->dp.lttprs = 2; break; 675 case 0x20: outp->dp.lttprs = 3; break; 676 case 0x10: outp->dp.lttprs = 4; break; 677 case 0x08: outp->dp.lttprs = 5; break; 678 case 0x04: outp->dp.lttprs = 6; break; 679 case 0x02: outp->dp.lttprs = 7; break; 680 case 0x01: outp->dp.lttprs = 8; break; 681 default: 682 /* Unknown LTTPR count, we'll switch to transparent mode. */ 683 WARN_ON(1); 684 outp->dp.lttprs = 0; 685 break; 686 } 687 } else { 688 /* No LTTPR support, or zero LTTPR count - don't touch it at all. */ 689 memset(outp->dp.lttpr, 0x00, sizeof(outp->dp.lttpr)); 690 } 691 692 if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, sizeof(outp->dp.dpcd))) { 693 const u8 rates[] = { 0x1e, 0x14, 0x0a, 0x06, 0 }; 694 const u8 *rate; 695 int rate_max; 696 697 outp->dp.rates = 0; 698 outp->dp.links = outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_MAX_LANE_COUNT; 699 outp->dp.links = min(outp->dp.links, outp->info.dpconf.link_nr); 700 if (outp->dp.lttprs && outp->dp.lttpr[4]) 701 outp->dp.links = min_t(int, outp->dp.links, outp->dp.lttpr[4]); 702 703 rate_max = outp->dp.dpcd[DPCD_RC01_MAX_LINK_RATE]; 704 rate_max = min(rate_max, outp->info.dpconf.link_bw); 705 if (outp->dp.lttprs && outp->dp.lttpr[1]) 706 rate_max = min_t(int, rate_max, outp->dp.lttpr[1]); 707 708 if (!nvkm_dp_enable_supported_link_rates(outp)) { 709 for (rate = rates; *rate; rate++) { 710 if (*rate > rate_max) 711 continue; 712 713 if (WARN_ON(outp->dp.rates == ARRAY_SIZE(outp->dp.rate))) 714 break; 715 716 outp->dp.rate[outp->dp.rates].dpcd = -1; 717 outp->dp.rate[outp->dp.rates].rate = *rate * 27000; 718 outp->dp.rates++; 719 } 720 } 721 } 722 } else 723 if (!auxpwr && outp->dp.aux_pwr) { 724 OUTP_DBG(outp, "aux power -> demand"); 725 nvkm_i2c_aux_monitor(aux, false); 726 outp->dp.aux_pwr = false; 727 atomic_set(&outp->dp.lt.done, 0); 728 729 /* Restore eDP panel GPIO to its prior state if we changed it, as 730 * it could potentially interfere with other outputs. 731 */ 732 if (outp->conn->info.type == DCB_CONNECTOR_eDP) { 733 if (outp->dp.aux_pwr_pu) { 734 nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 0); 735 outp->dp.aux_pwr_pu = false; 736 } 737 } 738 } 739 } 740 741 static void 742 nvkm_dp_fini(struct nvkm_outp *outp) 743 { 744 nvkm_dp_enable(outp, false); 745 } 746 747 static void 748 nvkm_dp_init(struct nvkm_outp *outp) 749 { 750 nvkm_dp_enable(outp, outp->dp.enabled); 751 } 752 753 static void * 754 nvkm_dp_dtor(struct nvkm_outp *outp) 755 { 756 return outp; 757 } 758 759 static const struct nvkm_outp_func 760 nvkm_dp_func = { 761 .dtor = nvkm_dp_dtor, 762 .init = nvkm_dp_init, 763 .fini = nvkm_dp_fini, 764 .acquire = nvkm_dp_acquire, 765 .release = nvkm_dp_release, 766 .disable = nvkm_dp_disable, 767 }; 768 769 int 770 nvkm_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, struct nvkm_outp **poutp) 771 { 772 struct nvkm_device *device = disp->engine.subdev.device; 773 struct nvkm_bios *bios = device->bios; 774 struct nvkm_i2c *i2c = device->i2c; 775 struct nvkm_outp *outp; 776 u8 hdr, cnt, len; 777 u32 data; 778 int ret; 779 780 ret = nvkm_outp_new_(&nvkm_dp_func, disp, index, dcbE, poutp); 781 outp = *poutp; 782 if (ret) 783 return ret; 784 785 if (dcbE->location == 0) 786 outp->dp.aux = nvkm_i2c_aux_find(i2c, NVKM_I2C_AUX_CCB(dcbE->i2c_index)); 787 else 788 outp->dp.aux = nvkm_i2c_aux_find(i2c, NVKM_I2C_AUX_EXT(dcbE->extdev)); 789 if (!outp->dp.aux) { 790 OUTP_ERR(outp, "no aux"); 791 return -EINVAL; 792 } 793 794 /* bios data is not optional */ 795 data = nvbios_dpout_match(bios, outp->info.hasht, outp->info.hashm, 796 &outp->dp.version, &hdr, &cnt, &len, &outp->dp.info); 797 if (!data) { 798 OUTP_ERR(outp, "no bios dp data"); 799 return -EINVAL; 800 } 801 802 OUTP_DBG(outp, "bios dp %02x %02x %02x %02x", outp->dp.version, hdr, cnt, len); 803 804 mutex_init(&outp->dp.mutex); 805 atomic_set(&outp->dp.lt.done, 0); 806 return 0; 807 } 808