1 | // SPDX-License-Identifier: MIT |
2 | /* |
3 | * Copyright © 2020-2021 Intel Corporation |
4 | */ |
5 | |
6 | #include "i915_drv.h" |
7 | #include "i915_reg.h" |
8 | #include "i915_trace.h" |
9 | #include "intel_bios.h" |
10 | #include "intel_de.h" |
11 | #include "intel_display_types.h" |
12 | #include "intel_dp.h" |
13 | #include "intel_dp_aux.h" |
14 | #include "intel_dp_aux_regs.h" |
15 | #include "intel_pps.h" |
16 | #include "intel_tc.h" |
17 | |
18 | #define AUX_CH_NAME_BUFSIZE 6 |
19 | |
20 | static const char *aux_ch_name(struct drm_i915_private *i915, |
21 | char *buf, int size, enum aux_ch aux_ch) |
22 | { |
23 | if (DISPLAY_VER(i915) >= 13 && aux_ch >= AUX_CH_D_XELPD) |
24 | snprintf(buf, size, fmt: "%c" , 'A' + aux_ch - AUX_CH_D_XELPD + AUX_CH_D); |
25 | else if (DISPLAY_VER(i915) >= 12 && aux_ch >= AUX_CH_USBC1) |
26 | snprintf(buf, size, fmt: "USBC%c" , '1' + aux_ch - AUX_CH_USBC1); |
27 | else |
28 | snprintf(buf, size, fmt: "%c" , 'A' + aux_ch); |
29 | |
30 | return buf; |
31 | } |
32 | |
33 | u32 intel_dp_aux_pack(const u8 *src, int src_bytes) |
34 | { |
35 | int i; |
36 | u32 v = 0; |
37 | |
38 | if (src_bytes > 4) |
39 | src_bytes = 4; |
40 | for (i = 0; i < src_bytes; i++) |
41 | v |= ((u32)src[i]) << ((3 - i) * 8); |
42 | return v; |
43 | } |
44 | |
45 | static void intel_dp_aux_unpack(u32 src, u8 *dst, int dst_bytes) |
46 | { |
47 | int i; |
48 | |
49 | if (dst_bytes > 4) |
50 | dst_bytes = 4; |
51 | for (i = 0; i < dst_bytes; i++) |
52 | dst[i] = src >> ((3 - i) * 8); |
53 | } |
54 | |
55 | static u32 |
56 | intel_dp_aux_wait_done(struct intel_dp *intel_dp) |
57 | { |
58 | struct drm_i915_private *i915 = dp_to_i915(intel_dp); |
59 | i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp); |
60 | const unsigned int timeout_ms = 10; |
61 | u32 status; |
62 | int ret; |
63 | |
64 | ret = __intel_de_wait_for_register(i915, reg: ch_ctl, |
65 | DP_AUX_CH_CTL_SEND_BUSY, value: 0, |
66 | fast_timeout_us: 2, slow_timeout_ms: timeout_ms, out_value: &status); |
67 | |
68 | if (ret == -ETIMEDOUT) |
69 | drm_err(&i915->drm, |
70 | "%s: did not complete or timeout within %ums (status 0x%08x)\n" , |
71 | intel_dp->aux.name, timeout_ms, status); |
72 | |
73 | return status; |
74 | } |
75 | |
76 | static u32 g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index) |
77 | { |
78 | struct drm_i915_private *i915 = dp_to_i915(intel_dp); |
79 | |
80 | if (index) |
81 | return 0; |
82 | |
83 | /* |
84 | * The clock divider is based off the hrawclk, and would like to run at |
85 | * 2MHz. So, take the hrawclk value and divide by 2000 and use that |
86 | */ |
87 | return DIV_ROUND_CLOSEST(RUNTIME_INFO(i915)->rawclk_freq, 2000); |
88 | } |
89 | |
90 | static u32 ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index) |
91 | { |
92 | struct drm_i915_private *i915 = dp_to_i915(intel_dp); |
93 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
94 | u32 freq; |
95 | |
96 | if (index) |
97 | return 0; |
98 | |
99 | /* |
100 | * The clock divider is based off the cdclk or PCH rawclk, and would |
101 | * like to run at 2MHz. So, take the cdclk or PCH rawclk value and |
102 | * divide by 2000 and use that |
103 | */ |
104 | if (dig_port->aux_ch == AUX_CH_A) |
105 | freq = i915->display.cdclk.hw.cdclk; |
106 | else |
107 | freq = RUNTIME_INFO(i915)->rawclk_freq; |
108 | return DIV_ROUND_CLOSEST(freq, 2000); |
109 | } |
110 | |
111 | static u32 hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index) |
112 | { |
113 | struct drm_i915_private *i915 = dp_to_i915(intel_dp); |
114 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
115 | |
116 | if (dig_port->aux_ch != AUX_CH_A && HAS_PCH_LPT_H(i915)) { |
117 | /* Workaround for non-ULT HSW */ |
118 | switch (index) { |
119 | case 0: return 63; |
120 | case 1: return 72; |
121 | default: return 0; |
122 | } |
123 | } |
124 | |
125 | return ilk_get_aux_clock_divider(intel_dp, index); |
126 | } |
127 | |
128 | static u32 skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index) |
129 | { |
130 | /* |
131 | * SKL doesn't need us to program the AUX clock divider (Hardware will |
132 | * derive the clock from CDCLK automatically). We still implement the |
133 | * get_aux_clock_divider vfunc to plug-in into the existing code. |
134 | */ |
135 | return index ? 0 : 1; |
136 | } |
137 | |
138 | static int intel_dp_aux_sync_len(void) |
139 | { |
140 | int precharge = 16; /* 10-16 */ |
141 | int preamble = 16; |
142 | |
143 | return precharge + preamble; |
144 | } |
145 | |
146 | static int intel_dp_aux_fw_sync_len(void) |
147 | { |
148 | int precharge = 10; /* 10-16 */ |
149 | int preamble = 8; |
150 | |
151 | return precharge + preamble; |
152 | } |
153 | |
154 | static int g4x_dp_aux_precharge_len(void) |
155 | { |
156 | int precharge_min = 10; |
157 | int preamble = 16; |
158 | |
159 | /* HW wants the length of the extra precharge in 2us units */ |
160 | return (intel_dp_aux_sync_len() - |
161 | precharge_min - preamble) / 2; |
162 | } |
163 | |
164 | static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp, |
165 | int send_bytes, |
166 | u32 aux_clock_divider) |
167 | { |
168 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
169 | struct drm_i915_private *i915 = to_i915(dev: dig_port->base.base.dev); |
170 | u32 timeout; |
171 | |
172 | /* Max timeout value on G4x-BDW: 1.6ms */ |
173 | if (IS_BROADWELL(i915)) |
174 | timeout = DP_AUX_CH_CTL_TIME_OUT_600us; |
175 | else |
176 | timeout = DP_AUX_CH_CTL_TIME_OUT_400us; |
177 | |
178 | return DP_AUX_CH_CTL_SEND_BUSY | |
179 | DP_AUX_CH_CTL_DONE | |
180 | DP_AUX_CH_CTL_INTERRUPT | |
181 | DP_AUX_CH_CTL_TIME_OUT_ERROR | |
182 | timeout | |
183 | DP_AUX_CH_CTL_RECEIVE_ERROR | |
184 | DP_AUX_CH_CTL_MESSAGE_SIZE(send_bytes) | |
185 | DP_AUX_CH_CTL_PRECHARGE_2US(g4x_dp_aux_precharge_len()) | |
186 | DP_AUX_CH_CTL_BIT_CLOCK_2X(aux_clock_divider); |
187 | } |
188 | |
189 | static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp, |
190 | int send_bytes, |
191 | u32 unused) |
192 | { |
193 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
194 | struct drm_i915_private *i915 = to_i915(dev: dig_port->base.base.dev); |
195 | u32 ret; |
196 | |
197 | /* |
198 | * Max timeout values: |
199 | * SKL-GLK: 1.6ms |
200 | * ICL+: 4ms |
201 | */ |
202 | ret = DP_AUX_CH_CTL_SEND_BUSY | |
203 | DP_AUX_CH_CTL_DONE | |
204 | DP_AUX_CH_CTL_INTERRUPT | |
205 | DP_AUX_CH_CTL_TIME_OUT_ERROR | |
206 | DP_AUX_CH_CTL_TIME_OUT_MAX | |
207 | DP_AUX_CH_CTL_RECEIVE_ERROR | |
208 | DP_AUX_CH_CTL_MESSAGE_SIZE(send_bytes) | |
209 | DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(intel_dp_aux_fw_sync_len()) | |
210 | DP_AUX_CH_CTL_SYNC_PULSE_SKL(intel_dp_aux_sync_len()); |
211 | |
212 | if (intel_tc_port_in_tbt_alt_mode(dig_port)) |
213 | ret |= DP_AUX_CH_CTL_TBT_IO; |
214 | |
215 | /* |
216 | * Power request bit is already set during aux power well enable. |
217 | * Preserve the bit across aux transactions. |
218 | */ |
219 | if (DISPLAY_VER(i915) >= 14) |
220 | ret |= XELPDP_DP_AUX_CH_CTL_POWER_REQUEST; |
221 | |
222 | return ret; |
223 | } |
224 | |
225 | static int |
226 | intel_dp_aux_xfer(struct intel_dp *intel_dp, |
227 | const u8 *send, int send_bytes, |
228 | u8 *recv, int recv_size, |
229 | u32 aux_send_ctl_flags) |
230 | { |
231 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
232 | struct intel_encoder *encoder = &dig_port->base; |
233 | struct drm_i915_private *i915 = to_i915(dev: dig_port->base.base.dev); |
234 | i915_reg_t ch_ctl, ch_data[5]; |
235 | u32 aux_clock_divider; |
236 | enum intel_display_power_domain aux_domain; |
237 | intel_wakeref_t aux_wakeref; |
238 | intel_wakeref_t pps_wakeref; |
239 | int i, ret, recv_bytes; |
240 | int try, clock = 0; |
241 | u32 status; |
242 | bool vdd; |
243 | |
244 | ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp); |
245 | for (i = 0; i < ARRAY_SIZE(ch_data); i++) |
246 | ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i); |
247 | |
248 | intel_digital_port_lock(encoder); |
249 | /* |
250 | * Abort transfers on a disconnected port as required by |
251 | * DP 1.4a link CTS 4.2.1.5, also avoiding the long AUX |
252 | * timeouts that would otherwise happen. |
253 | */ |
254 | if (!intel_dp_is_edp(intel_dp) && |
255 | !intel_digital_port_connected_locked(encoder: &dig_port->base)) { |
256 | ret = -ENXIO; |
257 | goto out_unlock; |
258 | } |
259 | |
260 | aux_domain = intel_aux_power_domain(dig_port); |
261 | |
262 | aux_wakeref = intel_display_power_get(dev_priv: i915, domain: aux_domain); |
263 | pps_wakeref = intel_pps_lock(intel_dp); |
264 | |
265 | /* |
266 | * We will be called with VDD already enabled for dpcd/edid/oui reads. |
267 | * In such cases we want to leave VDD enabled and it's up to upper layers |
268 | * to turn it off. But for eg. i2c-dev access we need to turn it on/off |
269 | * ourselves. |
270 | */ |
271 | vdd = intel_pps_vdd_on_unlocked(intel_dp); |
272 | |
273 | /* |
274 | * dp aux is extremely sensitive to irq latency, hence request the |
275 | * lowest possible wakeup latency and so prevent the cpu from going into |
276 | * deep sleep states. |
277 | */ |
278 | cpu_latency_qos_update_request(req: &intel_dp->pm_qos, new_value: 0); |
279 | |
280 | intel_pps_check_power_unlocked(intel_dp); |
281 | |
282 | /* |
283 | * FIXME PSR should be disabled here to prevent |
284 | * it using the same AUX CH simultaneously |
285 | */ |
286 | |
287 | /* Try to wait for any previous AUX channel activity */ |
288 | for (try = 0; try < 3; try++) { |
289 | status = intel_de_read_notrace(i915, reg: ch_ctl); |
290 | if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) |
291 | break; |
292 | msleep(msecs: 1); |
293 | } |
294 | /* just trace the final value */ |
295 | trace_i915_reg_rw(write: false, reg: ch_ctl, val: status, len: sizeof(status), trace: true); |
296 | |
297 | if (try == 3) { |
298 | const u32 status = intel_de_read(i915, reg: ch_ctl); |
299 | |
300 | if (status != intel_dp->aux_busy_last_status) { |
301 | drm_WARN(&i915->drm, 1, |
302 | "%s: not started (status 0x%08x)\n" , |
303 | intel_dp->aux.name, status); |
304 | intel_dp->aux_busy_last_status = status; |
305 | } |
306 | |
307 | ret = -EBUSY; |
308 | goto out; |
309 | } |
310 | |
311 | /* Only 5 data registers! */ |
312 | if (drm_WARN_ON(&i915->drm, send_bytes > 20 || recv_size > 20)) { |
313 | ret = -E2BIG; |
314 | goto out; |
315 | } |
316 | |
317 | while ((aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, clock++))) { |
318 | u32 send_ctl = intel_dp->get_aux_send_ctl(intel_dp, |
319 | send_bytes, |
320 | aux_clock_divider); |
321 | |
322 | send_ctl |= aux_send_ctl_flags; |
323 | |
324 | /* Must try at least 3 times according to DP spec */ |
325 | for (try = 0; try < 5; try++) { |
326 | /* Load the send data into the aux channel data registers */ |
327 | for (i = 0; i < send_bytes; i += 4) |
328 | intel_de_write(i915, reg: ch_data[i >> 2], |
329 | val: intel_dp_aux_pack(src: send + i, |
330 | src_bytes: send_bytes - i)); |
331 | |
332 | /* Send the command and wait for it to complete */ |
333 | intel_de_write(i915, reg: ch_ctl, val: send_ctl); |
334 | |
335 | status = intel_dp_aux_wait_done(intel_dp); |
336 | |
337 | /* Clear done status and any errors */ |
338 | intel_de_write(i915, reg: ch_ctl, |
339 | val: status | DP_AUX_CH_CTL_DONE | |
340 | DP_AUX_CH_CTL_TIME_OUT_ERROR | |
341 | DP_AUX_CH_CTL_RECEIVE_ERROR); |
342 | |
343 | /* |
344 | * DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2 |
345 | * 400us delay required for errors and timeouts |
346 | * Timeout errors from the HW already meet this |
347 | * requirement so skip to next iteration |
348 | */ |
349 | if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) |
350 | continue; |
351 | |
352 | if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { |
353 | usleep_range(min: 400, max: 500); |
354 | continue; |
355 | } |
356 | if (status & DP_AUX_CH_CTL_DONE) |
357 | goto done; |
358 | } |
359 | } |
360 | |
361 | if ((status & DP_AUX_CH_CTL_DONE) == 0) { |
362 | drm_err(&i915->drm, "%s: not done (status 0x%08x)\n" , |
363 | intel_dp->aux.name, status); |
364 | ret = -EBUSY; |
365 | goto out; |
366 | } |
367 | |
368 | done: |
369 | /* |
370 | * Check for timeout or receive error. Timeouts occur when the sink is |
371 | * not connected. |
372 | */ |
373 | if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { |
374 | drm_err(&i915->drm, "%s: receive error (status 0x%08x)\n" , |
375 | intel_dp->aux.name, status); |
376 | ret = -EIO; |
377 | goto out; |
378 | } |
379 | |
380 | /* |
381 | * Timeouts occur when the device isn't connected, so they're "normal" |
382 | * -- don't fill the kernel log with these |
383 | */ |
384 | if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { |
385 | drm_dbg_kms(&i915->drm, "%s: timeout (status 0x%08x)\n" , |
386 | intel_dp->aux.name, status); |
387 | ret = -ETIMEDOUT; |
388 | goto out; |
389 | } |
390 | |
391 | /* Unload any bytes sent back from the other side */ |
392 | recv_bytes = REG_FIELD_GET(DP_AUX_CH_CTL_MESSAGE_SIZE_MASK, status); |
393 | |
394 | /* |
395 | * By BSpec: "Message sizes of 0 or >20 are not allowed." |
396 | * We have no idea of what happened so we return -EBUSY so |
397 | * drm layer takes care for the necessary retries. |
398 | */ |
399 | if (recv_bytes == 0 || recv_bytes > 20) { |
400 | drm_dbg_kms(&i915->drm, |
401 | "%s: Forbidden recv_bytes = %d on aux transaction\n" , |
402 | intel_dp->aux.name, recv_bytes); |
403 | ret = -EBUSY; |
404 | goto out; |
405 | } |
406 | |
407 | if (recv_bytes > recv_size) |
408 | recv_bytes = recv_size; |
409 | |
410 | for (i = 0; i < recv_bytes; i += 4) |
411 | intel_dp_aux_unpack(src: intel_de_read(i915, reg: ch_data[i >> 2]), |
412 | dst: recv + i, dst_bytes: recv_bytes - i); |
413 | |
414 | ret = recv_bytes; |
415 | out: |
416 | cpu_latency_qos_update_request(req: &intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE); |
417 | |
418 | if (vdd) |
419 | intel_pps_vdd_off_unlocked(intel_dp, sync: false); |
420 | |
421 | intel_pps_unlock(intel_dp, wakeref: pps_wakeref); |
422 | intel_display_power_put_async(i915, domain: aux_domain, wakeref: aux_wakeref); |
423 | out_unlock: |
424 | intel_digital_port_unlock(encoder); |
425 | |
426 | return ret; |
427 | } |
428 | |
429 | #define BARE_ADDRESS_SIZE 3 |
430 | #define (BARE_ADDRESS_SIZE + 1) |
431 | |
432 | static void |
433 | (u8 txbuf[HEADER_SIZE], |
434 | const struct drm_dp_aux_msg *msg) |
435 | { |
436 | txbuf[0] = (msg->request << 4) | ((msg->address >> 16) & 0xf); |
437 | txbuf[1] = (msg->address >> 8) & 0xff; |
438 | txbuf[2] = msg->address & 0xff; |
439 | txbuf[3] = msg->size - 1; |
440 | } |
441 | |
442 | static u32 intel_dp_aux_xfer_flags(const struct drm_dp_aux_msg *msg) |
443 | { |
444 | /* |
445 | * If we're trying to send the HDCP Aksv, we need to set a the Aksv |
446 | * select bit to inform the hardware to send the Aksv after our header |
447 | * since we can't access that data from software. |
448 | */ |
449 | if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_WRITE && |
450 | msg->address == DP_AUX_HDCP_AKSV) |
451 | return DP_AUX_CH_CTL_AUX_AKSV_SELECT; |
452 | |
453 | return 0; |
454 | } |
455 | |
456 | static ssize_t |
457 | intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) |
458 | { |
459 | struct intel_dp *intel_dp = container_of(aux, struct intel_dp, aux); |
460 | struct drm_i915_private *i915 = dp_to_i915(intel_dp); |
461 | u8 txbuf[20], rxbuf[20]; |
462 | size_t txsize, rxsize; |
463 | u32 flags = intel_dp_aux_xfer_flags(msg); |
464 | int ret; |
465 | |
466 | intel_dp_aux_header(txbuf, msg); |
467 | |
468 | switch (msg->request & ~DP_AUX_I2C_MOT) { |
469 | case DP_AUX_NATIVE_WRITE: |
470 | case DP_AUX_I2C_WRITE: |
471 | case DP_AUX_I2C_WRITE_STATUS_UPDATE: |
472 | txsize = msg->size ? HEADER_SIZE + msg->size : BARE_ADDRESS_SIZE; |
473 | rxsize = 2; /* 0 or 1 data bytes */ |
474 | |
475 | if (drm_WARN_ON(&i915->drm, txsize > 20)) |
476 | return -E2BIG; |
477 | |
478 | drm_WARN_ON(&i915->drm, !msg->buffer != !msg->size); |
479 | |
480 | if (msg->buffer) |
481 | memcpy(txbuf + HEADER_SIZE, msg->buffer, msg->size); |
482 | |
483 | ret = intel_dp_aux_xfer(intel_dp, send: txbuf, send_bytes: txsize, |
484 | recv: rxbuf, recv_size: rxsize, aux_send_ctl_flags: flags); |
485 | if (ret > 0) { |
486 | msg->reply = rxbuf[0] >> 4; |
487 | |
488 | if (ret > 1) { |
489 | /* Number of bytes written in a short write. */ |
490 | ret = clamp_t(int, rxbuf[1], 0, msg->size); |
491 | } else { |
492 | /* Return payload size. */ |
493 | ret = msg->size; |
494 | } |
495 | } |
496 | break; |
497 | |
498 | case DP_AUX_NATIVE_READ: |
499 | case DP_AUX_I2C_READ: |
500 | txsize = msg->size ? HEADER_SIZE : BARE_ADDRESS_SIZE; |
501 | rxsize = msg->size + 1; |
502 | |
503 | if (drm_WARN_ON(&i915->drm, rxsize > 20)) |
504 | return -E2BIG; |
505 | |
506 | ret = intel_dp_aux_xfer(intel_dp, send: txbuf, send_bytes: txsize, |
507 | recv: rxbuf, recv_size: rxsize, aux_send_ctl_flags: flags); |
508 | if (ret > 0) { |
509 | msg->reply = rxbuf[0] >> 4; |
510 | /* |
511 | * Assume happy day, and copy the data. The caller is |
512 | * expected to check msg->reply before touching it. |
513 | * |
514 | * Return payload size. |
515 | */ |
516 | ret--; |
517 | memcpy(msg->buffer, rxbuf + 1, ret); |
518 | } |
519 | break; |
520 | |
521 | default: |
522 | ret = -EINVAL; |
523 | break; |
524 | } |
525 | |
526 | return ret; |
527 | } |
528 | |
529 | static i915_reg_t vlv_aux_ctl_reg(struct intel_dp *intel_dp) |
530 | { |
531 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
532 | enum aux_ch aux_ch = dig_port->aux_ch; |
533 | |
534 | switch (aux_ch) { |
535 | case AUX_CH_B: |
536 | case AUX_CH_C: |
537 | case AUX_CH_D: |
538 | return VLV_DP_AUX_CH_CTL(aux_ch); |
539 | default: |
540 | MISSING_CASE(aux_ch); |
541 | return VLV_DP_AUX_CH_CTL(AUX_CH_B); |
542 | } |
543 | } |
544 | |
545 | static i915_reg_t vlv_aux_data_reg(struct intel_dp *intel_dp, int index) |
546 | { |
547 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
548 | enum aux_ch aux_ch = dig_port->aux_ch; |
549 | |
550 | switch (aux_ch) { |
551 | case AUX_CH_B: |
552 | case AUX_CH_C: |
553 | case AUX_CH_D: |
554 | return VLV_DP_AUX_CH_DATA(aux_ch, index); |
555 | default: |
556 | MISSING_CASE(aux_ch); |
557 | return VLV_DP_AUX_CH_DATA(AUX_CH_B, index); |
558 | } |
559 | } |
560 | |
561 | static i915_reg_t g4x_aux_ctl_reg(struct intel_dp *intel_dp) |
562 | { |
563 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
564 | enum aux_ch aux_ch = dig_port->aux_ch; |
565 | |
566 | switch (aux_ch) { |
567 | case AUX_CH_B: |
568 | case AUX_CH_C: |
569 | case AUX_CH_D: |
570 | return DP_AUX_CH_CTL(aux_ch); |
571 | default: |
572 | MISSING_CASE(aux_ch); |
573 | return DP_AUX_CH_CTL(AUX_CH_B); |
574 | } |
575 | } |
576 | |
577 | static i915_reg_t g4x_aux_data_reg(struct intel_dp *intel_dp, int index) |
578 | { |
579 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
580 | enum aux_ch aux_ch = dig_port->aux_ch; |
581 | |
582 | switch (aux_ch) { |
583 | case AUX_CH_B: |
584 | case AUX_CH_C: |
585 | case AUX_CH_D: |
586 | return DP_AUX_CH_DATA(aux_ch, index); |
587 | default: |
588 | MISSING_CASE(aux_ch); |
589 | return DP_AUX_CH_DATA(AUX_CH_B, index); |
590 | } |
591 | } |
592 | |
593 | static i915_reg_t ilk_aux_ctl_reg(struct intel_dp *intel_dp) |
594 | { |
595 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
596 | enum aux_ch aux_ch = dig_port->aux_ch; |
597 | |
598 | switch (aux_ch) { |
599 | case AUX_CH_A: |
600 | return DP_AUX_CH_CTL(aux_ch); |
601 | case AUX_CH_B: |
602 | case AUX_CH_C: |
603 | case AUX_CH_D: |
604 | return PCH_DP_AUX_CH_CTL(aux_ch); |
605 | default: |
606 | MISSING_CASE(aux_ch); |
607 | return DP_AUX_CH_CTL(AUX_CH_A); |
608 | } |
609 | } |
610 | |
611 | static i915_reg_t ilk_aux_data_reg(struct intel_dp *intel_dp, int index) |
612 | { |
613 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
614 | enum aux_ch aux_ch = dig_port->aux_ch; |
615 | |
616 | switch (aux_ch) { |
617 | case AUX_CH_A: |
618 | return DP_AUX_CH_DATA(aux_ch, index); |
619 | case AUX_CH_B: |
620 | case AUX_CH_C: |
621 | case AUX_CH_D: |
622 | return PCH_DP_AUX_CH_DATA(aux_ch, index); |
623 | default: |
624 | MISSING_CASE(aux_ch); |
625 | return DP_AUX_CH_DATA(AUX_CH_A, index); |
626 | } |
627 | } |
628 | |
629 | static i915_reg_t skl_aux_ctl_reg(struct intel_dp *intel_dp) |
630 | { |
631 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
632 | enum aux_ch aux_ch = dig_port->aux_ch; |
633 | |
634 | switch (aux_ch) { |
635 | case AUX_CH_A: |
636 | case AUX_CH_B: |
637 | case AUX_CH_C: |
638 | case AUX_CH_D: |
639 | case AUX_CH_E: |
640 | case AUX_CH_F: |
641 | return DP_AUX_CH_CTL(aux_ch); |
642 | default: |
643 | MISSING_CASE(aux_ch); |
644 | return DP_AUX_CH_CTL(AUX_CH_A); |
645 | } |
646 | } |
647 | |
648 | static i915_reg_t skl_aux_data_reg(struct intel_dp *intel_dp, int index) |
649 | { |
650 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
651 | enum aux_ch aux_ch = dig_port->aux_ch; |
652 | |
653 | switch (aux_ch) { |
654 | case AUX_CH_A: |
655 | case AUX_CH_B: |
656 | case AUX_CH_C: |
657 | case AUX_CH_D: |
658 | case AUX_CH_E: |
659 | case AUX_CH_F: |
660 | return DP_AUX_CH_DATA(aux_ch, index); |
661 | default: |
662 | MISSING_CASE(aux_ch); |
663 | return DP_AUX_CH_DATA(AUX_CH_A, index); |
664 | } |
665 | } |
666 | |
667 | static i915_reg_t tgl_aux_ctl_reg(struct intel_dp *intel_dp) |
668 | { |
669 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
670 | enum aux_ch aux_ch = dig_port->aux_ch; |
671 | |
672 | switch (aux_ch) { |
673 | case AUX_CH_A: |
674 | case AUX_CH_B: |
675 | case AUX_CH_C: |
676 | case AUX_CH_USBC1: |
677 | case AUX_CH_USBC2: |
678 | case AUX_CH_USBC3: |
679 | case AUX_CH_USBC4: |
680 | case AUX_CH_USBC5: /* aka AUX_CH_D_XELPD */ |
681 | case AUX_CH_USBC6: /* aka AUX_CH_E_XELPD */ |
682 | return DP_AUX_CH_CTL(aux_ch); |
683 | default: |
684 | MISSING_CASE(aux_ch); |
685 | return DP_AUX_CH_CTL(AUX_CH_A); |
686 | } |
687 | } |
688 | |
689 | static i915_reg_t tgl_aux_data_reg(struct intel_dp *intel_dp, int index) |
690 | { |
691 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
692 | enum aux_ch aux_ch = dig_port->aux_ch; |
693 | |
694 | switch (aux_ch) { |
695 | case AUX_CH_A: |
696 | case AUX_CH_B: |
697 | case AUX_CH_C: |
698 | case AUX_CH_USBC1: |
699 | case AUX_CH_USBC2: |
700 | case AUX_CH_USBC3: |
701 | case AUX_CH_USBC4: |
702 | case AUX_CH_USBC5: /* aka AUX_CH_D_XELPD */ |
703 | case AUX_CH_USBC6: /* aka AUX_CH_E_XELPD */ |
704 | return DP_AUX_CH_DATA(aux_ch, index); |
705 | default: |
706 | MISSING_CASE(aux_ch); |
707 | return DP_AUX_CH_DATA(AUX_CH_A, index); |
708 | } |
709 | } |
710 | |
711 | static i915_reg_t xelpdp_aux_ctl_reg(struct intel_dp *intel_dp) |
712 | { |
713 | struct drm_i915_private *i915 = dp_to_i915(intel_dp); |
714 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
715 | enum aux_ch aux_ch = dig_port->aux_ch; |
716 | |
717 | switch (aux_ch) { |
718 | case AUX_CH_A: |
719 | case AUX_CH_B: |
720 | case AUX_CH_USBC1: |
721 | case AUX_CH_USBC2: |
722 | case AUX_CH_USBC3: |
723 | case AUX_CH_USBC4: |
724 | return XELPDP_DP_AUX_CH_CTL(i915, aux_ch); |
725 | default: |
726 | MISSING_CASE(aux_ch); |
727 | return XELPDP_DP_AUX_CH_CTL(i915, AUX_CH_A); |
728 | } |
729 | } |
730 | |
731 | static i915_reg_t xelpdp_aux_data_reg(struct intel_dp *intel_dp, int index) |
732 | { |
733 | struct drm_i915_private *i915 = dp_to_i915(intel_dp); |
734 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
735 | enum aux_ch aux_ch = dig_port->aux_ch; |
736 | |
737 | switch (aux_ch) { |
738 | case AUX_CH_A: |
739 | case AUX_CH_B: |
740 | case AUX_CH_USBC1: |
741 | case AUX_CH_USBC2: |
742 | case AUX_CH_USBC3: |
743 | case AUX_CH_USBC4: |
744 | return XELPDP_DP_AUX_CH_DATA(i915, aux_ch, index); |
745 | default: |
746 | MISSING_CASE(aux_ch); |
747 | return XELPDP_DP_AUX_CH_DATA(i915, AUX_CH_A, index); |
748 | } |
749 | } |
750 | |
751 | void intel_dp_aux_fini(struct intel_dp *intel_dp) |
752 | { |
753 | if (cpu_latency_qos_request_active(req: &intel_dp->pm_qos)) |
754 | cpu_latency_qos_remove_request(req: &intel_dp->pm_qos); |
755 | |
756 | kfree(objp: intel_dp->aux.name); |
757 | } |
758 | |
759 | void intel_dp_aux_init(struct intel_dp *intel_dp) |
760 | { |
761 | struct drm_i915_private *i915 = dp_to_i915(intel_dp); |
762 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
763 | struct intel_encoder *encoder = &dig_port->base; |
764 | enum aux_ch aux_ch = dig_port->aux_ch; |
765 | char buf[AUX_CH_NAME_BUFSIZE]; |
766 | |
767 | if (DISPLAY_VER(i915) >= 14) { |
768 | intel_dp->aux_ch_ctl_reg = xelpdp_aux_ctl_reg; |
769 | intel_dp->aux_ch_data_reg = xelpdp_aux_data_reg; |
770 | } else if (DISPLAY_VER(i915) >= 12) { |
771 | intel_dp->aux_ch_ctl_reg = tgl_aux_ctl_reg; |
772 | intel_dp->aux_ch_data_reg = tgl_aux_data_reg; |
773 | } else if (DISPLAY_VER(i915) >= 9) { |
774 | intel_dp->aux_ch_ctl_reg = skl_aux_ctl_reg; |
775 | intel_dp->aux_ch_data_reg = skl_aux_data_reg; |
776 | } else if (HAS_PCH_SPLIT(i915)) { |
777 | intel_dp->aux_ch_ctl_reg = ilk_aux_ctl_reg; |
778 | intel_dp->aux_ch_data_reg = ilk_aux_data_reg; |
779 | } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { |
780 | intel_dp->aux_ch_ctl_reg = vlv_aux_ctl_reg; |
781 | intel_dp->aux_ch_data_reg = vlv_aux_data_reg; |
782 | } else { |
783 | intel_dp->aux_ch_ctl_reg = g4x_aux_ctl_reg; |
784 | intel_dp->aux_ch_data_reg = g4x_aux_data_reg; |
785 | } |
786 | |
787 | if (DISPLAY_VER(i915) >= 9) |
788 | intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider; |
789 | else if (IS_BROADWELL(i915) || IS_HASWELL(i915)) |
790 | intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider; |
791 | else if (HAS_PCH_SPLIT(i915)) |
792 | intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider; |
793 | else |
794 | intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider; |
795 | |
796 | if (DISPLAY_VER(i915) >= 9) |
797 | intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl; |
798 | else |
799 | intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl; |
800 | |
801 | intel_dp->aux.drm_dev = &i915->drm; |
802 | drm_dp_aux_init(aux: &intel_dp->aux); |
803 | |
804 | /* Failure to allocate our preferred name is not critical */ |
805 | intel_dp->aux.name = kasprintf(GFP_KERNEL, fmt: "AUX %s/%s" , |
806 | aux_ch_name(i915, buf, size: sizeof(buf), aux_ch), |
807 | encoder->base.name); |
808 | |
809 | intel_dp->aux.transfer = intel_dp_aux_transfer; |
810 | cpu_latency_qos_add_request(req: &intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE); |
811 | } |
812 | |
813 | static enum aux_ch default_aux_ch(struct intel_encoder *encoder) |
814 | { |
815 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
816 | |
817 | /* SKL has DDI E but no AUX E */ |
818 | if (DISPLAY_VER(i915) == 9 && encoder->port == PORT_E) |
819 | return AUX_CH_A; |
820 | |
821 | return (enum aux_ch)encoder->port; |
822 | } |
823 | |
824 | static struct intel_encoder * |
825 | get_encoder_by_aux_ch(struct intel_encoder *encoder, |
826 | enum aux_ch aux_ch) |
827 | { |
828 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
829 | struct intel_encoder *other; |
830 | |
831 | for_each_intel_encoder(&i915->drm, other) { |
832 | if (other == encoder) |
833 | continue; |
834 | |
835 | if (!intel_encoder_is_dig_port(encoder: other)) |
836 | continue; |
837 | |
838 | if (enc_to_dig_port(encoder: other)->aux_ch == aux_ch) |
839 | return other; |
840 | } |
841 | |
842 | return NULL; |
843 | } |
844 | |
845 | enum aux_ch intel_dp_aux_ch(struct intel_encoder *encoder) |
846 | { |
847 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
848 | struct intel_encoder *other; |
849 | const char *source; |
850 | enum aux_ch aux_ch; |
851 | char buf[AUX_CH_NAME_BUFSIZE]; |
852 | |
853 | aux_ch = intel_bios_dp_aux_ch(devdata: encoder->devdata); |
854 | source = "VBT" ; |
855 | |
856 | if (aux_ch == AUX_CH_NONE) { |
857 | aux_ch = default_aux_ch(encoder); |
858 | source = "platform default" ; |
859 | } |
860 | |
861 | if (aux_ch == AUX_CH_NONE) |
862 | return AUX_CH_NONE; |
863 | |
864 | /* FIXME validate aux_ch against platform caps */ |
865 | |
866 | other = get_encoder_by_aux_ch(encoder, aux_ch); |
867 | if (other) { |
868 | drm_dbg_kms(&i915->drm, |
869 | "[ENCODER:%d:%s] AUX CH %s already claimed by [ENCODER:%d:%s]\n" , |
870 | encoder->base.base.id, encoder->base.name, |
871 | aux_ch_name(i915, buf, sizeof(buf), aux_ch), |
872 | other->base.base.id, other->base.name); |
873 | return AUX_CH_NONE; |
874 | } |
875 | |
876 | drm_dbg_kms(&i915->drm, |
877 | "[ENCODER:%d:%s] Using AUX CH %s (%s)\n" , |
878 | encoder->base.base.id, encoder->base.name, |
879 | aux_ch_name(i915, buf, sizeof(buf), aux_ch), source); |
880 | |
881 | return aux_ch; |
882 | } |
883 | |
884 | void intel_dp_aux_irq_handler(struct drm_i915_private *i915) |
885 | { |
886 | wake_up_all(&i915->display.gmbus.wait_queue); |
887 | } |
888 | |