diff options
author | Dave Airlie <airlied@redhat.com> | 2014-02-26 23:30:08 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-02-26 23:30:08 -0500 |
commit | 6ba6b7cdaf1a48b24c23c303871ffe1640a866e8 (patch) | |
tree | 0e67c7aad3b51a879c8d6ae07ae8276c29514b38 | |
parent | cfbf8d4857c26a8a307fb7cd258074c9dcd8c691 (diff) | |
parent | 88759686c702f1fbbb8e737e6231b64a9880db73 (diff) |
Merge tag 'drm/dp-aux-for-3.15-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next
drm: DisplayPort AUX framework for v3.15-rc1
This series of patches implements a small framework that abstracts away
some of the functionality that the DisplayPort AUX channel provides. It
comes with a set of generic helpers that use the driver implementations
to reduce code duplication.
* tag 'drm/dp-aux-for-3.15-rc1' of git://anongit.freedesktop.org/tegra/linux:
drm/dp: Allow registering AUX channels as I2C busses
drm/dp: Add DisplayPort link helpers
drm/dp: Add drm_dp_dpcd_read_link_status()
drm/dp: Add AUX channel infrastructure
-rw-r--r-- | drivers/gpu/drm/drm_dp_helper.c | 395 | ||||
-rw-r--r-- | include/drm/drm_dp_helper.h | 111 |
2 files changed, 506 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 9e978aae8972..35251af3b14e 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c | |||
@@ -346,3 +346,398 @@ int drm_dp_bw_code_to_link_rate(u8 link_bw) | |||
346 | } | 346 | } |
347 | } | 347 | } |
348 | EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate); | 348 | EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate); |
349 | |||
350 | /** | ||
351 | * DOC: dp helpers | ||
352 | * | ||
353 | * The DisplayPort AUX channel is an abstraction to allow generic, driver- | ||
354 | * independent access to AUX functionality. Drivers can take advantage of | ||
355 | * this by filling in the fields of the drm_dp_aux structure. | ||
356 | * | ||
357 | * Transactions are described using a hardware-independent drm_dp_aux_msg | ||
358 | * structure, which is passed into a driver's .transfer() implementation. | ||
359 | * Both native and I2C-over-AUX transactions are supported. | ||
360 | */ | ||
361 | |||
362 | static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, | ||
363 | unsigned int offset, void *buffer, size_t size) | ||
364 | { | ||
365 | struct drm_dp_aux_msg msg; | ||
366 | unsigned int retry; | ||
367 | int err; | ||
368 | |||
369 | memset(&msg, 0, sizeof(msg)); | ||
370 | msg.address = offset; | ||
371 | msg.request = request; | ||
372 | msg.buffer = buffer; | ||
373 | msg.size = size; | ||
374 | |||
375 | /* | ||
376 | * The specification doesn't give any recommendation on how often to | ||
377 | * retry native transactions, so retry 7 times like for I2C-over-AUX | ||
378 | * transactions. | ||
379 | */ | ||
380 | for (retry = 0; retry < 7; retry++) { | ||
381 | err = aux->transfer(aux, &msg); | ||
382 | if (err < 0) { | ||
383 | if (err == -EBUSY) | ||
384 | continue; | ||
385 | |||
386 | return err; | ||
387 | } | ||
388 | |||
389 | if (err < size) | ||
390 | return -EPROTO; | ||
391 | |||
392 | switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) { | ||
393 | case DP_AUX_NATIVE_REPLY_ACK: | ||
394 | return err; | ||
395 | |||
396 | case DP_AUX_NATIVE_REPLY_NACK: | ||
397 | return -EIO; | ||
398 | |||
399 | case DP_AUX_NATIVE_REPLY_DEFER: | ||
400 | usleep_range(400, 500); | ||
401 | break; | ||
402 | } | ||
403 | } | ||
404 | |||
405 | DRM_ERROR("too many retries, giving up\n"); | ||
406 | return -EIO; | ||
407 | } | ||
408 | |||
409 | /** | ||
410 | * drm_dp_dpcd_read() - read a series of bytes from the DPCD | ||
411 | * @aux: DisplayPort AUX channel | ||
412 | * @offset: address of the (first) register to read | ||
413 | * @buffer: buffer to store the register values | ||
414 | * @size: number of bytes in @buffer | ||
415 | * | ||
416 | * Returns the number of bytes transferred on success, or a negative error | ||
417 | * code on failure. -EIO is returned if the request was NAKed by the sink or | ||
418 | * if the retry count was exceeded. If not all bytes were transferred, this | ||
419 | * function returns -EPROTO. Errors from the underlying AUX channel transfer | ||
420 | * function, with the exception of -EBUSY (which causes the transaction to | ||
421 | * be retried), are propagated to the caller. | ||
422 | */ | ||
423 | ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset, | ||
424 | void *buffer, size_t size) | ||
425 | { | ||
426 | return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset, buffer, | ||
427 | size); | ||
428 | } | ||
429 | EXPORT_SYMBOL(drm_dp_dpcd_read); | ||
430 | |||
431 | /** | ||
432 | * drm_dp_dpcd_write() - write a series of bytes to the DPCD | ||
433 | * @aux: DisplayPort AUX channel | ||
434 | * @offset: address of the (first) register to write | ||
435 | * @buffer: buffer containing the values to write | ||
436 | * @size: number of bytes in @buffer | ||
437 | * | ||
438 | * Returns the number of bytes transferred on success, or a negative error | ||
439 | * code on failure. -EIO is returned if the request was NAKed by the sink or | ||
440 | * if the retry count was exceeded. If not all bytes were transferred, this | ||
441 | * function returns -EPROTO. Errors from the underlying AUX channel transfer | ||
442 | * function, with the exception of -EBUSY (which causes the transaction to | ||
443 | * be retried), are propagated to the caller. | ||
444 | */ | ||
445 | ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset, | ||
446 | void *buffer, size_t size) | ||
447 | { | ||
448 | return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer, | ||
449 | size); | ||
450 | } | ||
451 | EXPORT_SYMBOL(drm_dp_dpcd_write); | ||
452 | |||
453 | /** | ||
454 | * drm_dp_dpcd_read_link_status() - read DPCD link status (bytes 0x202-0x207) | ||
455 | * @aux: DisplayPort AUX channel | ||
456 | * @status: buffer to store the link status in (must be at least 6 bytes) | ||
457 | * | ||
458 | * Returns the number of bytes transferred on success or a negative error | ||
459 | * code on failure. | ||
460 | */ | ||
461 | int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux, | ||
462 | u8 status[DP_LINK_STATUS_SIZE]) | ||
463 | { | ||
464 | return drm_dp_dpcd_read(aux, DP_LANE0_1_STATUS, status, | ||
465 | DP_LINK_STATUS_SIZE); | ||
466 | } | ||
467 | EXPORT_SYMBOL(drm_dp_dpcd_read_link_status); | ||
468 | |||
469 | /** | ||
470 | * drm_dp_link_probe() - probe a DisplayPort link for capabilities | ||
471 | * @aux: DisplayPort AUX channel | ||
472 | * @link: pointer to structure in which to return link capabilities | ||
473 | * | ||
474 | * The structure filled in by this function can usually be passed directly | ||
475 | * into drm_dp_link_power_up() and drm_dp_link_configure() to power up and | ||
476 | * configure the link based on the link's capabilities. | ||
477 | * | ||
478 | * Returns 0 on success or a negative error code on failure. | ||
479 | */ | ||
480 | int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link) | ||
481 | { | ||
482 | u8 values[3]; | ||
483 | int err; | ||
484 | |||
485 | memset(link, 0, sizeof(*link)); | ||
486 | |||
487 | err = drm_dp_dpcd_read(aux, DP_DPCD_REV, values, sizeof(values)); | ||
488 | if (err < 0) | ||
489 | return err; | ||
490 | |||
491 | link->revision = values[0]; | ||
492 | link->rate = drm_dp_bw_code_to_link_rate(values[1]); | ||
493 | link->num_lanes = values[2] & DP_MAX_LANE_COUNT_MASK; | ||
494 | |||
495 | if (values[2] & DP_ENHANCED_FRAME_CAP) | ||
496 | link->capabilities |= DP_LINK_CAP_ENHANCED_FRAMING; | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | EXPORT_SYMBOL(drm_dp_link_probe); | ||
501 | |||
502 | /** | ||
503 | * drm_dp_link_power_up() - power up a DisplayPort link | ||
504 | * @aux: DisplayPort AUX channel | ||
505 | * @link: pointer to a structure containing the link configuration | ||
506 | * | ||
507 | * Returns 0 on success or a negative error code on failure. | ||
508 | */ | ||
509 | int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link) | ||
510 | { | ||
511 | u8 value; | ||
512 | int err; | ||
513 | |||
514 | /* DP_SET_POWER register is only available on DPCD v1.1 and later */ | ||
515 | if (link->revision < 0x11) | ||
516 | return 0; | ||
517 | |||
518 | err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); | ||
519 | if (err < 0) | ||
520 | return err; | ||
521 | |||
522 | value &= ~DP_SET_POWER_MASK; | ||
523 | value |= DP_SET_POWER_D0; | ||
524 | |||
525 | err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); | ||
526 | if (err < 0) | ||
527 | return err; | ||
528 | |||
529 | /* | ||
530 | * According to the DP 1.1 specification, a "Sink Device must exit the | ||
531 | * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink | ||
532 | * Control Field" (register 0x600). | ||
533 | */ | ||
534 | usleep_range(1000, 2000); | ||
535 | |||
536 | return 0; | ||
537 | } | ||
538 | EXPORT_SYMBOL(drm_dp_link_power_up); | ||
539 | |||
540 | /** | ||
541 | * drm_dp_link_configure() - configure a DisplayPort link | ||
542 | * @aux: DisplayPort AUX channel | ||
543 | * @link: pointer to a structure containing the link configuration | ||
544 | * | ||
545 | * Returns 0 on success or a negative error code on failure. | ||
546 | */ | ||
547 | int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link) | ||
548 | { | ||
549 | u8 values[2]; | ||
550 | int err; | ||
551 | |||
552 | values[0] = drm_dp_link_rate_to_bw_code(link->rate); | ||
553 | values[1] = link->num_lanes; | ||
554 | |||
555 | if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING) | ||
556 | values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; | ||
557 | |||
558 | err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values)); | ||
559 | if (err < 0) | ||
560 | return err; | ||
561 | |||
562 | return 0; | ||
563 | } | ||
564 | EXPORT_SYMBOL(drm_dp_link_configure); | ||
565 | |||
566 | /* | ||
567 | * I2C-over-AUX implementation | ||
568 | */ | ||
569 | |||
570 | static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter) | ||
571 | { | ||
572 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | | ||
573 | I2C_FUNC_SMBUS_READ_BLOCK_DATA | | ||
574 | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | | ||
575 | I2C_FUNC_10BIT_ADDR; | ||
576 | } | ||
577 | |||
578 | /* | ||
579 | * Transfer a single I2C-over-AUX message and handle various error conditions, | ||
580 | * retrying the transaction as appropriate. | ||
581 | */ | ||
582 | static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | ||
583 | { | ||
584 | unsigned int retry; | ||
585 | int err; | ||
586 | |||
587 | /* | ||
588 | * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device | ||
589 | * is required to retry at least seven times upon receiving AUX_DEFER | ||
590 | * before giving up the AUX transaction. | ||
591 | */ | ||
592 | for (retry = 0; retry < 7; retry++) { | ||
593 | err = aux->transfer(aux, msg); | ||
594 | if (err < 0) { | ||
595 | if (err == -EBUSY) | ||
596 | continue; | ||
597 | |||
598 | DRM_DEBUG_KMS("transaction failed: %d\n", err); | ||
599 | return err; | ||
600 | } | ||
601 | |||
602 | if (err < msg->size) | ||
603 | return -EPROTO; | ||
604 | |||
605 | switch (msg->reply & DP_AUX_NATIVE_REPLY_MASK) { | ||
606 | case DP_AUX_NATIVE_REPLY_ACK: | ||
607 | /* | ||
608 | * For I2C-over-AUX transactions this isn't enough, we | ||
609 | * need to check for the I2C ACK reply. | ||
610 | */ | ||
611 | break; | ||
612 | |||
613 | case DP_AUX_NATIVE_REPLY_NACK: | ||
614 | DRM_DEBUG_KMS("native nack\n"); | ||
615 | return -EREMOTEIO; | ||
616 | |||
617 | case DP_AUX_NATIVE_REPLY_DEFER: | ||
618 | DRM_DEBUG_KMS("native defer"); | ||
619 | /* | ||
620 | * We could check for I2C bit rate capabilities and if | ||
621 | * available adjust this interval. We could also be | ||
622 | * more careful with DP-to-legacy adapters where a | ||
623 | * long legacy cable may force very low I2C bit rates. | ||
624 | * | ||
625 | * For now just defer for long enough to hopefully be | ||
626 | * safe for all use-cases. | ||
627 | */ | ||
628 | usleep_range(500, 600); | ||
629 | continue; | ||
630 | |||
631 | default: | ||
632 | DRM_ERROR("invalid native reply %#04x\n", msg->reply); | ||
633 | return -EREMOTEIO; | ||
634 | } | ||
635 | |||
636 | switch (msg->reply & DP_AUX_I2C_REPLY_MASK) { | ||
637 | case DP_AUX_I2C_REPLY_ACK: | ||
638 | /* | ||
639 | * Both native ACK and I2C ACK replies received. We | ||
640 | * can assume the transfer was successful. | ||
641 | */ | ||
642 | return 0; | ||
643 | |||
644 | case DP_AUX_I2C_REPLY_NACK: | ||
645 | DRM_DEBUG_KMS("I2C nack\n"); | ||
646 | return -EREMOTEIO; | ||
647 | |||
648 | case DP_AUX_I2C_REPLY_DEFER: | ||
649 | DRM_DEBUG_KMS("I2C defer\n"); | ||
650 | usleep_range(400, 500); | ||
651 | continue; | ||
652 | |||
653 | default: | ||
654 | DRM_ERROR("invalid I2C reply %#04x\n", msg->reply); | ||
655 | return -EREMOTEIO; | ||
656 | } | ||
657 | } | ||
658 | |||
659 | DRM_ERROR("too many retries, giving up\n"); | ||
660 | return -EREMOTEIO; | ||
661 | } | ||
662 | |||
663 | static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, | ||
664 | int num) | ||
665 | { | ||
666 | struct drm_dp_aux *aux = adapter->algo_data; | ||
667 | unsigned int i, j; | ||
668 | |||
669 | for (i = 0; i < num; i++) { | ||
670 | struct drm_dp_aux_msg msg; | ||
671 | int err; | ||
672 | |||
673 | /* | ||
674 | * Many hardware implementations support FIFOs larger than a | ||
675 | * single byte, but it has been empirically determined that | ||
676 | * transferring data in larger chunks can actually lead to | ||
677 | * decreased performance. Therefore each message is simply | ||
678 | * transferred byte-by-byte. | ||
679 | */ | ||
680 | for (j = 0; j < msgs[i].len; j++) { | ||
681 | memset(&msg, 0, sizeof(msg)); | ||
682 | msg.address = msgs[i].addr; | ||
683 | |||
684 | msg.request = (msgs[i].flags & I2C_M_RD) ? | ||
685 | DP_AUX_I2C_READ : | ||
686 | DP_AUX_I2C_WRITE; | ||
687 | |||
688 | /* | ||
689 | * All messages except the last one are middle-of- | ||
690 | * transfer messages. | ||
691 | */ | ||
692 | if ((i < num - 1) || (j < msgs[i].len - 1)) | ||
693 | msg.request |= DP_AUX_I2C_MOT; | ||
694 | |||
695 | msg.buffer = msgs[i].buf + j; | ||
696 | msg.size = 1; | ||
697 | |||
698 | err = drm_dp_i2c_do_msg(aux, &msg); | ||
699 | if (err < 0) | ||
700 | return err; | ||
701 | } | ||
702 | } | ||
703 | |||
704 | return num; | ||
705 | } | ||
706 | |||
707 | static const struct i2c_algorithm drm_dp_i2c_algo = { | ||
708 | .functionality = drm_dp_i2c_functionality, | ||
709 | .master_xfer = drm_dp_i2c_xfer, | ||
710 | }; | ||
711 | |||
712 | /** | ||
713 | * drm_dp_aux_register_i2c_bus() - register an I2C adapter for I2C-over-AUX | ||
714 | * @aux: DisplayPort AUX channel | ||
715 | * | ||
716 | * Returns 0 on success or a negative error code on failure. | ||
717 | */ | ||
718 | int drm_dp_aux_register_i2c_bus(struct drm_dp_aux *aux) | ||
719 | { | ||
720 | aux->ddc.algo = &drm_dp_i2c_algo; | ||
721 | aux->ddc.algo_data = aux; | ||
722 | aux->ddc.retries = 3; | ||
723 | |||
724 | aux->ddc.class = I2C_CLASS_DDC; | ||
725 | aux->ddc.owner = THIS_MODULE; | ||
726 | aux->ddc.dev.parent = aux->dev; | ||
727 | aux->ddc.dev.of_node = aux->dev->of_node; | ||
728 | |||
729 | strncpy(aux->ddc.name, dev_name(aux->dev), sizeof(aux->ddc.name)); | ||
730 | |||
731 | return i2c_add_adapter(&aux->ddc); | ||
732 | } | ||
733 | EXPORT_SYMBOL(drm_dp_aux_register_i2c_bus); | ||
734 | |||
735 | /** | ||
736 | * drm_dp_aux_unregister_i2c_bus() - unregister an I2C-over-AUX adapter | ||
737 | * @aux: DisplayPort AUX channel | ||
738 | */ | ||
739 | void drm_dp_aux_unregister_i2c_bus(struct drm_dp_aux *aux) | ||
740 | { | ||
741 | i2c_del_adapter(&aux->ddc); | ||
742 | } | ||
743 | EXPORT_SYMBOL(drm_dp_aux_unregister_i2c_bus); | ||
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 1d09050a8c00..b7488c9849ad 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h | |||
@@ -291,6 +291,7 @@ | |||
291 | #define DP_SET_POWER 0x600 | 291 | #define DP_SET_POWER 0x600 |
292 | # define DP_SET_POWER_D0 0x1 | 292 | # define DP_SET_POWER_D0 0x1 |
293 | # define DP_SET_POWER_D3 0x2 | 293 | # define DP_SET_POWER_D3 0x2 |
294 | # define DP_SET_POWER_MASK 0x3 | ||
294 | 295 | ||
295 | #define DP_PSR_ERROR_STATUS 0x2006 /* XXX 1.2? */ | 296 | #define DP_PSR_ERROR_STATUS 0x2006 /* XXX 1.2? */ |
296 | # define DP_PSR_LINK_CRC_ERROR (1 << 0) | 297 | # define DP_PSR_LINK_CRC_ERROR (1 << 0) |
@@ -398,4 +399,114 @@ drm_dp_enhanced_frame_cap(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) | |||
398 | (dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP); | 399 | (dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP); |
399 | } | 400 | } |
400 | 401 | ||
402 | /* | ||
403 | * DisplayPort AUX channel | ||
404 | */ | ||
405 | |||
406 | /** | ||
407 | * struct drm_dp_aux_msg - DisplayPort AUX channel transaction | ||
408 | * @address: address of the (first) register to access | ||
409 | * @request: contains the type of transaction (see DP_AUX_* macros) | ||
410 | * @reply: upon completion, contains the reply type of the transaction | ||
411 | * @buffer: pointer to a transmission or reception buffer | ||
412 | * @size: size of @buffer | ||
413 | */ | ||
414 | struct drm_dp_aux_msg { | ||
415 | unsigned int address; | ||
416 | u8 request; | ||
417 | u8 reply; | ||
418 | void *buffer; | ||
419 | size_t size; | ||
420 | }; | ||
421 | |||
422 | /** | ||
423 | * struct drm_dp_aux - DisplayPort AUX channel | ||
424 | * @ddc: I2C adapter that can be used for I2C-over-AUX communication | ||
425 | * @dev: pointer to struct device that is the parent for this AUX channel | ||
426 | * @transfer: transfers a message representing a single AUX transaction | ||
427 | * | ||
428 | * The .dev field should be set to a pointer to the device that implements | ||
429 | * the AUX channel. | ||
430 | * | ||
431 | * Drivers provide a hardware-specific implementation of how transactions | ||
432 | * are executed via the .transfer() function. A pointer to a drm_dp_aux_msg | ||
433 | * structure describing the transaction is passed into this function. Upon | ||
434 | * success, the implementation should return the number of payload bytes | ||
435 | * that were transferred, or a negative error-code on failure. Helpers | ||
436 | * propagate errors from the .transfer() function, with the exception of | ||
437 | * the -EBUSY error, which causes a transaction to be retried. On a short, | ||
438 | * helpers will return -EPROTO to make it simpler to check for failure. | ||
439 | * | ||
440 | * An AUX channel can also be used to transport I2C messages to a sink. A | ||
441 | * typical application of that is to access an EDID that's present in the | ||
442 | * sink device. The .transfer() function can also be used to execute such | ||
443 | * transactions. The drm_dp_aux_register_i2c_bus() function registers an | ||
444 | * I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers | ||
445 | * should call drm_dp_aux_unregister_i2c_bus() to remove the I2C adapter. | ||
446 | */ | ||
447 | struct drm_dp_aux { | ||
448 | struct i2c_adapter ddc; | ||
449 | struct device *dev; | ||
450 | |||
451 | ssize_t (*transfer)(struct drm_dp_aux *aux, | ||
452 | struct drm_dp_aux_msg *msg); | ||
453 | }; | ||
454 | |||
455 | ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset, | ||
456 | void *buffer, size_t size); | ||
457 | ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset, | ||
458 | void *buffer, size_t size); | ||
459 | |||
460 | /** | ||
461 | * drm_dp_dpcd_readb() - read a single byte from the DPCD | ||
462 | * @aux: DisplayPort AUX channel | ||
463 | * @offset: address of the register to read | ||
464 | * @valuep: location where the value of the register will be stored | ||
465 | * | ||
466 | * Returns the number of bytes transferred (1) on success, or a negative | ||
467 | * error code on failure. | ||
468 | */ | ||
469 | static inline ssize_t drm_dp_dpcd_readb(struct drm_dp_aux *aux, | ||
470 | unsigned int offset, u8 *valuep) | ||
471 | { | ||
472 | return drm_dp_dpcd_read(aux, offset, valuep, 1); | ||
473 | } | ||
474 | |||
475 | /** | ||
476 | * drm_dp_dpcd_writeb() - write a single byte to the DPCD | ||
477 | * @aux: DisplayPort AUX channel | ||
478 | * @offset: address of the register to write | ||
479 | * @value: value to write to the register | ||
480 | * | ||
481 | * Returns the number of bytes transferred (1) on success, or a negative | ||
482 | * error code on failure. | ||
483 | */ | ||
484 | static inline ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux *aux, | ||
485 | unsigned int offset, u8 value) | ||
486 | { | ||
487 | return drm_dp_dpcd_write(aux, offset, &value, 1); | ||
488 | } | ||
489 | |||
490 | int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux, | ||
491 | u8 status[DP_LINK_STATUS_SIZE]); | ||
492 | |||
493 | /* | ||
494 | * DisplayPort link | ||
495 | */ | ||
496 | #define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0) | ||
497 | |||
498 | struct drm_dp_link { | ||
499 | unsigned char revision; | ||
500 | unsigned int rate; | ||
501 | unsigned int num_lanes; | ||
502 | unsigned long capabilities; | ||
503 | }; | ||
504 | |||
505 | int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link); | ||
506 | int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link); | ||
507 | int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link); | ||
508 | |||
509 | int drm_dp_aux_register_i2c_bus(struct drm_dp_aux *aux); | ||
510 | void drm_dp_aux_unregister_i2c_bus(struct drm_dp_aux *aux); | ||
511 | |||
401 | #endif /* _DRM_DP_HELPER_H_ */ | 512 | #endif /* _DRM_DP_HELPER_H_ */ |