All of lore.kernel.org
 help / color / mirror / Atom feed
From: Imre Deak <imre.deak@intel.com>
To: Gustavo Sousa <gustavo.sousa@intel.com>
Cc: intel-xe@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
	"Ankit Nautiyal" <ankit.k.nautiyal@intel.com>,
	"Dnyaneshwar Bhadane" <dnyaneshwar.bhadane@intel.com>,
	"Jouni Högander" <jouni.hogander@intel.com>,
	"Juha-pekka Heikkila" <juha-pekka.heikkila@intel.com>,
	"Luca Coelho" <luciano.coelho@intel.com>,
	"Lucas De Marchi" <lucas.demarchi@intel.com>,
	"Matt Atwood" <matthew.s.atwood@intel.com>,
	"Matt Roper" <matthew.d.roper@intel.com>,
	"Ravi Kumar Vodapalli" <ravi.kumar.vodapalli@intel.com>,
	"Shekhar Chauhan" <shekhar.chauhan@intel.com>,
	"Vinod Govindapillai" <vinod.govindapillai@intel.com>
Subject: Re: [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
Date: Wed, 12 Nov 2025 19:53:47 +0200	[thread overview]
Message-ID: <aRTJq2h7ic7EcpL6@ideak-desk> (raw)
In-Reply-To: <20251107-xe3p_lpd-basic-enabling-v4-7-ab3367f65f15@intel.com>

On Fri, Nov 07, 2025 at 09:05:40PM -0300, Gustavo Sousa wrote:
> Xe3p_LPD has a new feature that allows the driver to allocate at runtime
> the DDI (TC ones) port to drive a legacy connection on the Type-C
> subsystem.  This allows better resource utilization, because now there
> is no need to statically reserve ports for legacy connectors on the
> Type-C subsystem.
> 
> That said, our driver is not yet ready for the dynamic allocation.
> Thus, as an incremental step, let's add the logic containing the
> required programming sequence for the allocation, but, instead of
> selecting the first available port, we try so use the 1:1 mapping
> expected by the driver today.
> 
> Bspec: 68954
> Co-developed-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
> Signed-off-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> ---
> 
> NOTE: This patch is still a WIP. There are some opens to resolve here.
> Nevertheless, I'm sending it here for early feedback.
> 
> For the HIP-index stuff, I have a local refactor started and need to
> finish it up and send it.
> 
> The other open is about concurrent calls to iom_dp_resource_lock().  It
> is likely that we need to have a software lock to prevent concurrent
> access to IOM_DP_HW_RESOURCE_SEMAPHORE from our driver.
> ---
>  drivers/gpu/drm/i915/display/intel_display_regs.h |  20 ++-
>  drivers/gpu/drm/i915/display/intel_tc.c           | 151 +++++++++++++++++++++-
>  2 files changed, 169 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
> index 89ea0156ee06..0cf7d43ce210 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
> @@ -2908,6 +2908,25 @@ enum skl_power_gate {
>  #define   DP_PIN_ASSIGNMENT(idx, x)		((x) << ((idx) * 4))
>  /* See enum intel_tc_pin_assignment for the pin assignment field values. */
>  
> +/*
> + * FIXME: There is also a definition for this register in intel_dkl_phy_regs.h.
> + * We need to consolidate the definitions.
> + */
> +#define HIP_INDEX_REG0				_MMIO(0x1010a0)
> +#define   HIP_168_INDEX_MASK			REG_GENMASK(3, 0)
> +#define   HIP_168_IOM_RES_MGMT			REG_FIELD_PREP(HIP_168_INDEX_MASK, 0x1)
> +
> +#define IOM_DP_HW_RESOURCE_SEMAPHORE		_MMIO(0x168038)
> +#define   IOM_DP_HW_SEMLOCK			REG_BIT(31)
> +#define   IOM_REQUESTOR_ID_MASK			REG_GENMASK(3, 0)
> +#define   IOM_REQUESTOR_ID_DISPLAY_ENGINE	REG_FIELD_PREP(IOM_REQUESTOR_ID_MASK, 0x4)
> +
> +#define IOM_DP_RESOURCE_MNG			_MMIO(0x16802c)
> +#define   IOM_DDI_CONSUMER_SHIFT(tc_port)	((tc_port) * 4)
> +#define   IOM_DDI_CONSUMER_MASK(tc_port)	(0xf << IOM_DDI_CONSUMER_SHIFT(tc_port))
> +#define   IOM_DDI_CONSUMER(tc_port, x)		((x) << IOM_DDI_CONSUMER_SHIFT(tc_port))
> +#define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)	IOM_DDI_CONSUMER(tc_port, 0x8 + (tc_port))

It would be simpler to define the above without the shift, i.e. as 8 +
tc_port.

> +
>  #define _TCSS_DDI_STATUS_1			0x161500
>  #define _TCSS_DDI_STATUS_2			0x161504
>  #define TCSS_DDI_STATUS(tc)			_MMIO(_PICK_EVEN(tc, \
> @@ -2946,5 +2965,4 @@ enum skl_power_gate {
>  #define   MTL_TRDPRE_MASK		REG_GENMASK(7, 0)
>  
>  
> -
>  #endif /* __INTEL_DISPLAY_REGS_H__ */
> diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
> index 7e17ca018748..3c333999bbe4 100644
> --- a/drivers/gpu/drm/i915/display/intel_tc.c
> +++ b/drivers/gpu/drm/i915/display/intel_tc.c
> @@ -9,6 +9,7 @@
>  
>  #include "i915_reg.h"
>  #include "intel_atomic.h"
> +#include "intel_bios.h"
>  #include "intel_cx0_phy_regs.h"
>  #include "intel_ddi.h"
>  #include "intel_de.h"
> @@ -25,6 +26,9 @@
>  #include "intel_modeset_lock.h"
>  #include "intel_tc.h"
>  
> +#define IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US	10
> +#define IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US	10000

The above param names should make it clear how poll_timeout_us() uses
them (i.e. stg like sleep vs. timeout instead of lock_timeout vs.
retry_timeout), but probably even clearer to just drop the defines and
inline the values in the call.

> +
>  enum tc_port_mode {
>  	TC_PORT_DISCONNECTED,
>  	TC_PORT_TBT_ALT,
> @@ -1200,6 +1204,143 @@ static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)
>  	__tc_cold_unblock(tc, domain, tc_cold_wref);
>  }
>  
> +static void iom_res_mgmt_prepare_reg_access(struct intel_display *display)
> +{
> +	/*
> +	 * IOM resource management registers live in the 2nd 4KB page of IOM
> +	 * address space. So we need to configure HIP_INDEX_REG0 with the
> +	 * correct index.
> +	 *
> +	 * FIXME: We need to have this and dekel PHY implementation using a
> +	 * common abstraction to access registers on the HIP-indexed ranges, and
> +	 * this function would then be dropped.
> +	 */
> +	intel_de_rmw(display, HIP_INDEX_REG0,
> +		     HIP_168_INDEX_MASK, HIP_168_IOM_RES_MGMT);

This matches what intel_dkl_phy.c does, that one also taking the
required lock around the access. At one point the intel_dkl_phy
file/interface could be renamed to intel_tc_reg or similar accordingly.

> +}
> +
> +/*
> + * FIXME: This function also needs to avoid concurrent accesses from the driver
> + * itself, possibly via a software lock.
> + */
> +static int iom_dp_resource_lock(struct intel_tc_port *tc)
> +{
> +	struct intel_display *display = to_intel_display(tc->dig_port);
> +	u32 val = IOM_DP_HW_SEMLOCK | IOM_REQUESTOR_ID_DISPLAY_ENGINE;
> +	int ret;
> +
> +	iom_res_mgmt_prepare_reg_access(display);
> +	ret = poll_timeout_us(intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, val),
> +			      (intel_de_read(display, IOM_DP_HW_RESOURCE_SEMAPHORE) & val) == val,

This happens to work, but it's more future proof/bspec conformant to
properly mask the requestor ID field when reading it back.

> +			      IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US,
> +			      IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US, false);
> +
> +	if (ret)
> +		drm_err(display->drm, "Port %s: timeout trying to lock IOM semaphore\n",
> +			tc->port_name);
> +
> +	return ret;
> +}
> +
> +static void iom_dp_resource_unlock(struct intel_tc_port *tc)
> +{
> +	struct intel_display *display = to_intel_display(tc->dig_port);
> +
> +	iom_res_mgmt_prepare_reg_access(display);
> +	intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, IOM_REQUESTOR_ID_DISPLAY_ENGINE);
> +}
> +
> +static bool xe3p_tc_iom_allocate_ddi(struct intel_tc_port *tc, bool allocate)
> +{
> +	struct intel_display *display = to_intel_display(tc->dig_port);
> +	struct intel_digital_port *dig_port = tc->dig_port;
> +	enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base);
> +	u32 val;
> +	u32 consumer;
> +	u32 expected_consumer;
> +	bool ret;
> +
> +	if (DISPLAY_VER(display) < 35)
> +		return true;
> +
> +	if (tc->mode != TC_PORT_LEGACY)
> +		return true;
> +
> +	if (!intel_bios_encoder_supports_dyn_port_over_tc(dig_port->base.devdata))

