1aa850fb1SJani Nikula // SPDX-License-Identifier: MIT
2aa850fb1SJani Nikula /*
3aa850fb1SJani Nikula * Copyright © 2020-2021 Intel Corporation
4aa850fb1SJani Nikula */
5aa850fb1SJani Nikula
6aa850fb1SJani Nikula #include "i915_drv.h"
7801543b2SJani Nikula #include "i915_reg.h"
8aa850fb1SJani Nikula #include "i915_trace.h"
9bb45217fSVille Syrjälä #include "intel_bios.h"
10ec2593e3SJani Nikula #include "intel_de.h"
11aa850fb1SJani Nikula #include "intel_display_types.h"
12aa850fb1SJani Nikula #include "intel_dp_aux.h"
1389e790ecSJani Nikula #include "intel_dp_aux_regs.h"
14aa850fb1SJani Nikula #include "intel_pps.h"
15aa850fb1SJani Nikula #include "intel_tc.h"
16aa850fb1SJani Nikula
intel_dp_aux_pack(const u8 * src,int src_bytes)17a181e940SVille Syrjälä u32 intel_dp_aux_pack(const u8 *src, int src_bytes)
18aa850fb1SJani Nikula {
19aa850fb1SJani Nikula int i;
20aa850fb1SJani Nikula u32 v = 0;
21aa850fb1SJani Nikula
22aa850fb1SJani Nikula if (src_bytes > 4)
23aa850fb1SJani Nikula src_bytes = 4;
24aa850fb1SJani Nikula for (i = 0; i < src_bytes; i++)
25aa850fb1SJani Nikula v |= ((u32)src[i]) << ((3 - i) * 8);
26aa850fb1SJani Nikula return v;
27aa850fb1SJani Nikula }
28aa850fb1SJani Nikula
intel_dp_aux_unpack(u32 src,u8 * dst,int dst_bytes)292616be2eSJani Nikula static void intel_dp_aux_unpack(u32 src, u8 *dst, int dst_bytes)
30aa850fb1SJani Nikula {
31aa850fb1SJani Nikula int i;
32aa850fb1SJani Nikula
33aa850fb1SJani Nikula if (dst_bytes > 4)
34aa850fb1SJani Nikula dst_bytes = 4;
35aa850fb1SJani Nikula for (i = 0; i < dst_bytes; i++)
36aa850fb1SJani Nikula dst[i] = src >> ((3 - i) * 8);
37aa850fb1SJani Nikula }
38aa850fb1SJani Nikula
39aa850fb1SJani Nikula static u32
intel_dp_aux_wait_done(struct intel_dp * intel_dp)40aa850fb1SJani Nikula intel_dp_aux_wait_done(struct intel_dp *intel_dp)
41aa850fb1SJani Nikula {
42aa850fb1SJani Nikula struct drm_i915_private *i915 = dp_to_i915(intel_dp);
43aa850fb1SJani Nikula i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
44aa850fb1SJani Nikula const unsigned int timeout_ms = 10;
45aa850fb1SJani Nikula u32 status;
465a9b0c74SArun R Murthy int ret;
47aa850fb1SJani Nikula
485a9b0c74SArun R Murthy ret = __intel_de_wait_for_register(i915, ch_ctl,
495a9b0c74SArun R Murthy DP_AUX_CH_CTL_SEND_BUSY, 0,
505a9b0c74SArun R Murthy 2, timeout_ms, &status);
51aa850fb1SJani Nikula
525a9b0c74SArun R Murthy if (ret == -ETIMEDOUT)
53aa850fb1SJani Nikula drm_err(&i915->drm,
54aa850fb1SJani Nikula "%s: did not complete or timeout within %ums (status 0x%08x)\n",
55aa850fb1SJani Nikula intel_dp->aux.name, timeout_ms, status);
56aa850fb1SJani Nikula
57aa850fb1SJani Nikula return status;
58aa850fb1SJani Nikula }
59aa850fb1SJani Nikula
g4x_get_aux_clock_divider(struct intel_dp * intel_dp,int index)60aa850fb1SJani Nikula static u32 g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
61aa850fb1SJani Nikula {
62aa850fb1SJani Nikula struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
63aa850fb1SJani Nikula
64aa850fb1SJani Nikula if (index)
65aa850fb1SJani Nikula return 0;
66aa850fb1SJani Nikula
67aa850fb1SJani Nikula /*
68aa850fb1SJani Nikula * The clock divider is based off the hrawclk, and would like to run at
69aa850fb1SJani Nikula * 2MHz. So, take the hrawclk value and divide by 2000 and use that
70aa850fb1SJani Nikula */
71aa850fb1SJani Nikula return DIV_ROUND_CLOSEST(RUNTIME_INFO(dev_priv)->rawclk_freq, 2000);
72aa850fb1SJani Nikula }
73aa850fb1SJani Nikula
ilk_get_aux_clock_divider(struct intel_dp * intel_dp,int index)74aa850fb1SJani Nikula static u32 ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
75aa850fb1SJani Nikula {
76aa850fb1SJani Nikula struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
77aa850fb1SJani Nikula struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
78aa850fb1SJani Nikula u32 freq;
79aa850fb1SJani Nikula
80aa850fb1SJani Nikula if (index)
81aa850fb1SJani Nikula return 0;
82aa850fb1SJani Nikula
83aa850fb1SJani Nikula /*
84aa850fb1SJani Nikula * The clock divider is based off the cdclk or PCH rawclk, and would
85aa850fb1SJani Nikula * like to run at 2MHz. So, take the cdclk or PCH rawclk value and
86aa850fb1SJani Nikula * divide by 2000 and use that
87aa850fb1SJani Nikula */
88aa850fb1SJani Nikula if (dig_port->aux_ch == AUX_CH_A)
89d51309b4SJani Nikula freq = dev_priv->display.cdclk.hw.cdclk;
90aa850fb1SJani Nikula else
91aa850fb1SJani Nikula freq = RUNTIME_INFO(dev_priv)->rawclk_freq;
92aa850fb1SJani Nikula return DIV_ROUND_CLOSEST(freq, 2000);
93aa850fb1SJani Nikula }
94aa850fb1SJani Nikula
hsw_get_aux_clock_divider(struct intel_dp * intel_dp,int index)95aa850fb1SJani Nikula static u32 hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
96aa850fb1SJani Nikula {
97aa850fb1SJani Nikula struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
98aa850fb1SJani Nikula struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
99aa850fb1SJani Nikula
100aa850fb1SJani Nikula if (dig_port->aux_ch != AUX_CH_A && HAS_PCH_LPT_H(dev_priv)) {
101aa850fb1SJani Nikula /* Workaround for non-ULT HSW */
102aa850fb1SJani Nikula switch (index) {
103aa850fb1SJani Nikula case 0: return 63;
104aa850fb1SJani Nikula case 1: return 72;
105aa850fb1SJani Nikula default: return 0;
106aa850fb1SJani Nikula }
107aa850fb1SJani Nikula }
108aa850fb1SJani Nikula
109aa850fb1SJani Nikula return ilk_get_aux_clock_divider(intel_dp, index);
110aa850fb1SJani Nikula }
111aa850fb1SJani Nikula
skl_get_aux_clock_divider(struct intel_dp * intel_dp,int index)112aa850fb1SJani Nikula static u32 skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
113aa850fb1SJani Nikula {
114aa850fb1SJani Nikula /*
115aa850fb1SJani Nikula * SKL doesn't need us to program the AUX clock divider (Hardware will
116aa850fb1SJani Nikula * derive the clock from CDCLK automatically). We still implement the
117aa850fb1SJani Nikula * get_aux_clock_divider vfunc to plug-in into the existing code.
118aa850fb1SJani Nikula */
119aa850fb1SJani Nikula return index ? 0 : 1;
120aa850fb1SJani Nikula }
121aa850fb1SJani Nikula
intel_dp_aux_sync_len(void)12226bfc3f3SVille Syrjälä static int intel_dp_aux_sync_len(void)
12326bfc3f3SVille Syrjälä {
12426bfc3f3SVille Syrjälä int precharge = 16; /* 10-16 */
12526bfc3f3SVille Syrjälä int preamble = 16;
12626bfc3f3SVille Syrjälä
12726bfc3f3SVille Syrjälä return precharge + preamble;
12826bfc3f3SVille Syrjälä }
12926bfc3f3SVille Syrjälä
intel_dp_aux_fw_sync_len(void)13026bfc3f3SVille Syrjälä static int intel_dp_aux_fw_sync_len(void)
13126bfc3f3SVille Syrjälä {
132b29a20f7SJouni Högander int precharge = 10; /* 10-16 */
13326bfc3f3SVille Syrjälä int preamble = 8;
13426bfc3f3SVille Syrjälä
13526bfc3f3SVille Syrjälä return precharge + preamble;
13626bfc3f3SVille Syrjälä }
13726bfc3f3SVille Syrjälä
g4x_dp_aux_precharge_len(void)13826bfc3f3SVille Syrjälä static int g4x_dp_aux_precharge_len(void)
13926bfc3f3SVille Syrjälä {
14026bfc3f3SVille Syrjälä int precharge_min = 10;
14126bfc3f3SVille Syrjälä int preamble = 16;
14226bfc3f3SVille Syrjälä
14326bfc3f3SVille Syrjälä /* HW wants the length of the extra precharge in 2us units */
14426bfc3f3SVille Syrjälä return (intel_dp_aux_sync_len() -
14526bfc3f3SVille Syrjälä precharge_min - preamble) / 2;
14626bfc3f3SVille Syrjälä }
14726bfc3f3SVille Syrjälä
g4x_get_aux_send_ctl(struct intel_dp * intel_dp,int send_bytes,u32 aux_clock_divider)148aa850fb1SJani Nikula static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
149aa850fb1SJani Nikula int send_bytes,
150aa850fb1SJani Nikula u32 aux_clock_divider)
151aa850fb1SJani Nikula {
152aa850fb1SJani Nikula struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
153aa850fb1SJani Nikula struct drm_i915_private *dev_priv =
154aa850fb1SJani Nikula to_i915(dig_port->base.base.dev);
1558ec7d10aSVille Syrjälä u32 timeout;
156aa850fb1SJani Nikula
157984982f3SImre Deak /* Max timeout value on G4x-BDW: 1.6ms */
158aa850fb1SJani Nikula if (IS_BROADWELL(dev_priv))
159aa850fb1SJani Nikula timeout = DP_AUX_CH_CTL_TIME_OUT_600us;
160aa850fb1SJani Nikula else
161aa850fb1SJani Nikula timeout = DP_AUX_CH_CTL_TIME_OUT_400us;
162aa850fb1SJani Nikula
163aa850fb1SJani Nikula return DP_AUX_CH_CTL_SEND_BUSY |
164aa850fb1SJani Nikula DP_AUX_CH_CTL_DONE |
165aa850fb1SJani Nikula DP_AUX_CH_CTL_INTERRUPT |
166aa850fb1SJani Nikula DP_AUX_CH_CTL_TIME_OUT_ERROR |
167aa850fb1SJani Nikula timeout |
168aa850fb1SJani Nikula DP_AUX_CH_CTL_RECEIVE_ERROR |
1690cad796aSVille Syrjälä DP_AUX_CH_CTL_MESSAGE_SIZE(send_bytes) |
1700cad796aSVille Syrjälä DP_AUX_CH_CTL_PRECHARGE_2US(g4x_dp_aux_precharge_len()) |
1710cad796aSVille Syrjälä DP_AUX_CH_CTL_BIT_CLOCK_2X(aux_clock_divider);
172aa850fb1SJani Nikula }
173aa850fb1SJani Nikula
skl_get_aux_send_ctl(struct intel_dp * intel_dp,int send_bytes,u32 unused)174aa850fb1SJani Nikula static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
175aa850fb1SJani Nikula int send_bytes,
176aa850fb1SJani Nikula u32 unused)
177aa850fb1SJani Nikula {
178aa850fb1SJani Nikula struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
17940151be7SImre Deak struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
180aa850fb1SJani Nikula u32 ret;
181aa850fb1SJani Nikula
182984982f3SImre Deak /*
183984982f3SImre Deak * Max timeout values:
184984982f3SImre Deak * SKL-GLK: 1.6ms
185984982f3SImre Deak * ICL+: 4ms
186984982f3SImre Deak */
187aa850fb1SJani Nikula ret = DP_AUX_CH_CTL_SEND_BUSY |
188aa850fb1SJani Nikula DP_AUX_CH_CTL_DONE |
189aa850fb1SJani Nikula DP_AUX_CH_CTL_INTERRUPT |
190aa850fb1SJani Nikula DP_AUX_CH_CTL_TIME_OUT_ERROR |
191aa850fb1SJani Nikula DP_AUX_CH_CTL_TIME_OUT_MAX |
192aa850fb1SJani Nikula DP_AUX_CH_CTL_RECEIVE_ERROR |
1930cad796aSVille Syrjälä DP_AUX_CH_CTL_MESSAGE_SIZE(send_bytes) |
19426bfc3f3SVille Syrjälä DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(intel_dp_aux_fw_sync_len()) |
19526bfc3f3SVille Syrjälä DP_AUX_CH_CTL_SYNC_PULSE_SKL(intel_dp_aux_sync_len());
196aa850fb1SJani Nikula
19711a89708SImre Deak if (intel_tc_port_in_tbt_alt_mode(dig_port))
198aa850fb1SJani Nikula ret |= DP_AUX_CH_CTL_TBT_IO;
199aa850fb1SJani Nikula
20040151be7SImre Deak /*
20140151be7SImre Deak * Power request bit is already set during aux power well enable.
20240151be7SImre Deak * Preserve the bit across aux transactions.
20340151be7SImre Deak */
20440151be7SImre Deak if (DISPLAY_VER(i915) >= 14)
20540151be7SImre Deak ret |= XELPDP_DP_AUX_CH_CTL_POWER_REQUEST;
20640151be7SImre Deak
207aa850fb1SJani Nikula return ret;
208aa850fb1SJani Nikula }
209aa850fb1SJani Nikula
210aa850fb1SJani Nikula static int
intel_dp_aux_xfer(struct intel_dp * intel_dp,const u8 * send,int send_bytes,u8 * recv,int recv_size,u32 aux_send_ctl_flags)211aa850fb1SJani Nikula intel_dp_aux_xfer(struct intel_dp *intel_dp,
212aa850fb1SJani Nikula const u8 *send, int send_bytes,
213aa850fb1SJani Nikula u8 *recv, int recv_size,
214aa850fb1SJani Nikula u32 aux_send_ctl_flags)
215aa850fb1SJani Nikula {
216aa850fb1SJani Nikula struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
217aa850fb1SJani Nikula struct drm_i915_private *i915 =
218aa850fb1SJani Nikula to_i915(dig_port->base.base.dev);
219aa850fb1SJani Nikula enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
220aa850fb1SJani Nikula bool is_tc_port = intel_phy_is_tc(i915, phy);
221aa850fb1SJani Nikula i915_reg_t ch_ctl, ch_data[5];
222aa850fb1SJani Nikula u32 aux_clock_divider;
223aa850fb1SJani Nikula enum intel_display_power_domain aux_domain;
224aa850fb1SJani Nikula intel_wakeref_t aux_wakeref;
225aa850fb1SJani Nikula intel_wakeref_t pps_wakeref;
226aa850fb1SJani Nikula int i, ret, recv_bytes;
227aa850fb1SJani Nikula int try, clock = 0;
228aa850fb1SJani Nikula u32 status;
229aa850fb1SJani Nikula bool vdd;
230aa850fb1SJani Nikula
231aa850fb1SJani Nikula ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
232aa850fb1SJani Nikula for (i = 0; i < ARRAY_SIZE(ch_data); i++)
233aa850fb1SJani Nikula ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i);
234aa850fb1SJani Nikula
235a972cd3fSImre Deak if (is_tc_port) {
236aa850fb1SJani Nikula intel_tc_port_lock(dig_port);
237a972cd3fSImre Deak /*
238a972cd3fSImre Deak * Abort transfers on a disconnected port as required by
239a972cd3fSImre Deak * DP 1.4a link CTS 4.2.1.5, also avoiding the long AUX
240a972cd3fSImre Deak * timeouts that would otherwise happen.
241a972cd3fSImre Deak * TODO: abort the transfer on non-TC ports as well.
242a972cd3fSImre Deak */
243a972cd3fSImre Deak if (!intel_tc_port_connected_locked(&dig_port->base)) {
244a972cd3fSImre Deak ret = -ENXIO;
245a972cd3fSImre Deak goto out_unlock;
246a972cd3fSImre Deak }
247a972cd3fSImre Deak }
248aa850fb1SJani Nikula
249aa850fb1SJani Nikula aux_domain = intel_aux_power_domain(dig_port);
250aa850fb1SJani Nikula
251aa850fb1SJani Nikula aux_wakeref = intel_display_power_get(i915, aux_domain);
252aa850fb1SJani Nikula pps_wakeref = intel_pps_lock(intel_dp);
253aa850fb1SJani Nikula
254aa850fb1SJani Nikula /*
255aa850fb1SJani Nikula * We will be called with VDD already enabled for dpcd/edid/oui reads.
256aa850fb1SJani Nikula * In such cases we want to leave VDD enabled and it's up to upper layers
257aa850fb1SJani Nikula * to turn it off. But for eg. i2c-dev access we need to turn it on/off
258aa850fb1SJani Nikula * ourselves.
259aa850fb1SJani Nikula */
260aa850fb1SJani Nikula vdd = intel_pps_vdd_on_unlocked(intel_dp);
261aa850fb1SJani Nikula
262aa850fb1SJani Nikula /*
263aa850fb1SJani Nikula * dp aux is extremely sensitive to irq latency, hence request the
264aa850fb1SJani Nikula * lowest possible wakeup latency and so prevent the cpu from going into
265aa850fb1SJani Nikula * deep sleep states.
266aa850fb1SJani Nikula */
267aa850fb1SJani Nikula cpu_latency_qos_update_request(&intel_dp->pm_qos, 0);
268aa850fb1SJani Nikula
269aa850fb1SJani Nikula intel_pps_check_power_unlocked(intel_dp);
270aa850fb1SJani Nikula
271da57e3d6SVille Syrjälä /*
272da57e3d6SVille Syrjälä * FIXME PSR should be disabled here to prevent
273da57e3d6SVille Syrjälä * it using the same AUX CH simultaneously
274da57e3d6SVille Syrjälä */
275da57e3d6SVille Syrjälä
276aa850fb1SJani Nikula /* Try to wait for any previous AUX channel activity */
277aa850fb1SJani Nikula for (try = 0; try < 3; try++) {
278ec2593e3SJani Nikula status = intel_de_read_notrace(i915, ch_ctl);
279aa850fb1SJani Nikula if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
280aa850fb1SJani Nikula break;
281aa850fb1SJani Nikula msleep(1);
282aa850fb1SJani Nikula }
283aa850fb1SJani Nikula /* just trace the final value */
284aa850fb1SJani Nikula trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true);
285aa850fb1SJani Nikula
286aa850fb1SJani Nikula if (try == 3) {
287ec2593e3SJani Nikula const u32 status = intel_de_read(i915, ch_ctl);
288aa850fb1SJani Nikula
289aa850fb1SJani Nikula if (status != intel_dp->aux_busy_last_status) {
290aa850fb1SJani Nikula drm_WARN(&i915->drm, 1,
291aa850fb1SJani Nikula "%s: not started (status 0x%08x)\n",
292aa850fb1SJani Nikula intel_dp->aux.name, status);
293aa850fb1SJani Nikula intel_dp->aux_busy_last_status = status;
294aa850fb1SJani Nikula }
295aa850fb1SJani Nikula
296aa850fb1SJani Nikula ret = -EBUSY;
297aa850fb1SJani Nikula goto out;
298aa850fb1SJani Nikula }
299aa850fb1SJani Nikula
300aa850fb1SJani Nikula /* Only 5 data registers! */
301aa850fb1SJani Nikula if (drm_WARN_ON(&i915->drm, send_bytes > 20 || recv_size > 20)) {
302aa850fb1SJani Nikula ret = -E2BIG;
303aa850fb1SJani Nikula goto out;
304aa850fb1SJani Nikula }
305aa850fb1SJani Nikula
306aa850fb1SJani Nikula while ((aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, clock++))) {
307aa850fb1SJani Nikula u32 send_ctl = intel_dp->get_aux_send_ctl(intel_dp,
308aa850fb1SJani Nikula send_bytes,
309aa850fb1SJani Nikula aux_clock_divider);
310aa850fb1SJani Nikula
311aa850fb1SJani Nikula send_ctl |= aux_send_ctl_flags;
312aa850fb1SJani Nikula
313aa850fb1SJani Nikula /* Must try at least 3 times according to DP spec */
314aa850fb1SJani Nikula for (try = 0; try < 5; try++) {
315aa850fb1SJani Nikula /* Load the send data into the aux channel data registers */
316aa850fb1SJani Nikula for (i = 0; i < send_bytes; i += 4)
317ec2593e3SJani Nikula intel_de_write(i915, ch_data[i >> 2],
3182616be2eSJani Nikula intel_dp_aux_pack(send + i,
319aa850fb1SJani Nikula send_bytes - i));
320aa850fb1SJani Nikula
321aa850fb1SJani Nikula /* Send the command and wait for it to complete */
322ec2593e3SJani Nikula intel_de_write(i915, ch_ctl, send_ctl);
323aa850fb1SJani Nikula
324aa850fb1SJani Nikula status = intel_dp_aux_wait_done(intel_dp);
325aa850fb1SJani Nikula
326aa850fb1SJani Nikula /* Clear done status and any errors */
327ec2593e3SJani Nikula intel_de_write(i915, ch_ctl,
328ec2593e3SJani Nikula status | DP_AUX_CH_CTL_DONE |
329aa850fb1SJani Nikula DP_AUX_CH_CTL_TIME_OUT_ERROR |
330aa850fb1SJani Nikula DP_AUX_CH_CTL_RECEIVE_ERROR);
331aa850fb1SJani Nikula
332aa850fb1SJani Nikula /*
333aa850fb1SJani Nikula * DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2
334aa850fb1SJani Nikula * 400us delay required for errors and timeouts
335aa850fb1SJani Nikula * Timeout errors from the HW already meet this
336aa850fb1SJani Nikula * requirement so skip to next iteration
337aa850fb1SJani Nikula */
338aa850fb1SJani Nikula if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR)
339aa850fb1SJani Nikula continue;
340aa850fb1SJani Nikula
341aa850fb1SJani Nikula if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
342aa850fb1SJani Nikula usleep_range(400, 500);
343aa850fb1SJani Nikula continue;
344aa850fb1SJani Nikula }
345aa850fb1SJani Nikula if (status & DP_AUX_CH_CTL_DONE)
346aa850fb1SJani Nikula goto done;
347aa850fb1SJani Nikula }
348aa850fb1SJani Nikula }
349aa850fb1SJani Nikula
350aa850fb1SJani Nikula if ((status & DP_AUX_CH_CTL_DONE) == 0) {
351aa850fb1SJani Nikula drm_err(&i915->drm, "%s: not done (status 0x%08x)\n",
352aa850fb1SJani Nikula intel_dp->aux.name, status);
353aa850fb1SJani Nikula ret = -EBUSY;
354aa850fb1SJani Nikula goto out;
355aa850fb1SJani Nikula }
356aa850fb1SJani Nikula
357aa850fb1SJani Nikula done:
358aa850fb1SJani Nikula /*
359aa850fb1SJani Nikula * Check for timeout or receive error. Timeouts occur when the sink is
360aa850fb1SJani Nikula * not connected.
361aa850fb1SJani Nikula */
362aa850fb1SJani Nikula if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
363aa850fb1SJani Nikula drm_err(&i915->drm, "%s: receive error (status 0x%08x)\n",
364aa850fb1SJani Nikula intel_dp->aux.name, status);
365aa850fb1SJani Nikula ret = -EIO;
366aa850fb1SJani Nikula goto out;
367aa850fb1SJani Nikula }
368aa850fb1SJani Nikula
369aa850fb1SJani Nikula /*
370aa850fb1SJani Nikula * Timeouts occur when the device isn't connected, so they're "normal"
371aa850fb1SJani Nikula * -- don't fill the kernel log with these
372aa850fb1SJani Nikula */
373aa850fb1SJani Nikula if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
374aa850fb1SJani Nikula drm_dbg_kms(&i915->drm, "%s: timeout (status 0x%08x)\n",
375aa850fb1SJani Nikula intel_dp->aux.name, status);
376aa850fb1SJani Nikula ret = -ETIMEDOUT;
377aa850fb1SJani Nikula goto out;
378aa850fb1SJani Nikula }
379aa850fb1SJani Nikula
380aa850fb1SJani Nikula /* Unload any bytes sent back from the other side */
3810cad796aSVille Syrjälä recv_bytes = REG_FIELD_GET(DP_AUX_CH_CTL_MESSAGE_SIZE_MASK, status);
382aa850fb1SJani Nikula
383aa850fb1SJani Nikula /*
384aa850fb1SJani Nikula * By BSpec: "Message sizes of 0 or >20 are not allowed."
385aa850fb1SJani Nikula * We have no idea of what happened so we return -EBUSY so
386aa850fb1SJani Nikula * drm layer takes care for the necessary retries.
387aa850fb1SJani Nikula */
388aa850fb1SJani Nikula if (recv_bytes == 0 || recv_bytes > 20) {
389aa850fb1SJani Nikula drm_dbg_kms(&i915->drm,
390aa850fb1SJani Nikula "%s: Forbidden recv_bytes = %d on aux transaction\n",
391aa850fb1SJani Nikula intel_dp->aux.name, recv_bytes);
392aa850fb1SJani Nikula ret = -EBUSY;
393aa850fb1SJani Nikula goto out;
394aa850fb1SJani Nikula }
395aa850fb1SJani Nikula
396aa850fb1SJani Nikula if (recv_bytes > recv_size)
397aa850fb1SJani Nikula recv_bytes = recv_size;
398aa850fb1SJani Nikula
399aa850fb1SJani Nikula for (i = 0; i < recv_bytes; i += 4)
400ec2593e3SJani Nikula intel_dp_aux_unpack(intel_de_read(i915, ch_data[i >> 2]),
401aa850fb1SJani Nikula recv + i, recv_bytes - i);
402aa850fb1SJani Nikula
403aa850fb1SJani Nikula ret = recv_bytes;
404aa850fb1SJani Nikula out:
405aa850fb1SJani Nikula cpu_latency_qos_update_request(&intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE);
406aa850fb1SJani Nikula
407aa850fb1SJani Nikula if (vdd)
408aa850fb1SJani Nikula intel_pps_vdd_off_unlocked(intel_dp, false);
409aa850fb1SJani Nikula
410aa850fb1SJani Nikula intel_pps_unlock(intel_dp, pps_wakeref);
411aa850fb1SJani Nikula intel_display_power_put_async(i915, aux_domain, aux_wakeref);
412a972cd3fSImre Deak out_unlock:
413aa850fb1SJani Nikula if (is_tc_port)
414aa850fb1SJani Nikula intel_tc_port_unlock(dig_port);
415aa850fb1SJani Nikula
416aa850fb1SJani Nikula return ret;
417aa850fb1SJani Nikula }
418aa850fb1SJani Nikula
419aa850fb1SJani Nikula #define BARE_ADDRESS_SIZE 3
420aa850fb1SJani Nikula #define HEADER_SIZE (BARE_ADDRESS_SIZE + 1)
421aa850fb1SJani Nikula
422aa850fb1SJani Nikula static void
intel_dp_aux_header(u8 txbuf[HEADER_SIZE],const struct drm_dp_aux_msg * msg)423aa850fb1SJani Nikula intel_dp_aux_header(u8 txbuf[HEADER_SIZE],
424aa850fb1SJani Nikula const struct drm_dp_aux_msg *msg)
425aa850fb1SJani Nikula {
426aa850fb1SJani Nikula txbuf[0] = (msg->request << 4) | ((msg->address >> 16) & 0xf);
427aa850fb1SJani Nikula txbuf[1] = (msg->address >> 8) & 0xff;
428aa850fb1SJani Nikula txbuf[2] = msg->address & 0xff;
429aa850fb1SJani Nikula txbuf[3] = msg->size - 1;
430aa850fb1SJani Nikula }
431aa850fb1SJani Nikula
intel_dp_aux_xfer_flags(const struct drm_dp_aux_msg * msg)432aa850fb1SJani Nikula static u32 intel_dp_aux_xfer_flags(const struct drm_dp_aux_msg *msg)
433aa850fb1SJani Nikula {
434aa850fb1SJani Nikula /*
435aa850fb1SJani Nikula * If we're trying to send the HDCP Aksv, we need to set a the Aksv
436aa850fb1SJani Nikula * select bit to inform the hardware to send the Aksv after our header
437aa850fb1SJani Nikula * since we can't access that data from software.
438aa850fb1SJani Nikula */
439aa850fb1SJani Nikula if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_WRITE &&
440aa850fb1SJani Nikula msg->address == DP_AUX_HDCP_AKSV)
441aa850fb1SJani Nikula return DP_AUX_CH_CTL_AUX_AKSV_SELECT;
442aa850fb1SJani Nikula
443aa850fb1SJani Nikula return 0;
444aa850fb1SJani Nikula }
445aa850fb1SJani Nikula
446aa850fb1SJani Nikula static ssize_t
intel_dp_aux_transfer(struct drm_dp_aux * aux,struct drm_dp_aux_msg * msg)447aa850fb1SJani Nikula intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
448aa850fb1SJani Nikula {
449aa850fb1SJani Nikula struct intel_dp *intel_dp = container_of(aux, struct intel_dp, aux);
450aa850fb1SJani Nikula struct drm_i915_private *i915 = dp_to_i915(intel_dp);
451aa850fb1SJani Nikula u8 txbuf[20], rxbuf[20];
452aa850fb1SJani Nikula size_t txsize, rxsize;
453aa850fb1SJani Nikula u32 flags = intel_dp_aux_xfer_flags(msg);
454aa850fb1SJani Nikula int ret;
455aa850fb1SJani Nikula
456aa850fb1SJani Nikula intel_dp_aux_header(txbuf, msg);
457aa850fb1SJani Nikula
458aa850fb1SJani Nikula switch (msg->request & ~DP_AUX_I2C_MOT) {
459aa850fb1SJani Nikula case DP_AUX_NATIVE_WRITE:
460aa850fb1SJani Nikula case DP_AUX_I2C_WRITE:
461aa850fb1SJani Nikula case DP_AUX_I2C_WRITE_STATUS_UPDATE:
462aa850fb1SJani Nikula txsize = msg->size ? HEADER_SIZE + msg->size : BARE_ADDRESS_SIZE;
463aa850fb1SJani Nikula rxsize = 2; /* 0 or 1 data bytes */
464aa850fb1SJani Nikula
465aa850fb1SJani Nikula if (drm_WARN_ON(&i915->drm, txsize > 20))
466aa850fb1SJani Nikula return -E2BIG;
467aa850fb1SJani Nikula
468aa850fb1SJani Nikula drm_WARN_ON(&i915->drm, !msg->buffer != !msg->size);
469aa850fb1SJani Nikula
470aa850fb1SJani Nikula if (msg->buffer)
471aa850fb1SJani Nikula memcpy(txbuf + HEADER_SIZE, msg->buffer, msg->size);
472aa850fb1SJani Nikula
473aa850fb1SJani Nikula ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize,
474aa850fb1SJani Nikula rxbuf, rxsize, flags);
475aa850fb1SJani Nikula if (ret > 0) {
476aa850fb1SJani Nikula msg->reply = rxbuf[0] >> 4;
477aa850fb1SJani Nikula
478aa850fb1SJani Nikula if (ret > 1) {
479aa850fb1SJani Nikula /* Number of bytes written in a short write. */
480aa850fb1SJani Nikula ret = clamp_t(int, rxbuf[1], 0, msg->size);
481aa850fb1SJani Nikula } else {
482aa850fb1SJani Nikula /* Return payload size. */
483aa850fb1SJani Nikula ret = msg->size;
484aa850fb1SJani Nikula }
485aa850fb1SJani Nikula }
486aa850fb1SJani Nikula break;
487aa850fb1SJani Nikula
488aa850fb1SJani Nikula case DP_AUX_NATIVE_READ:
489aa850fb1SJani Nikula case DP_AUX_I2C_READ:
490aa850fb1SJani Nikula txsize = msg->size ? HEADER_SIZE : BARE_ADDRESS_SIZE;
491aa850fb1SJani Nikula rxsize = msg->size + 1;
492aa850fb1SJani Nikula
493aa850fb1SJani Nikula if (drm_WARN_ON(&i915->drm, rxsize > 20))
494aa850fb1SJani Nikula return -E2BIG;
495aa850fb1SJani Nikula
496aa850fb1SJani Nikula ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize,
497aa850fb1SJani Nikula rxbuf, rxsize, flags);
498aa850fb1SJani Nikula if (ret > 0) {
499aa850fb1SJani Nikula msg->reply = rxbuf[0] >> 4;
500aa850fb1SJani Nikula /*
501aa850fb1SJani Nikula * Assume happy day, and copy the data. The caller is
502aa850fb1SJani Nikula * expected to check msg->reply before touching it.
503aa850fb1SJani Nikula *
504aa850fb1SJani Nikula * Return payload size.
505aa850fb1SJani Nikula */
506aa850fb1SJani Nikula ret--;
507aa850fb1SJani Nikula memcpy(msg->buffer, rxbuf + 1, ret);
508aa850fb1SJani Nikula }
509aa850fb1SJani Nikula break;
510aa850fb1SJani Nikula
511aa850fb1SJani Nikula default:
512aa850fb1SJani Nikula ret = -EINVAL;
513aa850fb1SJani Nikula break;
514aa850fb1SJani Nikula }
515aa850fb1SJani Nikula
516aa850fb1SJani Nikula return ret;
517aa850fb1SJani Nikula }
518aa850fb1SJani Nikula
g4x_aux_ctl_reg(struct intel_dp * intel_dp)519aa850fb1SJani Nikula static i915_reg_t g4x_aux_ctl_reg(struct intel_dp *intel_dp)
520aa850fb1SJani Nikula {
521aa850fb1SJani Nikula struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
522aa850fb1SJani Nikula struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
523aa850fb1SJani Nikula enum aux_ch aux_ch = dig_port->aux_ch;
524aa850fb1SJani Nikula
525aa850fb1SJani Nikula switch (aux_ch) {
526aa850fb1SJani Nikula case AUX_CH_B:
527aa850fb1SJani Nikula case AUX_CH_C:
528aa850fb1SJani Nikula case AUX_CH_D:
529aa850fb1SJani Nikula return DP_AUX_CH_CTL(aux_ch);
530aa850fb1SJani Nikula default:
531aa850fb1SJani Nikula MISSING_CASE(aux_ch);
532aa850fb1SJani Nikula return DP_AUX_CH_CTL(AUX_CH_B);
533aa850fb1SJani Nikula }
534aa850fb1SJani Nikula }
535aa850fb1SJani Nikula
g4x_aux_data_reg(struct intel_dp * intel_dp,int index)536aa850fb1SJani Nikula static i915_reg_t g4x_aux_data_reg(struct intel_dp *intel_dp, int index)
537aa850fb1SJani Nikula {
538aa850fb1SJani Nikula struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
539aa850fb1SJani Nikula struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
540aa850fb1SJani Nikula enum aux_ch aux_ch = dig_port->aux_ch;
541aa850fb1SJani Nikula
542aa850fb1SJani Nikula switch (aux_ch) {
543aa850fb1SJani Nikula case AUX_CH_B:
544aa850fb1SJani Nikula case AUX_CH_C:
545aa850fb1SJani Nikula case AUX_CH_D:
546aa850fb1SJani Nikula return DP_AUX_CH_DATA(aux_ch, index);
547aa850fb1SJani Nikula default:
548aa850fb1SJani Nikula MISSING_CASE(aux_ch);
549aa850fb1SJani Nikula return DP_AUX_CH_DATA(AUX_CH_B, index);
550aa850fb1SJani Nikula }
551aa850fb1SJani Nikula }
552aa850fb1SJani Nikula
ilk_aux_ctl_reg(struct intel_dp * intel_dp)553aa850fb1SJani Nikula static i915_reg_t ilk_aux_ctl_reg(struct intel_dp *intel_dp)
554aa850fb1SJani Nikula {
555aa850fb1SJani Nikula struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
556aa850fb1SJani Nikula struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
557aa850fb1SJani Nikula enum aux_ch aux_ch = dig_port->aux_ch;
558aa850fb1SJani Nikula
559aa850fb1SJani Nikula switch (aux_ch) {
560aa850fb1SJani Nikula case AUX_CH_A:
561aa850fb1SJani Nikula return DP_AUX_CH_CTL(aux_ch);
562aa850fb1SJani Nikula case AUX_CH_B:
563aa850fb1SJani Nikula case AUX_CH_C:
564aa850fb1SJani Nikula case AUX_CH_D:
565aa850fb1SJani Nikula return PCH_DP_AUX_CH_CTL(aux_ch);
566aa850fb1SJani Nikula default:
567aa850fb1SJani Nikula MISSING_CASE(aux_ch);
568aa850fb1SJani Nikula return DP_AUX_CH_CTL(AUX_CH_A);
569aa850fb1SJani Nikula }
570aa850fb1SJani Nikula }
571aa850fb1SJani Nikula
ilk_aux_data_reg(struct intel_dp * intel_dp,int index)572aa850fb1SJani Nikula static i915_reg_t ilk_aux_data_reg(struct intel_dp *intel_dp, int index)
573aa850fb1SJani Nikula {
574aa850fb1SJani Nikula struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
575aa850fb1SJani Nikula struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
576aa850fb1SJani Nikula enum aux_ch aux_ch = dig_port->aux_ch;
577aa850fb1SJani Nikula
578aa850fb1SJani Nikula switch (aux_ch) {
579aa850fb1SJani Nikula case AUX_CH_A:
580aa850fb1SJani Nikula return DP_AUX_CH_DATA(aux_ch, index);
581aa850fb1SJani Nikula case AUX_CH_B:
582aa850fb1SJani Nikula case AUX_CH_C:
583aa850fb1SJani Nikula case AUX_CH_D:
584aa850fb1SJani Nikula return PCH_DP_AUX_CH_DATA(aux_ch, index);
585aa850fb1SJani Nikula default:
586aa850fb1SJani Nikula MISSING_CASE(aux_ch);
587aa850fb1SJani Nikula return DP_AUX_CH_DATA(AUX_CH_A, index);
588aa850fb1SJani Nikula }
589aa850fb1SJani Nikula }
590aa850fb1SJani Nikula
skl_aux_ctl_reg(struct intel_dp * intel_dp)591aa850fb1SJani Nikula static i915_reg_t skl_aux_ctl_reg(struct intel_dp *intel_dp)
592aa850fb1SJani Nikula {
593aa850fb1SJani Nikula struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
594aa850fb1SJani Nikula struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
595aa850fb1SJani Nikula enum aux_ch aux_ch = dig_port->aux_ch;
596aa850fb1SJani Nikula
597aa850fb1SJani Nikula switch (aux_ch) {
598aa850fb1SJani Nikula case AUX_CH_A:
599aa850fb1SJani Nikula case AUX_CH_B:
600aa850fb1SJani Nikula case AUX_CH_C:
601aa850fb1SJani Nikula case AUX_CH_D:
602aa850fb1SJani Nikula case AUX_CH_E:
603aa850fb1SJani Nikula case AUX_CH_F:
604aa850fb1SJani Nikula return DP_AUX_CH_CTL(aux_ch);
605aa850fb1SJani Nikula default:
606aa850fb1SJani Nikula MISSING_CASE(aux_ch);
607aa850fb1SJani Nikula return DP_AUX_CH_CTL(AUX_CH_A);
608aa850fb1SJani Nikula }
609aa850fb1SJani Nikula }
610aa850fb1SJani Nikula
skl_aux_data_reg(struct intel_dp * intel_dp,int index)611aa850fb1SJani Nikula static i915_reg_t skl_aux_data_reg(struct intel_dp *intel_dp, int index)
612aa850fb1SJani Nikula {
613aa850fb1SJani Nikula struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
614aa850fb1SJani Nikula struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
615aa850fb1SJani Nikula enum aux_ch aux_ch = dig_port->aux_ch;
616aa850fb1SJani Nikula
617aa850fb1SJani Nikula switch (aux_ch) {
618aa850fb1SJani Nikula case AUX_CH_A:
619aa850fb1SJani Nikula case AUX_CH_B:
620aa850fb1SJani Nikula case AUX_CH_C:
621aa850fb1SJani Nikula case AUX_CH_D:
622aa850fb1SJani Nikula case AUX_CH_E:
623aa850fb1SJani Nikula case AUX_CH_F:
624aa850fb1SJani Nikula return DP_AUX_CH_DATA(aux_ch, index);
625aa850fb1SJani Nikula default:
626aa850fb1SJani Nikula MISSING_CASE(aux_ch);
627aa850fb1SJani Nikula return DP_AUX_CH_DATA(AUX_CH_A, index);
628aa850fb1SJani Nikula }
629aa850fb1SJani Nikula }
630aa850fb1SJani Nikula
tgl_aux_ctl_reg(struct intel_dp * intel_dp)631aa850fb1SJani Nikula static i915_reg_t tgl_aux_ctl_reg(struct intel_dp *intel_dp)
632aa850fb1SJani Nikula {
633aa850fb1SJani Nikula struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
634aa850fb1SJani Nikula struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
635aa850fb1SJani Nikula enum aux_ch aux_ch = dig_port->aux_ch;
636aa850fb1SJani Nikula
637aa850fb1SJani Nikula switch (aux_ch) {
638aa850fb1SJani Nikula case AUX_CH_A:
639aa850fb1SJani Nikula case AUX_CH_B:
640aa850fb1SJani Nikula case AUX_CH_C:
641aa850fb1SJani Nikula case AUX_CH_USBC1:
642aa850fb1SJani Nikula case AUX_CH_USBC2:
643aa850fb1SJani Nikula case AUX_CH_USBC3:
644aa850fb1SJani Nikula case AUX_CH_USBC4:
645ed2615a8SMatt Roper case AUX_CH_USBC5: /* aka AUX_CH_D_XELPD */
646ed2615a8SMatt Roper case AUX_CH_USBC6: /* aka AUX_CH_E_XELPD */
647aa850fb1SJani Nikula return DP_AUX_CH_CTL(aux_ch);
648aa850fb1SJani Nikula default:
649aa850fb1SJani Nikula MISSING_CASE(aux_ch);
650aa850fb1SJani Nikula return DP_AUX_CH_CTL(AUX_CH_A);
651aa850fb1SJani Nikula }
652aa850fb1SJani Nikula }
653aa850fb1SJani Nikula
tgl_aux_data_reg(struct intel_dp * intel_dp,int index)654aa850fb1SJani Nikula static i915_reg_t tgl_aux_data_reg(struct intel_dp *intel_dp, int index)
655aa850fb1SJani Nikula {
656aa850fb1SJani Nikula struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
657aa850fb1SJani Nikula struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
658aa850fb1SJani Nikula enum aux_ch aux_ch = dig_port->aux_ch;
659aa850fb1SJani Nikula
660aa850fb1SJani Nikula switch (aux_ch) {
661aa850fb1SJani Nikula case AUX_CH_A:
662aa850fb1SJani Nikula case AUX_CH_B:
663aa850fb1SJani Nikula case AUX_CH_C:
664aa850fb1SJani Nikula case AUX_CH_USBC1:
665aa850fb1SJani Nikula case AUX_CH_USBC2:
666aa850fb1SJani Nikula case AUX_CH_USBC3:
667aa850fb1SJani Nikula case AUX_CH_USBC4:
668ed2615a8SMatt Roper case AUX_CH_USBC5: /* aka AUX_CH_D_XELPD */
669ed2615a8SMatt Roper case AUX_CH_USBC6: /* aka AUX_CH_E_XELPD */
670aa850fb1SJani Nikula return DP_AUX_CH_DATA(aux_ch, index);
671aa850fb1SJani Nikula default:
672aa850fb1SJani Nikula MISSING_CASE(aux_ch);
673aa850fb1SJani Nikula return DP_AUX_CH_DATA(AUX_CH_A, index);
674aa850fb1SJani Nikula }
675aa850fb1SJani Nikula }
676aa850fb1SJani Nikula
xelpdp_aux_ctl_reg(struct intel_dp * intel_dp)67785d53200SImre Deak static i915_reg_t xelpdp_aux_ctl_reg(struct intel_dp *intel_dp)
67885d53200SImre Deak {
67985d53200SImre Deak struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
68085d53200SImre Deak struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
68185d53200SImre Deak enum aux_ch aux_ch = dig_port->aux_ch;
68285d53200SImre Deak
68385d53200SImre Deak switch (aux_ch) {
68485d53200SImre Deak case AUX_CH_A:
68585d53200SImre Deak case AUX_CH_B:
68685d53200SImre Deak case AUX_CH_USBC1:
68785d53200SImre Deak case AUX_CH_USBC2:
68885d53200SImre Deak case AUX_CH_USBC3:
68985d53200SImre Deak case AUX_CH_USBC4:
69085d53200SImre Deak return XELPDP_DP_AUX_CH_CTL(aux_ch);
69185d53200SImre Deak default:
69285d53200SImre Deak MISSING_CASE(aux_ch);
69385d53200SImre Deak return XELPDP_DP_AUX_CH_CTL(AUX_CH_A);
69485d53200SImre Deak }
69585d53200SImre Deak }
69685d53200SImre Deak
xelpdp_aux_data_reg(struct intel_dp * intel_dp,int index)69785d53200SImre Deak static i915_reg_t xelpdp_aux_data_reg(struct intel_dp *intel_dp, int index)
69885d53200SImre Deak {
69985d53200SImre Deak struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
70085d53200SImre Deak struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
70185d53200SImre Deak enum aux_ch aux_ch = dig_port->aux_ch;
70285d53200SImre Deak
70385d53200SImre Deak switch (aux_ch) {
70485d53200SImre Deak case AUX_CH_A:
70585d53200SImre Deak case AUX_CH_B:
70685d53200SImre Deak case AUX_CH_USBC1:
70785d53200SImre Deak case AUX_CH_USBC2:
70885d53200SImre Deak case AUX_CH_USBC3:
70985d53200SImre Deak case AUX_CH_USBC4:
71085d53200SImre Deak return XELPDP_DP_AUX_CH_DATA(aux_ch, index);
71185d53200SImre Deak default:
71285d53200SImre Deak MISSING_CASE(aux_ch);
71385d53200SImre Deak return XELPDP_DP_AUX_CH_DATA(AUX_CH_A, index);
71485d53200SImre Deak }
71585d53200SImre Deak }
71685d53200SImre Deak
intel_dp_aux_fini(struct intel_dp * intel_dp)717aa850fb1SJani Nikula void intel_dp_aux_fini(struct intel_dp *intel_dp)
718aa850fb1SJani Nikula {
719aa850fb1SJani Nikula if (cpu_latency_qos_request_active(&intel_dp->pm_qos))
720aa850fb1SJani Nikula cpu_latency_qos_remove_request(&intel_dp->pm_qos);
721aa850fb1SJani Nikula
722aa850fb1SJani Nikula kfree(intel_dp->aux.name);
723aa850fb1SJani Nikula }
724aa850fb1SJani Nikula
intel_dp_aux_init(struct intel_dp * intel_dp)725aa850fb1SJani Nikula void intel_dp_aux_init(struct intel_dp *intel_dp)
726aa850fb1SJani Nikula {
727aa850fb1SJani Nikula struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
728aa850fb1SJani Nikula struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
729aa850fb1SJani Nikula struct intel_encoder *encoder = &dig_port->base;
730aa850fb1SJani Nikula enum aux_ch aux_ch = dig_port->aux_ch;
731aa850fb1SJani Nikula
73285d53200SImre Deak if (DISPLAY_VER(dev_priv) >= 14) {
73385d53200SImre Deak intel_dp->aux_ch_ctl_reg = xelpdp_aux_ctl_reg;
73485d53200SImre Deak intel_dp->aux_ch_data_reg = xelpdp_aux_data_reg;
73585d53200SImre Deak } else if (DISPLAY_VER(dev_priv) >= 12) {
736aa850fb1SJani Nikula intel_dp->aux_ch_ctl_reg = tgl_aux_ctl_reg;
737aa850fb1SJani Nikula intel_dp->aux_ch_data_reg = tgl_aux_data_reg;
738005e9537SMatt Roper } else if (DISPLAY_VER(dev_priv) >= 9) {
739aa850fb1SJani Nikula intel_dp->aux_ch_ctl_reg = skl_aux_ctl_reg;
740aa850fb1SJani Nikula intel_dp->aux_ch_data_reg = skl_aux_data_reg;
741aa850fb1SJani Nikula } else if (HAS_PCH_SPLIT(dev_priv)) {
742aa850fb1SJani Nikula intel_dp->aux_ch_ctl_reg = ilk_aux_ctl_reg;
743aa850fb1SJani Nikula intel_dp->aux_ch_data_reg = ilk_aux_data_reg;
744aa850fb1SJani Nikula } else {
745aa850fb1SJani Nikula intel_dp->aux_ch_ctl_reg = g4x_aux_ctl_reg;
746aa850fb1SJani Nikula intel_dp->aux_ch_data_reg = g4x_aux_data_reg;
747aa850fb1SJani Nikula }
748aa850fb1SJani Nikula
749005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 9)
750aa850fb1SJani Nikula intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider;
751aa850fb1SJani Nikula else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
752aa850fb1SJani Nikula intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider;
753aa850fb1SJani Nikula else if (HAS_PCH_SPLIT(dev_priv))
754aa850fb1SJani Nikula intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider;
755aa850fb1SJani Nikula else
756aa850fb1SJani Nikula intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider;
757aa850fb1SJani Nikula
758005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 9)
759aa850fb1SJani Nikula intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl;
760aa850fb1SJani Nikula else
761aa850fb1SJani Nikula intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl;
762aa850fb1SJani Nikula
7636cba3fe4SLyude Paul intel_dp->aux.drm_dev = &dev_priv->drm;
764aa850fb1SJani Nikula drm_dp_aux_init(&intel_dp->aux);
765aa850fb1SJani Nikula
766aa850fb1SJani Nikula /* Failure to allocate our preferred name is not critical */
767ed2615a8SMatt Roper if (DISPLAY_VER(dev_priv) >= 13 && aux_ch >= AUX_CH_D_XELPD)
768ed2615a8SMatt Roper intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX %c/%s",
769ed2615a8SMatt Roper aux_ch_name(aux_ch - AUX_CH_D_XELPD + AUX_CH_D),
770ed2615a8SMatt Roper encoder->base.name);
771ed2615a8SMatt Roper else if (DISPLAY_VER(dev_priv) >= 12 && aux_ch >= AUX_CH_USBC1)
772aa850fb1SJani Nikula intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX USBC%c/%s",
773aa850fb1SJani Nikula aux_ch - AUX_CH_USBC1 + '1',
774aa850fb1SJani Nikula encoder->base.name);
775aa850fb1SJani Nikula else
776aa850fb1SJani Nikula intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX %c/%s",
777aa850fb1SJani Nikula aux_ch_name(aux_ch),
778aa850fb1SJani Nikula encoder->base.name);
779aa850fb1SJani Nikula
780aa850fb1SJani Nikula intel_dp->aux.transfer = intel_dp_aux_transfer;
781aa850fb1SJani Nikula cpu_latency_qos_add_request(&intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE);
782aa850fb1SJani Nikula }
783bb45217fSVille Syrjälä
default_aux_ch(struct intel_encoder * encoder)78401a789faSVille Syrjälä static enum aux_ch default_aux_ch(struct intel_encoder *encoder)
78501a789faSVille Syrjälä {
78601a789faSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
78701a789faSVille Syrjälä
78801a789faSVille Syrjälä /* SKL has DDI E but no AUX E */
78901a789faSVille Syrjälä if (DISPLAY_VER(i915) == 9 && encoder->port == PORT_E)
79001a789faSVille Syrjälä return AUX_CH_A;
79101a789faSVille Syrjälä
79201a789faSVille Syrjälä return (enum aux_ch)encoder->port;
79301a789faSVille Syrjälä }
79401a789faSVille Syrjälä
795*b8a13e87SVille Syrjälä static struct intel_encoder *
get_encoder_by_aux_ch(struct intel_encoder * encoder,enum aux_ch aux_ch)796*b8a13e87SVille Syrjälä get_encoder_by_aux_ch(struct intel_encoder *encoder,
797*b8a13e87SVille Syrjälä enum aux_ch aux_ch)
798*b8a13e87SVille Syrjälä {
799*b8a13e87SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
800*b8a13e87SVille Syrjälä struct intel_encoder *other;
801*b8a13e87SVille Syrjälä
802*b8a13e87SVille Syrjälä for_each_intel_encoder(&i915->drm, other) {
803*b8a13e87SVille Syrjälä if (other == encoder)
804*b8a13e87SVille Syrjälä continue;
805*b8a13e87SVille Syrjälä
806*b8a13e87SVille Syrjälä if (!intel_encoder_is_dig_port(other))
807*b8a13e87SVille Syrjälä continue;
808*b8a13e87SVille Syrjälä
809*b8a13e87SVille Syrjälä if (enc_to_dig_port(other)->aux_ch == aux_ch)
810*b8a13e87SVille Syrjälä return other;
811*b8a13e87SVille Syrjälä }
812*b8a13e87SVille Syrjälä
813*b8a13e87SVille Syrjälä return NULL;
814*b8a13e87SVille Syrjälä }
815*b8a13e87SVille Syrjälä
intel_dp_aux_ch(struct intel_encoder * encoder)816bb45217fSVille Syrjälä enum aux_ch intel_dp_aux_ch(struct intel_encoder *encoder)
817bb45217fSVille Syrjälä {
818bb45217fSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
819*b8a13e87SVille Syrjälä struct intel_encoder *other;
820*b8a13e87SVille Syrjälä const char *source;
821bb45217fSVille Syrjälä enum aux_ch aux_ch;
822bb45217fSVille Syrjälä
823bb45217fSVille Syrjälä aux_ch = intel_bios_dp_aux_ch(encoder->devdata);
824*b8a13e87SVille Syrjälä source = "VBT";
825*b8a13e87SVille Syrjälä
826*b8a13e87SVille Syrjälä if (aux_ch == AUX_CH_NONE) {
827*b8a13e87SVille Syrjälä aux_ch = default_aux_ch(encoder);
828*b8a13e87SVille Syrjälä source = "platform default";
829bb45217fSVille Syrjälä }
830bb45217fSVille Syrjälä
831*b8a13e87SVille Syrjälä if (aux_ch == AUX_CH_NONE)
832*b8a13e87SVille Syrjälä return AUX_CH_NONE;
833*b8a13e87SVille Syrjälä
834*b8a13e87SVille Syrjälä /* FIXME validate aux_ch against platform caps */
835*b8a13e87SVille Syrjälä
836*b8a13e87SVille Syrjälä other = get_encoder_by_aux_ch(encoder, aux_ch);
837*b8a13e87SVille Syrjälä if (other) {
838*b8a13e87SVille Syrjälä drm_dbg_kms(&i915->drm,
839*b8a13e87SVille Syrjälä "[ENCODER:%d:%s] AUX CH %c already claimed by [ENCODER:%d:%s]\n",
840*b8a13e87SVille Syrjälä encoder->base.base.id, encoder->base.name, aux_ch_name(aux_ch),
841*b8a13e87SVille Syrjälä other->base.base.id, other->base.name);
842*b8a13e87SVille Syrjälä return AUX_CH_NONE;
843*b8a13e87SVille Syrjälä }
844bb45217fSVille Syrjälä
845bb45217fSVille Syrjälä drm_dbg_kms(&i915->drm,
846*b8a13e87SVille Syrjälä "[ENCODER:%d:%s] Using AUX CH %c (%s)\n",
847fce187caSVille Syrjälä encoder->base.base.id, encoder->base.name,
848*b8a13e87SVille Syrjälä aux_ch_name(aux_ch), source);
849bb45217fSVille Syrjälä
850bb45217fSVille Syrjälä return aux_ch;
851bb45217fSVille Syrjälä }
852685282a3SJani Nikula
intel_dp_aux_irq_handler(struct drm_i915_private * i915)853685282a3SJani Nikula void intel_dp_aux_irq_handler(struct drm_i915_private *i915)
854685282a3SJani Nikula {
855685282a3SJani Nikula wake_up_all(&i915->display.gmbus.wait_queue);
856685282a3SJani Nikula }
857