diff options
author | Jani Nikula <jani.nikula@intel.com> | 2014-03-14 10:51:17 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-03-18 10:05:48 -0400 |
commit | 0b99836f238f37a8632a3ab4f9a8cc2346a36d40 (patch) | |
tree | 239f23a54a0724ca8cd9a1f8164ca39aec8c2f1d | |
parent | 33ad6626a1a9155fcbb04869c7cdde0552976396 (diff) |
drm/i915/dp: use the new drm helpers for dp i2c-over-aux
The functionality remains largerly the same. The main difference is that
i2c-over-aux defer timeouts are increased to be safe for all use cases
instead of depending on DP device type and properties.
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 197 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 2 |
2 files changed, 30 insertions, 169 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 623b50c46bbc..160d5b30b3bc 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -645,19 +645,25 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) | |||
645 | struct drm_device *dev = intel_dp_to_dev(intel_dp); | 645 | struct drm_device *dev = intel_dp_to_dev(intel_dp); |
646 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | 646 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
647 | enum port port = intel_dig_port->port; | 647 | enum port port = intel_dig_port->port; |
648 | const char *name = NULL; | ||
649 | int ret; | ||
648 | 650 | ||
649 | switch (port) { | 651 | switch (port) { |
650 | case PORT_A: | 652 | case PORT_A: |
651 | intel_dp->aux_ch_ctl_reg = DPA_AUX_CH_CTL; | 653 | intel_dp->aux_ch_ctl_reg = DPA_AUX_CH_CTL; |
654 | name = "DPDDC-A"; | ||
652 | break; | 655 | break; |
653 | case PORT_B: | 656 | case PORT_B: |
654 | intel_dp->aux_ch_ctl_reg = PCH_DPB_AUX_CH_CTL; | 657 | intel_dp->aux_ch_ctl_reg = PCH_DPB_AUX_CH_CTL; |
658 | name = "DPDDC-B"; | ||
655 | break; | 659 | break; |
656 | case PORT_C: | 660 | case PORT_C: |
657 | intel_dp->aux_ch_ctl_reg = PCH_DPC_AUX_CH_CTL; | 661 | intel_dp->aux_ch_ctl_reg = PCH_DPC_AUX_CH_CTL; |
662 | name = "DPDDC-C"; | ||
658 | break; | 663 | break; |
659 | case PORT_D: | 664 | case PORT_D: |
660 | intel_dp->aux_ch_ctl_reg = PCH_DPD_AUX_CH_CTL; | 665 | intel_dp->aux_ch_ctl_reg = PCH_DPD_AUX_CH_CTL; |
666 | name = "DPDDC-D"; | ||
661 | break; | 667 | break; |
662 | default: | 668 | default: |
663 | BUG(); | 669 | BUG(); |
@@ -666,128 +672,27 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) | |||
666 | if (!HAS_DDI(dev)) | 672 | if (!HAS_DDI(dev)) |
667 | intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10; | 673 | intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10; |
668 | 674 | ||
675 | intel_dp->aux.name = name; | ||
669 | intel_dp->aux.dev = dev->dev; | 676 | intel_dp->aux.dev = dev->dev; |
670 | intel_dp->aux.transfer = intel_dp_aux_transfer; | 677 | intel_dp->aux.transfer = intel_dp_aux_transfer; |
671 | } | ||
672 | 678 | ||
673 | static int | 679 | DRM_DEBUG_KMS("registering %s bus for %s\n", name, |
674 | intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, | 680 | connector->base.kdev->kobj.name); |
675 | uint8_t write_byte, uint8_t *read_byte) | ||
676 | { | ||
677 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
678 | struct intel_dp *intel_dp = container_of(adapter, | ||
679 | struct intel_dp, | ||
680 | adapter); | ||
681 | uint16_t address = algo_data->address; | ||
682 | uint8_t msg[5]; | ||
683 | uint8_t reply[2]; | ||
684 | unsigned retry; | ||
685 | int msg_bytes; | ||
686 | int reply_bytes; | ||
687 | int ret; | ||
688 | |||
689 | /* Set up the command byte */ | ||
690 | if (mode & MODE_I2C_READ) | ||
691 | msg[0] = DP_AUX_I2C_READ << 4; | ||
692 | else | ||
693 | msg[0] = DP_AUX_I2C_WRITE << 4; | ||
694 | 681 | ||
695 | if (!(mode & MODE_I2C_STOP)) | 682 | ret = drm_dp_aux_register_i2c_bus(&intel_dp->aux); |
696 | msg[0] |= DP_AUX_I2C_MOT << 4; | 683 | if (ret < 0) { |
697 | 684 | DRM_ERROR("drm_dp_aux_register_i2c_bus() for %s failed (%d)\n", | |
698 | msg[1] = address >> 8; | 685 | name, ret); |
699 | msg[2] = address; | 686 | return; |
700 | |||
701 | switch (mode) { | ||
702 | case MODE_I2C_WRITE: | ||
703 | msg[3] = 0; | ||
704 | msg[4] = write_byte; | ||
705 | msg_bytes = 5; | ||
706 | reply_bytes = 1; | ||
707 | break; | ||
708 | case MODE_I2C_READ: | ||
709 | msg[3] = 0; | ||
710 | msg_bytes = 4; | ||
711 | reply_bytes = 2; | ||
712 | break; | ||
713 | default: | ||
714 | msg_bytes = 3; | ||
715 | reply_bytes = 1; | ||
716 | break; | ||
717 | } | 687 | } |
718 | 688 | ||
719 | /* | 689 | ret = sysfs_create_link(&connector->base.kdev->kobj, |
720 | * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device is | 690 | &intel_dp->aux.ddc.dev.kobj, |
721 | * required to retry at least seven times upon receiving AUX_DEFER | 691 | intel_dp->aux.ddc.dev.kobj.name); |
722 | * before giving up the AUX transaction. | 692 | if (ret < 0) { |
723 | */ | 693 | DRM_ERROR("sysfs_create_link() for %s failed (%d)\n", name, ret); |
724 | for (retry = 0; retry < 7; retry++) { | 694 | drm_dp_aux_unregister_i2c_bus(&intel_dp->aux); |
725 | ret = intel_dp_aux_ch(intel_dp, | ||
726 | msg, msg_bytes, | ||
727 | reply, reply_bytes); | ||
728 | if (ret < 0) { | ||
729 | DRM_DEBUG_KMS("aux_ch failed %d\n", ret); | ||
730 | goto out; | ||
731 | } | ||
732 | |||
733 | switch ((reply[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK) { | ||
734 | case DP_AUX_NATIVE_REPLY_ACK: | ||
735 | /* I2C-over-AUX Reply field is only valid | ||
736 | * when paired with AUX ACK. | ||
737 | */ | ||
738 | break; | ||
739 | case DP_AUX_NATIVE_REPLY_NACK: | ||
740 | DRM_DEBUG_KMS("aux_ch native nack\n"); | ||
741 | ret = -EREMOTEIO; | ||
742 | goto out; | ||
743 | case DP_AUX_NATIVE_REPLY_DEFER: | ||
744 | /* | ||
745 | * For now, just give more slack to branch devices. We | ||
746 | * could check the DPCD for I2C bit rate capabilities, | ||
747 | * and if available, adjust the interval. We could also | ||
748 | * be more careful with DP-to-Legacy adapters where a | ||
749 | * long legacy cable may force very low I2C bit rates. | ||
750 | */ | ||
751 | if (intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & | ||
752 | DP_DWN_STRM_PORT_PRESENT) | ||
753 | usleep_range(500, 600); | ||
754 | else | ||
755 | usleep_range(300, 400); | ||
756 | continue; | ||
757 | default: | ||
758 | DRM_ERROR("aux_ch invalid native reply 0x%02x\n", | ||
759 | reply[0]); | ||
760 | ret = -EREMOTEIO; | ||
761 | goto out; | ||
762 | } | ||
763 | |||
764 | switch ((reply[0] >> 4) & DP_AUX_I2C_REPLY_MASK) { | ||
765 | case DP_AUX_I2C_REPLY_ACK: | ||
766 | if (mode == MODE_I2C_READ) { | ||
767 | *read_byte = reply[1]; | ||
768 | } | ||
769 | ret = reply_bytes - 1; | ||
770 | goto out; | ||
771 | case DP_AUX_I2C_REPLY_NACK: | ||
772 | DRM_DEBUG_KMS("aux_i2c nack\n"); | ||
773 | ret = -EREMOTEIO; | ||
774 | goto out; | ||
775 | case DP_AUX_I2C_REPLY_DEFER: | ||
776 | DRM_DEBUG_KMS("aux_i2c defer\n"); | ||
777 | udelay(100); | ||
778 | break; | ||
779 | default: | ||
780 | DRM_ERROR("aux_i2c invalid reply 0x%02x\n", reply[0]); | ||
781 | ret = -EREMOTEIO; | ||
782 | goto out; | ||
783 | } | ||
784 | } | 695 | } |
785 | |||
786 | DRM_ERROR("too many retries, giving up\n"); | ||
787 | ret = -EREMOTEIO; | ||
788 | |||
789 | out: | ||
790 | return ret; | ||
791 | } | 696 | } |
792 | 697 | ||
793 | static void | 698 | static void |
@@ -796,43 +701,10 @@ intel_dp_connector_unregister(struct intel_connector *intel_connector) | |||
796 | struct intel_dp *intel_dp = intel_attached_dp(&intel_connector->base); | 701 | struct intel_dp *intel_dp = intel_attached_dp(&intel_connector->base); |
797 | 702 | ||
798 | sysfs_remove_link(&intel_connector->base.kdev->kobj, | 703 | sysfs_remove_link(&intel_connector->base.kdev->kobj, |
799 | intel_dp->adapter.dev.kobj.name); | 704 | intel_dp->aux.ddc.dev.kobj.name); |
800 | intel_connector_unregister(intel_connector); | 705 | intel_connector_unregister(intel_connector); |
801 | } | 706 | } |
802 | 707 | ||
803 | static int | ||
804 | intel_dp_i2c_init(struct intel_dp *intel_dp, | ||
805 | struct intel_connector *intel_connector, const char *name) | ||
806 | { | ||
807 | int ret; | ||
808 | |||
809 | DRM_DEBUG_KMS("i2c_init %s\n", name); | ||
810 | intel_dp->algo.running = false; | ||
811 | intel_dp->algo.address = 0; | ||
812 | intel_dp->algo.aux_ch = intel_dp_i2c_aux_ch; | ||
813 | |||
814 | memset(&intel_dp->adapter, '\0', sizeof(intel_dp->adapter)); | ||
815 | intel_dp->adapter.owner = THIS_MODULE; | ||
816 | intel_dp->adapter.class = I2C_CLASS_DDC; | ||
817 | strncpy(intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1); | ||
818 | intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0'; | ||
819 | intel_dp->adapter.algo_data = &intel_dp->algo; | ||
820 | intel_dp->adapter.dev.parent = intel_connector->base.dev->dev; | ||
821 | |||
822 | ret = i2c_dp_aux_add_bus(&intel_dp->adapter); | ||
823 | if (ret < 0) | ||
824 | return ret; | ||
825 | |||
826 | ret = sysfs_create_link(&intel_connector->base.kdev->kobj, | ||
827 | &intel_dp->adapter.dev.kobj, | ||
828 | intel_dp->adapter.dev.kobj.name); | ||
829 | |||
830 | if (ret < 0) | ||
831 | i2c_del_adapter(&intel_dp->adapter); | ||
832 | |||
833 | return ret; | ||
834 | } | ||
835 | |||
836 | static void | 708 | static void |
837 | intel_dp_set_clock(struct intel_encoder *encoder, | 709 | intel_dp_set_clock(struct intel_encoder *encoder, |
838 | struct intel_crtc_config *pipe_config, int link_bw) | 710 | struct intel_crtc_config *pipe_config, int link_bw) |
@@ -3098,7 +2970,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) | |||
3098 | } | 2970 | } |
3099 | 2971 | ||
3100 | /* If no HPD, poke DDC gently */ | 2972 | /* If no HPD, poke DDC gently */ |
3101 | if (drm_probe_ddc(&intel_dp->adapter)) | 2973 | if (drm_probe_ddc(&intel_dp->aux.ddc)) |
3102 | return connector_status_connected; | 2974 | return connector_status_connected; |
3103 | 2975 | ||
3104 | /* Well we tried, say unknown for unreliable port types */ | 2976 | /* Well we tried, say unknown for unreliable port types */ |
@@ -3266,7 +3138,7 @@ intel_dp_detect(struct drm_connector *connector, bool force) | |||
3266 | if (intel_dp->force_audio != HDMI_AUDIO_AUTO) { | 3138 | if (intel_dp->force_audio != HDMI_AUDIO_AUTO) { |
3267 | intel_dp->has_audio = (intel_dp->force_audio == HDMI_AUDIO_ON); | 3139 | intel_dp->has_audio = (intel_dp->force_audio == HDMI_AUDIO_ON); |
3268 | } else { | 3140 | } else { |
3269 | edid = intel_dp_get_edid(connector, &intel_dp->adapter); | 3141 | edid = intel_dp_get_edid(connector, &intel_dp->aux.ddc); |
3270 | if (edid) { | 3142 | if (edid) { |
3271 | intel_dp->has_audio = drm_detect_monitor_audio(edid); | 3143 | intel_dp->has_audio = drm_detect_monitor_audio(edid); |
3272 | kfree(edid); | 3144 | kfree(edid); |
@@ -3302,7 +3174,7 @@ static int intel_dp_get_modes(struct drm_connector *connector) | |||
3302 | power_domain = intel_display_port_power_domain(intel_encoder); | 3174 | power_domain = intel_display_port_power_domain(intel_encoder); |
3303 | intel_display_power_get(dev_priv, power_domain); | 3175 | intel_display_power_get(dev_priv, power_domain); |
3304 | 3176 | ||
3305 | ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter); | 3177 | ret = intel_dp_get_edid_modes(connector, &intel_dp->aux.ddc); |
3306 | intel_display_power_put(dev_priv, power_domain); | 3178 | intel_display_power_put(dev_priv, power_domain); |
3307 | if (ret) | 3179 | if (ret) |
3308 | return ret; | 3180 | return ret; |
@@ -3335,7 +3207,7 @@ intel_dp_detect_audio(struct drm_connector *connector) | |||
3335 | power_domain = intel_display_port_power_domain(intel_encoder); | 3207 | power_domain = intel_display_port_power_domain(intel_encoder); |
3336 | intel_display_power_get(dev_priv, power_domain); | 3208 | intel_display_power_get(dev_priv, power_domain); |
3337 | 3209 | ||
3338 | edid = intel_dp_get_edid(connector, &intel_dp->adapter); | 3210 | edid = intel_dp_get_edid(connector, &intel_dp->aux.ddc); |
3339 | if (edid) { | 3211 | if (edid) { |
3340 | has_audio = drm_detect_monitor_audio(edid); | 3212 | has_audio = drm_detect_monitor_audio(edid); |
3341 | kfree(edid); | 3213 | kfree(edid); |
@@ -3457,7 +3329,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) | |||
3457 | struct intel_dp *intel_dp = &intel_dig_port->dp; | 3329 | struct intel_dp *intel_dp = &intel_dig_port->dp; |
3458 | struct drm_device *dev = intel_dp_to_dev(intel_dp); | 3330 | struct drm_device *dev = intel_dp_to_dev(intel_dp); |
3459 | 3331 | ||
3460 | i2c_del_adapter(&intel_dp->adapter); | 3332 | drm_dp_aux_unregister_i2c_bus(&intel_dp->aux); |
3461 | drm_encoder_cleanup(encoder); | 3333 | drm_encoder_cleanup(encoder); |
3462 | if (is_edp(intel_dp)) { | 3334 | if (is_edp(intel_dp)) { |
3463 | cancel_delayed_work_sync(&intel_dp->panel_vdd_work); | 3335 | cancel_delayed_work_sync(&intel_dp->panel_vdd_work); |
@@ -3769,7 +3641,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, | |||
3769 | /* We now know it's not a ghost, init power sequence regs. */ | 3641 | /* We now know it's not a ghost, init power sequence regs. */ |
3770 | intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq); | 3642 | intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq); |
3771 | 3643 | ||
3772 | edid = drm_get_edid(connector, &intel_dp->adapter); | 3644 | edid = drm_get_edid(connector, &intel_dp->aux.ddc); |
3773 | if (edid) { | 3645 | if (edid) { |
3774 | if (drm_add_edid_modes(connector, edid)) { | 3646 | if (drm_add_edid_modes(connector, edid)) { |
3775 | drm_mode_connector_update_edid_property(connector, | 3647 | drm_mode_connector_update_edid_property(connector, |
@@ -3817,8 +3689,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
3817 | struct drm_i915_private *dev_priv = dev->dev_private; | 3689 | struct drm_i915_private *dev_priv = dev->dev_private; |
3818 | enum port port = intel_dig_port->port; | 3690 | enum port port = intel_dig_port->port; |
3819 | struct edp_power_seq power_seq = { 0 }; | 3691 | struct edp_power_seq power_seq = { 0 }; |
3820 | const char *name = NULL; | 3692 | int type; |
3821 | int type, error; | ||
3822 | 3693 | ||
3823 | /* intel_dp vfuncs */ | 3694 | /* intel_dp vfuncs */ |
3824 | if (IS_VALLEYVIEW(dev)) | 3695 | if (IS_VALLEYVIEW(dev)) |
@@ -3871,23 +3742,19 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
3871 | intel_connector->get_hw_state = intel_connector_get_hw_state; | 3742 | intel_connector->get_hw_state = intel_connector_get_hw_state; |
3872 | intel_connector->unregister = intel_dp_connector_unregister; | 3743 | intel_connector->unregister = intel_dp_connector_unregister; |
3873 | 3744 | ||
3874 | /* Set up the DDC bus. */ | 3745 | /* Set up the hotplug pin. */ |
3875 | switch (port) { | 3746 | switch (port) { |
3876 | case PORT_A: | 3747 | case PORT_A: |
3877 | intel_encoder->hpd_pin = HPD_PORT_A; | 3748 | intel_encoder->hpd_pin = HPD_PORT_A; |
3878 | name = "DPDDC-A"; | ||
3879 | break; | 3749 | break; |
3880 | case PORT_B: | 3750 | case PORT_B: |
3881 | intel_encoder->hpd_pin = HPD_PORT_B; | 3751 | intel_encoder->hpd_pin = HPD_PORT_B; |
3882 | name = "DPDDC-B"; | ||
3883 | break; | 3752 | break; |
3884 | case PORT_C: | 3753 | case PORT_C: |
3885 | intel_encoder->hpd_pin = HPD_PORT_C; | 3754 | intel_encoder->hpd_pin = HPD_PORT_C; |
3886 | name = "DPDDC-C"; | ||
3887 | break; | 3755 | break; |
3888 | case PORT_D: | 3756 | case PORT_D: |
3889 | intel_encoder->hpd_pin = HPD_PORT_D; | 3757 | intel_encoder->hpd_pin = HPD_PORT_D; |
3890 | name = "DPDDC-D"; | ||
3891 | break; | 3758 | break; |
3892 | default: | 3759 | default: |
3893 | BUG(); | 3760 | BUG(); |
@@ -3900,14 +3767,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
3900 | 3767 | ||
3901 | intel_dp_aux_init(intel_dp, intel_connector); | 3768 | intel_dp_aux_init(intel_dp, intel_connector); |
3902 | 3769 | ||
3903 | error = intel_dp_i2c_init(intel_dp, intel_connector, name); | ||
3904 | WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n", | ||
3905 | error, port_name(port)); | ||
3906 | |||
3907 | intel_dp->psr_setup_done = false; | 3770 | intel_dp->psr_setup_done = false; |
3908 | 3771 | ||
3909 | if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) { | 3772 | if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) { |
3910 | i2c_del_adapter(&intel_dp->adapter); | 3773 | drm_dp_aux_unregister_i2c_bus(&intel_dp->aux); |
3911 | if (is_edp(intel_dp)) { | 3774 | if (is_edp(intel_dp)) { |
3912 | cancel_delayed_work_sync(&intel_dp->panel_vdd_work); | 3775 | cancel_delayed_work_sync(&intel_dp->panel_vdd_work); |
3913 | mutex_lock(&dev->mode_config.mutex); | 3776 | mutex_lock(&dev->mode_config.mutex); |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 578c18ed982c..5ca293b3ef5c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -485,8 +485,6 @@ struct intel_dp { | |||
485 | uint8_t dpcd[DP_RECEIVER_CAP_SIZE]; | 485 | uint8_t dpcd[DP_RECEIVER_CAP_SIZE]; |
486 | uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE]; | 486 | uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE]; |
487 | uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; | 487 | uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; |
488 | struct i2c_adapter adapter; | ||
489 | struct i2c_algo_dp_aux_data algo; | ||
490 | struct drm_dp_aux aux; | 488 | struct drm_dp_aux aux; |
491 | uint8_t train_set[4]; | 489 | uint8_t train_set[4]; |
492 | int panel_power_up_delay; | 490 | int panel_power_up_delay; |