dedicated_external is stored separately in dig_port, why the "related"
dyn_port_over_tc flag isn't?

> +		return true;
> +
> +	if (iom_dp_resource_lock(tc))
> +		return false;
> +
> +	val = intel_de_read(display, IOM_DP_RESOURCE_MNG);
> +
> +	consumer = val & IOM_DDI_CONSUMER_MASK(tc_port);
> +	consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
> +
> +	/*
> +	 * Bspec instructs to select first available DDI, but our driver is not
> +	 * ready for such dynamic allocation yet. For now, we force a "static"
> +	 * allocation: map the physical port (where HPD happens) to the
> +	 * encoder's DDI (logical TC port, represented by tc_port).
> +	 */
> +	expected_consumer = IOM_DDI_CONSUMER_STATIC_TC(tc_port);
> +	expected_consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
> +
> +	if (allocate) {
> +		struct intel_encoder *other_encoder;
> +
> +		/*
> +		 * Check if this encoder's DDI is already allocated for another
> +		 * physical port, which could have happened prior to the driver
> +		 * taking over (e.g. GOP).
> +		 */
> +		for_each_intel_encoder(display->drm, other_encoder) {
> +			enum tc_port other_tc_port = intel_encoder_to_tc(other_encoder);
> +			u32 other_consumer;
> +
> +			if (tc_port == TC_PORT_NONE || other_tc_port == tc_port)
> +				continue;
> +
> +			other_consumer = val & IOM_DDI_CONSUMER_MASK(other_tc_port);
> +			other_consumer >>= IOM_DDI_CONSUMER_SHIFT(other_tc_port);
> +			if (other_consumer == expected_consumer) {
> +				drm_err(display->drm, "Port %s: expected consumer %u already allocated another DDI; IOM_DP_RESOURCE_MNG=0x%08x\n",
> +					tc->port_name, expected_consumer, val);
> +				ret = false;
> +				goto out_resource_unlock;
> +			}
> +		}
> +
> +		if (consumer == 0) {
> +			/* DDI is free to use, let's allocate it. */
> +			val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
> +			val |= IOM_DDI_CONSUMER(tc_port, expected_consumer);
> +			intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
> +			ret = true;
> +		} else if (consumer == expected_consumer) {
> +			/*
> +			 * Nothing to do, as the expected "static" DDI allocation is
> +			 * already in place.
> +			 */
> +			ret = true;
> +		} else {
> +			drm_err(display->drm, "Port %s: DDI already allocated for consumer %u; IOM_DP_RESOURCE_MNG=0x%08x\n",
> +				tc->port_name, consumer, val);
> +			ret = false;
> +		}
> +	} else {
> +		drm_WARN_ON(display->drm, consumer != expected_consumer);
> +		val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
> +		intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
> +		ret = true;
> +	}
> +
> +out_resource_unlock:
> +	iom_dp_resource_unlock(tc);
> +
> +	return ret;
> +}
> +
>  static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
>  {
>  	tc->lock_wakeref = tc_cold_block(tc);
> @@ -1210,9 +1351,12 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
>  		return true;
>  	}
>  
> -	if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
> +	if (!xe3p_tc_iom_allocate_ddi(tc, true))

