1 // SPDX-License-Identifier: MIT 2 3 #include <drm/drm_atomic.h> 4 #include <drm/drm_connector.h> 5 #include <drm/drm_edid.h> 6 #include <drm/drm_print.h> 7 8 #include <drm/display/drm_hdmi_audio_helper.h> 9 #include <drm/display/drm_hdmi_helper.h> 10 #include <drm/display/drm_hdmi_state_helper.h> 11 12 /** 13 * __drm_atomic_helper_connector_hdmi_reset() - Initializes all HDMI @drm_connector_state resources 14 * @connector: DRM connector 15 * @new_conn_state: connector state to reset 16 * 17 * Initializes all HDMI resources from a @drm_connector_state without 18 * actually allocating it. This is useful for HDMI drivers, in 19 * combination with __drm_atomic_helper_connector_reset() or 20 * drm_atomic_helper_connector_reset(). 21 */ 22 void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector *connector, 23 struct drm_connector_state *new_conn_state) 24 { 25 unsigned int max_bpc = connector->max_bpc; 26 27 new_conn_state->max_bpc = max_bpc; 28 new_conn_state->max_requested_bpc = max_bpc; 29 new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO; 30 } 31 EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset); 32 33 static const struct drm_display_mode * 34 connector_state_get_mode(const struct drm_connector_state *conn_state) 35 { 36 struct drm_atomic_state *state; 37 struct drm_crtc_state *crtc_state; 38 struct drm_crtc *crtc; 39 40 state = conn_state->state; 41 if (!state) 42 return NULL; 43 44 crtc = conn_state->crtc; 45 if (!crtc) 46 return NULL; 47 48 crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 49 if (!crtc_state) 50 return NULL; 51 52 return &crtc_state->mode; 53 } 54 55 static bool hdmi_is_limited_range(const struct drm_connector *connector, 56 const struct drm_connector_state *conn_state) 57 { 58 const struct drm_display_info *info = &connector->display_info; 59 const struct drm_display_mode *mode = 60 connector_state_get_mode(conn_state); 61 62 /* 63 * The Broadcast RGB property only applies to RGB format, and 64 * i915 just assumes limited range for YCbCr output, so let's 65 * just do the same. 66 */ 67 if (conn_state->hdmi.output_format != HDMI_COLORSPACE_RGB) 68 return true; 69 70 if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_FULL) 71 return false; 72 73 if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_LIMITED) 74 return true; 75 76 if (!info->is_hdmi) 77 return false; 78 79 return drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED; 80 } 81 82 static bool 83 sink_supports_format_bpc(const struct drm_connector *connector, 84 const struct drm_display_info *info, 85 const struct drm_display_mode *mode, 86 unsigned int format, unsigned int bpc) 87 { 88 struct drm_device *dev = connector->dev; 89 u8 vic = drm_match_cea_mode(mode); 90 91 /* 92 * CTA-861-F, section 5.4 - Color Coding & Quantization states 93 * that the bpc must be 8, 10, 12 or 16 except for the default 94 * 640x480 VIC1 where the value must be 8. 95 * 96 * The definition of default here is ambiguous but the spec 97 * refers to VIC1 being the default timing in several occasions 98 * so our understanding is that for the default timing (ie, 99 * VIC1), the bpc must be 8. 100 */ 101 if (vic == 1 && bpc != 8) { 102 drm_dbg_kms(dev, "VIC1 requires a bpc of 8, got %u\n", bpc); 103 return false; 104 } 105 106 if (!info->is_hdmi && 107 (format != HDMI_COLORSPACE_RGB || bpc != 8)) { 108 drm_dbg_kms(dev, "DVI Monitors require an RGB output at 8 bpc\n"); 109 return false; 110 } 111 112 if (!(connector->hdmi.supported_formats & BIT(format))) { 113 drm_dbg_kms(dev, "%s format unsupported by the connector.\n", 114 drm_hdmi_connector_get_output_format_name(format)); 115 return false; 116 } 117 118 switch (format) { 119 case HDMI_COLORSPACE_RGB: 120 drm_dbg_kms(dev, "RGB Format, checking the constraints.\n"); 121 122 /* 123 * In some cases, like when the EDID readout fails, or 124 * is not an HDMI compliant EDID for some reason, the 125 * color_formats field will be blank and not report any 126 * format supported. In such a case, assume that RGB is 127 * supported so we can keep things going and light up 128 * the display. 129 */ 130 if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444)) 131 drm_warn(dev, "HDMI Sink doesn't support RGB, something's wrong.\n"); 132 133 if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) { 134 drm_dbg_kms(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); 135 return false; 136 } 137 138 if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) { 139 drm_dbg_kms(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); 140 return false; 141 } 142 143 drm_dbg_kms(dev, "RGB format supported in that configuration.\n"); 144 145 return true; 146 147 case HDMI_COLORSPACE_YUV420: 148 /* TODO: YUV420 is unsupported at the moment. */ 149 drm_dbg_kms(dev, "YUV420 format isn't supported yet.\n"); 150 return false; 151 152 case HDMI_COLORSPACE_YUV422: 153 drm_dbg_kms(dev, "YUV422 format, checking the constraints.\n"); 154 155 if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) { 156 drm_dbg_kms(dev, "Sink doesn't support YUV422.\n"); 157 return false; 158 } 159 160 if (bpc > 12) { 161 drm_dbg_kms(dev, "YUV422 only supports 12 bpc or lower.\n"); 162 return false; 163 } 164 165 /* 166 * HDMI Spec 1.3 - Section 6.5 Pixel Encodings and Color Depth 167 * states that Deep Color is not relevant for YUV422 so we 168 * don't need to check the Deep Color bits in the EDIDs here. 169 */ 170 171 drm_dbg_kms(dev, "YUV422 format supported in that configuration.\n"); 172 173 return true; 174 175 case HDMI_COLORSPACE_YUV444: 176 drm_dbg_kms(dev, "YUV444 format, checking the constraints.\n"); 177 178 if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) { 179 drm_dbg_kms(dev, "Sink doesn't support YUV444.\n"); 180 return false; 181 } 182 183 if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) { 184 drm_dbg_kms(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); 185 return false; 186 } 187 188 if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) { 189 drm_dbg_kms(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); 190 return false; 191 } 192 193 drm_dbg_kms(dev, "YUV444 format supported in that configuration.\n"); 194 195 return true; 196 } 197 198 drm_dbg_kms(dev, "Unsupported pixel format.\n"); 199 return false; 200 } 201 202 static enum drm_mode_status 203 hdmi_clock_valid(const struct drm_connector *connector, 204 const struct drm_display_mode *mode, 205 unsigned long long clock) 206 { 207 const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; 208 const struct drm_display_info *info = &connector->display_info; 209 210 if (info->max_tmds_clock && clock > info->max_tmds_clock * 1000) 211 return MODE_CLOCK_HIGH; 212 213 if (funcs && funcs->tmds_char_rate_valid) { 214 enum drm_mode_status status; 215 216 status = funcs->tmds_char_rate_valid(connector, mode, clock); 217 if (status != MODE_OK) 218 return status; 219 } 220 221 return MODE_OK; 222 } 223 224 static int 225 hdmi_compute_clock(const struct drm_connector *connector, 226 struct drm_connector_state *conn_state, 227 const struct drm_display_mode *mode, 228 unsigned int bpc, enum hdmi_colorspace fmt) 229 { 230 enum drm_mode_status status; 231 unsigned long long clock; 232 233 clock = drm_hdmi_compute_mode_clock(mode, bpc, fmt); 234 if (!clock) 235 return -EINVAL; 236 237 status = hdmi_clock_valid(connector, mode, clock); 238 if (status != MODE_OK) 239 return -EINVAL; 240 241 conn_state->hdmi.tmds_char_rate = clock; 242 243 return 0; 244 } 245 246 static bool 247 hdmi_try_format_bpc(const struct drm_connector *connector, 248 struct drm_connector_state *conn_state, 249 const struct drm_display_mode *mode, 250 unsigned int bpc, enum hdmi_colorspace fmt) 251 { 252 const struct drm_display_info *info = &connector->display_info; 253 struct drm_device *dev = connector->dev; 254 int ret; 255 256 drm_dbg_kms(dev, "Trying %s output format\n", 257 drm_hdmi_connector_get_output_format_name(fmt)); 258 259 if (!sink_supports_format_bpc(connector, info, mode, fmt, bpc)) { 260 drm_dbg_kms(dev, "%s output format not supported with %u bpc\n", 261 drm_hdmi_connector_get_output_format_name(fmt), 262 bpc); 263 return false; 264 } 265 266 ret = hdmi_compute_clock(connector, conn_state, mode, bpc, fmt); 267 if (ret) { 268 drm_dbg_kms(dev, "Couldn't compute clock for %s output format and %u bpc\n", 269 drm_hdmi_connector_get_output_format_name(fmt), 270 bpc); 271 return false; 272 } 273 274 drm_dbg_kms(dev, "%s output format supported with %u (TMDS char rate: %llu Hz)\n", 275 drm_hdmi_connector_get_output_format_name(fmt), 276 bpc, conn_state->hdmi.tmds_char_rate); 277 278 return true; 279 } 280 281 static int 282 hdmi_compute_format(const struct drm_connector *connector, 283 struct drm_connector_state *conn_state, 284 const struct drm_display_mode *mode, 285 unsigned int bpc) 286 { 287 struct drm_device *dev = connector->dev; 288 289 /* 290 * TODO: Add support for YCbCr420 output for HDMI 2.0 capable 291 * devices, for modes that only support YCbCr420. 292 */ 293 if (hdmi_try_format_bpc(connector, conn_state, mode, bpc, HDMI_COLORSPACE_RGB)) { 294 conn_state->hdmi.output_format = HDMI_COLORSPACE_RGB; 295 return 0; 296 } 297 298 drm_dbg_kms(dev, "Failed. No Format Supported for that bpc count.\n"); 299 300 return -EINVAL; 301 } 302 303 static int 304 hdmi_compute_config(const struct drm_connector *connector, 305 struct drm_connector_state *conn_state, 306 const struct drm_display_mode *mode) 307 { 308 struct drm_device *dev = connector->dev; 309 unsigned int max_bpc = clamp_t(unsigned int, 310 conn_state->max_bpc, 311 8, connector->max_bpc); 312 unsigned int bpc; 313 int ret; 314 315 for (bpc = max_bpc; bpc >= 8; bpc -= 2) { 316 drm_dbg_kms(dev, "Trying with a %d bpc output\n", bpc); 317 318 ret = hdmi_compute_format(connector, conn_state, mode, bpc); 319 if (ret) 320 continue; 321 322 conn_state->hdmi.output_bpc = bpc; 323 324 drm_dbg_kms(dev, 325 "Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n", 326 mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), 327 conn_state->hdmi.output_bpc, 328 drm_hdmi_connector_get_output_format_name(conn_state->hdmi.output_format), 329 conn_state->hdmi.tmds_char_rate); 330 331 return 0; 332 } 333 334 return -EINVAL; 335 } 336 337 static int hdmi_generate_avi_infoframe(const struct drm_connector *connector, 338 struct drm_connector_state *conn_state) 339 { 340 const struct drm_display_mode *mode = 341 connector_state_get_mode(conn_state); 342 struct drm_connector_hdmi_infoframe *infoframe = 343 &conn_state->hdmi.infoframes.avi; 344 struct hdmi_avi_infoframe *frame = 345 &infoframe->data.avi; 346 bool is_limited_range = conn_state->hdmi.is_limited_range; 347 enum hdmi_quantization_range rgb_quant_range = 348 is_limited_range ? HDMI_QUANTIZATION_RANGE_LIMITED : HDMI_QUANTIZATION_RANGE_FULL; 349 int ret; 350 351 infoframe->set = false; 352 353 ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector, mode); 354 if (ret) 355 return ret; 356 357 frame->colorspace = conn_state->hdmi.output_format; 358 359 /* 360 * FIXME: drm_hdmi_avi_infoframe_quant_range() doesn't handle 361 * YUV formats at all at the moment, so if we ever support YUV 362 * formats this needs to be revised. 363 */ 364 drm_hdmi_avi_infoframe_quant_range(frame, connector, mode, rgb_quant_range); 365 drm_hdmi_avi_infoframe_colorimetry(frame, conn_state); 366 drm_hdmi_avi_infoframe_bars(frame, conn_state); 367 368 infoframe->set = true; 369 370 return 0; 371 } 372 373 static int hdmi_generate_spd_infoframe(const struct drm_connector *connector, 374 struct drm_connector_state *conn_state) 375 { 376 struct drm_connector_hdmi_infoframe *infoframe = 377 &conn_state->hdmi.infoframes.spd; 378 struct hdmi_spd_infoframe *frame = 379 &infoframe->data.spd; 380 int ret; 381 382 infoframe->set = false; 383 384 ret = hdmi_spd_infoframe_init(frame, 385 connector->hdmi.vendor, 386 connector->hdmi.product); 387 if (ret) 388 return ret; 389 390 frame->sdi = HDMI_SPD_SDI_PC; 391 392 infoframe->set = true; 393 394 return 0; 395 } 396 397 static int hdmi_generate_hdr_infoframe(const struct drm_connector *connector, 398 struct drm_connector_state *conn_state) 399 { 400 struct drm_connector_hdmi_infoframe *infoframe = 401 &conn_state->hdmi.infoframes.hdr_drm; 402 struct hdmi_drm_infoframe *frame = 403 &infoframe->data.drm; 404 int ret; 405 406 infoframe->set = false; 407 408 if (connector->max_bpc < 10) 409 return 0; 410 411 if (!conn_state->hdr_output_metadata) 412 return 0; 413 414 ret = drm_hdmi_infoframe_set_hdr_metadata(frame, conn_state); 415 if (ret) 416 return ret; 417 418 infoframe->set = true; 419 420 return 0; 421 } 422 423 static int hdmi_generate_hdmi_vendor_infoframe(const struct drm_connector *connector, 424 struct drm_connector_state *conn_state) 425 { 426 const struct drm_display_info *info = &connector->display_info; 427 const struct drm_display_mode *mode = 428 connector_state_get_mode(conn_state); 429 struct drm_connector_hdmi_infoframe *infoframe = 430 &conn_state->hdmi.infoframes.hdmi; 431 struct hdmi_vendor_infoframe *frame = 432 &infoframe->data.vendor.hdmi; 433 int ret; 434 435 infoframe->set = false; 436 437 if (!info->has_hdmi_infoframe) 438 return 0; 439 440 ret = drm_hdmi_vendor_infoframe_from_display_mode(frame, connector, mode); 441 if (ret) 442 return ret; 443 444 infoframe->set = true; 445 446 return 0; 447 } 448 449 static int 450 hdmi_generate_infoframes(const struct drm_connector *connector, 451 struct drm_connector_state *conn_state) 452 { 453 const struct drm_display_info *info = &connector->display_info; 454 int ret; 455 456 if (!info->is_hdmi) 457 return 0; 458 459 ret = hdmi_generate_avi_infoframe(connector, conn_state); 460 if (ret) 461 return ret; 462 463 ret = hdmi_generate_spd_infoframe(connector, conn_state); 464 if (ret) 465 return ret; 466 467 /* 468 * Audio Infoframes will be generated by ALSA, and updated by 469 * drm_atomic_helper_connector_hdmi_update_audio_infoframe(). 470 */ 471 472 ret = hdmi_generate_hdr_infoframe(connector, conn_state); 473 if (ret) 474 return ret; 475 476 ret = hdmi_generate_hdmi_vendor_infoframe(connector, conn_state); 477 if (ret) 478 return ret; 479 480 return 0; 481 } 482 483 /** 484 * drm_atomic_helper_connector_hdmi_check() - Helper to check HDMI connector atomic state 485 * @connector: DRM Connector 486 * @state: the DRM State object 487 * 488 * Provides a default connector state check handler for HDMI connectors. 489 * Checks that a desired connector update is valid, and updates various 490 * fields of derived state. 491 * 492 * RETURNS: 493 * Zero on success, or an errno code otherwise. 494 */ 495 int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector, 496 struct drm_atomic_state *state) 497 { 498 struct drm_connector_state *old_conn_state = 499 drm_atomic_get_old_connector_state(state, connector); 500 struct drm_connector_state *new_conn_state = 501 drm_atomic_get_new_connector_state(state, connector); 502 const struct drm_display_mode *mode = 503 connector_state_get_mode(new_conn_state); 504 int ret; 505 506 if (!new_conn_state->crtc || !new_conn_state->best_encoder) 507 return 0; 508 509 new_conn_state->hdmi.is_limited_range = hdmi_is_limited_range(connector, new_conn_state); 510 511 ret = hdmi_compute_config(connector, new_conn_state, mode); 512 if (ret) 513 return ret; 514 515 ret = hdmi_generate_infoframes(connector, new_conn_state); 516 if (ret) 517 return ret; 518 519 if (old_conn_state->hdmi.broadcast_rgb != new_conn_state->hdmi.broadcast_rgb || 520 old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc || 521 old_conn_state->hdmi.output_format != new_conn_state->hdmi.output_format) { 522 struct drm_crtc *crtc = new_conn_state->crtc; 523 struct drm_crtc_state *crtc_state; 524 525 crtc_state = drm_atomic_get_crtc_state(state, crtc); 526 if (IS_ERR(crtc_state)) 527 return PTR_ERR(crtc_state); 528 529 crtc_state->mode_changed = true; 530 } 531 532 return 0; 533 } 534 EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check); 535 536 /** 537 * drm_hdmi_connector_mode_valid() - Check if mode is valid for HDMI connector 538 * @connector: DRM connector to validate the mode 539 * @mode: Display mode to validate 540 * 541 * Generic .mode_valid implementation for HDMI connectors. 542 */ 543 enum drm_mode_status 544 drm_hdmi_connector_mode_valid(struct drm_connector *connector, 545 struct drm_display_mode *mode) 546 { 547 unsigned long long clock; 548 549 clock = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB); 550 if (!clock) 551 return MODE_ERROR; 552 553 return hdmi_clock_valid(connector, mode, clock); 554 } 555 EXPORT_SYMBOL(drm_hdmi_connector_mode_valid); 556 557 static int clear_device_infoframe(struct drm_connector *connector, 558 enum hdmi_infoframe_type type) 559 { 560 const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; 561 struct drm_device *dev = connector->dev; 562 int ret; 563 564 drm_dbg_kms(dev, "Clearing infoframe type 0x%x\n", type); 565 566 if (!funcs || !funcs->clear_infoframe) { 567 drm_dbg_kms(dev, "Function not implemented, bailing.\n"); 568 return 0; 569 } 570 571 ret = funcs->clear_infoframe(connector, type); 572 if (ret) { 573 drm_dbg_kms(dev, "Call failed: %d\n", ret); 574 return ret; 575 } 576 577 return 0; 578 } 579 580 static int clear_infoframe(struct drm_connector *connector, 581 struct drm_connector_hdmi_infoframe *old_frame) 582 { 583 int ret; 584 585 ret = clear_device_infoframe(connector, old_frame->data.any.type); 586 if (ret) 587 return ret; 588 589 return 0; 590 } 591 592 static int write_device_infoframe(struct drm_connector *connector, 593 union hdmi_infoframe *frame) 594 { 595 const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; 596 struct drm_device *dev = connector->dev; 597 u8 buffer[HDMI_INFOFRAME_SIZE(MAX)]; 598 int ret; 599 int len; 600 601 drm_dbg_kms(dev, "Writing infoframe type %x\n", frame->any.type); 602 603 if (!funcs || !funcs->write_infoframe) { 604 drm_dbg_kms(dev, "Function not implemented, bailing.\n"); 605 return -EINVAL; 606 } 607 608 len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer)); 609 if (len < 0) 610 return len; 611 612 ret = funcs->write_infoframe(connector, frame->any.type, buffer, len); 613 if (ret) { 614 drm_dbg_kms(dev, "Call failed: %d\n", ret); 615 return ret; 616 } 617 618 return 0; 619 } 620 621 static int write_infoframe(struct drm_connector *connector, 622 struct drm_connector_hdmi_infoframe *new_frame) 623 { 624 int ret; 625 626 ret = write_device_infoframe(connector, &new_frame->data); 627 if (ret) 628 return ret; 629 630 return 0; 631 } 632 633 static int write_or_clear_infoframe(struct drm_connector *connector, 634 struct drm_connector_hdmi_infoframe *old_frame, 635 struct drm_connector_hdmi_infoframe *new_frame) 636 { 637 if (new_frame->set) 638 return write_infoframe(connector, new_frame); 639 640 if (old_frame->set && !new_frame->set) 641 return clear_infoframe(connector, old_frame); 642 643 return 0; 644 } 645 646 /** 647 * drm_atomic_helper_connector_hdmi_update_infoframes - Update the Infoframes 648 * @connector: A pointer to the HDMI connector 649 * @state: The HDMI connector state to generate the infoframe from 650 * 651 * This function is meant for HDMI connector drivers to write their 652 * infoframes. It will typically be used in a 653 * @drm_connector_helper_funcs.atomic_enable implementation. 654 * 655 * Returns: 656 * Zero on success, error code on failure. 657 */ 658 int drm_atomic_helper_connector_hdmi_update_infoframes(struct drm_connector *connector, 659 struct drm_atomic_state *state) 660 { 661 struct drm_connector_state *old_conn_state = 662 drm_atomic_get_old_connector_state(state, connector); 663 struct drm_connector_state *new_conn_state = 664 drm_atomic_get_new_connector_state(state, connector); 665 struct drm_display_info *info = &connector->display_info; 666 int ret; 667 668 if (!info->is_hdmi) 669 return 0; 670 671 mutex_lock(&connector->hdmi.infoframes.lock); 672 673 ret = write_or_clear_infoframe(connector, 674 &old_conn_state->hdmi.infoframes.avi, 675 &new_conn_state->hdmi.infoframes.avi); 676 if (ret) 677 goto out; 678 679 if (connector->hdmi.infoframes.audio.set) { 680 ret = write_infoframe(connector, 681 &connector->hdmi.infoframes.audio); 682 if (ret) 683 goto out; 684 } 685 686 ret = write_or_clear_infoframe(connector, 687 &old_conn_state->hdmi.infoframes.hdr_drm, 688 &new_conn_state->hdmi.infoframes.hdr_drm); 689 if (ret) 690 goto out; 691 692 ret = write_or_clear_infoframe(connector, 693 &old_conn_state->hdmi.infoframes.spd, 694 &new_conn_state->hdmi.infoframes.spd); 695 if (ret) 696 goto out; 697 698 if (info->has_hdmi_infoframe) { 699 ret = write_or_clear_infoframe(connector, 700 &old_conn_state->hdmi.infoframes.hdmi, 701 &new_conn_state->hdmi.infoframes.hdmi); 702 if (ret) 703 goto out; 704 } 705 706 out: 707 mutex_unlock(&connector->hdmi.infoframes.lock); 708 return ret; 709 } 710 EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_infoframes); 711 712 /** 713 * drm_atomic_helper_connector_hdmi_update_audio_infoframe - Update the Audio Infoframe 714 * @connector: A pointer to the HDMI connector 715 * @frame: A pointer to the audio infoframe to write 716 * 717 * This function is meant for HDMI connector drivers to update their 718 * audio infoframe. It will typically be used in one of the ALSA hooks 719 * (most likely prepare). 720 * 721 * Returns: 722 * Zero on success, error code on failure. 723 */ 724 int 725 drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct drm_connector *connector, 726 struct hdmi_audio_infoframe *frame) 727 { 728 struct drm_connector_hdmi_infoframe *infoframe = 729 &connector->hdmi.infoframes.audio; 730 struct drm_display_info *info = &connector->display_info; 731 int ret; 732 733 if (!info->is_hdmi) 734 return 0; 735 736 mutex_lock(&connector->hdmi.infoframes.lock); 737 738 memcpy(&infoframe->data, frame, sizeof(infoframe->data)); 739 infoframe->set = true; 740 741 ret = write_infoframe(connector, infoframe); 742 743 mutex_unlock(&connector->hdmi.infoframes.lock); 744 745 return ret; 746 } 747 EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_audio_infoframe); 748 749 /** 750 * drm_atomic_helper_connector_hdmi_clear_audio_infoframe - Stop sending the Audio Infoframe 751 * @connector: A pointer to the HDMI connector 752 * 753 * This function is meant for HDMI connector drivers to stop sending their 754 * audio infoframe. It will typically be used in one of the ALSA hooks 755 * (most likely shutdown). 756 * 757 * Returns: 758 * Zero on success, error code on failure. 759 */ 760 int 761 drm_atomic_helper_connector_hdmi_clear_audio_infoframe(struct drm_connector *connector) 762 { 763 struct drm_connector_hdmi_infoframe *infoframe = 764 &connector->hdmi.infoframes.audio; 765 struct drm_display_info *info = &connector->display_info; 766 int ret; 767 768 if (!info->is_hdmi) 769 return 0; 770 771 mutex_lock(&connector->hdmi.infoframes.lock); 772 773 infoframe->set = false; 774 775 ret = clear_infoframe(connector, infoframe); 776 777 memset(&infoframe->data, 0, sizeof(infoframe->data)); 778 779 mutex_unlock(&connector->hdmi.infoframes.lock); 780 781 return ret; 782 } 783 EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_clear_audio_infoframe); 784 785 static void 786 drm_atomic_helper_connector_hdmi_update(struct drm_connector *connector, 787 enum drm_connector_status status) 788 { 789 const struct drm_edid *drm_edid; 790 791 if (status == connector_status_disconnected) { 792 // TODO: also handle CEC and scramber, HDMI sink disconnected. 793 drm_connector_hdmi_audio_plugged_notify(connector, false); 794 drm_edid_connector_update(connector, NULL); 795 return; 796 } 797 798 if (connector->hdmi.funcs->read_edid) 799 drm_edid = connector->hdmi.funcs->read_edid(connector); 800 else 801 drm_edid = drm_edid_read(connector); 802 803 drm_edid_connector_update(connector, drm_edid); 804 805 drm_edid_free(drm_edid); 806 807 if (status == connector_status_connected) { 808 // TODO: also handle CEC and scramber, HDMI sink is now connected. 809 drm_connector_hdmi_audio_plugged_notify(connector, true); 810 } 811 } 812 813 /** 814 * drm_atomic_helper_connector_hdmi_hotplug - Handle the hotplug event for the HDMI connector 815 * @connector: A pointer to the HDMI connector 816 * @status: Connection status 817 * 818 * This function should be called as a part of the .detect() / .detect_ctx() 819 * callbacks, updating the HDMI-specific connector's data. 820 */ 821 void drm_atomic_helper_connector_hdmi_hotplug(struct drm_connector *connector, 822 enum drm_connector_status status) 823 { 824 drm_atomic_helper_connector_hdmi_update(connector, status); 825 } 826 EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_hotplug); 827 828 /** 829 * drm_atomic_helper_connector_hdmi_force - HDMI Connector implementation of the force callback 830 * @connector: A pointer to the HDMI connector 831 * 832 * This function implements the .force() callback for the HDMI connectors. It 833 * can either be used directly as the callback or should be called from within 834 * the .force() callback implementation to maintain the HDMI-specific 835 * connector's data. 836 */ 837 void drm_atomic_helper_connector_hdmi_force(struct drm_connector *connector) 838 { 839 drm_atomic_helper_connector_hdmi_update(connector, connector->status); 840 } 841 EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_force); 842