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