This doesn't work. A connector registered to userspace must be always
functional (except for MST connectors which are dynamically registered).
So the DDI allocation and with that connecting the PHY cannot fail here
for a legacy connector/PHY. Instead of this the allocation could be
moved to happen already in intel_tc_phy_ops::init for now, allocating a
DDI for a legacy PHY (intel_tc_port::legacy_port == true) and if that
fails also fail the corresponding connector/encoder registration in
intel_ddi_init(). The DDI would need to be released by
intel_tc_port_cleanup().

>  		goto out_unblock_tccold;
>  
> +	if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
> +		goto out_deallocate_ddi;
> +
>  	xelpdp_tc_phy_take_ownership(tc, true);
>  
>  	read_pin_configuration(tc);
> @@ -1226,6 +1370,9 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
>  	xelpdp_tc_phy_take_ownership(tc, false);
>  	xelpdp_tc_phy_wait_for_tcss_power(tc, false);
>  
> +out_deallocate_ddi:
> +	xe3p_tc_iom_allocate_ddi(tc, false);
> +
>  out_unblock_tccold:
>  	tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
>  
> @@ -1236,6 +1383,8 @@ static void xelpdp_tc_phy_disconnect(struct intel_tc_port *tc)
>  {
>  	switch (tc->mode) {
>  	case TC_PORT_LEGACY:
> +		xe3p_tc_iom_allocate_ddi(tc, false);
> +		fallthrough;
>  	case TC_PORT_DP_ALT:
>  		xelpdp_tc_phy_take_ownership(tc, false);
>  		xelpdp_tc_phy_enable_tcss_power(tc, false);
> 
> -- 
> 2.51.0
> 

  reply	other threads:[~2025-11-12 17:53 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 01/11] drm/i915/wm: Do not make latency values monotonic on Xe3 onward Gustavo Sousa
2025-11-12  3:46   ` Kandpal, Suraj
2025-11-12 12:45     ` Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 02/11] drm/i915/vbt: Add fields dedicated_external and dyn_port_over_tc Gustavo Sousa
2025-11-11 16:02   ` Imre Deak
2025-11-11 16:15     ` Imre Deak
2025-11-12 13:00       ` Gustavo Sousa
2025-11-12 13:20         ` Imre Deak
2025-11-13 22:01           ` Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 03/11] drm/i915/power: Use intel_encoder_is_tc() Gustavo Sousa
2025-11-12 16:19   ` Imre Deak
2025-11-13 22:01     ` Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 04/11] drm/i915/display: Handle dedicated external ports in intel_encoder_is_tc() Gustavo Sousa
2025-11-12 16:24   ` Imre Deak
2025-11-13 22:02     ` Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 05/11] drm/i915/fbc: Add intel_fbc_id_for_pipe() Gustavo Sousa
2025-11-10 16:35   ` Matt Roper
2025-11-10 17:03     ` Ville Syrjälä
2025-11-10 22:18       ` Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 06/11] drm/i915/xe3p_lpd: Handle underrun debug bits Gustavo Sousa
2025-11-10 11:45   ` Jani Nikula
2025-11-11  0:23     ` Gustavo Sousa
2025-11-11 10:22       ` Jani Nikula
2025-11-11 12:22         ` Gustavo Sousa
2025-11-10 17:03   ` Ville Syrjälä
2025-11-10 23:42     ` Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation Gustavo Sousa
2025-11-12 17:53   ` Imre Deak [this message]
2025-11-14 19:46     ` Gustavo Sousa
2025-11-15  0:40       ` Imre Deak
2025-11-15  1:22         ` Imre Deak
2025-11-17 15:02           ` Gustavo Sousa
2025-11-17 15:17             ` Imre Deak
2025-11-17 17:23               ` Gustavo Sousa
2025-11-17 17:58                 ` Imre Deak
2025-11-17 15:33         ` Gustavo Sousa
2025-11-17 16:01           ` Imre Deak
2025-11-08  0:05 ` [PATCH v4 08/11] drm/i915/nvls: Add NVL-S display support Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 09/11] drm/i915/display: Use platform check in HAS_LT_PHY() Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 10/11] drm/i915/display: Move HAS_LT_PHY() to intel_display_device.h Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 11/11] drm/i915/display: Use HAS_LT_PHY() for LT PHY AUX power Gustavo Sousa
2025-11-08  0:15 ` [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
2025-11-08  1:10 ` ✓ i915.CI.BAT: success for drm/i915/display: Add initial support for Xe3p_LPD (rev4) Patchwork
2025-11-08  1:52 ` ✗ CI.checkpatch: warning " Patchwork
2025-11-08  1:54 ` ✓ CI.KUnit: success " Patchwork
2025-11-08  2:09 ` ✗ CI.checksparse: warning " Patchwork
2025-11-08  2:31 ` ✗ Xe.CI.BAT: failure " Patchwork
2025-11-09  0:12 ` ✗ i915.CI.Full: " Patchwork
2025-11-09  8:10 ` ✗ Xe.CI.Full: " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aRTJq2h7ic7EcpL6@ideak-desk \
    --to=imre.deak@intel.com \
    --cc=ankit.k.nautiyal@intel.com \
    --cc=dnyaneshwar.bhadane@intel.com \
    --cc=gustavo.sousa@intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=jouni.hogander@intel.com \
    --cc=juha-pekka.heikkila@intel.com \
    --cc=lucas.demarchi@intel.com \
    --cc=luciano.coelho@intel.com \
    --cc=matthew.d.roper@intel.com \
    --cc=matthew.s.atwood@intel.com \
    --cc=ravi.kumar.vodapalli@intel.com \
    --cc=shekhar.chauhan@intel.com \
    --cc=vinod.govindapillai@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.