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