xref: /linux/drivers/gpu/drm/i915/display/intel_dp_link_caps.c (revision 4e69c1856bfd9ffb7e9d335a25842fa211628929)
1ebf5ad5cSImre Deak // SPDX-License-Identifier: MIT
2ebf5ad5cSImre Deak /*
3ebf5ad5cSImre Deak  * Copyright © 2026 Intel Corporation
4ebf5ad5cSImre Deak  */
5ebf5ad5cSImre Deak 
667cd7367SImre Deak #include <linux/bitops.h>
7fdd4b01bSImre Deak #include <linux/debugfs.h>
8b9d98594SImre Deak #include <linux/log2.h>
996d07a10SImre Deak #include <linux/seq_buf.h>
10ebf5ad5cSImre Deak #include <linux/slab.h>
11b9d98594SImre Deak #include <linux/sort.h>
127aa14e73SImre Deak #include <linux/string.h>
1367cd7367SImre Deak #include <linux/types.h>
14ebf5ad5cSImre Deak 
1523331943SImre Deak #include <drm/drm_print.h>
1623331943SImre Deak 
1723331943SImre Deak #include "intel_display_core.h"
1823331943SImre Deak #include "intel_display_types.h"
1939e30bdfSImre Deak #include "intel_display_utils.h"
2023331943SImre Deak #include "intel_dp.h"
21ebf5ad5cSImre Deak #include "intel_dp_link_caps.h"
22ebf5ad5cSImre Deak 
23ee8f7484SImre Deak /**
24ee8f7484SImre Deak  * DOC: DisplayPort link capabilities
25ee8f7484SImre Deak  *
26ee8f7484SImre Deak  * The Intel DP link caps API tracks the supported and allowed
27ee8f7484SImre Deak  * DisplayPort link configurations for a DP encoder and its attached
28ee8f7484SImre Deak  * connectors, and provides helpers to iterate over the allowed
29ee8f7484SImre Deak  * configurations and constrain them by filtering, disabling, or
30ee8f7484SImre Deak  * limiting them to maximum link parameters.
31ee8f7484SImre Deak  *
32ee8f7484SImre Deak  * Locking
33ee8f7484SImre Deak  * -------
34ee8f7484SImre Deak  *
35ee8f7484SImre Deak  * All accesses to this API must be serialized. The only exception
36ee8f7484SImre Deak  * is intel_dp_link_caps_get_max_limits(), which allow lockless
37ee8f7484SImre Deak  * lookup. Such lookups may observe an out-of-sync &struct
38ee8f7484SImre Deak  * intel_dp_link_config tuple, i.e. a rate from one state and a lane
39ee8f7484SImre Deak  * count from another.
40ee8f7484SImre Deak  *
41ee8f7484SImre Deak  * The Intel i915/xe drivers ensure the above serialization by holding
42ee8f7484SImre Deak  * &drm_mode_config.connection_mutex and, while holding the lock,
43ee8f7484SImre Deak  * waiting for any pending asynchronous atomic commits. This also allows
44ee8f7484SImre Deak  * use of the API from the tails of asynchronous atomic commits, which
45ee8f7484SImre Deak  * cannot hold the lock.
46ee8f7484SImre Deak  *
47ee8f7484SImre Deak  * Iterating and restricting link configurations
48ee8f7484SImre Deak  * ---------------------------------------------
49ee8f7484SImre Deak  *
50ee8f7484SImre Deak  * The link configuration iterators can iterate the ``allowed
51ee8f7484SImre Deak  * configurations`` during modeset configuration selection or link
52ee8f7484SImre Deak  * training fallback handling in a configurable order.
53ee8f7484SImre Deak  *
54ee8f7484SImre Deak  * The iteration order can depend on connector type (eDP, DP SST,
55ee8f7484SImre Deak  * DP MST) and modeset-specific conditions or driver policies, such
56ee8f7484SImre Deak  * as DSC vs. non-DSC modes, power saving vs. better user experience,
57ee8f7484SImre Deak  * or policy changes after a link training failure.
58ee8f7484SImre Deak  *
59ee8f7484SImre Deak  * The configurations exposed via the iterators can be additionally
60ee8f7484SImre Deak  * constrained in the following ways:
61ee8f7484SImre Deak  *
62ee8f7484SImre Deak  * - Filtered for a given modeset based on modeset-specific conditions.
63ee8f7484SImre Deak  *   Examples for such conditions include driver policies preferring
64ee8f7484SImre Deak  *   power saving or better user experience, post-link training failure
65ee8f7484SImre Deak  *   preference changes, or sink automated test requests limiting the
66ee8f7484SImre Deak  *   usable configurations.
67ee8f7484SImre Deak  *
68ee8f7484SImre Deak  * - Disabled permanently for the connected sink. Examples of reasons
69ee8f7484SImre Deak  *   to disable a configuration include a link training failure for a
70ee8f7484SImre Deak  *   given configuration or a driver workaround preventing the use of
71ee8f7484SImre Deak  *   a particular configuration.
72ee8f7484SImre Deak  *
73ee8f7484SImre Deak  * - Limited via a maximum link rate and lane count. For example, after
74ee8f7484SImre Deak  *   a link training failure, subsequent modesets may be limited to
75ee8f7484SImre Deak  *   configurations at or below the failed parameters.
76ee8f7484SImre Deak  *
77ee8f7484SImre Deak  *   This mechanism exists for backward compatibility only. Eventually,
78ee8f7484SImre Deak  *   it will be removed in favor of relying solely on individually
79ee8f7484SImre Deak  *   disabled configurations, as described above.
80ee8f7484SImre Deak  *
81ee8f7484SImre Deak  * Terminology
82ee8f7484SImre Deak  * -----------
83ee8f7484SImre Deak  *
84ee8f7484SImre Deak  * ``Common link capabilities`` (or ``common caps``) refer to the link
85ee8f7484SImre Deak  * rates and maximum lane count supported by both the source and the
86ee8f7484SImre Deak  * sink, i.e. the intersection of their respective capabilities.
87ee8f7484SImre Deak  *
88ee8f7484SImre Deak  * ``Supported configurations`` are all configurations defined by the
89ee8f7484SImre Deak  * ``Common link capabilities``' link rates and maximum lane count.
90ee8f7484SImre Deak  *
91ee8f7484SImre Deak  * ``Disabled configurations`` are ``Supported configurations`` disabled
92ee8f7484SImre Deak  * via this API.
93ee8f7484SImre Deak  *
94ee8f7484SImre Deak  * ``Enabled configurations`` are ``Supported configurations`` that are
95ee8f7484SImre Deak  * not disabled.
96ee8f7484SImre Deak  *
97ee8f7484SImre Deak  * ``Forced configurations`` are ``Enabled configurations`` forced via
98ee8f7484SImre Deak  * forced link parameter debugfs entries.
99ee8f7484SImre Deak  *
100ee8f7484SImre Deak  * ``Allowed configurations`` are the ``Enabled configurations``, or if
101ee8f7484SImre Deak  * forcing is in effect the ``Forced configurations``, constrained by a
102ee8f7484SImre Deak  * maximum rate and lane count set via the API.
103ee8f7484SImre Deak  */
104ebf5ad5cSImre Deak struct intel_dp_link_caps {
105ebf5ad5cSImre Deak 	struct intel_dp *dp;
1069382aacfSImre Deak 
10770f6d73aSImre Deak 	/* Rate, lane count caps common to source and sink. */
10870f6d73aSImre Deak 	int num_rates;
10970f6d73aSImre Deak 	int rates[DP_MAX_SUPPORTED_RATES];
110de87e3bfSImre Deak 	int max_lane_count;
11170f6d73aSImre Deak 
11267cd7367SImre Deak 	/* common rate,lane_count configs in bw order */
11367cd7367SImre Deak 	int num_configs;
11467cd7367SImre Deak #define INTEL_DP_MAX_LANE_COUNT			4
11567cd7367SImre Deak #define INTEL_DP_MAX_SUPPORTED_LANE_CONFIGS	(ilog2(INTEL_DP_MAX_LANE_COUNT) + 1)
11667cd7367SImre Deak #define INTEL_DP_LANE_COUNT_EXP_BITS		order_base_2(INTEL_DP_MAX_SUPPORTED_LANE_CONFIGS)
11767cd7367SImre Deak #define INTEL_DP_LINK_RATE_IDX_BITS		(BITS_PER_TYPE(u8) - INTEL_DP_LANE_COUNT_EXP_BITS)
11867cd7367SImre Deak #define INTEL_DP_MAX_LINK_CONFIGS		(DP_MAX_SUPPORTED_RATES * \
11967cd7367SImre Deak 						 INTEL_DP_MAX_SUPPORTED_LANE_CONFIGS)
12067cd7367SImre Deak 	struct intel_dp_link_config_entry {
12170f6d73aSImre Deak 		/* index into rates[] */
12267cd7367SImre Deak 		u8 link_rate_idx:INTEL_DP_LINK_RATE_IDX_BITS;
12367cd7367SImre Deak 		u8 lane_count_exp:INTEL_DP_LANE_COUNT_EXP_BITS;
12467cd7367SImre Deak 	} configs[INTEL_DP_MAX_LINK_CONFIGS];
12567cd7367SImre Deak 
1269382aacfSImre Deak 	/*
1274074974bSImre Deak 	 * Indices to intel_dp_link_caps::configs[] in rate/lane count,
1284074974bSImre Deak 	 * lane_count/rate order.
1294074974bSImre Deak 	 */
1304074974bSImre Deak 	u8 rate_lane_map[INTEL_DP_MAX_LINK_CONFIGS];
1314074974bSImre Deak 	u8 lane_rate_map[INTEL_DP_MAX_LINK_CONFIGS];
1324074974bSImre Deak 
1334074974bSImre Deak 	/*
1341e574621SImre Deak 	 * Filter of configurations enabled for the current sink
1351e574621SImre Deak 	 * connection.
1361e574621SImre Deak 	 *
1371e574621SImre Deak 	 * Each bit in the filter's configuration mask corresponds to a
1381e574621SImre Deak 	 * configuration index in the intel_dp_link_caps::configs[] array.
1391e574621SImre Deak 	 *
1401e574621SImre Deak 	 * All configurations start out enabled in the filter after a
1411e574621SImre Deak 	 * new sink is connected. Users disable configurations afterwards
1421e574621SImre Deak 	 * via the link caps API. All configurations get re-enabled
1431e574621SImre Deak 	 * internally in the following cases:
1441e574621SImre Deak 	 * - when forcing a link rate or lane count
1451e574621SImre Deak 	 * - when intel_dp_link_caps_update(reset=true) is called after
1461e574621SImre Deak 	 *   a new sink is connected
1471e574621SImre Deak 	 * - when intel_dp_link_caps_update(reset=false) with changed
1481e574621SImre Deak 	 *   link capabilities is called
1491e574621SImre Deak 	 * - when intel_dp_link_caps_reset() is called after a new sink
1501e574621SImre Deak 	 *   is connected
1511e574621SImre Deak 	 */
1521e574621SImre Deak 	struct intel_dp_link_caps_filter enabled_configs;
1531e574621SImre Deak 
1541e574621SImre Deak 	/*
1551e574621SImre Deak 	 * Allowed configurations are the supported configurations defined by
1561e574621SImre Deak 	 * config_table.rates and config_table.max_lane_count, constrained by
1571e574621SImre Deak 	 * config_table.enabled_configs and the forced_params and
1581e574621SImre Deak 	 * max_limits values below.
1591e574621SImre Deak 	 *
1601e574621SImre Deak 	 * See get_allowed_config_filter() for the filter of these
1611e574621SImre Deak 	 * configurations.
1621e574621SImre Deak 	 */
1631e574621SImre Deak 
1641e574621SImre Deak 	/*
1659382aacfSImre Deak 	 * Forced parameters requested via debugfs. Remains set across sink
1669382aacfSImre Deak 	 * disconnects.
1679382aacfSImre Deak 	 */
1689382aacfSImre Deak 	struct intel_dp_link_config forced_params;
169ba4680deSImre Deak 
170ba4680deSImre Deak 	/*
171ba4680deSImre Deak 	 * User set maximum limits. These limits constrain the currently
172ba4680deSImre Deak 	 * allowed set of configurations and are not adjusted when sink
173ba4680deSImre Deak 	 * capabilities change.
174ba4680deSImre Deak 	 *
175ba4680deSImre Deak 	 * max_limits.rate/lane_count may come from different allowed
176ba4680deSImre Deak 	 * configurations, i.e. the (max_limits.rate, max_limits.lane_count)
177ba4680deSImre Deak 	 * tuple itself may not be an allowed configuration.
178ba4680deSImre Deak 	 */
179ba4680deSImre Deak 	struct intel_dp_link_config max_limits;
180ebf5ad5cSImre Deak };
18139e30bdfSImre Deak static_assert(BITS_PER_TYPE(((struct intel_dp_link_caps_filter *)NULL)->config_mask) >=
18239e30bdfSImre Deak 	      ARRAY_SIZE(((struct intel_dp_link_caps *)NULL)->configs));
18339e30bdfSImre Deak 
18439e30bdfSImre Deak static struct intel_dp_link_caps_order bw_desc_config_order(void)
18539e30bdfSImre Deak {
18639e30bdfSImre Deak 	struct intel_dp_link_caps_order order = {
18739e30bdfSImre Deak 		.key = INTEL_DP_LINK_CAPS_ORDER_KEY_BW,
18839e30bdfSImre Deak 		.dir = INTEL_DP_LINK_CAPS_ORDER_DIR_DESC,
18939e30bdfSImre Deak 	};
19039e30bdfSImre Deak 
19139e30bdfSImre Deak 	return order;
19239e30bdfSImre Deak }
193ebf5ad5cSImre Deak 
1949d4bd665SImre Deak static enum intel_dp_link_caps_order_key
1959d4bd665SImre Deak connector_compute_order_key(bool is_mst)
1969d4bd665SImre Deak {
1979d4bd665SImre Deak 	if (is_mst)
1989d4bd665SImre Deak 		return INTEL_DP_LINK_CAPS_ORDER_KEY_BW;
1999d4bd665SImre Deak 	else
2009d4bd665SImre Deak 		return INTEL_DP_LINK_CAPS_ORDER_KEY_RATE_LANE;
2019d4bd665SImre Deak }
2029d4bd665SImre Deak 
2039d4bd665SImre Deak static enum intel_dp_link_caps_order_key
2049d4bd665SImre Deak connector_fallback_order_key(bool is_mst)
2059d4bd665SImre Deak {
2069d4bd665SImre Deak 	if (is_mst)
2079d4bd665SImre Deak 		return INTEL_DP_LINK_CAPS_ORDER_KEY_BW;
2089d4bd665SImre Deak 	else
2099d4bd665SImre Deak 		return INTEL_DP_LINK_CAPS_ORDER_KEY_LANE_RATE;
2109d4bd665SImre Deak }
2119d4bd665SImre Deak 
2129d4bd665SImre Deak static enum intel_dp_link_caps_order_direction
2139d4bd665SImre Deak connector_compute_order_dir(bool is_mst, bool use_max_params)
2149d4bd665SImre Deak {
2159d4bd665SImre Deak 	if (is_mst || use_max_params)
2169d4bd665SImre Deak 		return INTEL_DP_LINK_CAPS_ORDER_DIR_DESC;
2179d4bd665SImre Deak 	else
2189d4bd665SImre Deak 		return INTEL_DP_LINK_CAPS_ORDER_DIR_ASC;
2199d4bd665SImre Deak }
2209d4bd665SImre Deak 
2219d4bd665SImre Deak struct intel_dp_link_caps_order
2229d4bd665SImre Deak intel_dp_link_caps_connector_compute_order(struct intel_connector *connector)
2239d4bd665SImre Deak {
2249d4bd665SImre Deak 	struct intel_dp *intel_dp = intel_attached_dp(connector);
2259d4bd665SImre Deak 	struct intel_dp_link_caps_order order = {
2269d4bd665SImre Deak 		.key = connector_compute_order_key(connector->mst.dp),
2279d4bd665SImre Deak 		.dir = connector_compute_order_dir(connector->mst.dp, intel_dp->use_max_params)
2289d4bd665SImre Deak 	};
2299d4bd665SImre Deak 
2309d4bd665SImre Deak 	return order;
2319d4bd665SImre Deak }
2329d4bd665SImre Deak 
2339d4bd665SImre Deak struct intel_dp_link_caps_order
2349d4bd665SImre Deak intel_dp_link_caps_connector_fallback_order(bool is_mst)
2359d4bd665SImre Deak {
2369d4bd665SImre Deak 	struct intel_dp_link_caps_order order = {
2379d4bd665SImre Deak 		.key = connector_fallback_order_key(is_mst),
2389d4bd665SImre Deak 		.dir = INTEL_DP_LINK_CAPS_ORDER_DIR_DESC,
2399d4bd665SImre Deak 	};
2409d4bd665SImre Deak 
2419d4bd665SImre Deak 	return order;
2429d4bd665SImre Deak }
2439d4bd665SImre Deak 
24423331943SImre Deak /* Get length of common rates array potentially limited by max_rate. */
24577265110SImre Deak static int intel_dp_common_len_rate_limit(struct intel_dp_link_caps *link_caps,
24623331943SImre Deak 					  int max_rate)
24723331943SImre Deak {
24870f6d73aSImre Deak 	return intel_dp_rate_limit_len(link_caps->rates,
24970f6d73aSImre Deak 				       link_caps->num_rates, max_rate);
25023331943SImre Deak }
25123331943SImre Deak 
25286e66421SImre Deak static int intel_dp_common_rate(struct intel_dp_link_caps *link_caps, int index)
25323331943SImre Deak {
2549e6bb4b2SImre Deak 	struct intel_display *display = to_intel_display(link_caps->dp);
25523331943SImre Deak 
25623331943SImre Deak 	if (drm_WARN_ON(display->drm,
25770f6d73aSImre Deak 			index < 0 || index >= link_caps->num_rates))
25823331943SImre Deak 		return 162000;
25923331943SImre Deak 
26070f6d73aSImre Deak 	return link_caps->rates[index];
26123331943SImre Deak }
26223331943SImre Deak 
26323331943SImre Deak /* Theoretical max between source and sink */
26486e66421SImre Deak static int intel_dp_max_common_rate(struct intel_dp_link_caps *link_caps)
26523331943SImre Deak {
2669e6bb4b2SImre Deak 	return intel_dp_common_rate(link_caps, link_caps->num_rates - 1);
26723331943SImre Deak }
26823331943SImre Deak 
26996d07a10SImre Deak void intel_dp_link_caps_print_common_rates(struct intel_dp_link_caps *link_caps)
27096d07a10SImre Deak {
27170f6d73aSImre Deak 	struct intel_display *display = to_intel_display(link_caps->dp);
27296d07a10SImre Deak 	DECLARE_SEQ_BUF(s, 128);
27396d07a10SImre Deak 	int i;
27496d07a10SImre Deak 
27570f6d73aSImre Deak 	for (i = 0; i < link_caps->num_rates; i++)
27670f6d73aSImre Deak 		seq_buf_printf(&s, "%s%d", i ? ", " : "", link_caps->rates[i]);
27796d07a10SImre Deak 
27896d07a10SImre Deak 	drm_dbg_kms(display->drm, "common rates: %s\n", seq_buf_str(&s));
27996d07a10SImre Deak }
28096d07a10SImre Deak 
2819fe6cae3SImre Deak static int intel_dp_link_caps_max_common_lane_count(struct intel_dp_link_caps *link_caps)
282bbf51a67SImre Deak {
283bbf51a67SImre Deak 	return link_caps->max_lane_count;
284bbf51a67SImre Deak }
285bbf51a67SImre Deak 
28624e7de99SImre Deak static int forced_lane_count(struct intel_dp_link_caps *link_caps)
287690e3194SImre Deak {
2889382aacfSImre Deak 	if (!link_caps->forced_params.lane_count)
2897f5f0e8aSImre Deak 		return 0;
2907f5f0e8aSImre Deak 
2919382aacfSImre Deak 	return clamp(link_caps->forced_params.lane_count,
292bbf51a67SImre Deak 		     1, intel_dp_link_caps_max_common_lane_count(link_caps));
293690e3194SImre Deak }
294690e3194SImre Deak 
29524e7de99SImre Deak static int forced_link_rate(struct intel_dp_link_caps *link_caps)
296690e3194SImre Deak {
2977f5f0e8aSImre Deak 	int len;
298690e3194SImre Deak 
2999382aacfSImre Deak 	if (!link_caps->forced_params.rate)
3007f5f0e8aSImre Deak 		return 0;
3017f5f0e8aSImre Deak 
3029e6bb4b2SImre Deak 	len = intel_dp_common_len_rate_limit(link_caps, link_caps->forced_params.rate);
303690e3194SImre Deak 	if (len == 0)
3049e6bb4b2SImre Deak 		return intel_dp_common_rate(link_caps, 0);
305690e3194SImre Deak 
3069e6bb4b2SImre Deak 	return intel_dp_common_rate(link_caps, len - 1);
307690e3194SImre Deak }
308690e3194SImre Deak 
309690e3194SImre Deak void intel_dp_link_caps_get_forced_params(struct intel_dp_link_caps *link_caps,
310690e3194SImre Deak 					  struct intel_dp_link_config *forced_params)
311690e3194SImre Deak {
31224e7de99SImre Deak 	forced_params->rate = forced_link_rate(link_caps);
31324e7de99SImre Deak 	forced_params->lane_count = forced_lane_count(link_caps);
314690e3194SImre Deak }
315690e3194SImre Deak 
31624e7de99SImre Deak static int intel_dp_link_config_rate(struct intel_dp_link_caps *link_caps,
3176929823fSMichał Grzelak 				     const struct intel_dp_link_config_entry *lce)
318b9d98594SImre Deak {
3196929823fSMichał Grzelak 	return intel_dp_common_rate(link_caps, lce->link_rate_idx);
320b9d98594SImre Deak }
321b9d98594SImre Deak 
3226929823fSMichał Grzelak static int intel_dp_link_config_lane_count(const struct intel_dp_link_config_entry *lce)
323b9d98594SImre Deak {
3246929823fSMichał Grzelak 	return 1 << lce->lane_count_exp;
325b9d98594SImre Deak }
326b9d98594SImre Deak 
32787b79644SImre Deak static void
32887b79644SImre Deak to_intel_dp_link_config(struct intel_dp_link_caps *link_caps,
32987b79644SImre Deak 			int config_idx, struct intel_dp_link_config *config)
33087b79644SImre Deak {
33187b79644SImre Deak 	const struct intel_dp_link_config_entry *lce = &link_caps->configs[config_idx];
33287b79644SImre Deak 
33387b79644SImre Deak 	config->rate = intel_dp_link_config_rate(link_caps, lce);
33487b79644SImre Deak 	config->lane_count = intel_dp_link_config_lane_count(lce);
33587b79644SImre Deak }
33687b79644SImre Deak 
33739e30bdfSImre Deak static int
33839e30bdfSImre Deak iter_pos_to_idx(struct intel_dp_link_caps *link_caps,
33939e30bdfSImre Deak 		struct intel_dp_link_caps_order config_order,
34039e30bdfSImre Deak 		int iter_pos)
34139e30bdfSImre Deak {
34239e30bdfSImre Deak 	int config_idx;
34339e30bdfSImre Deak 
34439e30bdfSImre Deak 	if (!in_range(iter_pos, 0, link_caps->num_configs))
34539e30bdfSImre Deak 		return -1;
34639e30bdfSImre Deak 
34739e30bdfSImre Deak 	switch (config_order.dir) {
34839e30bdfSImre Deak 	case INTEL_DP_LINK_CAPS_ORDER_DIR_ASC:
34939e30bdfSImre Deak 		break;
35039e30bdfSImre Deak 	case INTEL_DP_LINK_CAPS_ORDER_DIR_DESC:
35139e30bdfSImre Deak 		iter_pos = link_caps->num_configs - 1 - iter_pos;
35239e30bdfSImre Deak 
35339e30bdfSImre Deak 		break;
35439e30bdfSImre Deak 	default:
35539e30bdfSImre Deak 		MISSING_CASE(config_order.dir);
35639e30bdfSImre Deak 
35739e30bdfSImre Deak 		return -1;
35839e30bdfSImre Deak 	}
35939e30bdfSImre Deak 
36039e30bdfSImre Deak 	switch (config_order.key) {
36139e30bdfSImre Deak 	case INTEL_DP_LINK_CAPS_ORDER_KEY_BW:
36239e30bdfSImre Deak 		config_idx = iter_pos;
36339e30bdfSImre Deak 
36439e30bdfSImre Deak 		break;
36539e30bdfSImre Deak 	case INTEL_DP_LINK_CAPS_ORDER_KEY_RATE_LANE:
36639e30bdfSImre Deak 		config_idx = link_caps->rate_lane_map[iter_pos];
36739e30bdfSImre Deak 
36839e30bdfSImre Deak 		break;
36939e30bdfSImre Deak 	case INTEL_DP_LINK_CAPS_ORDER_KEY_LANE_RATE:
37039e30bdfSImre Deak 		config_idx = link_caps->lane_rate_map[iter_pos];
37139e30bdfSImre Deak 
37239e30bdfSImre Deak 		break;
37339e30bdfSImre Deak 	default:
37439e30bdfSImre Deak 		MISSING_CASE(config_order.key);
37539e30bdfSImre Deak 
37639e30bdfSImre Deak 		return -1;
37739e30bdfSImre Deak 	}
37839e30bdfSImre Deak 
37939e30bdfSImre Deak 	return config_idx;
38039e30bdfSImre Deak }
38139e30bdfSImre Deak 
38239e30bdfSImre Deak static bool iter_get_next_config(struct intel_dp_link_caps_iter *iter,
38339e30bdfSImre Deak 				 struct intel_dp_link_config *config)
38439e30bdfSImre Deak {
38539e30bdfSImre Deak 	while (true) {
38639e30bdfSImre Deak 		int config_idx;
38739e30bdfSImre Deak 
38839e30bdfSImre Deak 		iter->pos++;
38939e30bdfSImre Deak 
39039e30bdfSImre Deak 		config_idx = iter_pos_to_idx(iter->link_caps, iter->order, iter->pos);
39139e30bdfSImre Deak 		if (config_idx < 0) {
39239e30bdfSImre Deak 			iter->pos = -1;
39339e30bdfSImre Deak 			*config = INTEL_DP_LINK_CONFIG_NULL;
39439e30bdfSImre Deak 
39539e30bdfSImre Deak 			break;
39639e30bdfSImre Deak 		}
39739e30bdfSImre Deak 
39839e30bdfSImre Deak 		if (!(BIT(config_idx) & iter->filter.config_mask))
39939e30bdfSImre Deak 			continue;
40039e30bdfSImre Deak 
40139e30bdfSImre Deak 		to_intel_dp_link_config(iter->link_caps, config_idx, config);
40239e30bdfSImre Deak 
40339e30bdfSImre Deak 		break;
40439e30bdfSImre Deak 	}
40539e30bdfSImre Deak 
40639e30bdfSImre Deak 	return iter->pos >= 0;
40739e30bdfSImre Deak }
40839e30bdfSImre Deak 
40939e30bdfSImre Deak static void iter_start(struct intel_dp_link_caps_iter *iter,
41039e30bdfSImre Deak 		       struct intel_dp_link_caps *link_caps,
41139e30bdfSImre Deak 		       struct intel_dp_link_caps_order order,
41239e30bdfSImre Deak 		       struct intel_dp_link_caps_filter filter)
41339e30bdfSImre Deak {
41439e30bdfSImre Deak 	iter->link_caps = link_caps;
41539e30bdfSImre Deak 	iter->pos = -1;
41639e30bdfSImre Deak 	iter->order = order;
41739e30bdfSImre Deak 	iter->filter = filter;
41839e30bdfSImre Deak 
41939e30bdfSImre Deak 	iter->get_next_config = iter_get_next_config;
42039e30bdfSImre Deak }
42139e30bdfSImre Deak 
42239e30bdfSImre Deak static struct intel_dp_link_caps_filter
42339e30bdfSImre Deak calc_allowed_config_filter(struct intel_dp_link_caps *link_caps,
42439e30bdfSImre Deak 			   struct intel_dp_link_caps_filter enabled_configs,
42539e30bdfSImre Deak 			   const struct intel_dp_link_config *max_limits,
42639e30bdfSImre Deak 			   const struct intel_dp_link_config *forced_params)
42739e30bdfSImre Deak {
42839e30bdfSImre Deak 	struct intel_dp_link_caps_filter allowed_configs = INTEL_DP_LINK_CAPS_FILTER_NONE;
42939e30bdfSImre Deak 	struct intel_dp_link_caps_order order = bw_desc_config_order();
43039e30bdfSImre Deak 	struct intel_dp_link_caps_iter iter;
43139e30bdfSImre Deak 	struct intel_dp_link_config config;
43239e30bdfSImre Deak 
43339e30bdfSImre Deak 	iter_start(&iter, link_caps, order, enabled_configs);
43439e30bdfSImre Deak 	for_each_dp_link_config(&iter, &config) {
43539e30bdfSImre Deak 		if (forced_params->rate &&
43639e30bdfSImre Deak 		    forced_params->rate != config.rate)
43739e30bdfSImre Deak 			continue;
43839e30bdfSImre Deak 
43939e30bdfSImre Deak 		if (forced_params->lane_count &&
44039e30bdfSImre Deak 		    forced_params->lane_count != config.lane_count)
44139e30bdfSImre Deak 			continue;
44239e30bdfSImre Deak 
44339e30bdfSImre Deak 		if (config.rate > max_limits->rate)
44439e30bdfSImre Deak 			continue;
44539e30bdfSImre Deak 
44639e30bdfSImre Deak 		if (config.lane_count > max_limits->lane_count)
44739e30bdfSImre Deak 			continue;
44839e30bdfSImre Deak 
44939e30bdfSImre Deak 		allowed_configs.config_mask |= BIT(iter_pos_to_idx(link_caps, order, iter.pos));
45039e30bdfSImre Deak 	}
45139e30bdfSImre Deak 	intel_dp_link_caps_iter_end(&iter);
45239e30bdfSImre Deak 
45339e30bdfSImre Deak 	return allowed_configs;
45439e30bdfSImre Deak }
45539e30bdfSImre Deak 
45639e30bdfSImre Deak /*
45739e30bdfSImre Deak  * get_allowed_config_filter - get filter for the currently allowed configs
45839e30bdfSImre Deak  * @link_caps: link capabilities state
45939e30bdfSImre Deak  *
46039e30bdfSImre Deak  * Return:
46139e30bdfSImre Deak  * Filter of link configurations allowed after applying the current
46239e30bdfSImre Deak  * maximum link limits, and further narrowing them by removing any disabled
46339e30bdfSImre Deak  * configuration and limiting to forced link parameters.
46439e30bdfSImre Deak  *
46539e30bdfSImre Deak  * See also:
46639e30bdfSImre Deak  * - intel_dp_link_caps_get_max_limits()
46739e30bdfSImre Deak  * - intel_dp_link_caps_get_forced_params()
46839e30bdfSImre Deak  */
46939e30bdfSImre Deak static struct intel_dp_link_caps_filter
47039e30bdfSImre Deak get_allowed_config_filter(struct intel_dp_link_caps *link_caps)
47139e30bdfSImre Deak {
47239e30bdfSImre Deak 	struct intel_dp_link_config forced_params;
47339e30bdfSImre Deak 
47439e30bdfSImre Deak 	intel_dp_link_caps_get_forced_params(link_caps, &forced_params);
47539e30bdfSImre Deak 
4761e574621SImre Deak 	return calc_allowed_config_filter(link_caps, link_caps->enabled_configs,
47739e30bdfSImre Deak 					  &link_caps->max_limits, &forced_params);
47839e30bdfSImre Deak }
47939e30bdfSImre Deak 
48039e30bdfSImre Deak void intel_dp_link_caps_iter_start(struct intel_dp_link_caps_iter *iter,
48139e30bdfSImre Deak 				   struct intel_dp_link_caps *link_caps,
48239e30bdfSImre Deak 				   struct intel_dp_link_caps_order order,
48339e30bdfSImre Deak 				   struct intel_dp_link_caps_filter filter)
48439e30bdfSImre Deak {
48539e30bdfSImre Deak 	filter.config_mask &= get_allowed_config_filter(link_caps).config_mask;
48639e30bdfSImre Deak 
48739e30bdfSImre Deak 	iter_start(iter, link_caps, order, filter);
48839e30bdfSImre Deak }
48939e30bdfSImre Deak 
49039e30bdfSImre Deak void intel_dp_link_caps_iter_end(struct intel_dp_link_caps_iter *iter)
49139e30bdfSImre Deak {
49239e30bdfSImre Deak 	memset(iter, 0, sizeof(*iter));
49339e30bdfSImre Deak }
49439e30bdfSImre Deak 
49569505f3fSImre Deak /**
49669505f3fSImre Deak  * intel_dp_link_caps_get_max_config - get the maximum config in a given order
49769505f3fSImre Deak  * @link_caps: link capabilities state
49869505f3fSImre Deak  * @order_key: ordering key used to rank candidate configurations
49969505f3fSImre Deak  * @filter: filter for candidate configurations
50069505f3fSImre Deak  * @max_config: returned maximum link configuration
50169505f3fSImre Deak  *
50269505f3fSImre Deak  * Find the last configuration among the currently allowed
50369505f3fSImre Deak  * configurations filtered by @filter in the iteration order
50469505f3fSImre Deak  * selected by @order_key, and store it in @max_config.
50569505f3fSImre Deak  *
50669505f3fSImre Deak  * See also:
50769505f3fSImre Deak  * - &enum intel_dp_link_caps_order_key
50869505f3fSImre Deak  *
50969505f3fSImre Deak  * Returns:
51069505f3fSImre Deak  * %true if a maximum config is returned
51169505f3fSImre Deak  * %false otherwise.
51269505f3fSImre Deak  */
51369505f3fSImre Deak bool intel_dp_link_caps_get_max_config(struct intel_dp_link_caps *link_caps,
51469505f3fSImre Deak 				       enum intel_dp_link_caps_order_key order_key,
51569505f3fSImre Deak 				       struct intel_dp_link_caps_filter filter,
51669505f3fSImre Deak 				       struct intel_dp_link_config *max_config)
51769505f3fSImre Deak {
51869505f3fSImre Deak 	struct intel_dp_link_caps_order order = {
51969505f3fSImre Deak 		.key = order_key,
52069505f3fSImre Deak 		.dir = INTEL_DP_LINK_CAPS_ORDER_DIR_DESC
52169505f3fSImre Deak 	};
52269505f3fSImre Deak 	struct intel_dp_link_config iter_config;
52369505f3fSImre Deak 	struct intel_dp_link_caps_iter iter;
52469505f3fSImre Deak 	bool found = false;
52569505f3fSImre Deak 
52669505f3fSImre Deak 	intel_dp_link_caps_iter_start(&iter, link_caps, order, filter);
52769505f3fSImre Deak 	for_each_dp_link_config(&iter, &iter_config) {
52869505f3fSImre Deak 		found = true;
52969505f3fSImre Deak 		break;
53069505f3fSImre Deak 	}
53169505f3fSImre Deak 	intel_dp_link_caps_iter_end(&iter);
53269505f3fSImre Deak 
53369505f3fSImre Deak 	if (!found)
53469505f3fSImre Deak 		return false;
53569505f3fSImre Deak 
53669505f3fSImre Deak 	*max_config = iter_config;
53769505f3fSImre Deak 
53869505f3fSImre Deak 	return true;
53969505f3fSImre Deak }
54069505f3fSImre Deak 
5419791229bSImre Deak /**
5429791229bSImre Deak  * intel_dp_link_caps_get_max_bw_config - get maximum BW link configuration
5439791229bSImre Deak  * @link_caps: link capabilities state
5449791229bSImre Deak  * @max_config: returned maximum link configuration
5459791229bSImre Deak  *
5469791229bSImre Deak  * Return the maximum BW link configuration among the currently
5479791229bSImre Deak  * allowed configurations.
5489791229bSImre Deak  */
5499791229bSImre Deak void intel_dp_link_caps_get_max_bw_config(struct intel_dp_link_caps *link_caps,
5509791229bSImre Deak 					  struct intel_dp_link_config *max_config)
5519791229bSImre Deak {
5529791229bSImre Deak 	if (!intel_dp_link_caps_get_max_config(link_caps,
5539791229bSImre Deak 					       bw_desc_config_order().key, INTEL_DP_LINK_CAPS_FILTER_ALL,
5549791229bSImre Deak 					       max_config))
5559791229bSImre Deak 		*max_config = INTEL_DP_LINK_CONFIG_NULL;
5569791229bSImre Deak }
5579791229bSImre Deak 
55839e30bdfSImre Deak static int find_config_idx(struct intel_dp_link_caps *link_caps,
55939e30bdfSImre Deak 			   struct intel_dp_link_caps_filter filter,
56039e30bdfSImre Deak 			   const struct intel_dp_link_config *link_config)
56139e30bdfSImre Deak {
56239e30bdfSImre Deak 	struct intel_dp_link_caps_order order = bw_desc_config_order();
56339e30bdfSImre Deak 	struct intel_dp_link_config iter_config;
56439e30bdfSImre Deak 	struct intel_dp_link_caps_iter iter;
56539e30bdfSImre Deak 	int pos = -1;
56639e30bdfSImre Deak 
56739e30bdfSImre Deak 	intel_dp_link_caps_iter_start(&iter, link_caps, order, filter);
56839e30bdfSImre Deak 	for_each_dp_link_config(&iter, &iter_config) {
56939e30bdfSImre Deak 		if (iter_config.rate == link_config->rate &&
57039e30bdfSImre Deak 		    iter_config.lane_count == link_config->lane_count) {
57139e30bdfSImre Deak 			pos = iter.pos;
57239e30bdfSImre Deak 
57339e30bdfSImre Deak 			break;
57439e30bdfSImre Deak 		}
57539e30bdfSImre Deak 	}
57639e30bdfSImre Deak 	intel_dp_link_caps_iter_end(&iter);
57739e30bdfSImre Deak 
57839e30bdfSImre Deak 	if (pos < 0)
57939e30bdfSImre Deak 		return pos;
58039e30bdfSImre Deak 
58139e30bdfSImre Deak 	return iter_pos_to_idx(link_caps, order, pos);
58239e30bdfSImre Deak }
58339e30bdfSImre Deak 
58439e30bdfSImre Deak bool intel_dp_link_caps_filter_add(struct intel_dp_link_caps *link_caps,
58539e30bdfSImre Deak 				   struct intel_dp_link_caps_filter *filter,
58639e30bdfSImre Deak 				   const struct intel_dp_link_config *config)
58739e30bdfSImre Deak {
58839e30bdfSImre Deak 	int idx;
58939e30bdfSImre Deak 
59039e30bdfSImre Deak 	idx = find_config_idx(link_caps, get_allowed_config_filter(link_caps), config);
59139e30bdfSImre Deak 	if (idx < 0)
59239e30bdfSImre Deak 		return false;
59339e30bdfSImre Deak 
59439e30bdfSImre Deak 	filter->config_mask |= BIT(idx);
59539e30bdfSImre Deak 
59639e30bdfSImre Deak 	return true;
59739e30bdfSImre Deak }
59839e30bdfSImre Deak 
59955b131b3SImre Deak static bool intel_dp_link_caps_filter_remove(struct intel_dp_link_caps *link_caps,
60055b131b3SImre Deak 					     struct intel_dp_link_caps_filter *filter,
60155b131b3SImre Deak 					     const struct intel_dp_link_config *config)
60255b131b3SImre Deak {
60355b131b3SImre Deak 	int idx;
60455b131b3SImre Deak 
60555b131b3SImre Deak 	idx = find_config_idx(link_caps, get_allowed_config_filter(link_caps), config);
60655b131b3SImre Deak 	if (idx < 0)
60755b131b3SImre Deak 		return false;
60855b131b3SImre Deak 
60955b131b3SImre Deak 	filter->config_mask &= ~BIT(idx);
61055b131b3SImre Deak 
61155b131b3SImre Deak 	return true;
61255b131b3SImre Deak }
61355b131b3SImre Deak 
614ac24d562SImre Deak static void set_max_link_limits(struct intel_dp_link_caps *link_caps,
61517659f83SImre Deak 				const struct intel_dp_link_config *max_link_limits)
61617659f83SImre Deak {
617ba4680deSImre Deak 	link_caps->max_limits = *max_link_limits;
61817659f83SImre Deak }
61917659f83SImre Deak 
620ac24d562SImre Deak static void reset_max_link_limits(struct intel_dp_link_caps *link_caps)
62113b1b0b9SImre Deak {
62213b1b0b9SImre Deak 	struct intel_dp_link_config max_link_limits = {
6239e6bb4b2SImre Deak 		.rate = intel_dp_max_common_rate(link_caps),
62413b1b0b9SImre Deak 		.lane_count = intel_dp_link_caps_max_common_lane_count(link_caps),
62513b1b0b9SImre Deak 	};
62613b1b0b9SImre Deak 
627ac24d562SImre Deak 	set_max_link_limits(link_caps, &max_link_limits);
62813b1b0b9SImre Deak }
62913b1b0b9SImre Deak 
630cfc31f49SImre Deak static void reset_max_link_limits_reenable_all(struct intel_dp_link_caps *link_caps)
631cfc31f49SImre Deak {
632cfc31f49SImre Deak 	link_caps->enabled_configs = INTEL_DP_LINK_CAPS_FILTER_ALL;
633ac24d562SImre Deak 	reset_max_link_limits(link_caps);
634cfc31f49SImre Deak }
635cfc31f49SImre Deak 
63645408c4cSImre Deak /**
63755b131b3SImre Deak  * intel_dp_link_caps_disable_config - disable a configuration
63855b131b3SImre Deak  * @link_caps: link capabilities state
63955b131b3SImre Deak  * @config: configuration to disable
64055b131b3SImre Deak  *
64155b131b3SImre Deak  * Disable the configuration identified by @config. This removes the
64255b131b3SImre Deak  * configuration from the set of allowed configurations. The disabling
64355b131b3SImre Deak  * shouldn't leave the remaining configuration set empty.
64455b131b3SImre Deak  *
64555b131b3SImre Deak  * The configuration remains disallowed until intel_dp_link_caps() with
64655b131b3SImre Deak  * reset=%true or changed sink capabilities is called, or
64755b131b3SImre Deak  * intel_dp_link_caps_reset() is called. Each of these happens after a
64855b131b3SImre Deak  * new sink is connected or the currently connected sink changes its
64955b131b3SImre Deak  * capabilities.
65055b131b3SImre Deak  *
65155b131b3SImre Deak  * Return:
65255b131b3SImre Deak  * - %true  if @config was valid and the derived state was updated.
65355b131b3SImre Deak  * - %false if @config was invalid or the remaining configuration set
65455b131b3SImre Deak  *   would remain empty.
65555b131b3SImre Deak  */
65655b131b3SImre Deak bool intel_dp_link_caps_disable_config(struct intel_dp_link_caps *link_caps,
65755b131b3SImre Deak 				       const struct intel_dp_link_config *config)
65855b131b3SImre Deak {
65955b131b3SImre Deak 	struct intel_dp_link_caps_filter enabled_configs = link_caps->enabled_configs;
66055b131b3SImre Deak 	struct intel_dp_link_config forced_params;
66155b131b3SImre Deak 
66255b131b3SImre Deak 	if (!intel_dp_link_caps_filter_remove(link_caps, &enabled_configs, config))
66355b131b3SImre Deak 		return false;
66455b131b3SImre Deak 
66555b131b3SImre Deak 	intel_dp_link_caps_get_forced_params(link_caps, &forced_params);
66655b131b3SImre Deak 
66755b131b3SImre Deak 	if (!calc_allowed_config_filter(link_caps, enabled_configs,
66855b131b3SImre Deak 					&link_caps->max_limits, &forced_params).config_mask)
66955b131b3SImre Deak 		return false;
67055b131b3SImre Deak 
67155b131b3SImre Deak 	link_caps->enabled_configs = enabled_configs;
67255b131b3SImre Deak 
67355b131b3SImre Deak 	return true;
67455b131b3SImre Deak }
67555b131b3SImre Deak 
67655b131b3SImre Deak /**
67745408c4cSImre Deak  * intel_dp_link_caps_get_max_limits - get the current maximum link limits
67845408c4cSImre Deak  * @link_caps: link capabilities state
67945408c4cSImre Deak  * @max_link_limits: returned maximum link limits
68045408c4cSImre Deak  *
68145408c4cSImre Deak  * Return the current maximum rate and lane count limits in
68245408c4cSImre Deak  * @max_link_limits.
68345408c4cSImre Deak  *
68445408c4cSImre Deak  * These limits constrain the set of allowed configurations.
68545408c4cSImre Deak  *
68645408c4cSImre Deak  * The limits are set to the maximum common supported values after
68745408c4cSImre Deak  * intel_dp_link_caps_reset() is called, and can later be modified by
68845408c4cSImre Deak  * intel_dp_link_caps_set_max_limits(). The max rate and lane count
68945408c4cSImre Deak  * parameters are independent limits, so the pair does not necessarily
69045408c4cSImre Deak  * define a valid configuration.
69145408c4cSImre Deak  *
69245408c4cSImre Deak  * This function may be called without serializing against updates to
69345408c4cSImre Deak  * @link_caps. However, without such serialization the returned value may be
69445408c4cSImre Deak  * an out-of-sync (link rate, lane count) tuple, i.e. the parameters may
69545408c4cSImre Deak  * belong to different update snapshots in time.
69645408c4cSImre Deak  */
69745408c4cSImre Deak void intel_dp_link_caps_get_max_limits(struct intel_dp_link_caps *link_caps,
69845408c4cSImre Deak 				       struct intel_dp_link_config *max_link_limits)
69945408c4cSImre Deak {
700ba4680deSImre Deak 	*max_link_limits = link_caps->max_limits;
70145408c4cSImre Deak }
70245408c4cSImre Deak 
703e5cd9e17SImre Deak static bool max_link_limits_valid(struct intel_dp_link_caps *link_caps,
704e5cd9e17SImre Deak 				  const struct intel_dp_link_config *max_link_limits)
705e5cd9e17SImre Deak {
706e5cd9e17SImre Deak 	struct intel_dp_link_caps_filter allowed_configs;
707e5cd9e17SImre Deak 	struct intel_dp_link_config forced_params;
708e5cd9e17SImre Deak 
709e5cd9e17SImre Deak 	if (max_link_limits->lane_count > INTEL_DP_MAX_LANE_COUNT ||
710e5cd9e17SImre Deak 	    !is_power_of_2(max_link_limits->lane_count))
711e5cd9e17SImre Deak 		return false;
712e5cd9e17SImre Deak 
713e5cd9e17SImre Deak 	/* TODO: Validate max_link_limits->rate against the source supported rates. */
714e5cd9e17SImre Deak 
715e5cd9e17SImre Deak 	intel_dp_link_caps_get_forced_params(link_caps, &forced_params);
7161e574621SImre Deak 	allowed_configs = calc_allowed_config_filter(link_caps, link_caps->enabled_configs,
717e5cd9e17SImre Deak 						     max_link_limits, &forced_params);
718e5cd9e17SImre Deak 
719e5cd9e17SImre Deak 	return allowed_configs.config_mask != 0;
720e5cd9e17SImre Deak }
721e5cd9e17SImre Deak 
72217659f83SImre Deak /**
72317659f83SImre Deak  * intel_dp_link_caps_set_max_limits - set the current maximum link limits
72417659f83SImre Deak  * @link_caps: link capabilities state
72517659f83SImre Deak  * @max_link_limits: new maximum link limits
72617659f83SImre Deak  *
72717659f83SImre Deak  * Set the current maximum rate and lane count limits to @max_link_limits,
72817659f83SImre Deak  * constraining the set of allowed configurations.
72917659f83SImre Deak  *
730e5cd9e17SImre Deak  * The new limits must leave at least one configuration allowed: the limits
731e5cd9e17SImre Deak  * must not be below the currently active forced parameters or below all the
732e5cd9e17SImre Deak  * configurations that remain after disabled configurations are excluded.
733e5cd9e17SImre Deak  *
73417659f83SImre Deak  * Unlike intel_dp_link_caps_get_max_limits(), the caller must serialize
73517659f83SImre Deak  * this call against concurrent queries and updates to @link_caps, in line
73617659f83SImre Deak  * with the rest of the API.
73717659f83SImre Deak  *
73817659f83SImre Deak  * Return:
73917659f83SImre Deak  * - %true  if the @link_caps cached max limits value got updated with
74017659f83SImre Deak  *          @max_link_limits.
74117659f83SImre Deak  * - %false if @max_link_limits is invalid.
74217659f83SImre Deak  */
74317659f83SImre Deak bool intel_dp_link_caps_set_max_limits(struct intel_dp_link_caps *link_caps,
74417659f83SImre Deak 				       const struct intel_dp_link_config *max_link_limits)
74517659f83SImre Deak {
746e5cd9e17SImre Deak 	if (!max_link_limits_valid(link_caps, max_link_limits))
747e5cd9e17SImre Deak 		return false;
748e5cd9e17SImre Deak 
749ac24d562SImre Deak 	set_max_link_limits(link_caps, max_link_limits);
75017659f83SImre Deak 
75117659f83SImre Deak 	return true;
75217659f83SImre Deak }
75317659f83SImre Deak 
75413b1b0b9SImre Deak /**
75513b1b0b9SImre Deak  * intel_dp_link_caps_reset_max_limits - reset the current maximum link limits
75613b1b0b9SImre Deak  * @link_caps: link capabilities state
75713b1b0b9SImre Deak  *
75813b1b0b9SImre Deak  * Reset the current maximum link limits to the maximum supported common link
75913b1b0b9SImre Deak  * rate and lane count.
76013b1b0b9SImre Deak  */
76113b1b0b9SImre Deak void intel_dp_link_caps_reset_max_limits(struct intel_dp_link_caps *link_caps)
76213b1b0b9SImre Deak {
763ac24d562SImre Deak 	reset_max_link_limits(link_caps);
76413b1b0b9SImre Deak }
76513b1b0b9SImre Deak 
76624e7de99SImre Deak static int intel_dp_link_config_bw(struct intel_dp_link_caps *link_caps,
7676929823fSMichał Grzelak 				   const struct intel_dp_link_config_entry *lce)
768b9d98594SImre Deak {
7696929823fSMichał Grzelak 	return drm_dp_max_dprx_data_rate(intel_dp_link_config_rate(link_caps, lce),
7706929823fSMichał Grzelak 					 intel_dp_link_config_lane_count(lce));
771b9d98594SImre Deak }
772b9d98594SImre Deak 
773b9d98594SImre Deak static int link_config_cmp_by_bw(const void *a, const void *b, const void *p)
774b9d98594SImre Deak {
775b9d98594SImre Deak 	struct intel_dp *intel_dp = (struct intel_dp *)p;	/* remove const */
77624e7de99SImre Deak 	struct intel_dp_link_caps *link_caps = intel_dp->link.caps;
77724e7de99SImre Deak 
7786929823fSMichał Grzelak 	const struct intel_dp_link_config_entry *lce_a = a;
7796929823fSMichał Grzelak 	const struct intel_dp_link_config_entry *lce_b = b;
7806929823fSMichał Grzelak 	int bw_a = intel_dp_link_config_bw(link_caps, lce_a);
7816929823fSMichał Grzelak 	int bw_b = intel_dp_link_config_bw(link_caps, lce_b);
782b9d98594SImre Deak 
783b9d98594SImre Deak 	if (bw_a != bw_b)
784b9d98594SImre Deak 		return bw_a - bw_b;
785b9d98594SImre Deak 
7866929823fSMichał Grzelak 	return intel_dp_link_config_rate(link_caps, lce_a) -
7876929823fSMichał Grzelak 	       intel_dp_link_config_rate(link_caps, lce_b);
788b9d98594SImre Deak }
789b9d98594SImre Deak 
7904074974bSImre Deak static int link_config_cmp_by_rate_lane(const void *a, const void *b, const void *p)
7914074974bSImre Deak {
7924074974bSImre Deak 	const struct intel_dp_link_caps *link_caps = p;
7934074974bSImre Deak 	u8 *lce_a_idx = (u8 *)a;
7944074974bSImre Deak 	u8 *lce_b_idx = (u8 *)b;
7954074974bSImre Deak 	const struct intel_dp_link_config_entry *lce_a = &link_caps->configs[*lce_a_idx];
7964074974bSImre Deak 	const struct intel_dp_link_config_entry *lce_b = &link_caps->configs[*lce_b_idx];
7974074974bSImre Deak 
7984074974bSImre Deak 	if (lce_a->link_rate_idx != lce_b->link_rate_idx)
7994074974bSImre Deak 		return lce_a->link_rate_idx - lce_b->link_rate_idx;
8004074974bSImre Deak 
8014074974bSImre Deak 	return lce_a->lane_count_exp - lce_b->lane_count_exp;
8024074974bSImre Deak }
8034074974bSImre Deak 
8044074974bSImre Deak static int link_config_cmp_by_lane_rate(const void *a, const void *b, const void *p)
8054074974bSImre Deak {
8064074974bSImre Deak 	const struct intel_dp_link_caps *link_caps = p;
8074074974bSImre Deak 	u8 *lce_a_idx = (u8 *)a;
8084074974bSImre Deak 	u8 *lce_b_idx = (u8 *)b;
8094074974bSImre Deak 	const struct intel_dp_link_config_entry *lce_a = &link_caps->configs[*lce_a_idx];
8104074974bSImre Deak 	const struct intel_dp_link_config_entry *lce_b = &link_caps->configs[*lce_b_idx];
8114074974bSImre Deak 
8124074974bSImre Deak 	if (lce_a->lane_count_exp != lce_b->lane_count_exp)
8134074974bSImre Deak 		return lce_a->lane_count_exp - lce_b->lane_count_exp;
8144074974bSImre Deak 
8154074974bSImre Deak 	return lce_a->link_rate_idx - lce_b->link_rate_idx;
8164074974bSImre Deak }
8174074974bSImre Deak 
818ae40784fSImre Deak /**
819ae40784fSImre Deak  * intel_dp_link_caps_update - rebuild the supported link configuration state
820ae40784fSImre Deak  * @link_caps: link capabilities state
821ae40784fSImre Deak  * @rates: supported common link rates
822ae40784fSImre Deak  * @num_rates: number of entries in @rates
823ae40784fSImre Deak  * @max_lane_count: supported maximum lane count
824ae40784fSImre Deak  * @reset: reset limits and disabled configs
825ae40784fSImre Deak  *
826ae40784fSImre Deak  * Rebuild the supported link configuration state from @rates and
827ae40784fSImre Deak  * @max_lane_count.
828ae40784fSImre Deak  *
829ae40784fSImre Deak  * If @reset is %true, reset the maximum link limits to the maximum
830ae40784fSImre Deak  * supported rate and lane count, and re-enable all configurations.
831ae40784fSImre Deak  *
832ae40784fSImre Deak  * This function is called regularly, at least after a sink is connected,
833ae40784fSImre Deak  * but it may also be called later whenever the sink capabilities may have
834ae40784fSImre Deak  * changed, for example in response to HPD IRQ / RX_CAP_CHANGED signaling.
835ae40784fSImre Deak  *
836ae40784fSImre Deak  * In the Intel driver this function is currently called whenever the
837ae40784fSImre Deak  * connector detect handler runs, after reading the sink capabilities. This
838ae40784fSImre Deak  * may change if those capabilities are cached until the sink is
839ae40784fSImre Deak  * disconnected, or until RX_CAP_CHANGED is signaled. In any case, this
840ae40784fSImre Deak  * function should be called whenever the sink capabilities were read out
841ae40784fSImre Deak  * and may have changed.
842ae40784fSImre Deak  *
843ae40784fSImre Deak  * Returns:
844ae40784fSImre Deak  * - %true if the link capabilities have changed, %false otherwise.
845ae40784fSImre Deak  */
8463aa9d374SImre Deak bool intel_dp_link_caps_update(struct intel_dp_link_caps *link_caps,
847ae40784fSImre Deak 			       const int *rates, int num_rates, int max_lane_count,
848ae40784fSImre Deak 			       bool reset)
849b9d98594SImre Deak {
8503aa9d374SImre Deak 	struct intel_dp *intel_dp = link_caps->dp;
851b9d98594SImre Deak 	struct intel_display *display = to_intel_display(intel_dp);
8526929823fSMichał Grzelak 	struct intel_dp_link_config_entry *lce;
853ae40784fSImre Deak 	bool link_params_changed = reset;
854b9d98594SImre Deak 	int num_common_lane_configs;
855b9d98594SImre Deak 	int i;
856b9d98594SImre Deak 	int j;
857b9d98594SImre Deak 
858de87e3bfSImre Deak 	if (drm_WARN_ON(display->drm, !is_power_of_2(max_lane_count)))
8597aa14e73SImre Deak 		return false;
8607aa14e73SImre Deak 
86170f6d73aSImre Deak 	if (drm_WARN_ON(display->drm, num_rates > ARRAY_SIZE(link_caps->rates)))
8627aa14e73SImre Deak 		return false;
863b9d98594SImre Deak 
864de87e3bfSImre Deak 	num_common_lane_configs = ilog2(max_lane_count) + 1;
865b9d98594SImre Deak 
8667aa14e73SImre Deak 	if (drm_WARN_ON(display->drm, num_rates * num_common_lane_configs >
86767cd7367SImre Deak 				    ARRAY_SIZE(link_caps->configs)))
8687aa14e73SImre Deak 		return false;
869b9d98594SImre Deak 
8707aa14e73SImre Deak 	/* TODO: Add a struct containing both rates and number of rates. */
87170f6d73aSImre Deak 	static_assert(__same_type(rates[0], link_caps->rates[0]));
87270f6d73aSImre Deak 	if (num_rates != link_caps->num_rates ||
87370f6d73aSImre Deak 	    memcmp(rates, link_caps->rates, num_rates * sizeof(rates[0])))
8747aa14e73SImre Deak 		link_params_changed = true;
8757aa14e73SImre Deak 
876de87e3bfSImre Deak 	if (max_lane_count != link_caps->max_lane_count)
877de87e3bfSImre Deak 		link_params_changed = true;
878de87e3bfSImre Deak 
87970f6d73aSImre Deak 	memcpy(link_caps->rates, rates, num_rates * sizeof(rates[0]));
88070f6d73aSImre Deak 	link_caps->num_rates = num_rates;
881de87e3bfSImre Deak 	link_caps->max_lane_count = max_lane_count;
882de87e3bfSImre Deak 
8837aa14e73SImre Deak 	link_caps->num_configs = num_rates * num_common_lane_configs;
884b9d98594SImre Deak 
8856929823fSMichał Grzelak 	lce = &link_caps->configs[0];
88670f6d73aSImre Deak 	for (i = 0; i < link_caps->num_rates; i++) {
887b9d98594SImre Deak 		for (j = 0; j < num_common_lane_configs; j++) {
8886929823fSMichał Grzelak 			lce->lane_count_exp = j;
8896929823fSMichał Grzelak 			lce->link_rate_idx = i;
890b9d98594SImre Deak 
8916929823fSMichał Grzelak 			lce++;
892b9d98594SImre Deak 		}
893b9d98594SImre Deak 	}
894b9d98594SImre Deak 
89567cd7367SImre Deak 	sort_r(link_caps->configs, link_caps->num_configs,
89667cd7367SImre Deak 	       sizeof(link_caps->configs[0]),
897b9d98594SImre Deak 	       link_config_cmp_by_bw, NULL,
898b9d98594SImre Deak 	       intel_dp);
8997aa14e73SImre Deak 
9004074974bSImre Deak 	for (i = 0; i < link_caps->num_configs; i++) {
9014074974bSImre Deak 		link_caps->rate_lane_map[i] = i;
9024074974bSImre Deak 		link_caps->lane_rate_map[i] = i;
9034074974bSImre Deak 	}
9044074974bSImre Deak 
9054074974bSImre Deak 	sort_r(link_caps->rate_lane_map, link_caps->num_configs,
9064074974bSImre Deak 	       sizeof(link_caps->rate_lane_map[0]),
9074074974bSImre Deak 	       link_config_cmp_by_rate_lane, NULL,
9084074974bSImre Deak 	       link_caps);
9094074974bSImre Deak 
9104074974bSImre Deak 	sort_r(link_caps->lane_rate_map, link_caps->num_configs,
9114074974bSImre Deak 	       sizeof(link_caps->lane_rate_map[0]),
9124074974bSImre Deak 	       link_config_cmp_by_lane_rate, NULL,
9134074974bSImre Deak 	       link_caps);
9144074974bSImre Deak 
915ae40784fSImre Deak 	if (link_params_changed)
916ae40784fSImre Deak 		reset_max_link_limits_reenable_all(link_caps);
917ae40784fSImre Deak 
9187aa14e73SImre Deak 	return link_params_changed;
919b9d98594SImre Deak }
920b9d98594SImre Deak 
921cd0d2557SImre Deak /**
922cd0d2557SImre Deak  * intel_dp_link_caps_reset - reset link capability restrictions
923cd0d2557SImre Deak  * @link_caps: link capabilities state
924cd0d2557SImre Deak  *
925cd0d2557SImre Deak  * Reset all current restrictions except for the user requested forced
926cd0d2557SImre Deak  * parameters, thus updating the set of allowed configurations and the
927cd0d2557SImre Deak  * derived maximum link information accordingly.
928cd0d2557SImre Deak  *
929cd0d2557SImre Deak  * This function is regularly called after a sink is connected, either
930cd0d2557SImre Deak  * for the first time to the connector or after a previous sink was
931cd0d2557SImre Deak  * disconnected from it, and intel_dp_link_caps_update() was called.
932cd0d2557SImre Deak  */
933cd0d2557SImre Deak void intel_dp_link_caps_reset(struct intel_dp_link_caps *link_caps)
934cd0d2557SImre Deak {
935cfc31f49SImre Deak 	reset_max_link_limits_reenable_all(link_caps);
936cd0d2557SImre Deak }
937cd0d2557SImre Deak 
938fdd4b01bSImre Deak static int i915_dp_force_link_rate_show(struct seq_file *m, void *data)
939fdd4b01bSImre Deak {
940fdd4b01bSImre Deak 	struct intel_connector *connector = to_intel_connector(m->private);
941fdd4b01bSImre Deak 	struct intel_display *display = to_intel_display(connector);
942fdd4b01bSImre Deak 	struct intel_dp *intel_dp = intel_attached_dp(connector);
9439382aacfSImre Deak 	struct intel_dp_link_caps *link_caps = intel_dp->link.caps;
944fdd4b01bSImre Deak 	int current_rate = -1;
945fdd4b01bSImre Deak 	int force_rate;
946fdd4b01bSImre Deak 	int err;
947fdd4b01bSImre Deak 	int i;
948fdd4b01bSImre Deak 
949fdd4b01bSImre Deak 	err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
950fdd4b01bSImre Deak 	if (err)
951fdd4b01bSImre Deak 		return err;
952fdd4b01bSImre Deak 
953fdd4b01bSImre Deak 	intel_dp_flush_connector_commits(connector);
954fdd4b01bSImre Deak 
955fdd4b01bSImre Deak 	if (intel_dp->link.active)
956fdd4b01bSImre Deak 		current_rate = intel_dp->link_rate;
957fdd4b01bSImre Deak 
9589382aacfSImre Deak 	force_rate = link_caps->forced_params.rate;
959fdd4b01bSImre Deak 
960fdd4b01bSImre Deak 	drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
961fdd4b01bSImre Deak 
962fdd4b01bSImre Deak 	seq_printf(m, "%sauto%s",
963fdd4b01bSImre Deak 		   force_rate == 0 ? "[" : "",
964fdd4b01bSImre Deak 		   force_rate == 0 ? "]" : "");
965fdd4b01bSImre Deak 
966fdd4b01bSImre Deak 	for (i = 0; i < intel_dp->num_source_rates; i++)
967fdd4b01bSImre Deak 		seq_printf(m, " %s%d%s%s",
968fdd4b01bSImre Deak 			   intel_dp->source_rates[i] == force_rate ? "[" : "",
969fdd4b01bSImre Deak 			   intel_dp->source_rates[i],
970fdd4b01bSImre Deak 			   intel_dp->source_rates[i] == current_rate ? "*" : "",
971fdd4b01bSImre Deak 			   intel_dp->source_rates[i] == force_rate ? "]" : "");
972fdd4b01bSImre Deak 
973fdd4b01bSImre Deak 	seq_putc(m, '\n');
974fdd4b01bSImre Deak 
975fdd4b01bSImre Deak 	return 0;
976fdd4b01bSImre Deak }
977fdd4b01bSImre Deak 
97824e7de99SImre Deak static int parse_link_rate(struct intel_dp_link_caps *link_caps, const char __user *ubuf, size_t len)
979fdd4b01bSImre Deak {
98024e7de99SImre Deak 	struct intel_dp *intel_dp = link_caps->dp;
981fdd4b01bSImre Deak 	char *kbuf;
982fdd4b01bSImre Deak 	const char *p;
983fdd4b01bSImre Deak 	int rate;
984fdd4b01bSImre Deak 	int ret = 0;
985fdd4b01bSImre Deak 
986fdd4b01bSImre Deak 	kbuf = memdup_user_nul(ubuf, len);
987fdd4b01bSImre Deak 	if (IS_ERR(kbuf))
988fdd4b01bSImre Deak 		return PTR_ERR(kbuf);
989fdd4b01bSImre Deak 
990fdd4b01bSImre Deak 	p = strim(kbuf);
991fdd4b01bSImre Deak 
992fdd4b01bSImre Deak 	if (!strcmp(p, "auto")) {
993fdd4b01bSImre Deak 		rate = 0;
994fdd4b01bSImre Deak 	} else {
995fdd4b01bSImre Deak 		ret = kstrtoint(p, 0, &rate);
996fdd4b01bSImre Deak 		if (ret < 0)
997fdd4b01bSImre Deak 			goto out_free;
998fdd4b01bSImre Deak 
999fdd4b01bSImre Deak 		if (intel_dp_rate_index(intel_dp->source_rates,
1000fdd4b01bSImre Deak 					intel_dp->num_source_rates,
1001fdd4b01bSImre Deak 					rate) < 0)
1002fdd4b01bSImre Deak 			ret = -EINVAL;
1003fdd4b01bSImre Deak 	}
1004fdd4b01bSImre Deak 
1005fdd4b01bSImre Deak out_free:
1006fdd4b01bSImre Deak 	kfree(kbuf);
1007fdd4b01bSImre Deak 
1008fdd4b01bSImre Deak 	return ret < 0 ? ret : rate;
1009fdd4b01bSImre Deak }
1010fdd4b01bSImre Deak 
1011fdd4b01bSImre Deak static ssize_t i915_dp_force_link_rate_write(struct file *file,
1012fdd4b01bSImre Deak 					     const char __user *ubuf,
1013fdd4b01bSImre Deak 					     size_t len, loff_t *offp)
1014fdd4b01bSImre Deak {
1015fdd4b01bSImre Deak 	struct seq_file *m = file->private_data;
1016fdd4b01bSImre Deak 	struct intel_connector *connector = to_intel_connector(m->private);
1017fdd4b01bSImre Deak 	struct intel_display *display = to_intel_display(connector);
1018fdd4b01bSImre Deak 	struct intel_dp *intel_dp = intel_attached_dp(connector);
10199382aacfSImre Deak 	struct intel_dp_link_caps *link_caps = intel_dp->link.caps;
1020fdd4b01bSImre Deak 	int rate;
1021fdd4b01bSImre Deak 	int err;
1022fdd4b01bSImre Deak 
102324e7de99SImre Deak 	rate = parse_link_rate(link_caps, ubuf, len);
1024fdd4b01bSImre Deak 	if (rate < 0)
1025fdd4b01bSImre Deak 		return rate;
1026fdd4b01bSImre Deak 
1027fdd4b01bSImre Deak 	err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
1028fdd4b01bSImre Deak 	if (err)
1029fdd4b01bSImre Deak 		return err;
1030fdd4b01bSImre Deak 
1031fdd4b01bSImre Deak 	intel_dp_flush_connector_commits(connector);
1032fdd4b01bSImre Deak 
1033fdd4b01bSImre Deak 	intel_dp_reset_link_params(intel_dp);
10349382aacfSImre Deak 	link_caps->forced_params.rate = rate;
1035fdd4b01bSImre Deak 
1036fdd4b01bSImre Deak 	drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
1037fdd4b01bSImre Deak 
1038fdd4b01bSImre Deak 	*offp += len;
1039fdd4b01bSImre Deak 
1040fdd4b01bSImre Deak 	return len;
1041fdd4b01bSImre Deak }
1042fdd4b01bSImre Deak DEFINE_SHOW_STORE_ATTRIBUTE(i915_dp_force_link_rate);
1043fdd4b01bSImre Deak 
1044fdd4b01bSImre Deak static int i915_dp_force_lane_count_show(struct seq_file *m, void *data)
1045fdd4b01bSImre Deak {
1046fdd4b01bSImre Deak 	struct intel_connector *connector = to_intel_connector(m->private);
1047fdd4b01bSImre Deak 	struct intel_display *display = to_intel_display(connector);
1048fdd4b01bSImre Deak 	struct intel_dp *intel_dp = intel_attached_dp(connector);
10499382aacfSImre Deak 	struct intel_dp_link_caps *link_caps = intel_dp->link.caps;
1050fdd4b01bSImre Deak 	int current_lane_count = -1;
1051fdd4b01bSImre Deak 	int force_lane_count;
1052fdd4b01bSImre Deak 	int err;
1053fdd4b01bSImre Deak 	int i;
1054fdd4b01bSImre Deak 
1055fdd4b01bSImre Deak 	err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
1056fdd4b01bSImre Deak 	if (err)
1057fdd4b01bSImre Deak 		return err;
1058fdd4b01bSImre Deak 
1059fdd4b01bSImre Deak 	intel_dp_flush_connector_commits(connector);
1060fdd4b01bSImre Deak 
1061fdd4b01bSImre Deak 	if (intel_dp->link.active)
1062fdd4b01bSImre Deak 		current_lane_count = intel_dp->lane_count;
10639382aacfSImre Deak 	force_lane_count = link_caps->forced_params.lane_count;
1064fdd4b01bSImre Deak 
1065fdd4b01bSImre Deak 	drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
1066fdd4b01bSImre Deak 
1067fdd4b01bSImre Deak 	seq_printf(m, "%sauto%s",
1068fdd4b01bSImre Deak 		   force_lane_count == 0 ? "[" : "",
1069fdd4b01bSImre Deak 		   force_lane_count == 0 ? "]" : "");
1070fdd4b01bSImre Deak 
1071fdd4b01bSImre Deak 	for (i = 1; i <= 4; i <<= 1)
1072fdd4b01bSImre Deak 		seq_printf(m, " %s%d%s%s",
1073fdd4b01bSImre Deak 			   i == force_lane_count ? "[" : "",
1074fdd4b01bSImre Deak 			   i,
1075fdd4b01bSImre Deak 			   i == current_lane_count ? "*" : "",
1076fdd4b01bSImre Deak 			   i == force_lane_count ? "]" : "");
1077fdd4b01bSImre Deak 
1078fdd4b01bSImre Deak 	seq_putc(m, '\n');
1079fdd4b01bSImre Deak 
1080fdd4b01bSImre Deak 	return 0;
1081fdd4b01bSImre Deak }
1082fdd4b01bSImre Deak 
1083fdd4b01bSImre Deak static int parse_lane_count(const char __user *ubuf, size_t len)
1084fdd4b01bSImre Deak {
1085fdd4b01bSImre Deak 	char *kbuf;
1086fdd4b01bSImre Deak 	const char *p;
1087fdd4b01bSImre Deak 	int lane_count;
1088fdd4b01bSImre Deak 	int ret = 0;
1089fdd4b01bSImre Deak 
1090fdd4b01bSImre Deak 	kbuf = memdup_user_nul(ubuf, len);
1091fdd4b01bSImre Deak 	if (IS_ERR(kbuf))
1092fdd4b01bSImre Deak 		return PTR_ERR(kbuf);
1093fdd4b01bSImre Deak 
1094fdd4b01bSImre Deak 	p = strim(kbuf);
1095fdd4b01bSImre Deak 
1096fdd4b01bSImre Deak 	if (!strcmp(p, "auto")) {
1097fdd4b01bSImre Deak 		lane_count = 0;
1098fdd4b01bSImre Deak 	} else {
1099fdd4b01bSImre Deak 		ret = kstrtoint(p, 0, &lane_count);
1100fdd4b01bSImre Deak 		if (ret < 0)
1101fdd4b01bSImre Deak 			goto out_free;
1102fdd4b01bSImre Deak 
1103fdd4b01bSImre Deak 		switch (lane_count) {
1104fdd4b01bSImre Deak 		case 1:
1105fdd4b01bSImre Deak 		case 2:
1106fdd4b01bSImre Deak 		case 4:
1107fdd4b01bSImre Deak 			break;
1108fdd4b01bSImre Deak 		default:
1109fdd4b01bSImre Deak 			ret = -EINVAL;
1110fdd4b01bSImre Deak 		}
1111fdd4b01bSImre Deak 	}
1112fdd4b01bSImre Deak 
1113fdd4b01bSImre Deak out_free:
1114fdd4b01bSImre Deak 	kfree(kbuf);
1115fdd4b01bSImre Deak 
1116fdd4b01bSImre Deak 	return ret < 0 ? ret : lane_count;
1117fdd4b01bSImre Deak }
1118fdd4b01bSImre Deak 
1119fdd4b01bSImre Deak static ssize_t i915_dp_force_lane_count_write(struct file *file,
1120fdd4b01bSImre Deak 					      const char __user *ubuf,
1121fdd4b01bSImre Deak 					      size_t len, loff_t *offp)
1122fdd4b01bSImre Deak {
1123fdd4b01bSImre Deak 	struct seq_file *m = file->private_data;
1124fdd4b01bSImre Deak 	struct intel_connector *connector = to_intel_connector(m->private);
1125fdd4b01bSImre Deak 	struct intel_display *display = to_intel_display(connector);
1126fdd4b01bSImre Deak 	struct intel_dp *intel_dp = intel_attached_dp(connector);
11279382aacfSImre Deak 	struct intel_dp_link_caps *link_caps = intel_dp->link.caps;
1128fdd4b01bSImre Deak 	int lane_count;
1129fdd4b01bSImre Deak 	int err;
1130fdd4b01bSImre Deak 
1131fdd4b01bSImre Deak 	lane_count = parse_lane_count(ubuf, len);
1132fdd4b01bSImre Deak 	if (lane_count < 0)
1133fdd4b01bSImre Deak 		return lane_count;
1134fdd4b01bSImre Deak 
1135fdd4b01bSImre Deak 	err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
1136fdd4b01bSImre Deak 	if (err)
1137fdd4b01bSImre Deak 		return err;
1138fdd4b01bSImre Deak 
1139fdd4b01bSImre Deak 	intel_dp_flush_connector_commits(connector);
1140fdd4b01bSImre Deak 
1141fdd4b01bSImre Deak 	intel_dp_reset_link_params(intel_dp);
11429382aacfSImre Deak 	link_caps->forced_params.lane_count = lane_count;
1143fdd4b01bSImre Deak 
1144fdd4b01bSImre Deak 	drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
1145fdd4b01bSImre Deak 
1146fdd4b01bSImre Deak 	*offp += len;
1147fdd4b01bSImre Deak 
1148fdd4b01bSImre Deak 	return len;
1149fdd4b01bSImre Deak }
1150fdd4b01bSImre Deak DEFINE_SHOW_STORE_ATTRIBUTE(i915_dp_force_lane_count);
1151fdd4b01bSImre Deak 
1152fdd4b01bSImre Deak static int i915_dp_max_link_rate_show(void *data, u64 *val)
1153fdd4b01bSImre Deak {
1154fdd4b01bSImre Deak 	struct intel_connector *connector = to_intel_connector(data);
1155fdd4b01bSImre Deak 	struct intel_display *display = to_intel_display(connector);
1156fdd4b01bSImre Deak 	struct intel_dp *intel_dp = intel_attached_dp(connector);
115745408c4cSImre Deak 	struct intel_dp_link_config max_link_limits;
1158fdd4b01bSImre Deak 	int err;
1159fdd4b01bSImre Deak 
1160fdd4b01bSImre Deak 	err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
1161fdd4b01bSImre Deak 	if (err)
1162fdd4b01bSImre Deak 		return err;
1163fdd4b01bSImre Deak 
1164fdd4b01bSImre Deak 	intel_dp_flush_connector_commits(connector);
1165fdd4b01bSImre Deak 
116645408c4cSImre Deak 	intel_dp_link_caps_get_max_limits(intel_dp->link.caps, &max_link_limits);
116745408c4cSImre Deak 	*val = max_link_limits.rate;
1168fdd4b01bSImre Deak 
1169fdd4b01bSImre Deak 	drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
1170fdd4b01bSImre Deak 
1171fdd4b01bSImre Deak 	return 0;
1172fdd4b01bSImre Deak }
1173fdd4b01bSImre Deak DEFINE_DEBUGFS_ATTRIBUTE(i915_dp_max_link_rate_fops, i915_dp_max_link_rate_show, NULL, "%llu\n");
1174fdd4b01bSImre Deak 
1175fdd4b01bSImre Deak static int i915_dp_max_lane_count_show(void *data, u64 *val)
1176fdd4b01bSImre Deak {
1177fdd4b01bSImre Deak 	struct intel_connector *connector = to_intel_connector(data);
1178fdd4b01bSImre Deak 	struct intel_display *display = to_intel_display(connector);
1179fdd4b01bSImre Deak 	struct intel_dp *intel_dp = intel_attached_dp(connector);
118045408c4cSImre Deak 	struct intel_dp_link_config max_link_limits;
1181fdd4b01bSImre Deak 	int err;
1182fdd4b01bSImre Deak 
1183fdd4b01bSImre Deak 	err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
1184fdd4b01bSImre Deak 	if (err)
1185fdd4b01bSImre Deak 		return err;
1186fdd4b01bSImre Deak 
1187fdd4b01bSImre Deak 	intel_dp_flush_connector_commits(connector);
1188fdd4b01bSImre Deak 
118945408c4cSImre Deak 	intel_dp_link_caps_get_max_limits(intel_dp->link.caps, &max_link_limits);
119045408c4cSImre Deak 	*val = max_link_limits.lane_count;
1191fdd4b01bSImre Deak 
1192fdd4b01bSImre Deak 	drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
1193fdd4b01bSImre Deak 
1194fdd4b01bSImre Deak 	return 0;
1195fdd4b01bSImre Deak }
1196fdd4b01bSImre Deak DEFINE_DEBUGFS_ATTRIBUTE(i915_dp_max_lane_count_fops, i915_dp_max_lane_count_show, NULL, "%llu\n");
1197fdd4b01bSImre Deak 
1198cf65aa9dSImre Deak static int intel_dp_allowed_link_configs_show(struct seq_file *m, void *data)
1199cf65aa9dSImre Deak {
1200cf65aa9dSImre Deak 	struct intel_connector *connector = to_intel_connector(m->private);
1201cf65aa9dSImre Deak 	struct intel_display *display = to_intel_display(connector);
1202cf65aa9dSImre Deak 	struct intel_dp *intel_dp = intel_attached_dp(connector);
1203cf65aa9dSImre Deak 	struct intel_dp_link_caps *link_caps = intel_dp->link.caps;
1204cf65aa9dSImre Deak 	struct intel_dp_link_config link_config;
1205cf65aa9dSImre Deak 	struct intel_dp_link_caps_iter iter;
1206cf65aa9dSImre Deak 	int err;
1207cf65aa9dSImre Deak 	int i;
1208cf65aa9dSImre Deak 
1209cf65aa9dSImre Deak 	err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
1210cf65aa9dSImre Deak 	if (err)
1211cf65aa9dSImre Deak 		return err;
1212cf65aa9dSImre Deak 
1213cf65aa9dSImre Deak 	intel_dp_flush_connector_commits(connector);
1214cf65aa9dSImre Deak 
1215cf65aa9dSImre Deak 	i = 0;
1216cf65aa9dSImre Deak 	intel_dp_link_caps_iter_start(&iter,
1217cf65aa9dSImre Deak 				      link_caps,
1218cf65aa9dSImre Deak 				      intel_dp_link_caps_connector_compute_order(connector),
1219cf65aa9dSImre Deak 				      INTEL_DP_LINK_CAPS_FILTER_ALL);
1220cf65aa9dSImre Deak 	for_each_dp_link_config(&iter, &link_config) {
1221cf65aa9dSImre Deak 		seq_printf(m, "%s%dx%d",
1222cf65aa9dSImre Deak 			   i ? " " : "",
1223cf65aa9dSImre Deak 			   link_config.lane_count, link_config.rate);
1224cf65aa9dSImre Deak 		i++;
1225cf65aa9dSImre Deak 	}
1226cf65aa9dSImre Deak 	intel_dp_link_caps_iter_end(&iter);
1227cf65aa9dSImre Deak 
1228cf65aa9dSImre Deak 	drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
1229cf65aa9dSImre Deak 
1230cf65aa9dSImre Deak 	seq_putc(m, '\n');
1231cf65aa9dSImre Deak 
1232cf65aa9dSImre Deak 	return 0;
1233cf65aa9dSImre Deak }
1234cf65aa9dSImre Deak DEFINE_SHOW_ATTRIBUTE(intel_dp_allowed_link_configs);
1235fdd4b01bSImre Deak 
1236fdd4b01bSImre Deak /**
1237fdd4b01bSImre Deak  * intel_dp_link_caps_debugfs_add - add link caps debugfs files for a connector
1238fdd4b01bSImre Deak  * @connector: connector to add the debugfs files for
1239fdd4b01bSImre Deak  *
1240fdd4b01bSImre Deak  * Add the link-capability debugfs files for a DP @connector.
1241fdd4b01bSImre Deak  */
1242fdd4b01bSImre Deak void intel_dp_link_caps_debugfs_add(struct intel_connector *connector)
1243fdd4b01bSImre Deak {
1244fdd4b01bSImre Deak 	struct dentry *root = connector->base.debugfs_entry;
1245fdd4b01bSImre Deak 
1246fdd4b01bSImre Deak 	if (connector->base.connector_type != DRM_MODE_CONNECTOR_DisplayPort &&
1247fdd4b01bSImre Deak 	    connector->base.connector_type != DRM_MODE_CONNECTOR_eDP)
1248fdd4b01bSImre Deak 		return;
1249fdd4b01bSImre Deak 
1250fdd4b01bSImre Deak 	debugfs_create_file("i915_dp_force_link_rate", 0644, root,
1251fdd4b01bSImre Deak 			    connector, &i915_dp_force_link_rate_fops);
1252fdd4b01bSImre Deak 
1253fdd4b01bSImre Deak 	debugfs_create_file("i915_dp_force_lane_count", 0644, root,
1254fdd4b01bSImre Deak 			    connector, &i915_dp_force_lane_count_fops);
1255fdd4b01bSImre Deak 
1256fdd4b01bSImre Deak 	debugfs_create_file("i915_dp_max_link_rate", 0444, root,
1257fdd4b01bSImre Deak 			    connector, &i915_dp_max_link_rate_fops);
1258fdd4b01bSImre Deak 
1259fdd4b01bSImre Deak 	debugfs_create_file("i915_dp_max_lane_count", 0444, root,
1260fdd4b01bSImre Deak 			    connector, &i915_dp_max_lane_count_fops);
1261cf65aa9dSImre Deak 
1262cf65aa9dSImre Deak 	debugfs_create_file("intel_dp_allowed_link_configs", 0444, root,
1263cf65aa9dSImre Deak 			    connector, &intel_dp_allowed_link_configs_fops);
1264fdd4b01bSImre Deak }
1265fdd4b01bSImre Deak 
1266ebf5ad5cSImre Deak struct intel_dp_link_caps *intel_dp_link_caps_init(struct intel_dp *intel_dp)
1267ebf5ad5cSImre Deak {
1268ebf5ad5cSImre Deak 	struct intel_dp_link_caps *link_caps;
1269ebf5ad5cSImre Deak 
1270ebf5ad5cSImre Deak 	link_caps = kzalloc_obj(*link_caps);
1271ebf5ad5cSImre Deak 	if (!link_caps)
1272ebf5ad5cSImre Deak 		return NULL;
1273ebf5ad5cSImre Deak 
1274ebf5ad5cSImre Deak 	link_caps->dp = intel_dp;
12751e574621SImre Deak 	link_caps->enabled_configs = INTEL_DP_LINK_CAPS_FILTER_ALL;
1276ebf5ad5cSImre Deak 
1277ebf5ad5cSImre Deak 	return link_caps;
1278ebf5ad5cSImre Deak }
1279ebf5ad5cSImre Deak 
1280ebf5ad5cSImre Deak void intel_dp_link_caps_cleanup(struct intel_dp_link_caps *link_caps)
1281ebf5ad5cSImre Deak {
1282ebf5ad5cSImre Deak 	kfree(link_caps);
1283ebf5ad5cSImre Deak }
1284*2eb9982fSImre Deak 
1285*2eb9982fSImre Deak #if IS_ENABLED(CONFIG_KUNIT)
1286*2eb9982fSImre Deak 
1287*2eb9982fSImre Deak #define __INIT_MEMBER(__name, __fn) \
1288*2eb9982fSImre Deak 	.__name = __fn,
1289*2eb9982fSImre Deak 
1290*2eb9982fSImre Deak #define INTEL_DP_LINK_CAPS_TEST_OPS_INIT \
1291*2eb9982fSImre Deak 	INTEL_DP_LINK_CAPS_TEST_OPS_MEMBERS(__INIT_MEMBER)
1292*2eb9982fSImre Deak 
1293*2eb9982fSImre Deak #ifdef I915
1294*2eb9982fSImre Deak 
1295*2eb9982fSImre Deak const struct intel_dp_link_caps_test_ops i915_display_dp_link_caps_test_ops = {
1296*2eb9982fSImre Deak 	INTEL_DP_LINK_CAPS_TEST_OPS_INIT
1297*2eb9982fSImre Deak };
1298*2eb9982fSImre Deak EXPORT_SYMBOL(i915_display_dp_link_caps_test_ops);
1299*2eb9982fSImre Deak 
1300*2eb9982fSImre Deak #else
1301*2eb9982fSImre Deak 
1302*2eb9982fSImre Deak const struct intel_dp_link_caps_test_ops intel_display_dp_link_caps_test_ops = {
1303*2eb9982fSImre Deak 	INTEL_DP_LINK_CAPS_TEST_OPS_INIT
1304*2eb9982fSImre Deak };
1305*2eb9982fSImre Deak EXPORT_SYMBOL(intel_display_dp_link_caps_test_ops);
1306*2eb9982fSImre Deak 
1307*2eb9982fSImre Deak #endif	/* I915 */
1308*2eb9982fSImre Deak 
1309*2eb9982fSImre Deak #undef INTEL_DP_LINK_CAPS_TEST_OPS_INIT
1310*2eb9982fSImre Deak #undef __INIT_MEMBER
1311*2eb9982fSImre Deak 
1312*2eb9982fSImre Deak #endif	/* CONFIG_KUNIT */
1313