Rev 4560 | Rev 5271 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4560 | Rev 5060 | ||
---|---|---|---|
Line 25... | Line 25... | ||
25 | //#include |
25 | //#include |
26 | //#include |
26 | //#include |
27 | #include |
27 | #include |
28 | #include |
28 | #include |
29 | #include |
29 | #include |
30 | #include |
- | |
31 | #include |
30 | #include |
- | 31 | #include |
|
Line 32... | Line 32... | ||
32 | 32 | ||
33 | /** |
33 | /** |
34 | * DOC: dp helpers |
34 | * DOC: dp helpers |
35 | * |
35 | * |
Line 204... | Line 204... | ||
204 | 204 | ||
205 | /** |
205 | /** |
206 | * i2c_dp_aux_add_bus() - register an i2c adapter using the aux ch helper |
206 | * i2c_dp_aux_add_bus() - register an i2c adapter using the aux ch helper |
207 | * @adapter: i2c adapter to register |
207 | * @adapter: i2c adapter to register |
208 | * |
208 | * |
209 | * This registers an i2c adapater that uses dp aux channel as it's underlaying |
209 | * This registers an i2c adapter that uses dp aux channel as it's underlaying |
210 | * transport. The driver needs to fill out the &i2c_algo_dp_aux_data structure |
210 | * transport. The driver needs to fill out the &i2c_algo_dp_aux_data structure |
211 | * and store it in the algo_data member of the @adapter argument. This will be |
211 | * and store it in the algo_data member of the @adapter argument. This will be |
212 | * used by the i2c over dp aux algorithm to drive the hardware. |
212 | * used by the i2c over dp aux algorithm to drive the hardware. |
213 | * |
213 | * |
214 | * RETURNS: |
214 | * RETURNS: |
- | 215 | * 0 on success, -ERRNO on failure. |
|
- | 216 | * |
|
- | 217 | * IMPORTANT: |
|
- | 218 | * This interface is deprecated, please switch to the new dp aux helpers and |
|
215 | * 0 on success, -ERRNO on failure. |
219 | * drm_dp_aux_register(). |
216 | */ |
220 | */ |
217 | int |
221 | int |
218 | i2c_dp_aux_add_bus(struct i2c_adapter *adapter) |
222 | i2c_dp_aux_add_bus(struct i2c_adapter *adapter) |
219 | { |
223 | { |
Line 344... | Line 348... | ||
344 | case DP_LINK_BW_5_4: |
348 | case DP_LINK_BW_5_4: |
345 | return 540000; |
349 | return 540000; |
346 | } |
350 | } |
347 | } |
351 | } |
348 | EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate);><>><>>>>>>>>>> |
352 | EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate); |
- | 353 | ||
- | 354 | /** |
|
- | 355 | * DOC: dp helpers |
|
- | 356 | * |
|
- | 357 | * The DisplayPort AUX channel is an abstraction to allow generic, driver- |
|
- | 358 | * independent access to AUX functionality. Drivers can take advantage of |
|
- | 359 | * this by filling in the fields of the drm_dp_aux structure. |
|
- | 360 | * |
|
- | 361 | * Transactions are described using a hardware-independent drm_dp_aux_msg |
|
- | 362 | * structure, which is passed into a driver's .transfer() implementation. |
|
- | 363 | * Both native and I2C-over-AUX transactions are supported. |
|
- | 364 | */ |
|
- | 365 | ||
- | 366 | static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, |
|
- | 367 | unsigned int offset, void *buffer, size_t size) |
|
- | 368 | { |
|
- | 369 | struct drm_dp_aux_msg msg; |
|
- | 370 | unsigned int retry; |
|
- | 371 | int err; |
|
- | 372 | ||
- | 373 | memset(&msg, 0, sizeof(msg)); |
|
- | 374 | msg.address = offset; |
|
- | 375 | msg.request = request; |
|
- | 376 | msg.buffer = buffer; |
|
- | 377 | msg.size = size; |
|
- | 378 | ||
- | 379 | /* |
|
- | 380 | * The specification doesn't give any recommendation on how often to |
|
- | 381 | * retry native transactions, so retry 7 times like for I2C-over-AUX |
|
- | 382 | * transactions. |
|
- | 383 | */ |
|
- | 384 | for (retry = 0; retry < 7; retry++) { |
|
- | 385 | ||
- | 386 | mutex_lock(&aux->hw_mutex); |
|
- | 387 | err = aux->transfer(aux, &msg); |
|
- | 388 | mutex_unlock(&aux->hw_mutex); |
|
- | 389 | if (err < 0) { |
|
- | 390 | if (err == -EBUSY) |
|
- | 391 | continue; |
|
- | 392 | ||
- | 393 | return err; |
|
- | 394 | } |
|
- | 395 | ||
- | 396 | ||
- | 397 | switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) { |
|
- | 398 | case DP_AUX_NATIVE_REPLY_ACK: |
|
- | 399 | if (err < size) |
|
- | 400 | return -EPROTO; |
|
- | 401 | return err; |
|
- | 402 | ||
- | 403 | case DP_AUX_NATIVE_REPLY_NACK: |
|
- | 404 | return -EIO; |
|
- | 405 | ||
- | 406 | case DP_AUX_NATIVE_REPLY_DEFER: |
|
- | 407 | usleep(500); |
|
- | 408 | break; |
|
- | 409 | } |
|
- | 410 | } |
|
- | 411 | ||
- | 412 | DRM_DEBUG_KMS("too many retries, giving up\n"); |
|
- | 413 | return -EIO; |
|
- | 414 | } |
|
- | 415 | ||
- | 416 | /** |
|
- | 417 | * drm_dp_dpcd_read() - read a series of bytes from the DPCD |
|
- | 418 | * @aux: DisplayPort AUX channel |
|
- | 419 | * @offset: address of the (first) register to read |
|
- | 420 | * @buffer: buffer to store the register values |
|
- | 421 | * @size: number of bytes in @buffer |
|
- | 422 | * |
|
- | 423 | * Returns the number of bytes transferred on success, or a negative error |
|
- | 424 | * code on failure. -EIO is returned if the request was NAKed by the sink or |
|
- | 425 | * if the retry count was exceeded. If not all bytes were transferred, this |
|
- | 426 | * function returns -EPROTO. Errors from the underlying AUX channel transfer |
|
- | 427 | * function, with the exception of -EBUSY (which causes the transaction to |
|
- | 428 | * be retried), are propagated to the caller. |
|
- | 429 | */ |
|
- | 430 | ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset, |
|
- | 431 | void *buffer, size_t size) |
|
- | 432 | { |
|
- | 433 | return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset, buffer, |
|
- | 434 | size); |
|
- | 435 | } |
|
- | 436 | EXPORT_SYMBOL(drm_dp_dpcd_read); |
|
- | 437 | ||
- | 438 | /** |
|
- | 439 | * drm_dp_dpcd_write() - write a series of bytes to the DPCD |
|
- | 440 | * @aux: DisplayPort AUX channel |
|
- | 441 | * @offset: address of the (first) register to write |
|
- | 442 | * @buffer: buffer containing the values to write |
|
- | 443 | * @size: number of bytes in @buffer |
|
- | 444 | * |
|
- | 445 | * Returns the number of bytes transferred on success, or a negative error |
|
- | 446 | * code on failure. -EIO is returned if the request was NAKed by the sink or |
|
- | 447 | * if the retry count was exceeded. If not all bytes were transferred, this |
|
- | 448 | * function returns -EPROTO. Errors from the underlying AUX channel transfer |
|
- | 449 | * function, with the exception of -EBUSY (which causes the transaction to |
|
- | 450 | * be retried), are propagated to the caller. |
|
- | 451 | */ |
|
- | 452 | ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset, |
|
- | 453 | void *buffer, size_t size) |
|
- | 454 | { |
|
- | 455 | return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer, |
|
- | 456 | size); |
|
- | 457 | } |
|
- | 458 | EXPORT_SYMBOL(drm_dp_dpcd_write); |
|
- | 459 | ||
- | 460 | /** |
|
- | 461 | * drm_dp_dpcd_read_link_status() - read DPCD link status (bytes 0x202-0x207) |
|
- | 462 | * @aux: DisplayPort AUX channel |
|
- | 463 | * @status: buffer to store the link status in (must be at least 6 bytes) |
|
- | 464 | * |
|
- | 465 | * Returns the number of bytes transferred on success or a negative error |
|
- | 466 | * code on failure. |
|
- | 467 | */ |
|
- | 468 | int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux, |
|
- | 469 | u8 status[DP_LINK_STATUS_SIZE]) |
|
- | 470 | { |
|
- | 471 | return drm_dp_dpcd_read(aux, DP_LANE0_1_STATUS, status, |
|
- | 472 | DP_LINK_STATUS_SIZE); |
|
- | 473 | } |
|
- | 474 | EXPORT_SYMBOL(drm_dp_dpcd_read_link_status); |
|
- | 475 | ||
- | 476 | /** |
|
- | 477 | * drm_dp_link_probe() - probe a DisplayPort link for capabilities |
|
- | 478 | * @aux: DisplayPort AUX channel |
|
- | 479 | * @link: pointer to structure in which to return link capabilities |
|
- | 480 | * |
|
- | 481 | * The structure filled in by this function can usually be passed directly |
|
- | 482 | * into drm_dp_link_power_up() and drm_dp_link_configure() to power up and |
|
- | 483 | * configure the link based on the link's capabilities. |
|
- | 484 | * |
|
- | 485 | * Returns 0 on success or a negative error code on failure. |
|
- | 486 | */ |
|
- | 487 | int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link) |
|
- | 488 | { |
|
- | 489 | u8 values[3]; |
|
- | 490 | int err; |
|
- | 491 | ||
- | 492 | memset(link, 0, sizeof(*link)); |
|
- | 493 | ||
- | 494 | err = drm_dp_dpcd_read(aux, DP_DPCD_REV, values, sizeof(values)); |
|
- | 495 | if (err < 0) |
|
- | 496 | return err; |
|
- | 497 | ||
- | 498 | link->revision = values[0]; |
|
- | 499 | link->rate = drm_dp_bw_code_to_link_rate(values[1]); |
|
- | 500 | link->num_lanes = values[2] & DP_MAX_LANE_COUNT_MASK; |
|
- | 501 | ||
- | 502 | if (values[2] & DP_ENHANCED_FRAME_CAP) |
|
- | 503 | link->capabilities |= DP_LINK_CAP_ENHANCED_FRAMING; |
|
- | 504 | ||
- | 505 | return 0; |
|
- | 506 | } |
|
- | 507 | EXPORT_SYMBOL(drm_dp_link_probe); |
|
- | 508 | ||
- | 509 | /** |
|
- | 510 | * drm_dp_link_power_up() - power up a DisplayPort link |
|
- | 511 | * @aux: DisplayPort AUX channel |
|
- | 512 | * @link: pointer to a structure containing the link configuration |
|
- | 513 | * |
|
- | 514 | * Returns 0 on success or a negative error code on failure. |
|
- | 515 | */ |
|
- | 516 | int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link) |
|
- | 517 | { |
|
- | 518 | u8 value; |
|
- | 519 | int err; |
|
- | 520 | ||
- | 521 | /* DP_SET_POWER register is only available on DPCD v1.1 and later */ |
|
- | 522 | if (link->revision < 0x11) |
|
- | 523 | return 0; |
|
- | 524 | ||
- | 525 | err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); |
|
- | 526 | if (err < 0) |
|
- | 527 | return err; |
|
- | 528 | ||
- | 529 | value &= ~DP_SET_POWER_MASK; |
|
- | 530 | value |= DP_SET_POWER_D0; |
|
- | 531 | ||
- | 532 | err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); |
|
- | 533 | if (err < 0) |
|
- | 534 | return err; |
|
- | 535 | ||
- | 536 | /* |
|
- | 537 | * According to the DP 1.1 specification, a "Sink Device must exit the |
|
- | 538 | * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink |
|
- | 539 | * Control Field" (register 0x600). |
|
- | 540 | */ |
|
- | 541 | usleep(2000); |
|
- | 542 | ||
- | 543 | return 0; |
|
- | 544 | } |
|
- | 545 | EXPORT_SYMBOL(drm_dp_link_power_up); |
|
- | 546 | ||
- | 547 | /** |
|
- | 548 | * drm_dp_link_configure() - configure a DisplayPort link |
|
- | 549 | * @aux: DisplayPort AUX channel |
|
- | 550 | * @link: pointer to a structure containing the link configuration |
|
- | 551 | * |
|
- | 552 | * Returns 0 on success or a negative error code on failure. |
|
- | 553 | */ |
|
- | 554 | int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link) |
|
- | 555 | { |
|
- | 556 | u8 values[2]; |
|
- | 557 | int err; |
|
- | 558 | ||
- | 559 | values[0] = drm_dp_link_rate_to_bw_code(link->rate); |
|
- | 560 | values[1] = link->num_lanes; |
|
- | 561 | ||
- | 562 | if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING) |
|
- | 563 | values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; |
|
- | 564 | ||
- | 565 | err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values)); |
|
- | 566 | if (err < 0) |
|
- | 567 | return err; |
|
- | 568 | ||
- | 569 | return 0; |
|
- | 570 | } |
|
- | 571 | EXPORT_SYMBOL(drm_dp_link_configure); |
|
- | 572 | ||
- | 573 | /* |
|
- | 574 | * I2C-over-AUX implementation |
|
- | 575 | */ |
|
- | 576 | ||
- | 577 | static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter) |
|
- | 578 | { |
|
- | 579 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | |
|
- | 580 | I2C_FUNC_SMBUS_READ_BLOCK_DATA | |
|
- | 581 | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | |
|
- | 582 | I2C_FUNC_10BIT_ADDR; |
|
- | 583 | } |
|
- | 584 | ||
- | 585 | /* |
|
- | 586 | * Transfer a single I2C-over-AUX message and handle various error conditions, |
|
- | 587 | * retrying the transaction as appropriate. It is assumed that the |
|
- | 588 | * aux->transfer function does not modify anything in the msg other than the |
|
- | 589 | * reply field. |
|
- | 590 | */ |
|
- | 591 | static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) |
|
- | 592 | { |
|
- | 593 | unsigned int retry; |
|
- | 594 | int err; |
|
- | 595 | ||
- | 596 | /* |
|
- | 597 | * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device |
|
- | 598 | * is required to retry at least seven times upon receiving AUX_DEFER |
|
- | 599 | * before giving up the AUX transaction. |
|
- | 600 | */ |
|
- | 601 | for (retry = 0; retry < 7; retry++) { |
|
- | 602 | mutex_lock(&aux->hw_mutex); |
|
- | 603 | err = aux->transfer(aux, msg); |
|
- | 604 | mutex_unlock(&aux->hw_mutex); |
|
- | 605 | if (err < 0) { |
|
- | 606 | if (err == -EBUSY) |
|
- | 607 | continue; |
|
- | 608 | ||
- | 609 | DRM_DEBUG_KMS("transaction failed: %d\n", err); |
|
- | 610 | return err; |
|
- | 611 | } |
|
- | 612 | ||
- | 613 | ||
- | 614 | switch (msg->reply & DP_AUX_NATIVE_REPLY_MASK) { |
|
- | 615 | case DP_AUX_NATIVE_REPLY_ACK: |
|
- | 616 | /* |
|
- | 617 | * For I2C-over-AUX transactions this isn't enough, we |
|
- | 618 | * need to check for the I2C ACK reply. |
|
- | 619 | */ |
|
- | 620 | break; |
|
- | 621 | ||
- | 622 | case DP_AUX_NATIVE_REPLY_NACK: |
|
- | 623 | DRM_DEBUG_KMS("native nack\n"); |
|
- | 624 | return -EREMOTEIO; |
|
- | 625 | ||
- | 626 | case DP_AUX_NATIVE_REPLY_DEFER: |
|
- | 627 | DRM_DEBUG_KMS("native defer"); |
|
- | 628 | /* |
|
- | 629 | * We could check for I2C bit rate capabilities and if |
|
- | 630 | * available adjust this interval. We could also be |
|
- | 631 | * more careful with DP-to-legacy adapters where a |
|
- | 632 | * long legacy cable may force very low I2C bit rates. |
|
- | 633 | * |
|
- | 634 | * For now just defer for long enough to hopefully be |
|
- | 635 | * safe for all use-cases. |
|
- | 636 | */ |
|
- | 637 | usleep_range(500, 600); |
|
- | 638 | continue; |
|
- | 639 | ||
- | 640 | default: |
|
- | 641 | DRM_ERROR("invalid native reply %#04x\n", msg->reply); |
|
- | 642 | return -EREMOTEIO; |
|
- | 643 | } |
|
- | 644 | ||
- | 645 | switch (msg->reply & DP_AUX_I2C_REPLY_MASK) { |
|
- | 646 | case DP_AUX_I2C_REPLY_ACK: |
|
- | 647 | /* |
|
- | 648 | * Both native ACK and I2C ACK replies received. We |
|
- | 649 | * can assume the transfer was successful. |
|
- | 650 | */ |
|
- | 651 | if (err < msg->size) |
|
- | 652 | return -EPROTO; |
|
- | 653 | return 0; |
|
- | 654 | ||
- | 655 | case DP_AUX_I2C_REPLY_NACK: |
|
- | 656 | DRM_DEBUG_KMS("I2C nack\n"); |
|
- | 657 | return -EREMOTEIO; |
|
- | 658 | ||
- | 659 | case DP_AUX_I2C_REPLY_DEFER: |
|
- | 660 | DRM_DEBUG_KMS("I2C defer\n"); |
|
- | 661 | usleep_range(400, 500); |
|
- | 662 | continue; |
|
- | 663 | ||
- | 664 | default: |
|
- | 665 | DRM_ERROR("invalid I2C reply %#04x\n", msg->reply); |
|
- | 666 | return -EREMOTEIO; |
|
- | 667 | } |
|
- | 668 | } |
|
- | 669 | ||
- | 670 | DRM_DEBUG_KMS("too many retries, giving up\n"); |
|
- | 671 | return -EREMOTEIO; |
|
- | 672 | } |
|
- | 673 | ||
- | 674 | static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, |
|
- | 675 | int num) |
|
- | 676 | { |
|
- | 677 | struct drm_dp_aux *aux = adapter->algo_data; |
|
- | 678 | unsigned int i, j; |
|
- | 679 | struct drm_dp_aux_msg msg; |
|
- | 680 | int err = 0; |
|
- | 681 | ||
- | 682 | memset(&msg, 0, sizeof(msg)); |
|
- | 683 | ||
- | 684 | for (i = 0; i < num; i++) { |
|
- | 685 | msg.address = msgs[i].addr; |
|
- | 686 | msg.request = (msgs[i].flags & I2C_M_RD) ? |
|
- | 687 | DP_AUX_I2C_READ : |
|
- | 688 | DP_AUX_I2C_WRITE; |
|
- | 689 | msg.request |= DP_AUX_I2C_MOT; |
|
- | 690 | /* Send a bare address packet to start the transaction. |
|
- | 691 | * Zero sized messages specify an address only (bare |
|
- | 692 | * address) transaction. |
|
- | 693 | */ |
|
- | 694 | msg.buffer = NULL; |
|
- | 695 | msg.size = 0; |
|
- | 696 | err = drm_dp_i2c_do_msg(aux, &msg); |
|
- | 697 | if (err < 0) |
|
- | 698 | break; |
|
- | 699 | /* |
|
- | 700 | * Many hardware implementations support FIFOs larger than a |
|
- | 701 | * single byte, but it has been empirically determined that |
|
- | 702 | * transferring data in larger chunks can actually lead to |
|
- | 703 | * decreased performance. Therefore each message is simply |
|
- | 704 | * transferred byte-by-byte. |
|
- | 705 | */ |
|
- | 706 | for (j = 0; j < msgs[i].len; j++) { |
|
- | 707 | msg.buffer = msgs[i].buf + j; |
|
- | 708 | msg.size = 1; |
|
- | 709 | ||
- | 710 | err = drm_dp_i2c_do_msg(aux, &msg); |
|
- | 711 | if (err < 0) |
|
- | 712 | break; |
|
- | 713 | } |
|
- | 714 | if (err < 0) |
|
- | 715 | break; |
|
- | 716 | } |
|
- | 717 | if (err >= 0) |
|
- | 718 | err = num; |
|
- | 719 | /* Send a bare address packet to close out the transaction. |
|
- | 720 | * Zero sized messages specify an address only (bare |
|
- | 721 | * address) transaction. |
|
- | 722 | */ |
|
- | 723 | msg.request &= ~DP_AUX_I2C_MOT; |
|
- | 724 | msg.buffer = NULL; |
|
- | 725 | msg.size = 0; |
|
- | 726 | (void)drm_dp_i2c_do_msg(aux, &msg); |
|
- | 727 | ||
- | 728 | return err; |
|
- | 729 | } |
|
- | 730 | ||
- | 731 | static const struct i2c_algorithm drm_dp_i2c_algo = { |
|
- | 732 | .functionality = drm_dp_i2c_functionality, |
|
- | 733 | .master_xfer = drm_dp_i2c_xfer, |
|
- | 734 | }; |
|
- | 735 | ||
- | 736 | /** |
|
- | 737 | * drm_dp_aux_register() - initialise and register aux channel |
|
- | 738 | * @aux: DisplayPort AUX channel |
|
- | 739 | * |
|
- | 740 | * Returns 0 on success or a negative error code on failure. |
|
- | 741 | */ |
|
- | 742 | int drm_dp_aux_register(struct drm_dp_aux *aux) |
|
- | 743 | { |
|
- | 744 | mutex_init(&aux->hw_mutex); |
|
- | 745 | ||
- | 746 | aux->ddc.algo = &drm_dp_i2c_algo; |
|
- | 747 | aux->ddc.algo_data = aux; |
|
- | 748 | aux->ddc.retries = 3; |
|
- | 749 | ||
- | 750 | aux->ddc.class = I2C_CLASS_DDC; |
|
- | 751 | aux->ddc.owner = THIS_MODULE; |
|
- | 752 | aux->ddc.dev.parent = aux->dev; |
|
- | 753 | // aux->ddc.dev.of_node = aux->dev->of_node; |
|
- | 754 | ||
- | 755 | strlcpy(aux->ddc.name, aux->name ? aux->name : "aux", |
|
- | 756 | sizeof(aux->ddc.name)); |
|
- | 757 | ||
- | 758 | return i2c_add_adapter(&aux->ddc); |
|
- | 759 | } |
|
- | 760 | EXPORT_SYMBOL(drm_dp_aux_register); |
|
- | 761 | ||
- | 762 | /** |
|
- | 763 | * drm_dp_aux_unregister() - unregister an AUX adapter |
|
- | 764 | * @aux: DisplayPort AUX channel |
|
- | 765 | */ |
|
- | 766 | void drm_dp_aux_unregister(struct drm_dp_aux *aux) |
|
- | 767 | { |
|
- | 768 | i2c_del_adapter(&aux->ddc); |
|
- | 769 | } |
|
- | 770 | EXPORT_SYMBOL(drm_dp_aux_unregister);>>>>>>>>>>>>>>>>><>><>>>>>>>>>> |