1 /* 2 * Copyright © 2016 Intel Corporation 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 (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * 24 */ 25 26 #include <drm/display/drm_dp_dual_mode_helper.h> 27 #include <drm/display/drm_hdmi_helper.h> 28 #include <drm/drm_atomic_helper.h> 29 #include <drm/drm_edid.h> 30 #include <drm/drm_print.h> 31 32 #include "i915_utils.h" 33 #include "intel_de.h" 34 #include "intel_display_regs.h" 35 #include "intel_display_types.h" 36 #include "intel_dp.h" 37 #include "intel_hdmi.h" 38 #include "intel_lspcon.h" 39 40 /* LSPCON OUI Vendor ID(signatures) */ 41 #define LSPCON_VENDOR_PARADE_OUI 0x001CF8 42 #define LSPCON_VENDOR_MCA_OUI 0x0060AD 43 44 #define DPCD_MCA_LSPCON_HDR_STATUS 0x70003 45 #define DPCD_PARADE_LSPCON_HDR_STATUS 0x00511 46 47 /* AUX addresses to write MCA AVI IF */ 48 #define LSPCON_MCA_AVI_IF_WRITE_OFFSET 0x5C0 49 #define LSPCON_MCA_AVI_IF_CTRL 0x5DF 50 #define LSPCON_MCA_AVI_IF_KICKOFF (1 << 0) 51 #define LSPCON_MCA_AVI_IF_HANDLED (1 << 1) 52 53 /* AUX addresses to write Parade AVI IF */ 54 #define LSPCON_PARADE_AVI_IF_WRITE_OFFSET 0x516 55 #define LSPCON_PARADE_AVI_IF_CTRL 0x51E 56 #define LSPCON_PARADE_AVI_IF_KICKOFF (1 << 7) 57 #define LSPCON_PARADE_AVI_IF_DATA_SIZE 32 58 59 static struct intel_lspcon *enc_to_intel_lspcon(struct intel_encoder *encoder) 60 { 61 return &enc_to_dig_port(encoder)->lspcon; 62 } 63 64 static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon) 65 { 66 struct intel_digital_port *dig_port = 67 container_of(lspcon, struct intel_digital_port, lspcon); 68 69 return &dig_port->dp; 70 } 71 72 static const char *lspcon_mode_name(enum drm_lspcon_mode mode) 73 { 74 switch (mode) { 75 case DRM_LSPCON_MODE_PCON: 76 return "PCON"; 77 case DRM_LSPCON_MODE_LS: 78 return "LS"; 79 case DRM_LSPCON_MODE_INVALID: 80 return "INVALID"; 81 default: 82 MISSING_CASE(mode); 83 return "INVALID"; 84 } 85 } 86 87 static bool lspcon_detect_vendor(struct intel_lspcon *lspcon) 88 { 89 struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); 90 struct intel_display *display = to_intel_display(intel_dp); 91 struct drm_dp_dpcd_ident *ident; 92 u32 vendor_oui; 93 94 if (drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc, drm_dp_is_branch(intel_dp->dpcd))) { 95 drm_err(display->drm, "Can't read description\n"); 96 return false; 97 } 98 99 ident = &intel_dp->desc.ident; 100 vendor_oui = (ident->oui[0] << 16) | (ident->oui[1] << 8) | 101 ident->oui[2]; 102 103 switch (vendor_oui) { 104 case LSPCON_VENDOR_MCA_OUI: 105 lspcon->vendor = LSPCON_VENDOR_MCA; 106 drm_dbg_kms(display->drm, "Vendor: Mega Chips\n"); 107 break; 108 109 case LSPCON_VENDOR_PARADE_OUI: 110 lspcon->vendor = LSPCON_VENDOR_PARADE; 111 drm_dbg_kms(display->drm, "Vendor: Parade Tech\n"); 112 break; 113 114 default: 115 drm_err(display->drm, "Invalid/Unknown vendor OUI\n"); 116 return false; 117 } 118 119 return true; 120 } 121 122 static u32 get_hdr_status_reg(struct intel_lspcon *lspcon) 123 { 124 if (lspcon->vendor == LSPCON_VENDOR_MCA) 125 return DPCD_MCA_LSPCON_HDR_STATUS; 126 else 127 return DPCD_PARADE_LSPCON_HDR_STATUS; 128 } 129 130 bool intel_lspcon_detect_hdr_capability(struct intel_digital_port *dig_port) 131 { 132 struct intel_lspcon *lspcon = &dig_port->lspcon; 133 struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); 134 struct intel_display *display = to_intel_display(intel_dp); 135 u8 hdr_caps; 136 int ret; 137 138 ret = drm_dp_dpcd_read(&intel_dp->aux, get_hdr_status_reg(lspcon), 139 &hdr_caps, 1); 140 141 if (ret < 0) { 142 drm_dbg_kms(display->drm, "HDR capability detection failed\n"); 143 lspcon->hdr_supported = false; 144 } else if (hdr_caps & 0x1) { 145 drm_dbg_kms(display->drm, "LSPCON capable of HDR\n"); 146 lspcon->hdr_supported = true; 147 } 148 149 return lspcon->hdr_supported; 150 } 151 152 static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon) 153 { 154 struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); 155 struct intel_display *display = to_intel_display(intel_dp); 156 enum drm_lspcon_mode current_mode; 157 struct i2c_adapter *ddc = &intel_dp->aux.ddc; 158 159 if (drm_lspcon_get_mode(intel_dp->aux.drm_dev, ddc, ¤t_mode)) { 160 drm_dbg_kms(display->drm, "Error reading LSPCON mode\n"); 161 return DRM_LSPCON_MODE_INVALID; 162 } 163 return current_mode; 164 } 165 166 static int lspcon_get_mode_settle_timeout(struct intel_lspcon *lspcon) 167 { 168 /* 169 * On some CometLake-based device designs the Parade PS175 takes more 170 * than 400ms to settle in PCON mode. 100 reboot trials on one device 171 * resulted in a median settle time of 440ms and a maximum of 444ms. 172 * Even after increasing the timeout to 500ms, 2% of devices still had 173 * this error. So this sets the timeout to 800ms. 174 */ 175 return lspcon->vendor == LSPCON_VENDOR_PARADE ? 800 : 400; 176 } 177 178 static enum drm_lspcon_mode lspcon_wait_mode(struct intel_lspcon *lspcon, 179 enum drm_lspcon_mode mode) 180 { 181 struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); 182 struct intel_display *display = to_intel_display(intel_dp); 183 enum drm_lspcon_mode current_mode; 184 185 current_mode = lspcon_get_current_mode(lspcon); 186 if (current_mode == mode) 187 goto out; 188 189 drm_dbg_kms(display->drm, "Waiting for LSPCON mode %s to settle\n", 190 lspcon_mode_name(mode)); 191 192 wait_for((current_mode = lspcon_get_current_mode(lspcon)) == mode, 193 lspcon_get_mode_settle_timeout(lspcon)); 194 if (current_mode != mode) 195 drm_err(display->drm, "LSPCON mode hasn't settled\n"); 196 197 out: 198 drm_dbg_kms(display->drm, "Current LSPCON mode %s\n", 199 lspcon_mode_name(current_mode)); 200 201 return current_mode; 202 } 203 204 static int lspcon_change_mode(struct intel_lspcon *lspcon, 205 enum drm_lspcon_mode mode) 206 { 207 struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); 208 struct intel_display *display = to_intel_display(intel_dp); 209 int err; 210 enum drm_lspcon_mode current_mode; 211 struct i2c_adapter *ddc = &intel_dp->aux.ddc; 212 213 err = drm_lspcon_get_mode(intel_dp->aux.drm_dev, ddc, ¤t_mode); 214 if (err) { 215 drm_err(display->drm, "Error reading LSPCON mode\n"); 216 return err; 217 } 218 219 if (current_mode == mode) { 220 drm_dbg_kms(display->drm, "Current mode = desired LSPCON mode\n"); 221 return 0; 222 } 223 224 err = drm_lspcon_set_mode(intel_dp->aux.drm_dev, ddc, mode, 225 lspcon_get_mode_settle_timeout(lspcon)); 226 if (err < 0) { 227 drm_err(display->drm, "LSPCON mode change failed\n"); 228 return err; 229 } 230 231 lspcon->mode = mode; 232 drm_dbg_kms(display->drm, "LSPCON mode changed done\n"); 233 return 0; 234 } 235 236 static bool lspcon_wake_native_aux_ch(struct intel_lspcon *lspcon) 237 { 238 struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); 239 struct intel_display *display = to_intel_display(intel_dp); 240 u8 rev; 241 242 if (drm_dp_dpcd_readb(&lspcon_to_intel_dp(lspcon)->aux, DP_DPCD_REV, 243 &rev) != 1) { 244 drm_dbg_kms(display->drm, "Native AUX CH down\n"); 245 return false; 246 } 247 248 drm_dbg_kms(display->drm, "Native AUX CH up, DPCD version: %d.%d\n", 249 rev >> 4, rev & 0xf); 250 251 return true; 252 } 253 254 static bool lspcon_probe(struct intel_lspcon *lspcon) 255 { 256 struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); 257 struct intel_display *display = to_intel_display(intel_dp); 258 struct i2c_adapter *ddc = &intel_dp->aux.ddc; 259 enum drm_dp_dual_mode_type adaptor_type; 260 enum drm_lspcon_mode expected_mode; 261 int retry; 262 263 expected_mode = lspcon_wake_native_aux_ch(lspcon) ? 264 DRM_LSPCON_MODE_PCON : DRM_LSPCON_MODE_LS; 265 266 /* Lets probe the adaptor and check its type */ 267 for (retry = 0; retry < 6; retry++) { 268 if (retry) 269 usleep_range(500, 1000); 270 271 adaptor_type = drm_dp_dual_mode_detect(intel_dp->aux.drm_dev, ddc); 272 if (adaptor_type == DRM_DP_DUAL_MODE_LSPCON) 273 break; 274 } 275 276 if (adaptor_type != DRM_DP_DUAL_MODE_LSPCON) { 277 drm_dbg_kms(display->drm, "No LSPCON detected, found %s\n", 278 drm_dp_get_dual_mode_type_name(adaptor_type)); 279 return false; 280 } 281 282 /* Yay ... got a LSPCON device */ 283 drm_dbg_kms(display->drm, "LSPCON detected\n"); 284 lspcon->mode = lspcon_wait_mode(lspcon, expected_mode); 285 286 /* 287 * In the SW state machine, lets Put LSPCON in PCON mode only. 288 * In this way, it will work with both HDMI 1.4 sinks as well as HDMI 289 * 2.0 sinks. 290 */ 291 if (lspcon->mode != DRM_LSPCON_MODE_PCON) { 292 if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON) < 0) { 293 drm_err(display->drm, "LSPCON mode change to PCON failed\n"); 294 return false; 295 } 296 } 297 return true; 298 } 299 300 static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon) 301 { 302 struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); 303 struct intel_display *display = to_intel_display(intel_dp); 304 struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); 305 unsigned long start = jiffies; 306 307 while (1) { 308 if (intel_digital_port_connected(&dig_port->base)) { 309 drm_dbg_kms(display->drm, "LSPCON recovering in PCON mode after %u ms\n", 310 jiffies_to_msecs(jiffies - start)); 311 return; 312 } 313 314 if (time_after(jiffies, start + msecs_to_jiffies(1000))) 315 break; 316 317 usleep_range(10000, 15000); 318 } 319 320 drm_dbg_kms(display->drm, "LSPCON DP descriptor mismatch after resume\n"); 321 } 322 323 static bool lspcon_parade_fw_ready(struct drm_dp_aux *aux) 324 { 325 u8 avi_if_ctrl; 326 u8 retry; 327 ssize_t ret; 328 329 /* Check if LSPCON FW is ready for data */ 330 for (retry = 0; retry < 5; retry++) { 331 if (retry) 332 usleep_range(200, 300); 333 334 ret = drm_dp_dpcd_read(aux, LSPCON_PARADE_AVI_IF_CTRL, 335 &avi_if_ctrl, 1); 336 if (ret < 0) { 337 drm_err(aux->drm_dev, "Failed to read AVI IF control\n"); 338 return false; 339 } 340 341 if ((avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF) == 0) 342 return true; 343 } 344 345 drm_err(aux->drm_dev, "Parade FW not ready to accept AVI IF\n"); 346 return false; 347 } 348 349 static bool _lspcon_parade_write_infoframe_blocks(struct drm_dp_aux *aux, 350 u8 *avi_buf) 351 { 352 u8 avi_if_ctrl; 353 u8 block_count = 0; 354 u8 *data; 355 u16 reg; 356 ssize_t ret; 357 358 while (block_count < 4) { 359 if (!lspcon_parade_fw_ready(aux)) { 360 drm_dbg_kms(aux->drm_dev, "LSPCON FW not ready, block %d\n", 361 block_count); 362 return false; 363 } 364 365 reg = LSPCON_PARADE_AVI_IF_WRITE_OFFSET; 366 data = avi_buf + block_count * 8; 367 ret = drm_dp_dpcd_write(aux, reg, data, 8); 368 if (ret < 0) { 369 drm_err(aux->drm_dev, "Failed to write AVI IF block %d\n", 370 block_count); 371 return false; 372 } 373 374 /* 375 * Once a block of data is written, we have to inform the FW 376 * about this by writing into avi infoframe control register: 377 * - set the kickoff bit[7] to 1 378 * - write the block no. to bits[1:0] 379 */ 380 reg = LSPCON_PARADE_AVI_IF_CTRL; 381 avi_if_ctrl = LSPCON_PARADE_AVI_IF_KICKOFF | block_count; 382 ret = drm_dp_dpcd_write(aux, reg, &avi_if_ctrl, 1); 383 if (ret < 0) { 384 drm_err(aux->drm_dev, "Failed to update (0x%x), block %d\n", 385 reg, block_count); 386 return false; 387 } 388 389 block_count++; 390 } 391 392 drm_dbg_kms(aux->drm_dev, "Wrote AVI IF blocks successfully\n"); 393 return true; 394 } 395 396 static bool _lspcon_write_avi_infoframe_parade(struct drm_dp_aux *aux, 397 const u8 *frame, 398 ssize_t len) 399 { 400 u8 avi_if[LSPCON_PARADE_AVI_IF_DATA_SIZE] = {1, }; 401 402 /* 403 * Parade's frames contains 32 bytes of data, divided 404 * into 4 frames: 405 * Token byte (first byte of first frame, must be non-zero) 406 * HB0 to HB2 from AVI IF (3 bytes header) 407 * PB0 to PB27 from AVI IF (28 bytes data) 408 * So it should look like this 409 * first block: | <token> <HB0-HB2> <DB0-DB3> | 410 * next 3 blocks: |<DB4-DB11>|<DB12-DB19>|<DB20-DB28>| 411 */ 412 413 if (len > LSPCON_PARADE_AVI_IF_DATA_SIZE - 1) { 414 drm_err(aux->drm_dev, "Invalid length of infoframes\n"); 415 return false; 416 } 417 418 memcpy(&avi_if[1], frame, len); 419 420 if (!_lspcon_parade_write_infoframe_blocks(aux, avi_if)) { 421 drm_dbg_kms(aux->drm_dev, "Failed to write infoframe blocks\n"); 422 return false; 423 } 424 425 return true; 426 } 427 428 static bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux, 429 const u8 *buffer, ssize_t len) 430 { 431 int ret; 432 u32 val = 0; 433 u32 retry; 434 u16 reg; 435 const u8 *data = buffer; 436 437 reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET; 438 while (val < len) { 439 /* DPCD write for AVI IF can fail on a slow FW day, so retry */ 440 for (retry = 0; retry < 5; retry++) { 441 ret = drm_dp_dpcd_write(aux, reg, (void *)data, 1); 442 if (ret == 1) { 443 break; 444 } else if (retry < 4) { 445 mdelay(50); 446 continue; 447 } else { 448 drm_err(aux->drm_dev, "DPCD write failed at:0x%x\n", reg); 449 return false; 450 } 451 } 452 val++; reg++; data++; 453 } 454 455 val = 0; 456 reg = LSPCON_MCA_AVI_IF_CTRL; 457 ret = drm_dp_dpcd_read(aux, reg, &val, 1); 458 if (ret < 0) { 459 drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); 460 return false; 461 } 462 463 /* Indicate LSPCON chip about infoframe, clear bit 1 and set bit 0 */ 464 val &= ~LSPCON_MCA_AVI_IF_HANDLED; 465 val |= LSPCON_MCA_AVI_IF_KICKOFF; 466 467 ret = drm_dp_dpcd_write(aux, reg, &val, 1); 468 if (ret < 0) { 469 drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); 470 return false; 471 } 472 473 val = 0; 474 ret = drm_dp_dpcd_read(aux, reg, &val, 1); 475 if (ret < 0) { 476 drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); 477 return false; 478 } 479 480 if (val == LSPCON_MCA_AVI_IF_HANDLED) 481 drm_dbg_kms(aux->drm_dev, "AVI IF handled by FW\n"); 482 483 return true; 484 } 485 486 void lspcon_write_infoframe(struct intel_encoder *encoder, 487 const struct intel_crtc_state *crtc_state, 488 unsigned int type, 489 const void *frame, ssize_t len) 490 { 491 struct intel_display *display = to_intel_display(encoder); 492 struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 493 struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder); 494 bool ret = true; 495 496 switch (type) { 497 case HDMI_INFOFRAME_TYPE_AVI: 498 if (lspcon->vendor == LSPCON_VENDOR_MCA) 499 ret = _lspcon_write_avi_infoframe_mca(&intel_dp->aux, 500 frame, len); 501 else 502 ret = _lspcon_write_avi_infoframe_parade(&intel_dp->aux, 503 frame, len); 504 break; 505 case HDMI_PACKET_TYPE_GAMUT_METADATA: 506 drm_dbg_kms(display->drm, "Update HDR metadata for lspcon\n"); 507 /* It uses the legacy hsw implementation for the same */ 508 hsw_write_infoframe(encoder, crtc_state, type, frame, len); 509 break; 510 default: 511 return; 512 } 513 514 if (!ret) { 515 drm_err(display->drm, "Failed to write infoframes\n"); 516 return; 517 } 518 } 519 520 void lspcon_read_infoframe(struct intel_encoder *encoder, 521 const struct intel_crtc_state *crtc_state, 522 unsigned int type, 523 void *frame, ssize_t len) 524 { 525 /* FIXME implement for AVI Infoframe as well */ 526 if (type == HDMI_PACKET_TYPE_GAMUT_METADATA) 527 hsw_read_infoframe(encoder, crtc_state, type, 528 frame, len); 529 } 530 531 void lspcon_set_infoframes(struct intel_encoder *encoder, 532 bool enable, 533 const struct intel_crtc_state *crtc_state, 534 const struct drm_connector_state *conn_state) 535 { 536 struct intel_display *display = to_intel_display(encoder); 537 struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 538 struct intel_lspcon *lspcon = &dig_port->lspcon; 539 const struct drm_display_mode *adjusted_mode = 540 &crtc_state->hw.adjusted_mode; 541 union hdmi_infoframe frame; 542 u8 buf[VIDEO_DIP_DATA_SIZE]; 543 ssize_t ret; 544 545 if (!lspcon->active) { 546 drm_err(display->drm, "Writing infoframes while LSPCON disabled ?\n"); 547 return; 548 } 549 550 /* FIXME precompute infoframes */ 551 552 ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, 553 conn_state->connector, 554 adjusted_mode); 555 if (ret < 0) { 556 drm_err(display->drm, "couldn't fill AVI infoframe\n"); 557 return; 558 } 559 560 /* 561 * Currently there is no interface defined to 562 * check user preference between RGB/YCBCR444 563 * or YCBCR420. So the only possible case for 564 * YCBCR444 usage is driving YCBCR420 output 565 * with LSPCON, when pipe is configured for 566 * YCBCR444 output and LSPCON takes care of 567 * downsampling it. 568 */ 569 if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) 570 frame.avi.colorspace = HDMI_COLORSPACE_YUV420; 571 else 572 frame.avi.colorspace = HDMI_COLORSPACE_RGB; 573 574 /* Set the Colorspace as per the HDMI spec */ 575 drm_hdmi_avi_infoframe_colorimetry(&frame.avi, conn_state); 576 577 /* nonsense combination */ 578 drm_WARN_ON(encoder->base.dev, crtc_state->limited_color_range && 579 crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB); 580 581 if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_RGB) { 582 drm_hdmi_avi_infoframe_quant_range(&frame.avi, 583 conn_state->connector, 584 adjusted_mode, 585 crtc_state->limited_color_range ? 586 HDMI_QUANTIZATION_RANGE_LIMITED : 587 HDMI_QUANTIZATION_RANGE_FULL); 588 } else { 589 frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT; 590 frame.avi.ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; 591 } 592 593 drm_hdmi_avi_infoframe_content_type(&frame.avi, conn_state); 594 595 ret = hdmi_infoframe_pack(&frame, buf, sizeof(buf)); 596 if (ret < 0) { 597 drm_err(display->drm, "Failed to pack AVI IF\n"); 598 return; 599 } 600 601 dig_port->write_infoframe(encoder, crtc_state, HDMI_INFOFRAME_TYPE_AVI, 602 buf, ret); 603 } 604 605 static bool _lspcon_read_avi_infoframe_enabled_mca(struct drm_dp_aux *aux) 606 { 607 int ret; 608 u32 val = 0; 609 u16 reg = LSPCON_MCA_AVI_IF_CTRL; 610 611 ret = drm_dp_dpcd_read(aux, reg, &val, 1); 612 if (ret < 0) { 613 drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); 614 return false; 615 } 616 617 return val & LSPCON_MCA_AVI_IF_KICKOFF; 618 } 619 620 static bool _lspcon_read_avi_infoframe_enabled_parade(struct drm_dp_aux *aux) 621 { 622 int ret; 623 u32 val = 0; 624 u16 reg = LSPCON_PARADE_AVI_IF_CTRL; 625 626 ret = drm_dp_dpcd_read(aux, reg, &val, 1); 627 if (ret < 0) { 628 drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); 629 return false; 630 } 631 632 return val & LSPCON_PARADE_AVI_IF_KICKOFF; 633 } 634 635 u32 lspcon_infoframes_enabled(struct intel_encoder *encoder, 636 const struct intel_crtc_state *pipe_config) 637 { 638 struct intel_display *display = to_intel_display(encoder); 639 struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 640 struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder); 641 bool infoframes_enabled; 642 u32 val = 0; 643 u32 mask, tmp; 644 645 if (lspcon->vendor == LSPCON_VENDOR_MCA) 646 infoframes_enabled = _lspcon_read_avi_infoframe_enabled_mca(&intel_dp->aux); 647 else 648 infoframes_enabled = _lspcon_read_avi_infoframe_enabled_parade(&intel_dp->aux); 649 650 if (infoframes_enabled) 651 val |= intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI); 652 653 if (lspcon->hdr_supported) { 654 tmp = intel_de_read(display, 655 HSW_TVIDEO_DIP_CTL(display, pipe_config->cpu_transcoder)); 656 mask = VIDEO_DIP_ENABLE_GMP_HSW; 657 658 if (tmp & mask) 659 val |= intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA); 660 } 661 662 return val; 663 } 664 665 void intel_lspcon_wait_pcon_mode(struct intel_digital_port *dig_port) 666 { 667 struct intel_lspcon *lspcon = &dig_port->lspcon; 668 669 lspcon_wait_mode(lspcon, DRM_LSPCON_MODE_PCON); 670 } 671 672 bool intel_lspcon_init(struct intel_digital_port *dig_port) 673 { 674 struct intel_display *display = to_intel_display(dig_port); 675 struct intel_dp *intel_dp = &dig_port->dp; 676 struct intel_lspcon *lspcon = &dig_port->lspcon; 677 struct drm_connector *connector = &intel_dp->attached_connector->base; 678 679 lspcon->active = false; 680 lspcon->mode = DRM_LSPCON_MODE_INVALID; 681 682 if (!lspcon_probe(lspcon)) { 683 drm_err(display->drm, "Failed to probe lspcon\n"); 684 return false; 685 } 686 687 if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd) != 0) { 688 drm_err(display->drm, "LSPCON DPCD read failed\n"); 689 return false; 690 } 691 692 if (!lspcon_detect_vendor(lspcon)) { 693 drm_err(display->drm, "LSPCON vendor detection failed\n"); 694 return false; 695 } 696 697 connector->ycbcr_420_allowed = true; 698 lspcon->active = true; 699 drm_dbg_kms(display->drm, "Success: LSPCON init\n"); 700 return true; 701 } 702 703 bool intel_lspcon_active(struct intel_digital_port *dig_port) 704 { 705 struct intel_lspcon *lspcon = &dig_port->lspcon; 706 707 return lspcon->active; 708 } 709 710 u32 intel_lspcon_infoframes_enabled(struct intel_encoder *encoder, 711 const struct intel_crtc_state *pipe_config) 712 { 713 struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 714 715 return dig_port->infoframes_enabled(encoder, pipe_config); 716 } 717 718 void intel_lspcon_resume(struct intel_digital_port *dig_port) 719 { 720 struct intel_display *display = to_intel_display(dig_port); 721 struct intel_lspcon *lspcon = &dig_port->lspcon; 722 enum drm_lspcon_mode expected_mode; 723 724 if (!intel_bios_encoder_is_lspcon(dig_port->base.devdata)) 725 return; 726 727 if (!lspcon->active) { 728 if (!intel_lspcon_init(dig_port)) { 729 drm_err(display->drm, "LSPCON init failed on port %c\n", 730 port_name(dig_port->base.port)); 731 return; 732 } 733 } 734 735 if (lspcon_wake_native_aux_ch(lspcon)) { 736 expected_mode = DRM_LSPCON_MODE_PCON; 737 lspcon_resume_in_pcon_wa(lspcon); 738 } else { 739 expected_mode = DRM_LSPCON_MODE_LS; 740 } 741 742 if (lspcon_wait_mode(lspcon, expected_mode) == DRM_LSPCON_MODE_PCON) 743 return; 744 745 if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON)) 746 drm_err(display->drm, "LSPCON resume failed\n"); 747 else 748 drm_dbg_kms(display->drm, "LSPCON resume success\n"); 749 } 750