1 // SPDX-License-Identifier: MIT
3 * Copyright (C) 2013-2019 NVIDIA Corporation
4 * Copyright (C) 2015 Rob Clark
7 #include <drm/drm_dp_helper.h>
11 static void drm_dp_link_caps_reset(struct drm_dp_link_caps *caps)
13 caps->enhanced_framing = false;
16 void drm_dp_link_caps_copy(struct drm_dp_link_caps *dest,
17 const struct drm_dp_link_caps *src)
19 dest->enhanced_framing = src->enhanced_framing;
22 static void drm_dp_link_reset(struct drm_dp_link *link)
31 drm_dp_link_caps_reset(&link->caps);
38 * drm_dp_link_probe() - probe a DisplayPort link for capabilities
39 * @aux: DisplayPort AUX channel
40 * @link: pointer to structure in which to return link capabilities
42 * The structure filled in by this function can usually be passed directly
43 * into drm_dp_link_power_up() and drm_dp_link_configure() to power up and
44 * configure the link based on the link's capabilities.
46 * Returns 0 on success or a negative error code on failure.
48 int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link)
53 drm_dp_link_reset(link);
55 err = drm_dp_dpcd_read(aux, DP_DPCD_REV, values, sizeof(values));
59 link->revision = values[0];
60 link->max_rate = drm_dp_bw_code_to_link_rate(values[1]);
61 link->max_lanes = values[2] & DP_MAX_LANE_COUNT_MASK;
63 if (values[2] & DP_ENHANCED_FRAME_CAP)
64 link->caps.enhanced_framing = true;
66 link->rate = link->max_rate;
67 link->lanes = link->max_lanes;
73 * drm_dp_link_power_up() - power up a DisplayPort link
74 * @aux: DisplayPort AUX channel
75 * @link: pointer to a structure containing the link configuration
77 * Returns 0 on success or a negative error code on failure.
79 int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link)
84 /* DP_SET_POWER register is only available on DPCD v1.1 and later */
85 if (link->revision < 0x11)
88 err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
92 value &= ~DP_SET_POWER_MASK;
93 value |= DP_SET_POWER_D0;
95 err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
100 * According to the DP 1.1 specification, a "Sink Device must exit the
101 * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink
102 * Control Field" (register 0x600).
104 usleep_range(1000, 2000);
110 * drm_dp_link_power_down() - power down a DisplayPort link
111 * @aux: DisplayPort AUX channel
112 * @link: pointer to a structure containing the link configuration
114 * Returns 0 on success or a negative error code on failure.
116 int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link)
121 /* DP_SET_POWER register is only available on DPCD v1.1 and later */
122 if (link->revision < 0x11)
125 err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
129 value &= ~DP_SET_POWER_MASK;
130 value |= DP_SET_POWER_D3;
132 err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
140 * drm_dp_link_configure() - configure a DisplayPort link
141 * @aux: DisplayPort AUX channel
142 * @link: pointer to a structure containing the link configuration
144 * Returns 0 on success or a negative error code on failure.
146 int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link)
151 values[0] = drm_dp_link_rate_to_bw_code(link->rate);
152 values[1] = link->lanes;
154 if (link->caps.enhanced_framing)
155 values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
157 err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values));