Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915/dp: Ensure panel power remains enabled during connector detection

The sink's capabilities, like the DSC caps, depend on the source OUI
written to the sink's DPCD registers and so this OUI value should be
valid for the whole duration of the detection. An eDP sink will reset
this OUI value when the panel power is disabled, so prevent the
disabling - happening by default after a 1 sec idle period - for the
whole duration of detection.

v2: Update the documentation for intel_pps_on(). (Jani)

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241025160259.3088727-3-imre.deak@intel.com

+27 -6
+13 -5
drivers/gpu/drm/i915/display/intel_dp.c
··· 5619 5619 5620 5620 intel_dp_flush_connector_commits(intel_connector); 5621 5621 5622 + intel_pps_vdd_on(intel_dp); 5623 + 5622 5624 /* Can't disconnect eDP */ 5623 5625 if (intel_dp_is_edp(intel_dp)) 5624 5626 status = edp_detect(intel_dp); ··· 5651 5649 5652 5650 intel_dp_tunnel_disconnect(intel_dp); 5653 5651 5654 - goto out; 5652 + goto out_unset_edid; 5655 5653 } 5656 5654 5657 5655 ret = intel_dp_tunnel_detect(intel_dp, ctx); 5658 - if (ret == -EDEADLK) 5659 - return ret; 5656 + if (ret == -EDEADLK) { 5657 + status = ret; 5658 + 5659 + goto out_vdd_off; 5660 + } 5660 5661 5661 5662 if (ret == 1) 5662 5663 intel_connector->base.epoch_counter++; ··· 5687 5682 * with EDID on it 5688 5683 */ 5689 5684 status = connector_status_disconnected; 5690 - goto out; 5685 + goto out_unset_edid; 5691 5686 } 5692 5687 5693 5688 /* ··· 5716 5711 5717 5712 intel_dp_check_device_service_irq(intel_dp); 5718 5713 5719 - out: 5714 + out_unset_edid: 5720 5715 if (status != connector_status_connected && !intel_dp->is_mst) 5721 5716 intel_dp_unset_edid(intel_dp); 5722 5717 ··· 5725 5720 status, 5726 5721 intel_dp->dpcd, 5727 5722 intel_dp->downstream_ports); 5723 + out_vdd_off: 5724 + intel_pps_vdd_off(intel_dp); 5725 + 5728 5726 return status; 5729 5727 } 5730 5728
+13 -1
drivers/gpu/drm/i915/display/intel_pps.c
··· 797 797 } 798 798 799 799 /* 800 - * Must be paired with intel_pps_off(). 800 + * Must be paired with intel_pps_vdd_off() or - to disable 801 + * both VDD and panel power - intel_pps_off(). 801 802 * Nested calls to these functions are not allowed since 802 803 * we drop the lock. Caller must use some higher level 803 804 * locking to prevent nested calls from other threads. ··· 943 942 intel_pps_vdd_off_sync_unlocked(intel_dp); 944 943 else 945 944 edp_panel_vdd_schedule_off(intel_dp); 945 + } 946 + 947 + void intel_pps_vdd_off(struct intel_dp *intel_dp) 948 + { 949 + intel_wakeref_t wakeref; 950 + 951 + if (!intel_dp_is_edp(intel_dp)) 952 + return; 953 + 954 + with_intel_pps_lock(intel_dp, wakeref) 955 + intel_pps_vdd_off_unlocked(intel_dp, false); 946 956 } 947 957 948 958 void intel_pps_on_unlocked(struct intel_dp *intel_dp)
+1
drivers/gpu/drm/i915/display/intel_pps.h
··· 34 34 void intel_pps_check_power_unlocked(struct intel_dp *intel_dp); 35 35 36 36 void intel_pps_vdd_on(struct intel_dp *intel_dp); 37 + void intel_pps_vdd_off(struct intel_dp *intel_dp); 37 38 void intel_pps_on(struct intel_dp *intel_dp); 38 39 void intel_pps_off(struct intel_dp *intel_dp); 39 40 void intel_pps_vdd_off_sync(struct intel_dp *intel_dp);