Commit 9210e94a authored by Imre Deak's avatar Imre Deak
Browse files

drm/i915: Add intel_digital_port lock/unlock hooks

Add hooks to intel_digital_port to lock and unlock the port and add a
helper to check the connector's detect status while the port is locked
already. This simplifies checking the connector detect status in
intel_dp_aux_xfer() and intel_digital_port_connected() in the next two
patches aborting AUX transfers on all DP connectors (except eDP) and
filtering HPD glitches.

Link: https://patchwork.freedesktop.org/patch/msgid/20240104083008.2715733-11-imre.deak@intel.com


Reviewed-by: default avatarJouni Högander <jouni.hogander@intel.com>
Signed-off-by: default avatarImre Deak <imre.deak@intel.com>
parent bab87ef4
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -5117,6 +5117,9 @@ void intel_ddi_init(struct drm_i915_private *dev_priv,
		encoder->suspend_complete = intel_ddi_tc_encoder_suspend_complete;
		encoder->shutdown_complete = intel_ddi_tc_encoder_shutdown_complete;

		dig_port->lock = intel_tc_port_lock;
		dig_port->unlock = intel_tc_port_unlock;

		if (intel_tc_port_init(dig_port, is_legacy) < 0)
			goto err;
	}
+3 −0
Original line number Diff line number Diff line
@@ -1890,6 +1890,9 @@ struct intel_digital_port {
	u32 (*infoframes_enabled)(struct intel_encoder *encoder,
				  const struct intel_crtc_state *pipe_config);
	bool (*connected)(struct intel_encoder *encoder);

	void (*lock)(struct intel_digital_port *dig_port);
	void (*unlock)(struct intel_digital_port *dig_port);
};

struct intel_dp_mst_encoder {
+32 −2
Original line number Diff line number Diff line
@@ -5426,8 +5426,24 @@ edp_detect(struct intel_dp *intel_dp)
	return connector_status_connected;
}

void intel_digital_port_lock(struct intel_encoder *encoder)
{
	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);

	if (dig_port->lock)
		dig_port->lock(dig_port);
}

void intel_digital_port_unlock(struct intel_encoder *encoder)
{
	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);

	if (dig_port->unlock)
		dig_port->unlock(dig_port);
}

/*
 * intel_digital_port_connected - is the specified port connected?
 * intel_digital_port_connected_locked - is the specified port connected?
 * @encoder: intel_encoder
 *
 * In cases where there's a connector physically connected but it can't be used
@@ -5435,9 +5451,12 @@ edp_detect(struct intel_dp *intel_dp)
 * pretty much treat the port as disconnected. This is relevant for type-C
 * (starting on ICL) where there's ownership involved.
 *
 * The caller must hold the lock acquired by calling intel_digital_port_lock()
 * when calling this function.
 *
 * Return %true if port is connected, %false otherwise.
 */
bool intel_digital_port_connected(struct intel_encoder *encoder)
bool intel_digital_port_connected_locked(struct intel_encoder *encoder)
{
	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
@@ -5450,6 +5469,17 @@ bool intel_digital_port_connected(struct intel_encoder *encoder)
	return is_connected;
}

bool intel_digital_port_connected(struct intel_encoder *encoder)
{
	bool ret;

	intel_digital_port_lock(encoder);
	ret = intel_digital_port_connected_locked(encoder);
	intel_digital_port_unlock(encoder);

	return ret;
}

static const struct drm_edid *
intel_dp_get_edid(struct intel_dp *intel_dp)
{
+3 −0
Original line number Diff line number Diff line
@@ -115,7 +115,10 @@ void intel_dp_set_infoframes(struct intel_encoder *encoder, bool enable,
void intel_read_dp_sdp(struct intel_encoder *encoder,
		       struct intel_crtc_state *crtc_state,
		       unsigned int type);
void intel_digital_port_lock(struct intel_encoder *encoder);
void intel_digital_port_unlock(struct intel_encoder *encoder);
bool intel_digital_port_connected(struct intel_encoder *encoder);
bool intel_digital_port_connected_locked(struct intel_encoder *encoder);
int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
				 u8 dsc_max_bpc);
u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
+14 −14
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include "intel_bios.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_aux.h"
#include "intel_dp_aux_regs.h"
#include "intel_pps.h"
@@ -228,6 +229,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
		  u32 aux_send_ctl_flags)
{
	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
	struct intel_encoder *encoder = &dig_port->base;
	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
	bool is_tc_port = intel_phy_is_tc(i915, phy);
@@ -245,19 +247,18 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
	for (i = 0; i < ARRAY_SIZE(ch_data); i++)
		ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i);

	if (is_tc_port) {
		intel_tc_port_lock(dig_port);
	intel_digital_port_lock(encoder);
	/*
	 * Abort transfers on a disconnected port as required by
	 * DP 1.4a link CTS 4.2.1.5, also avoiding the long AUX
	 * timeouts that would otherwise happen.
	 * TODO: abort the transfer on non-TC ports as well.
	 */
		if (!intel_tc_port_connected_locked(&dig_port->base)) {
	if (is_tc_port &&
	    !intel_digital_port_connected_locked(&dig_port->base)) {
		ret = -ENXIO;
		goto out_unlock;
	}
	}

	aux_domain = intel_aux_power_domain(dig_port);

@@ -423,8 +424,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
	intel_pps_unlock(intel_dp, pps_wakeref);
	intel_display_power_put_async(i915, aux_domain, aux_wakeref);
out_unlock:
	if (is_tc_port)
		intel_tc_port_unlock(dig_port);
	intel_digital_port_unlock(encoder);

	return ret;
}
Loading