1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Analogix DP (Display Port) core interface driver. |
4 | * |
5 | * Copyright (C) 2012 Samsung Electronics Co., Ltd. |
6 | * Author: Jingoo Han <jg1.han@samsung.com> |
7 | */ |
8 | |
9 | #include <linux/clk.h> |
10 | #include <linux/component.h> |
11 | #include <linux/err.h> |
12 | #include <linux/gpio/consumer.h> |
13 | #include <linux/interrupt.h> |
14 | #include <linux/io.h> |
15 | #include <linux/iopoll.h> |
16 | #include <linux/module.h> |
17 | #include <linux/of.h> |
18 | #include <linux/phy/phy.h> |
19 | #include <linux/platform_device.h> |
20 | |
21 | #include <drm/bridge/analogix_dp.h> |
22 | #include <drm/drm_atomic.h> |
23 | #include <drm/drm_atomic_helper.h> |
24 | #include <drm/drm_bridge.h> |
25 | #include <drm/drm_crtc.h> |
26 | #include <drm/drm_device.h> |
27 | #include <drm/drm_edid.h> |
28 | #include <drm/drm_panel.h> |
29 | #include <drm/drm_print.h> |
30 | #include <drm/drm_probe_helper.h> |
31 | |
32 | #include "analogix_dp_core.h" |
33 | #include "analogix_dp_reg.h" |
34 | |
35 | #define to_dp(nm) container_of(nm, struct analogix_dp_device, nm) |
36 | |
37 | static const bool verify_fast_training; |
38 | |
39 | struct bridge_init { |
40 | struct i2c_client *client; |
41 | struct device_node *node; |
42 | }; |
43 | |
44 | static int analogix_dp_init_dp(struct analogix_dp_device *dp) |
45 | { |
46 | int ret; |
47 | |
48 | analogix_dp_reset(dp); |
49 | |
50 | analogix_dp_swreset(dp); |
51 | |
52 | analogix_dp_init_analog_param(dp); |
53 | analogix_dp_init_interrupt(dp); |
54 | |
55 | /* SW defined function Normal operation */ |
56 | analogix_dp_enable_sw_function(dp); |
57 | |
58 | analogix_dp_config_interrupt(dp); |
59 | ret = analogix_dp_init_analog_func(dp); |
60 | if (ret) |
61 | return ret; |
62 | |
63 | analogix_dp_init_hpd(dp); |
64 | analogix_dp_init_aux(dp); |
65 | return 0; |
66 | } |
67 | |
68 | static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) |
69 | { |
70 | int timeout_loop = 0; |
71 | |
72 | while (timeout_loop < DP_TIMEOUT_LOOP_COUNT) { |
73 | if (analogix_dp_get_plug_in_status(dp) == 0) |
74 | return 0; |
75 | |
76 | timeout_loop++; |
77 | usleep_range(min: 1000, max: 1100); |
78 | } |
79 | |
80 | /* |
81 | * Some edp screen do not have hpd signal, so we can't just |
82 | * return failed when hpd plug in detect failed, DT property |
83 | * "force-hpd" would indicate whether driver need this. |
84 | */ |
85 | if (!dp->force_hpd) |
86 | return -ETIMEDOUT; |
87 | |
88 | /* |
89 | * The eDP TRM indicate that if HPD_STATUS(RO) is 0, AUX CH |
90 | * will not work, so we need to give a force hpd action to |
91 | * set HPD_STATUS manually. |
92 | */ |
93 | dev_dbg(dp->dev, "failed to get hpd plug status, try to force hpd\n" ); |
94 | |
95 | analogix_dp_force_hpd(dp); |
96 | |
97 | if (analogix_dp_get_plug_in_status(dp) != 0) { |
98 | dev_err(dp->dev, "failed to get hpd plug in status\n" ); |
99 | return -EINVAL; |
100 | } |
101 | |
102 | dev_dbg(dp->dev, "success to get plug in status after force hpd\n" ); |
103 | |
104 | return 0; |
105 | } |
106 | |
107 | static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp) |
108 | { |
109 | unsigned char psr_version; |
110 | int ret; |
111 | |
112 | ret = drm_dp_dpcd_readb(aux: &dp->aux, DP_PSR_SUPPORT, valuep: &psr_version); |
113 | if (ret != 1) { |
114 | dev_err(dp->dev, "failed to get PSR version, disable it\n" ); |
115 | return false; |
116 | } |
117 | |
118 | dev_dbg(dp->dev, "Panel PSR version : %x\n" , psr_version); |
119 | return psr_version & DP_PSR_IS_SUPPORTED; |
120 | } |
121 | |
122 | static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp) |
123 | { |
124 | unsigned char psr_en; |
125 | int ret; |
126 | |
127 | /* Disable psr function */ |
128 | ret = drm_dp_dpcd_readb(aux: &dp->aux, DP_PSR_EN_CFG, valuep: &psr_en); |
129 | if (ret != 1) { |
130 | dev_err(dp->dev, "failed to get psr config\n" ); |
131 | goto end; |
132 | } |
133 | |
134 | psr_en &= ~DP_PSR_ENABLE; |
135 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_PSR_EN_CFG, value: psr_en); |
136 | if (ret != 1) { |
137 | dev_err(dp->dev, "failed to disable panel psr\n" ); |
138 | goto end; |
139 | } |
140 | |
141 | /* Main-Link transmitter remains active during PSR active states */ |
142 | psr_en = DP_PSR_CRC_VERIFICATION; |
143 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_PSR_EN_CFG, value: psr_en); |
144 | if (ret != 1) { |
145 | dev_err(dp->dev, "failed to set panel psr\n" ); |
146 | goto end; |
147 | } |
148 | |
149 | /* Enable psr function */ |
150 | psr_en = DP_PSR_ENABLE | DP_PSR_CRC_VERIFICATION; |
151 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_PSR_EN_CFG, value: psr_en); |
152 | if (ret != 1) { |
153 | dev_err(dp->dev, "failed to set panel psr\n" ); |
154 | goto end; |
155 | } |
156 | |
157 | analogix_dp_enable_psr_crc(dp); |
158 | |
159 | dp->psr_supported = true; |
160 | |
161 | return 0; |
162 | end: |
163 | dev_err(dp->dev, "enable psr fail, force to disable psr\n" ); |
164 | |
165 | return ret; |
166 | } |
167 | |
168 | static int |
169 | analogix_dp_enable_rx_to_enhanced_mode(struct analogix_dp_device *dp, |
170 | bool enable) |
171 | { |
172 | u8 data; |
173 | int ret; |
174 | |
175 | ret = drm_dp_dpcd_readb(aux: &dp->aux, DP_LANE_COUNT_SET, valuep: &data); |
176 | if (ret != 1) |
177 | return ret; |
178 | |
179 | if (enable) |
180 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_LANE_COUNT_SET, |
181 | DP_LANE_COUNT_ENHANCED_FRAME_EN | |
182 | DPCD_LANE_COUNT_SET(data)); |
183 | else |
184 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_LANE_COUNT_SET, |
185 | DPCD_LANE_COUNT_SET(data)); |
186 | |
187 | return ret < 0 ? ret : 0; |
188 | } |
189 | |
190 | static int analogix_dp_is_enhanced_mode_available(struct analogix_dp_device *dp, |
191 | u8 *enhanced_mode_support) |
192 | { |
193 | u8 data; |
194 | int ret; |
195 | |
196 | ret = drm_dp_dpcd_readb(aux: &dp->aux, DP_MAX_LANE_COUNT, valuep: &data); |
197 | if (ret != 1) { |
198 | *enhanced_mode_support = 0; |
199 | return ret; |
200 | } |
201 | |
202 | *enhanced_mode_support = DPCD_ENHANCED_FRAME_CAP(data); |
203 | |
204 | return 0; |
205 | } |
206 | |
207 | static int analogix_dp_set_enhanced_mode(struct analogix_dp_device *dp) |
208 | { |
209 | u8 data; |
210 | int ret; |
211 | |
212 | ret = analogix_dp_is_enhanced_mode_available(dp, enhanced_mode_support: &data); |
213 | if (ret < 0) |
214 | return ret; |
215 | |
216 | ret = analogix_dp_enable_rx_to_enhanced_mode(dp, enable: data); |
217 | if (ret < 0) |
218 | return ret; |
219 | |
220 | analogix_dp_enable_enhanced_mode(dp, enable: data); |
221 | |
222 | return 0; |
223 | } |
224 | |
225 | static int analogix_dp_training_pattern_dis(struct analogix_dp_device *dp) |
226 | { |
227 | int ret; |
228 | |
229 | analogix_dp_set_training_pattern(dp, pattern: DP_NONE); |
230 | |
231 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_TRAINING_PATTERN_SET, |
232 | DP_TRAINING_PATTERN_DISABLE); |
233 | |
234 | return ret < 0 ? ret : 0; |
235 | } |
236 | |
237 | static void |
238 | analogix_dp_set_lane_lane_pre_emphasis(struct analogix_dp_device *dp, |
239 | int pre_emphasis, int lane) |
240 | { |
241 | switch (lane) { |
242 | case 0: |
243 | analogix_dp_set_lane0_pre_emphasis(dp, level: pre_emphasis); |
244 | break; |
245 | case 1: |
246 | analogix_dp_set_lane1_pre_emphasis(dp, level: pre_emphasis); |
247 | break; |
248 | |
249 | case 2: |
250 | analogix_dp_set_lane2_pre_emphasis(dp, level: pre_emphasis); |
251 | break; |
252 | |
253 | case 3: |
254 | analogix_dp_set_lane3_pre_emphasis(dp, level: pre_emphasis); |
255 | break; |
256 | } |
257 | } |
258 | |
259 | static int analogix_dp_link_start(struct analogix_dp_device *dp) |
260 | { |
261 | u8 buf[4]; |
262 | int lane, lane_count, pll_tries, retval; |
263 | |
264 | lane_count = dp->link_train.lane_count; |
265 | |
266 | dp->link_train.lt_state = CLOCK_RECOVERY; |
267 | dp->link_train.eq_loop = 0; |
268 | |
269 | for (lane = 0; lane < lane_count; lane++) |
270 | dp->link_train.cr_loop[lane] = 0; |
271 | |
272 | /* Set link rate and count as you want to establish*/ |
273 | analogix_dp_set_link_bandwidth(dp, bwtype: dp->link_train.link_rate); |
274 | analogix_dp_set_lane_count(dp, count: dp->link_train.lane_count); |
275 | |
276 | /* Setup RX configuration */ |
277 | buf[0] = dp->link_train.link_rate; |
278 | buf[1] = dp->link_train.lane_count; |
279 | retval = drm_dp_dpcd_write(aux: &dp->aux, DP_LINK_BW_SET, buffer: buf, size: 2); |
280 | if (retval < 0) |
281 | return retval; |
282 | /* set enhanced mode if available */ |
283 | retval = analogix_dp_set_enhanced_mode(dp); |
284 | if (retval < 0) { |
285 | dev_err(dp->dev, "failed to set enhance mode\n" ); |
286 | return retval; |
287 | } |
288 | |
289 | /* Set TX pre-emphasis to minimum */ |
290 | for (lane = 0; lane < lane_count; lane++) |
291 | analogix_dp_set_lane_lane_pre_emphasis(dp, |
292 | pre_emphasis: PRE_EMPHASIS_LEVEL_0, lane); |
293 | |
294 | /* Wait for PLL lock */ |
295 | pll_tries = 0; |
296 | while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { |
297 | if (pll_tries == DP_TIMEOUT_LOOP_COUNT) { |
298 | dev_err(dp->dev, "Wait for PLL lock timed out\n" ); |
299 | return -ETIMEDOUT; |
300 | } |
301 | |
302 | pll_tries++; |
303 | usleep_range(min: 90, max: 120); |
304 | } |
305 | |
306 | /* Set training pattern 1 */ |
307 | analogix_dp_set_training_pattern(dp, pattern: TRAINING_PTN1); |
308 | |
309 | /* Set RX training pattern */ |
310 | retval = drm_dp_dpcd_writeb(aux: &dp->aux, DP_TRAINING_PATTERN_SET, |
311 | DP_LINK_SCRAMBLING_DISABLE | |
312 | DP_TRAINING_PATTERN_1); |
313 | if (retval < 0) |
314 | return retval; |
315 | |
316 | for (lane = 0; lane < lane_count; lane++) |
317 | buf[lane] = DP_TRAIN_PRE_EMPH_LEVEL_0 | |
318 | DP_TRAIN_VOLTAGE_SWING_LEVEL_0; |
319 | |
320 | retval = drm_dp_dpcd_write(aux: &dp->aux, DP_TRAINING_LANE0_SET, buffer: buf, |
321 | size: lane_count); |
322 | if (retval < 0) |
323 | return retval; |
324 | |
325 | return 0; |
326 | } |
327 | |
328 | static unsigned char analogix_dp_get_lane_status(u8 link_status[2], int lane) |
329 | { |
330 | int shift = (lane & 1) * 4; |
331 | u8 link_value = link_status[lane >> 1]; |
332 | |
333 | return (link_value >> shift) & 0xf; |
334 | } |
335 | |
336 | static int analogix_dp_clock_recovery_ok(u8 link_status[2], int lane_count) |
337 | { |
338 | int lane; |
339 | u8 lane_status; |
340 | |
341 | for (lane = 0; lane < lane_count; lane++) { |
342 | lane_status = analogix_dp_get_lane_status(link_status, lane); |
343 | if ((lane_status & DP_LANE_CR_DONE) == 0) |
344 | return -EINVAL; |
345 | } |
346 | return 0; |
347 | } |
348 | |
349 | static int analogix_dp_channel_eq_ok(u8 link_status[2], u8 link_align, |
350 | int lane_count) |
351 | { |
352 | int lane; |
353 | u8 lane_status; |
354 | |
355 | if ((link_align & DP_INTERLANE_ALIGN_DONE) == 0) |
356 | return -EINVAL; |
357 | |
358 | for (lane = 0; lane < lane_count; lane++) { |
359 | lane_status = analogix_dp_get_lane_status(link_status, lane); |
360 | lane_status &= DP_CHANNEL_EQ_BITS; |
361 | if (lane_status != DP_CHANNEL_EQ_BITS) |
362 | return -EINVAL; |
363 | } |
364 | |
365 | return 0; |
366 | } |
367 | |
368 | static unsigned char |
369 | analogix_dp_get_adjust_request_voltage(u8 adjust_request[2], int lane) |
370 | { |
371 | int shift = (lane & 1) * 4; |
372 | u8 link_value = adjust_request[lane >> 1]; |
373 | |
374 | return (link_value >> shift) & 0x3; |
375 | } |
376 | |
377 | static unsigned char analogix_dp_get_adjust_request_pre_emphasis( |
378 | u8 adjust_request[2], |
379 | int lane) |
380 | { |
381 | int shift = (lane & 1) * 4; |
382 | u8 link_value = adjust_request[lane >> 1]; |
383 | |
384 | return ((link_value >> shift) & 0xc) >> 2; |
385 | } |
386 | |
387 | static void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp, |
388 | u8 training_lane_set, int lane) |
389 | { |
390 | switch (lane) { |
391 | case 0: |
392 | analogix_dp_set_lane0_link_training(dp, training_lane: training_lane_set); |
393 | break; |
394 | case 1: |
395 | analogix_dp_set_lane1_link_training(dp, training_lane: training_lane_set); |
396 | break; |
397 | |
398 | case 2: |
399 | analogix_dp_set_lane2_link_training(dp, training_lane: training_lane_set); |
400 | break; |
401 | |
402 | case 3: |
403 | analogix_dp_set_lane3_link_training(dp, training_lane: training_lane_set); |
404 | break; |
405 | } |
406 | } |
407 | |
408 | static unsigned int |
409 | analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, |
410 | int lane) |
411 | { |
412 | u32 reg; |
413 | |
414 | switch (lane) { |
415 | case 0: |
416 | reg = analogix_dp_get_lane0_link_training(dp); |
417 | break; |
418 | case 1: |
419 | reg = analogix_dp_get_lane1_link_training(dp); |
420 | break; |
421 | case 2: |
422 | reg = analogix_dp_get_lane2_link_training(dp); |
423 | break; |
424 | case 3: |
425 | reg = analogix_dp_get_lane3_link_training(dp); |
426 | break; |
427 | default: |
428 | WARN_ON(1); |
429 | return 0; |
430 | } |
431 | |
432 | return reg; |
433 | } |
434 | |
435 | static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp) |
436 | { |
437 | analogix_dp_training_pattern_dis(dp); |
438 | analogix_dp_set_enhanced_mode(dp); |
439 | |
440 | dp->link_train.lt_state = FAILED; |
441 | } |
442 | |
443 | static void analogix_dp_get_adjust_training_lane(struct analogix_dp_device *dp, |
444 | u8 adjust_request[2]) |
445 | { |
446 | int lane, lane_count; |
447 | u8 voltage_swing, pre_emphasis, training_lane; |
448 | |
449 | lane_count = dp->link_train.lane_count; |
450 | for (lane = 0; lane < lane_count; lane++) { |
451 | voltage_swing = analogix_dp_get_adjust_request_voltage( |
452 | adjust_request, lane); |
453 | pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis( |
454 | adjust_request, lane); |
455 | training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | |
456 | DPCD_PRE_EMPHASIS_SET(pre_emphasis); |
457 | |
458 | if (voltage_swing == VOLTAGE_LEVEL_3) |
459 | training_lane |= DP_TRAIN_MAX_SWING_REACHED; |
460 | if (pre_emphasis == PRE_EMPHASIS_LEVEL_3) |
461 | training_lane |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; |
462 | |
463 | dp->link_train.training_lane[lane] = training_lane; |
464 | } |
465 | } |
466 | |
467 | static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp) |
468 | { |
469 | int lane, lane_count, retval; |
470 | u8 voltage_swing, pre_emphasis, training_lane; |
471 | u8 link_status[2], adjust_request[2]; |
472 | |
473 | usleep_range(min: 100, max: 101); |
474 | |
475 | lane_count = dp->link_train.lane_count; |
476 | |
477 | retval = drm_dp_dpcd_read(aux: &dp->aux, DP_LANE0_1_STATUS, buffer: link_status, size: 2); |
478 | if (retval < 0) |
479 | return retval; |
480 | |
481 | retval = drm_dp_dpcd_read(aux: &dp->aux, DP_ADJUST_REQUEST_LANE0_1, |
482 | buffer: adjust_request, size: 2); |
483 | if (retval < 0) |
484 | return retval; |
485 | |
486 | if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) { |
487 | /* set training pattern 2 for EQ */ |
488 | analogix_dp_set_training_pattern(dp, pattern: TRAINING_PTN2); |
489 | |
490 | retval = drm_dp_dpcd_writeb(aux: &dp->aux, DP_TRAINING_PATTERN_SET, |
491 | DP_LINK_SCRAMBLING_DISABLE | |
492 | DP_TRAINING_PATTERN_2); |
493 | if (retval < 0) |
494 | return retval; |
495 | |
496 | dev_dbg(dp->dev, "Link Training Clock Recovery success\n" ); |
497 | dp->link_train.lt_state = EQUALIZER_TRAINING; |
498 | } else { |
499 | for (lane = 0; lane < lane_count; lane++) { |
500 | training_lane = analogix_dp_get_lane_link_training( |
501 | dp, lane); |
502 | voltage_swing = analogix_dp_get_adjust_request_voltage( |
503 | adjust_request, lane); |
504 | pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis( |
505 | adjust_request, lane); |
506 | |
507 | if (DPCD_VOLTAGE_SWING_GET(training_lane) == |
508 | voltage_swing && |
509 | DPCD_PRE_EMPHASIS_GET(training_lane) == |
510 | pre_emphasis) |
511 | dp->link_train.cr_loop[lane]++; |
512 | |
513 | if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP || |
514 | voltage_swing == VOLTAGE_LEVEL_3 || |
515 | pre_emphasis == PRE_EMPHASIS_LEVEL_3) { |
516 | dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n" , |
517 | dp->link_train.cr_loop[lane], |
518 | voltage_swing, pre_emphasis); |
519 | analogix_dp_reduce_link_rate(dp); |
520 | return -EIO; |
521 | } |
522 | } |
523 | } |
524 | |
525 | analogix_dp_get_adjust_training_lane(dp, adjust_request); |
526 | |
527 | for (lane = 0; lane < lane_count; lane++) |
528 | analogix_dp_set_lane_link_training(dp, |
529 | training_lane_set: dp->link_train.training_lane[lane], lane); |
530 | |
531 | retval = drm_dp_dpcd_write(aux: &dp->aux, DP_TRAINING_LANE0_SET, |
532 | buffer: dp->link_train.training_lane, size: lane_count); |
533 | if (retval < 0) |
534 | return retval; |
535 | |
536 | return 0; |
537 | } |
538 | |
539 | static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) |
540 | { |
541 | int lane, lane_count, retval; |
542 | u32 reg; |
543 | u8 link_align, link_status[2], adjust_request[2]; |
544 | |
545 | usleep_range(min: 400, max: 401); |
546 | |
547 | lane_count = dp->link_train.lane_count; |
548 | |
549 | retval = drm_dp_dpcd_read(aux: &dp->aux, DP_LANE0_1_STATUS, buffer: link_status, size: 2); |
550 | if (retval < 0) |
551 | return retval; |
552 | |
553 | if (analogix_dp_clock_recovery_ok(link_status, lane_count)) { |
554 | analogix_dp_reduce_link_rate(dp); |
555 | return -EIO; |
556 | } |
557 | |
558 | retval = drm_dp_dpcd_read(aux: &dp->aux, DP_ADJUST_REQUEST_LANE0_1, |
559 | buffer: adjust_request, size: 2); |
560 | if (retval < 0) |
561 | return retval; |
562 | |
563 | retval = drm_dp_dpcd_readb(aux: &dp->aux, DP_LANE_ALIGN_STATUS_UPDATED, |
564 | valuep: &link_align); |
565 | if (retval < 0) |
566 | return retval; |
567 | |
568 | analogix_dp_get_adjust_training_lane(dp, adjust_request); |
569 | |
570 | if (!analogix_dp_channel_eq_ok(link_status, link_align, lane_count)) { |
571 | /* traing pattern Set to Normal */ |
572 | retval = analogix_dp_training_pattern_dis(dp); |
573 | if (retval < 0) |
574 | return retval; |
575 | |
576 | dev_dbg(dp->dev, "Link Training success!\n" ); |
577 | analogix_dp_get_link_bandwidth(dp, bwtype: ®); |
578 | dp->link_train.link_rate = reg; |
579 | dev_dbg(dp->dev, "final bandwidth = %.2x\n" , |
580 | dp->link_train.link_rate); |
581 | |
582 | analogix_dp_get_lane_count(dp, count: ®); |
583 | dp->link_train.lane_count = reg; |
584 | dev_dbg(dp->dev, "final lane count = %.2x\n" , |
585 | dp->link_train.lane_count); |
586 | |
587 | dp->link_train.lt_state = FINISHED; |
588 | |
589 | return 0; |
590 | } |
591 | |
592 | /* not all locked */ |
593 | dp->link_train.eq_loop++; |
594 | |
595 | if (dp->link_train.eq_loop > MAX_EQ_LOOP) { |
596 | dev_err(dp->dev, "EQ Max loop\n" ); |
597 | analogix_dp_reduce_link_rate(dp); |
598 | return -EIO; |
599 | } |
600 | |
601 | for (lane = 0; lane < lane_count; lane++) |
602 | analogix_dp_set_lane_link_training(dp, |
603 | training_lane_set: dp->link_train.training_lane[lane], lane); |
604 | |
605 | retval = drm_dp_dpcd_write(aux: &dp->aux, DP_TRAINING_LANE0_SET, |
606 | buffer: dp->link_train.training_lane, size: lane_count); |
607 | if (retval < 0) |
608 | return retval; |
609 | |
610 | return 0; |
611 | } |
612 | |
613 | static void analogix_dp_get_max_rx_bandwidth(struct analogix_dp_device *dp, |
614 | u8 *bandwidth) |
615 | { |
616 | u8 data; |
617 | |
618 | /* |
619 | * For DP rev.1.1, Maximum link rate of Main Link lanes |
620 | * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps |
621 | * For DP rev.1.2, Maximum link rate of Main Link lanes |
622 | * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps, 0x14 = 5.4Gbps |
623 | */ |
624 | drm_dp_dpcd_readb(aux: &dp->aux, DP_MAX_LINK_RATE, valuep: &data); |
625 | *bandwidth = data; |
626 | } |
627 | |
628 | static void analogix_dp_get_max_rx_lane_count(struct analogix_dp_device *dp, |
629 | u8 *lane_count) |
630 | { |
631 | u8 data; |
632 | |
633 | /* |
634 | * For DP rev.1.1, Maximum number of Main Link lanes |
635 | * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes |
636 | */ |
637 | drm_dp_dpcd_readb(aux: &dp->aux, DP_MAX_LANE_COUNT, valuep: &data); |
638 | *lane_count = DPCD_MAX_LANE_COUNT(data); |
639 | } |
640 | |
641 | static int analogix_dp_full_link_train(struct analogix_dp_device *dp, |
642 | u32 max_lanes, u32 max_rate) |
643 | { |
644 | int retval = 0; |
645 | bool training_finished = false; |
646 | |
647 | /* |
648 | * MACRO_RST must be applied after the PLL_LOCK to avoid |
649 | * the DP inter pair skew issue for at least 10 us |
650 | */ |
651 | analogix_dp_reset_macro(dp); |
652 | |
653 | /* Initialize by reading RX's DPCD */ |
654 | analogix_dp_get_max_rx_bandwidth(dp, bandwidth: &dp->link_train.link_rate); |
655 | analogix_dp_get_max_rx_lane_count(dp, lane_count: &dp->link_train.lane_count); |
656 | |
657 | if ((dp->link_train.link_rate != DP_LINK_BW_1_62) && |
658 | (dp->link_train.link_rate != DP_LINK_BW_2_7) && |
659 | (dp->link_train.link_rate != DP_LINK_BW_5_4)) { |
660 | dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n" , |
661 | dp->link_train.link_rate); |
662 | dp->link_train.link_rate = DP_LINK_BW_1_62; |
663 | } |
664 | |
665 | if (dp->link_train.lane_count == 0) { |
666 | dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n" , |
667 | dp->link_train.lane_count); |
668 | dp->link_train.lane_count = (u8)LANE_COUNT1; |
669 | } |
670 | |
671 | /* Setup TX lane count & rate */ |
672 | if (dp->link_train.lane_count > max_lanes) |
673 | dp->link_train.lane_count = max_lanes; |
674 | if (dp->link_train.link_rate > max_rate) |
675 | dp->link_train.link_rate = max_rate; |
676 | |
677 | /* All DP analog module power up */ |
678 | analogix_dp_set_analog_power_down(dp, block: POWER_ALL, enable: 0); |
679 | |
680 | dp->link_train.lt_state = START; |
681 | |
682 | /* Process here */ |
683 | while (!retval && !training_finished) { |
684 | switch (dp->link_train.lt_state) { |
685 | case START: |
686 | retval = analogix_dp_link_start(dp); |
687 | if (retval) |
688 | dev_err(dp->dev, "LT link start failed!\n" ); |
689 | break; |
690 | case CLOCK_RECOVERY: |
691 | retval = analogix_dp_process_clock_recovery(dp); |
692 | if (retval) |
693 | dev_err(dp->dev, "LT CR failed!\n" ); |
694 | break; |
695 | case EQUALIZER_TRAINING: |
696 | retval = analogix_dp_process_equalizer_training(dp); |
697 | if (retval) |
698 | dev_err(dp->dev, "LT EQ failed!\n" ); |
699 | break; |
700 | case FINISHED: |
701 | training_finished = 1; |
702 | break; |
703 | case FAILED: |
704 | return -EREMOTEIO; |
705 | } |
706 | } |
707 | if (retval) |
708 | dev_err(dp->dev, "eDP link training failed (%d)\n" , retval); |
709 | |
710 | return retval; |
711 | } |
712 | |
713 | static int analogix_dp_fast_link_train(struct analogix_dp_device *dp) |
714 | { |
715 | int i, ret; |
716 | u8 link_align, link_status[2]; |
717 | enum pll_status status; |
718 | |
719 | analogix_dp_reset_macro(dp); |
720 | |
721 | analogix_dp_set_link_bandwidth(dp, bwtype: dp->link_train.link_rate); |
722 | analogix_dp_set_lane_count(dp, count: dp->link_train.lane_count); |
723 | |
724 | for (i = 0; i < dp->link_train.lane_count; i++) { |
725 | analogix_dp_set_lane_link_training(dp, |
726 | training_lane_set: dp->link_train.training_lane[i], lane: i); |
727 | } |
728 | |
729 | ret = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, status, |
730 | status != PLL_UNLOCKED, 120, |
731 | 120 * DP_TIMEOUT_LOOP_COUNT); |
732 | if (ret) { |
733 | DRM_DEV_ERROR(dp->dev, "Wait for pll lock failed %d\n" , ret); |
734 | return ret; |
735 | } |
736 | |
737 | /* source Set training pattern 1 */ |
738 | analogix_dp_set_training_pattern(dp, pattern: TRAINING_PTN1); |
739 | /* From DP spec, pattern must be on-screen for a minimum 500us */ |
740 | usleep_range(min: 500, max: 600); |
741 | |
742 | analogix_dp_set_training_pattern(dp, pattern: TRAINING_PTN2); |
743 | /* From DP spec, pattern must be on-screen for a minimum 500us */ |
744 | usleep_range(min: 500, max: 600); |
745 | |
746 | /* TODO: enhanced_mode?*/ |
747 | analogix_dp_set_training_pattern(dp, pattern: DP_NONE); |
748 | |
749 | /* |
750 | * Useful for debugging issues with fast link training, disable for more |
751 | * speed |
752 | */ |
753 | if (verify_fast_training) { |
754 | ret = drm_dp_dpcd_readb(aux: &dp->aux, DP_LANE_ALIGN_STATUS_UPDATED, |
755 | valuep: &link_align); |
756 | if (ret < 0) { |
757 | DRM_DEV_ERROR(dp->dev, "Read align status failed %d\n" , |
758 | ret); |
759 | return ret; |
760 | } |
761 | |
762 | ret = drm_dp_dpcd_read(aux: &dp->aux, DP_LANE0_1_STATUS, buffer: link_status, |
763 | size: 2); |
764 | if (ret < 0) { |
765 | DRM_DEV_ERROR(dp->dev, "Read link status failed %d\n" , |
766 | ret); |
767 | return ret; |
768 | } |
769 | |
770 | if (analogix_dp_clock_recovery_ok(link_status, |
771 | lane_count: dp->link_train.lane_count)) { |
772 | DRM_DEV_ERROR(dp->dev, "Clock recovery failed\n" ); |
773 | analogix_dp_reduce_link_rate(dp); |
774 | return -EIO; |
775 | } |
776 | |
777 | if (analogix_dp_channel_eq_ok(link_status, link_align, |
778 | lane_count: dp->link_train.lane_count)) { |
779 | DRM_DEV_ERROR(dp->dev, "Channel EQ failed\n" ); |
780 | analogix_dp_reduce_link_rate(dp); |
781 | return -EIO; |
782 | } |
783 | } |
784 | |
785 | return 0; |
786 | } |
787 | |
788 | static int analogix_dp_train_link(struct analogix_dp_device *dp) |
789 | { |
790 | if (dp->fast_train_enable) |
791 | return analogix_dp_fast_link_train(dp); |
792 | |
793 | return analogix_dp_full_link_train(dp, max_lanes: dp->video_info.max_lane_count, |
794 | max_rate: dp->video_info.max_link_rate); |
795 | } |
796 | |
797 | static int analogix_dp_config_video(struct analogix_dp_device *dp) |
798 | { |
799 | int timeout_loop = 0; |
800 | int done_count = 0; |
801 | |
802 | analogix_dp_config_video_slave_mode(dp); |
803 | |
804 | analogix_dp_set_video_color_format(dp); |
805 | |
806 | if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { |
807 | dev_err(dp->dev, "PLL is not locked yet.\n" ); |
808 | return -EINVAL; |
809 | } |
810 | |
811 | for (;;) { |
812 | timeout_loop++; |
813 | if (analogix_dp_is_slave_video_stream_clock_on(dp) == 0) |
814 | break; |
815 | if (timeout_loop > DP_TIMEOUT_LOOP_COUNT) { |
816 | dev_err(dp->dev, "Timeout of slave video streamclk ok\n" ); |
817 | return -ETIMEDOUT; |
818 | } |
819 | usleep_range(min: 1000, max: 1001); |
820 | } |
821 | |
822 | /* Set to use the register calculated M/N video */ |
823 | analogix_dp_set_video_cr_mn(dp, type: CALCULATED_M, m_value: 0, n_value: 0); |
824 | |
825 | /* For video bist, Video timing must be generated by register */ |
826 | analogix_dp_set_video_timing_mode(dp, type: VIDEO_TIMING_FROM_CAPTURE); |
827 | |
828 | /* Disable video mute */ |
829 | analogix_dp_enable_video_mute(dp, enable: 0); |
830 | |
831 | /* Configure video slave mode */ |
832 | analogix_dp_enable_video_master(dp, enable: 0); |
833 | |
834 | /* Enable video */ |
835 | analogix_dp_start_video(dp); |
836 | |
837 | timeout_loop = 0; |
838 | |
839 | for (;;) { |
840 | timeout_loop++; |
841 | if (analogix_dp_is_video_stream_on(dp) == 0) { |
842 | done_count++; |
843 | if (done_count > 10) |
844 | break; |
845 | } else if (done_count) { |
846 | done_count = 0; |
847 | } |
848 | if (timeout_loop > DP_TIMEOUT_LOOP_COUNT) { |
849 | dev_warn(dp->dev, |
850 | "Ignoring timeout of video streamclk ok\n" ); |
851 | break; |
852 | } |
853 | |
854 | usleep_range(min: 1000, max: 1001); |
855 | } |
856 | |
857 | return 0; |
858 | } |
859 | |
860 | static int analogix_dp_enable_scramble(struct analogix_dp_device *dp, |
861 | bool enable) |
862 | { |
863 | u8 data; |
864 | int ret; |
865 | |
866 | if (enable) { |
867 | analogix_dp_enable_scrambling(dp); |
868 | |
869 | ret = drm_dp_dpcd_readb(aux: &dp->aux, DP_TRAINING_PATTERN_SET, |
870 | valuep: &data); |
871 | if (ret != 1) |
872 | return ret; |
873 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_TRAINING_PATTERN_SET, |
874 | value: (u8)(data & ~DP_LINK_SCRAMBLING_DISABLE)); |
875 | } else { |
876 | analogix_dp_disable_scrambling(dp); |
877 | |
878 | ret = drm_dp_dpcd_readb(aux: &dp->aux, DP_TRAINING_PATTERN_SET, |
879 | valuep: &data); |
880 | if (ret != 1) |
881 | return ret; |
882 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_TRAINING_PATTERN_SET, |
883 | value: (u8)(data | DP_LINK_SCRAMBLING_DISABLE)); |
884 | } |
885 | return ret < 0 ? ret : 0; |
886 | } |
887 | |
888 | static irqreturn_t analogix_dp_hardirq(int irq, void *arg) |
889 | { |
890 | struct analogix_dp_device *dp = arg; |
891 | irqreturn_t ret = IRQ_NONE; |
892 | enum dp_irq_type irq_type; |
893 | |
894 | irq_type = analogix_dp_get_irq_type(dp); |
895 | if (irq_type != DP_IRQ_TYPE_UNKNOWN) { |
896 | analogix_dp_mute_hpd_interrupt(dp); |
897 | ret = IRQ_WAKE_THREAD; |
898 | } |
899 | |
900 | return ret; |
901 | } |
902 | |
903 | static irqreturn_t analogix_dp_irq_thread(int irq, void *arg) |
904 | { |
905 | struct analogix_dp_device *dp = arg; |
906 | enum dp_irq_type irq_type; |
907 | |
908 | irq_type = analogix_dp_get_irq_type(dp); |
909 | if (irq_type & DP_IRQ_TYPE_HP_CABLE_IN || |
910 | irq_type & DP_IRQ_TYPE_HP_CABLE_OUT) { |
911 | dev_dbg(dp->dev, "Detected cable status changed!\n" ); |
912 | if (dp->drm_dev) |
913 | drm_helper_hpd_irq_event(dev: dp->drm_dev); |
914 | } |
915 | |
916 | if (irq_type != DP_IRQ_TYPE_UNKNOWN) { |
917 | analogix_dp_clear_hotplug_interrupts(dp); |
918 | analogix_dp_unmute_hpd_interrupt(dp); |
919 | } |
920 | |
921 | return IRQ_HANDLED; |
922 | } |
923 | |
924 | static int analogix_dp_fast_link_train_detection(struct analogix_dp_device *dp) |
925 | { |
926 | int ret; |
927 | u8 spread; |
928 | |
929 | ret = drm_dp_dpcd_readb(aux: &dp->aux, DP_MAX_DOWNSPREAD, valuep: &spread); |
930 | if (ret != 1) { |
931 | dev_err(dp->dev, "failed to read downspread %d\n" , ret); |
932 | return ret; |
933 | } |
934 | dp->fast_train_enable = !!(spread & DP_NO_AUX_HANDSHAKE_LINK_TRAINING); |
935 | dev_dbg(dp->dev, "fast link training %s\n" , |
936 | dp->fast_train_enable ? "supported" : "unsupported" ); |
937 | return 0; |
938 | } |
939 | |
940 | static int analogix_dp_commit(struct analogix_dp_device *dp) |
941 | { |
942 | int ret; |
943 | |
944 | /* Keep the panel disabled while we configure video */ |
945 | if (dp->plat_data->panel) { |
946 | if (drm_panel_disable(panel: dp->plat_data->panel)) |
947 | DRM_ERROR("failed to disable the panel\n" ); |
948 | } |
949 | |
950 | ret = analogix_dp_train_link(dp); |
951 | if (ret) { |
952 | dev_err(dp->dev, "unable to do link train, ret=%d\n" , ret); |
953 | return ret; |
954 | } |
955 | |
956 | ret = analogix_dp_enable_scramble(dp, enable: 1); |
957 | if (ret < 0) { |
958 | dev_err(dp->dev, "can not enable scramble\n" ); |
959 | return ret; |
960 | } |
961 | |
962 | analogix_dp_init_video(dp); |
963 | ret = analogix_dp_config_video(dp); |
964 | if (ret) { |
965 | dev_err(dp->dev, "unable to config video\n" ); |
966 | return ret; |
967 | } |
968 | |
969 | /* Safe to enable the panel now */ |
970 | if (dp->plat_data->panel) { |
971 | ret = drm_panel_enable(panel: dp->plat_data->panel); |
972 | if (ret) { |
973 | DRM_ERROR("failed to enable the panel\n" ); |
974 | return ret; |
975 | } |
976 | } |
977 | |
978 | /* Check whether panel supports fast training */ |
979 | ret = analogix_dp_fast_link_train_detection(dp); |
980 | if (ret) |
981 | return ret; |
982 | |
983 | if (analogix_dp_detect_sink_psr(dp)) { |
984 | ret = analogix_dp_enable_sink_psr(dp); |
985 | if (ret) |
986 | return ret; |
987 | } |
988 | |
989 | return ret; |
990 | } |
991 | |
992 | static int analogix_dp_enable_psr(struct analogix_dp_device *dp) |
993 | { |
994 | struct dp_sdp psr_vsc; |
995 | int ret; |
996 | u8 sink; |
997 | |
998 | ret = drm_dp_dpcd_readb(aux: &dp->aux, DP_PSR_STATUS, valuep: &sink); |
999 | if (ret != 1) |
1000 | DRM_DEV_ERROR(dp->dev, "Failed to read psr status %d\n" , ret); |
1001 | else if (sink == DP_PSR_SINK_ACTIVE_RFB) |
1002 | return 0; |
1003 | |
1004 | /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ |
1005 | memset(&psr_vsc, 0, sizeof(psr_vsc)); |
1006 | psr_vsc.sdp_header.HB0 = 0; |
1007 | psr_vsc.sdp_header.HB1 = 0x7; |
1008 | psr_vsc.sdp_header.HB2 = 0x2; |
1009 | psr_vsc.sdp_header.HB3 = 0x8; |
1010 | psr_vsc.db[0] = 0; |
1011 | psr_vsc.db[1] = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; |
1012 | |
1013 | ret = analogix_dp_send_psr_spd(dp, vsc: &psr_vsc, blocking: true); |
1014 | if (!ret) |
1015 | analogix_dp_set_analog_power_down(dp, block: POWER_ALL, enable: true); |
1016 | |
1017 | return ret; |
1018 | } |
1019 | |
1020 | static int analogix_dp_disable_psr(struct analogix_dp_device *dp) |
1021 | { |
1022 | struct dp_sdp psr_vsc; |
1023 | int ret; |
1024 | u8 sink; |
1025 | |
1026 | analogix_dp_set_analog_power_down(dp, block: POWER_ALL, enable: false); |
1027 | |
1028 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_SET_POWER, DP_SET_POWER_D0); |
1029 | if (ret != 1) { |
1030 | DRM_DEV_ERROR(dp->dev, "Failed to set DP Power0 %d\n" , ret); |
1031 | return ret; |
1032 | } |
1033 | |
1034 | ret = drm_dp_dpcd_readb(aux: &dp->aux, DP_PSR_STATUS, valuep: &sink); |
1035 | if (ret != 1) { |
1036 | DRM_DEV_ERROR(dp->dev, "Failed to read psr status %d\n" , ret); |
1037 | return ret; |
1038 | } else if (sink == DP_PSR_SINK_INACTIVE) { |
1039 | DRM_DEV_ERROR(dp->dev, "sink inactive, skip disable psr" ); |
1040 | return 0; |
1041 | } |
1042 | |
1043 | ret = analogix_dp_train_link(dp); |
1044 | if (ret) { |
1045 | DRM_DEV_ERROR(dp->dev, "Failed to train the link %d\n" , ret); |
1046 | return ret; |
1047 | } |
1048 | |
1049 | /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ |
1050 | memset(&psr_vsc, 0, sizeof(psr_vsc)); |
1051 | psr_vsc.sdp_header.HB0 = 0; |
1052 | psr_vsc.sdp_header.HB1 = 0x7; |
1053 | psr_vsc.sdp_header.HB2 = 0x2; |
1054 | psr_vsc.sdp_header.HB3 = 0x8; |
1055 | |
1056 | psr_vsc.db[0] = 0; |
1057 | psr_vsc.db[1] = 0; |
1058 | |
1059 | return analogix_dp_send_psr_spd(dp, vsc: &psr_vsc, blocking: true); |
1060 | } |
1061 | |
1062 | /* |
1063 | * This function is a bit of a catch-all for panel preparation, hopefully |
1064 | * simplifying the logic of functions that need to prepare/unprepare the panel |
1065 | * below. |
1066 | * |
1067 | * If @prepare is true, this function will prepare the panel. Conversely, if it |
1068 | * is false, the panel will be unprepared. |
1069 | * |
1070 | * If @is_modeset_prepare is true, the function will disregard the current state |
1071 | * of the panel and either prepare/unprepare the panel based on @prepare. Once |
1072 | * it finishes, it will update dp->panel_is_modeset to reflect the current state |
1073 | * of the panel. |
1074 | */ |
1075 | static int analogix_dp_prepare_panel(struct analogix_dp_device *dp, |
1076 | bool prepare, bool is_modeset_prepare) |
1077 | { |
1078 | int ret = 0; |
1079 | |
1080 | if (!dp->plat_data->panel) |
1081 | return 0; |
1082 | |
1083 | mutex_lock(&dp->panel_lock); |
1084 | |
1085 | /* |
1086 | * Exit early if this is a temporary prepare/unprepare and we're already |
1087 | * modeset (since we neither want to prepare twice or unprepare early). |
1088 | */ |
1089 | if (dp->panel_is_modeset && !is_modeset_prepare) |
1090 | goto out; |
1091 | |
1092 | if (prepare) |
1093 | ret = drm_panel_prepare(panel: dp->plat_data->panel); |
1094 | else |
1095 | ret = drm_panel_unprepare(panel: dp->plat_data->panel); |
1096 | |
1097 | if (ret) |
1098 | goto out; |
1099 | |
1100 | if (is_modeset_prepare) |
1101 | dp->panel_is_modeset = prepare; |
1102 | |
1103 | out: |
1104 | mutex_unlock(lock: &dp->panel_lock); |
1105 | return ret; |
1106 | } |
1107 | |
1108 | static int analogix_dp_get_modes(struct drm_connector *connector) |
1109 | { |
1110 | struct analogix_dp_device *dp = to_dp(connector); |
1111 | struct edid *edid; |
1112 | int ret, num_modes = 0; |
1113 | |
1114 | if (dp->plat_data->panel) { |
1115 | num_modes += drm_panel_get_modes(panel: dp->plat_data->panel, connector); |
1116 | } else { |
1117 | ret = analogix_dp_prepare_panel(dp, prepare: true, is_modeset_prepare: false); |
1118 | if (ret) { |
1119 | DRM_ERROR("Failed to prepare panel (%d)\n" , ret); |
1120 | return 0; |
1121 | } |
1122 | |
1123 | edid = drm_get_edid(connector, adapter: &dp->aux.ddc); |
1124 | if (edid) { |
1125 | drm_connector_update_edid_property(connector: &dp->connector, |
1126 | edid); |
1127 | num_modes += drm_add_edid_modes(connector: &dp->connector, edid); |
1128 | kfree(objp: edid); |
1129 | } |
1130 | |
1131 | ret = analogix_dp_prepare_panel(dp, prepare: false, is_modeset_prepare: false); |
1132 | if (ret) |
1133 | DRM_ERROR("Failed to unprepare panel (%d)\n" , ret); |
1134 | } |
1135 | |
1136 | if (dp->plat_data->get_modes) |
1137 | num_modes += dp->plat_data->get_modes(dp->plat_data, connector); |
1138 | |
1139 | return num_modes; |
1140 | } |
1141 | |
1142 | static struct drm_encoder * |
1143 | analogix_dp_best_encoder(struct drm_connector *connector) |
1144 | { |
1145 | struct analogix_dp_device *dp = to_dp(connector); |
1146 | |
1147 | return dp->encoder; |
1148 | } |
1149 | |
1150 | |
1151 | static int analogix_dp_atomic_check(struct drm_connector *connector, |
1152 | struct drm_atomic_state *state) |
1153 | { |
1154 | struct analogix_dp_device *dp = to_dp(connector); |
1155 | struct drm_connector_state *conn_state; |
1156 | struct drm_crtc_state *crtc_state; |
1157 | |
1158 | conn_state = drm_atomic_get_new_connector_state(state, connector); |
1159 | if (WARN_ON(!conn_state)) |
1160 | return -ENODEV; |
1161 | |
1162 | conn_state->self_refresh_aware = true; |
1163 | |
1164 | if (!conn_state->crtc) |
1165 | return 0; |
1166 | |
1167 | crtc_state = drm_atomic_get_new_crtc_state(state, crtc: conn_state->crtc); |
1168 | if (!crtc_state) |
1169 | return 0; |
1170 | |
1171 | if (crtc_state->self_refresh_active && !dp->psr_supported) |
1172 | return -EINVAL; |
1173 | |
1174 | return 0; |
1175 | } |
1176 | |
1177 | static const struct drm_connector_helper_funcs analogix_dp_connector_helper_funcs = { |
1178 | .get_modes = analogix_dp_get_modes, |
1179 | .best_encoder = analogix_dp_best_encoder, |
1180 | .atomic_check = analogix_dp_atomic_check, |
1181 | }; |
1182 | |
1183 | static enum drm_connector_status |
1184 | analogix_dp_detect(struct drm_connector *connector, bool force) |
1185 | { |
1186 | struct analogix_dp_device *dp = to_dp(connector); |
1187 | enum drm_connector_status status = connector_status_disconnected; |
1188 | int ret; |
1189 | |
1190 | if (dp->plat_data->panel) |
1191 | return connector_status_connected; |
1192 | |
1193 | ret = analogix_dp_prepare_panel(dp, prepare: true, is_modeset_prepare: false); |
1194 | if (ret) { |
1195 | DRM_ERROR("Failed to prepare panel (%d)\n" , ret); |
1196 | return connector_status_disconnected; |
1197 | } |
1198 | |
1199 | if (!analogix_dp_detect_hpd(dp)) |
1200 | status = connector_status_connected; |
1201 | |
1202 | ret = analogix_dp_prepare_panel(dp, prepare: false, is_modeset_prepare: false); |
1203 | if (ret) |
1204 | DRM_ERROR("Failed to unprepare panel (%d)\n" , ret); |
1205 | |
1206 | return status; |
1207 | } |
1208 | |
1209 | static const struct drm_connector_funcs analogix_dp_connector_funcs = { |
1210 | .fill_modes = drm_helper_probe_single_connector_modes, |
1211 | .detect = analogix_dp_detect, |
1212 | .destroy = drm_connector_cleanup, |
1213 | .reset = drm_atomic_helper_connector_reset, |
1214 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
1215 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
1216 | }; |
1217 | |
1218 | static int analogix_dp_bridge_attach(struct drm_bridge *bridge, |
1219 | enum drm_bridge_attach_flags flags) |
1220 | { |
1221 | struct analogix_dp_device *dp = bridge->driver_private; |
1222 | struct drm_encoder *encoder = dp->encoder; |
1223 | struct drm_connector *connector = NULL; |
1224 | int ret = 0; |
1225 | |
1226 | if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { |
1227 | DRM_ERROR("Fix bridge driver to make connector optional!" ); |
1228 | return -EINVAL; |
1229 | } |
1230 | |
1231 | if (!bridge->encoder) { |
1232 | DRM_ERROR("Parent encoder object not found" ); |
1233 | return -ENODEV; |
1234 | } |
1235 | |
1236 | if (!dp->plat_data->skip_connector) { |
1237 | connector = &dp->connector; |
1238 | connector->polled = DRM_CONNECTOR_POLL_HPD; |
1239 | |
1240 | ret = drm_connector_init(dev: dp->drm_dev, connector, |
1241 | funcs: &analogix_dp_connector_funcs, |
1242 | DRM_MODE_CONNECTOR_eDP); |
1243 | if (ret) { |
1244 | DRM_ERROR("Failed to initialize connector with drm\n" ); |
1245 | return ret; |
1246 | } |
1247 | |
1248 | drm_connector_helper_add(connector, |
1249 | funcs: &analogix_dp_connector_helper_funcs); |
1250 | drm_connector_attach_encoder(connector, encoder); |
1251 | } |
1252 | |
1253 | /* |
1254 | * NOTE: the connector registration is implemented in analogix |
1255 | * platform driver, that to say connector would be exist after |
1256 | * plat_data->attch return, that's why we record the connector |
1257 | * point after plat attached. |
1258 | */ |
1259 | if (dp->plat_data->attach) { |
1260 | ret = dp->plat_data->attach(dp->plat_data, bridge, connector); |
1261 | if (ret) { |
1262 | DRM_ERROR("Failed at platform attach func\n" ); |
1263 | return ret; |
1264 | } |
1265 | } |
1266 | |
1267 | return 0; |
1268 | } |
1269 | |
1270 | static |
1271 | struct drm_crtc *analogix_dp_get_old_crtc(struct analogix_dp_device *dp, |
1272 | struct drm_atomic_state *state) |
1273 | { |
1274 | struct drm_encoder *encoder = dp->encoder; |
1275 | struct drm_connector *connector; |
1276 | struct drm_connector_state *conn_state; |
1277 | |
1278 | connector = drm_atomic_get_old_connector_for_encoder(state, encoder); |
1279 | if (!connector) |
1280 | return NULL; |
1281 | |
1282 | conn_state = drm_atomic_get_old_connector_state(state, connector); |
1283 | if (!conn_state) |
1284 | return NULL; |
1285 | |
1286 | return conn_state->crtc; |
1287 | } |
1288 | |
1289 | static |
1290 | struct drm_crtc *analogix_dp_get_new_crtc(struct analogix_dp_device *dp, |
1291 | struct drm_atomic_state *state) |
1292 | { |
1293 | struct drm_encoder *encoder = dp->encoder; |
1294 | struct drm_connector *connector; |
1295 | struct drm_connector_state *conn_state; |
1296 | |
1297 | connector = drm_atomic_get_new_connector_for_encoder(state, encoder); |
1298 | if (!connector) |
1299 | return NULL; |
1300 | |
1301 | conn_state = drm_atomic_get_new_connector_state(state, connector); |
1302 | if (!conn_state) |
1303 | return NULL; |
1304 | |
1305 | return conn_state->crtc; |
1306 | } |
1307 | |
1308 | static void |
1309 | analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge, |
1310 | struct drm_bridge_state *old_bridge_state) |
1311 | { |
1312 | struct drm_atomic_state *old_state = old_bridge_state->base.state; |
1313 | struct analogix_dp_device *dp = bridge->driver_private; |
1314 | struct drm_crtc *crtc; |
1315 | struct drm_crtc_state *old_crtc_state; |
1316 | int ret; |
1317 | |
1318 | crtc = analogix_dp_get_new_crtc(dp, state: old_state); |
1319 | if (!crtc) |
1320 | return; |
1321 | |
1322 | old_crtc_state = drm_atomic_get_old_crtc_state(state: old_state, crtc); |
1323 | /* Don't touch the panel if we're coming back from PSR */ |
1324 | if (old_crtc_state && old_crtc_state->self_refresh_active) |
1325 | return; |
1326 | |
1327 | ret = analogix_dp_prepare_panel(dp, prepare: true, is_modeset_prepare: true); |
1328 | if (ret) |
1329 | DRM_ERROR("failed to setup the panel ret = %d\n" , ret); |
1330 | } |
1331 | |
1332 | static int analogix_dp_set_bridge(struct analogix_dp_device *dp) |
1333 | { |
1334 | int ret; |
1335 | |
1336 | pm_runtime_get_sync(dev: dp->dev); |
1337 | |
1338 | ret = clk_prepare_enable(clk: dp->clock); |
1339 | if (ret < 0) { |
1340 | DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n" , ret); |
1341 | goto out_dp_clk_pre; |
1342 | } |
1343 | |
1344 | if (dp->plat_data->power_on_start) |
1345 | dp->plat_data->power_on_start(dp->plat_data); |
1346 | |
1347 | phy_power_on(phy: dp->phy); |
1348 | |
1349 | ret = analogix_dp_init_dp(dp); |
1350 | if (ret) |
1351 | goto out_dp_init; |
1352 | |
1353 | /* |
1354 | * According to DP spec v1.3 chap 3.5.1.2 Link Training, |
1355 | * We should first make sure the HPD signal is asserted high by device |
1356 | * when we want to establish a link with it. |
1357 | */ |
1358 | ret = analogix_dp_detect_hpd(dp); |
1359 | if (ret) { |
1360 | DRM_ERROR("failed to get hpd single ret = %d\n" , ret); |
1361 | goto out_dp_init; |
1362 | } |
1363 | |
1364 | ret = analogix_dp_commit(dp); |
1365 | if (ret) { |
1366 | DRM_ERROR("dp commit error, ret = %d\n" , ret); |
1367 | goto out_dp_init; |
1368 | } |
1369 | |
1370 | if (dp->plat_data->power_on_end) |
1371 | dp->plat_data->power_on_end(dp->plat_data); |
1372 | |
1373 | enable_irq(irq: dp->irq); |
1374 | return 0; |
1375 | |
1376 | out_dp_init: |
1377 | phy_power_off(phy: dp->phy); |
1378 | if (dp->plat_data->power_off) |
1379 | dp->plat_data->power_off(dp->plat_data); |
1380 | clk_disable_unprepare(clk: dp->clock); |
1381 | out_dp_clk_pre: |
1382 | pm_runtime_put_sync(dev: dp->dev); |
1383 | |
1384 | return ret; |
1385 | } |
1386 | |
1387 | static void |
1388 | analogix_dp_bridge_atomic_enable(struct drm_bridge *bridge, |
1389 | struct drm_bridge_state *old_bridge_state) |
1390 | { |
1391 | struct drm_atomic_state *old_state = old_bridge_state->base.state; |
1392 | struct analogix_dp_device *dp = bridge->driver_private; |
1393 | struct drm_crtc *crtc; |
1394 | struct drm_crtc_state *old_crtc_state; |
1395 | int timeout_loop = 0; |
1396 | int ret; |
1397 | |
1398 | crtc = analogix_dp_get_new_crtc(dp, state: old_state); |
1399 | if (!crtc) |
1400 | return; |
1401 | |
1402 | old_crtc_state = drm_atomic_get_old_crtc_state(state: old_state, crtc); |
1403 | /* Not a full enable, just disable PSR and continue */ |
1404 | if (old_crtc_state && old_crtc_state->self_refresh_active) { |
1405 | ret = analogix_dp_disable_psr(dp); |
1406 | if (ret) |
1407 | DRM_ERROR("Failed to disable psr %d\n" , ret); |
1408 | return; |
1409 | } |
1410 | |
1411 | if (dp->dpms_mode == DRM_MODE_DPMS_ON) |
1412 | return; |
1413 | |
1414 | while (timeout_loop < MAX_PLL_LOCK_LOOP) { |
1415 | if (analogix_dp_set_bridge(dp) == 0) { |
1416 | dp->dpms_mode = DRM_MODE_DPMS_ON; |
1417 | return; |
1418 | } |
1419 | dev_err(dp->dev, "failed to set bridge, retry: %d\n" , |
1420 | timeout_loop); |
1421 | timeout_loop++; |
1422 | usleep_range(min: 10, max: 11); |
1423 | } |
1424 | dev_err(dp->dev, "too many times retry set bridge, give it up\n" ); |
1425 | } |
1426 | |
1427 | static void analogix_dp_bridge_disable(struct drm_bridge *bridge) |
1428 | { |
1429 | struct analogix_dp_device *dp = bridge->driver_private; |
1430 | int ret; |
1431 | |
1432 | if (dp->dpms_mode != DRM_MODE_DPMS_ON) |
1433 | return; |
1434 | |
1435 | if (dp->plat_data->panel) { |
1436 | if (drm_panel_disable(panel: dp->plat_data->panel)) { |
1437 | DRM_ERROR("failed to disable the panel\n" ); |
1438 | return; |
1439 | } |
1440 | } |
1441 | |
1442 | disable_irq(irq: dp->irq); |
1443 | |
1444 | if (dp->plat_data->power_off) |
1445 | dp->plat_data->power_off(dp->plat_data); |
1446 | |
1447 | analogix_dp_set_analog_power_down(dp, block: POWER_ALL, enable: 1); |
1448 | phy_power_off(phy: dp->phy); |
1449 | |
1450 | clk_disable_unprepare(clk: dp->clock); |
1451 | |
1452 | pm_runtime_put_sync(dev: dp->dev); |
1453 | |
1454 | ret = analogix_dp_prepare_panel(dp, prepare: false, is_modeset_prepare: true); |
1455 | if (ret) |
1456 | DRM_ERROR("failed to setup the panel ret = %d\n" , ret); |
1457 | |
1458 | dp->fast_train_enable = false; |
1459 | dp->psr_supported = false; |
1460 | dp->dpms_mode = DRM_MODE_DPMS_OFF; |
1461 | } |
1462 | |
1463 | static void |
1464 | analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge, |
1465 | struct drm_bridge_state *old_bridge_state) |
1466 | { |
1467 | struct drm_atomic_state *old_state = old_bridge_state->base.state; |
1468 | struct analogix_dp_device *dp = bridge->driver_private; |
1469 | struct drm_crtc *old_crtc, *new_crtc; |
1470 | struct drm_crtc_state *old_crtc_state = NULL; |
1471 | struct drm_crtc_state *new_crtc_state = NULL; |
1472 | int ret; |
1473 | |
1474 | new_crtc = analogix_dp_get_new_crtc(dp, state: old_state); |
1475 | if (!new_crtc) |
1476 | goto out; |
1477 | |
1478 | new_crtc_state = drm_atomic_get_new_crtc_state(state: old_state, crtc: new_crtc); |
1479 | if (!new_crtc_state) |
1480 | goto out; |
1481 | |
1482 | /* Don't do a full disable on PSR transitions */ |
1483 | if (new_crtc_state->self_refresh_active) |
1484 | return; |
1485 | |
1486 | out: |
1487 | old_crtc = analogix_dp_get_old_crtc(dp, state: old_state); |
1488 | if (old_crtc) { |
1489 | old_crtc_state = drm_atomic_get_old_crtc_state(state: old_state, |
1490 | crtc: old_crtc); |
1491 | |
1492 | /* When moving from PSR to fully disabled, exit PSR first. */ |
1493 | if (old_crtc_state && old_crtc_state->self_refresh_active) { |
1494 | ret = analogix_dp_disable_psr(dp); |
1495 | if (ret) |
1496 | DRM_ERROR("Failed to disable psr (%d)\n" , ret); |
1497 | } |
1498 | } |
1499 | |
1500 | analogix_dp_bridge_disable(bridge); |
1501 | } |
1502 | |
1503 | static void |
1504 | analogix_dp_bridge_atomic_post_disable(struct drm_bridge *bridge, |
1505 | struct drm_bridge_state *old_bridge_state) |
1506 | { |
1507 | struct drm_atomic_state *old_state = old_bridge_state->base.state; |
1508 | struct analogix_dp_device *dp = bridge->driver_private; |
1509 | struct drm_crtc *crtc; |
1510 | struct drm_crtc_state *new_crtc_state; |
1511 | int ret; |
1512 | |
1513 | crtc = analogix_dp_get_new_crtc(dp, state: old_state); |
1514 | if (!crtc) |
1515 | return; |
1516 | |
1517 | new_crtc_state = drm_atomic_get_new_crtc_state(state: old_state, crtc); |
1518 | if (!new_crtc_state || !new_crtc_state->self_refresh_active) |
1519 | return; |
1520 | |
1521 | ret = analogix_dp_enable_psr(dp); |
1522 | if (ret) |
1523 | DRM_ERROR("Failed to enable psr (%d)\n" , ret); |
1524 | } |
1525 | |
1526 | static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge, |
1527 | const struct drm_display_mode *orig_mode, |
1528 | const struct drm_display_mode *mode) |
1529 | { |
1530 | struct analogix_dp_device *dp = bridge->driver_private; |
1531 | struct drm_display_info *display_info = &dp->connector.display_info; |
1532 | struct video_info *video = &dp->video_info; |
1533 | struct device_node *dp_node = dp->dev->of_node; |
1534 | int vic; |
1535 | |
1536 | /* Input video interlaces & hsync pol & vsync pol */ |
1537 | video->interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); |
1538 | video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); |
1539 | video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); |
1540 | |
1541 | /* Input video dynamic_range & colorimetry */ |
1542 | vic = drm_match_cea_mode(to_match: mode); |
1543 | if ((vic == 6) || (vic == 7) || (vic == 21) || (vic == 22) || |
1544 | (vic == 2) || (vic == 3) || (vic == 17) || (vic == 18)) { |
1545 | video->dynamic_range = CEA; |
1546 | video->ycbcr_coeff = COLOR_YCBCR601; |
1547 | } else if (vic) { |
1548 | video->dynamic_range = CEA; |
1549 | video->ycbcr_coeff = COLOR_YCBCR709; |
1550 | } else { |
1551 | video->dynamic_range = VESA; |
1552 | video->ycbcr_coeff = COLOR_YCBCR709; |
1553 | } |
1554 | |
1555 | /* Input vide bpc and color_formats */ |
1556 | switch (display_info->bpc) { |
1557 | case 12: |
1558 | video->color_depth = COLOR_12; |
1559 | break; |
1560 | case 10: |
1561 | video->color_depth = COLOR_10; |
1562 | break; |
1563 | case 8: |
1564 | video->color_depth = COLOR_8; |
1565 | break; |
1566 | case 6: |
1567 | video->color_depth = COLOR_6; |
1568 | break; |
1569 | default: |
1570 | video->color_depth = COLOR_8; |
1571 | break; |
1572 | } |
1573 | if (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR444) |
1574 | video->color_space = COLOR_YCBCR444; |
1575 | else if (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR422) |
1576 | video->color_space = COLOR_YCBCR422; |
1577 | else |
1578 | video->color_space = COLOR_RGB; |
1579 | |
1580 | /* |
1581 | * NOTE: those property parsing code is used for providing backward |
1582 | * compatibility for samsung platform. |
1583 | * Due to we used the "of_property_read_u32" interfaces, when this |
1584 | * property isn't present, the "video_info" can keep the original |
1585 | * values and wouldn't be modified. |
1586 | */ |
1587 | of_property_read_u32(np: dp_node, propname: "samsung,color-space" , |
1588 | out_value: &video->color_space); |
1589 | of_property_read_u32(np: dp_node, propname: "samsung,dynamic-range" , |
1590 | out_value: &video->dynamic_range); |
1591 | of_property_read_u32(np: dp_node, propname: "samsung,ycbcr-coeff" , |
1592 | out_value: &video->ycbcr_coeff); |
1593 | of_property_read_u32(np: dp_node, propname: "samsung,color-depth" , |
1594 | out_value: &video->color_depth); |
1595 | if (of_property_read_bool(np: dp_node, propname: "hsync-active-high" )) |
1596 | video->h_sync_polarity = true; |
1597 | if (of_property_read_bool(np: dp_node, propname: "vsync-active-high" )) |
1598 | video->v_sync_polarity = true; |
1599 | if (of_property_read_bool(np: dp_node, propname: "interlaced" )) |
1600 | video->interlaced = true; |
1601 | } |
1602 | |
1603 | static const struct drm_bridge_funcs analogix_dp_bridge_funcs = { |
1604 | .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, |
1605 | .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, |
1606 | .atomic_reset = drm_atomic_helper_bridge_reset, |
1607 | .atomic_pre_enable = analogix_dp_bridge_atomic_pre_enable, |
1608 | .atomic_enable = analogix_dp_bridge_atomic_enable, |
1609 | .atomic_disable = analogix_dp_bridge_atomic_disable, |
1610 | .atomic_post_disable = analogix_dp_bridge_atomic_post_disable, |
1611 | .mode_set = analogix_dp_bridge_mode_set, |
1612 | .attach = analogix_dp_bridge_attach, |
1613 | }; |
1614 | |
1615 | static int analogix_dp_create_bridge(struct drm_device *drm_dev, |
1616 | struct analogix_dp_device *dp) |
1617 | { |
1618 | struct drm_bridge *bridge; |
1619 | |
1620 | bridge = devm_kzalloc(dev: drm_dev->dev, size: sizeof(*bridge), GFP_KERNEL); |
1621 | if (!bridge) { |
1622 | DRM_ERROR("failed to allocate for drm bridge\n" ); |
1623 | return -ENOMEM; |
1624 | } |
1625 | |
1626 | dp->bridge = bridge; |
1627 | |
1628 | bridge->driver_private = dp; |
1629 | bridge->funcs = &analogix_dp_bridge_funcs; |
1630 | |
1631 | return drm_bridge_attach(encoder: dp->encoder, bridge, NULL, flags: 0); |
1632 | } |
1633 | |
1634 | static int analogix_dp_dt_parse_pdata(struct analogix_dp_device *dp) |
1635 | { |
1636 | struct device_node *dp_node = dp->dev->of_node; |
1637 | struct video_info *video_info = &dp->video_info; |
1638 | |
1639 | switch (dp->plat_data->dev_type) { |
1640 | case RK3288_DP: |
1641 | case RK3399_EDP: |
1642 | /* |
1643 | * Like Rk3288 DisplayPort TRM indicate that "Main link |
1644 | * containing 4 physical lanes of 2.7/1.62 Gbps/lane". |
1645 | */ |
1646 | video_info->max_link_rate = 0x0A; |
1647 | video_info->max_lane_count = 0x04; |
1648 | break; |
1649 | case EXYNOS_DP: |
1650 | /* |
1651 | * NOTE: those property parseing code is used for |
1652 | * providing backward compatibility for samsung platform. |
1653 | */ |
1654 | of_property_read_u32(np: dp_node, propname: "samsung,link-rate" , |
1655 | out_value: &video_info->max_link_rate); |
1656 | of_property_read_u32(np: dp_node, propname: "samsung,lane-count" , |
1657 | out_value: &video_info->max_lane_count); |
1658 | break; |
1659 | } |
1660 | |
1661 | return 0; |
1662 | } |
1663 | |
1664 | static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, |
1665 | struct drm_dp_aux_msg *msg) |
1666 | { |
1667 | struct analogix_dp_device *dp = to_dp(aux); |
1668 | int ret; |
1669 | |
1670 | pm_runtime_get_sync(dev: dp->dev); |
1671 | |
1672 | ret = analogix_dp_detect_hpd(dp); |
1673 | if (ret) |
1674 | goto out; |
1675 | |
1676 | ret = analogix_dp_transfer(dp, msg); |
1677 | out: |
1678 | pm_runtime_mark_last_busy(dev: dp->dev); |
1679 | pm_runtime_put_autosuspend(dev: dp->dev); |
1680 | |
1681 | return ret; |
1682 | } |
1683 | |
1684 | struct analogix_dp_device * |
1685 | analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data) |
1686 | { |
1687 | struct platform_device *pdev = to_platform_device(dev); |
1688 | struct analogix_dp_device *dp; |
1689 | struct resource *res; |
1690 | unsigned int irq_flags; |
1691 | int ret; |
1692 | |
1693 | if (!plat_data) { |
1694 | dev_err(dev, "Invalided input plat_data\n" ); |
1695 | return ERR_PTR(error: -EINVAL); |
1696 | } |
1697 | |
1698 | dp = devm_kzalloc(dev, size: sizeof(struct analogix_dp_device), GFP_KERNEL); |
1699 | if (!dp) |
1700 | return ERR_PTR(error: -ENOMEM); |
1701 | |
1702 | dp->dev = &pdev->dev; |
1703 | dp->dpms_mode = DRM_MODE_DPMS_OFF; |
1704 | |
1705 | mutex_init(&dp->panel_lock); |
1706 | dp->panel_is_modeset = false; |
1707 | |
1708 | /* |
1709 | * platform dp driver need containor_of the plat_data to get |
1710 | * the driver private data, so we need to store the point of |
1711 | * plat_data, not the context of plat_data. |
1712 | */ |
1713 | dp->plat_data = plat_data; |
1714 | |
1715 | ret = analogix_dp_dt_parse_pdata(dp); |
1716 | if (ret) |
1717 | return ERR_PTR(error: ret); |
1718 | |
1719 | dp->phy = devm_phy_get(dev: dp->dev, string: "dp" ); |
1720 | if (IS_ERR(ptr: dp->phy)) { |
1721 | dev_err(dp->dev, "no DP phy configured\n" ); |
1722 | ret = PTR_ERR(ptr: dp->phy); |
1723 | if (ret) { |
1724 | /* |
1725 | * phy itself is not enabled, so we can move forward |
1726 | * assigning NULL to phy pointer. |
1727 | */ |
1728 | if (ret == -ENOSYS || ret == -ENODEV) |
1729 | dp->phy = NULL; |
1730 | else |
1731 | return ERR_PTR(error: ret); |
1732 | } |
1733 | } |
1734 | |
1735 | dp->clock = devm_clk_get(dev: &pdev->dev, id: "dp" ); |
1736 | if (IS_ERR(ptr: dp->clock)) { |
1737 | dev_err(&pdev->dev, "failed to get clock\n" ); |
1738 | return ERR_CAST(ptr: dp->clock); |
1739 | } |
1740 | |
1741 | clk_prepare_enable(clk: dp->clock); |
1742 | |
1743 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1744 | |
1745 | dp->reg_base = devm_ioremap_resource(dev: &pdev->dev, res); |
1746 | if (IS_ERR(ptr: dp->reg_base)) { |
1747 | ret = PTR_ERR(ptr: dp->reg_base); |
1748 | goto err_disable_clk; |
1749 | } |
1750 | |
1751 | dp->force_hpd = of_property_read_bool(np: dev->of_node, propname: "force-hpd" ); |
1752 | |
1753 | /* Try two different names */ |
1754 | dp->hpd_gpiod = devm_gpiod_get_optional(dev, con_id: "hpd" , flags: GPIOD_IN); |
1755 | if (!dp->hpd_gpiod) |
1756 | dp->hpd_gpiod = devm_gpiod_get_optional(dev, con_id: "samsung,hpd" , |
1757 | flags: GPIOD_IN); |
1758 | if (IS_ERR(ptr: dp->hpd_gpiod)) { |
1759 | dev_err(dev, "error getting HDP GPIO: %ld\n" , |
1760 | PTR_ERR(dp->hpd_gpiod)); |
1761 | ret = PTR_ERR(ptr: dp->hpd_gpiod); |
1762 | goto err_disable_clk; |
1763 | } |
1764 | |
1765 | if (dp->hpd_gpiod) { |
1766 | /* |
1767 | * Set up the hotplug GPIO from the device tree as an interrupt. |
1768 | * Simply specifying a different interrupt in the device tree |
1769 | * doesn't work since we handle hotplug rather differently when |
1770 | * using a GPIO. We also need the actual GPIO specifier so |
1771 | * that we can get the current state of the GPIO. |
1772 | */ |
1773 | dp->irq = gpiod_to_irq(desc: dp->hpd_gpiod); |
1774 | irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; |
1775 | } else { |
1776 | dp->irq = platform_get_irq(pdev, 0); |
1777 | irq_flags = 0; |
1778 | } |
1779 | |
1780 | if (dp->irq == -ENXIO) { |
1781 | dev_err(&pdev->dev, "failed to get irq\n" ); |
1782 | ret = -ENODEV; |
1783 | goto err_disable_clk; |
1784 | } |
1785 | |
1786 | ret = devm_request_threaded_irq(dev: &pdev->dev, irq: dp->irq, |
1787 | handler: analogix_dp_hardirq, |
1788 | thread_fn: analogix_dp_irq_thread, |
1789 | irqflags: irq_flags, devname: "analogix-dp" , dev_id: dp); |
1790 | if (ret) { |
1791 | dev_err(&pdev->dev, "failed to request irq\n" ); |
1792 | goto err_disable_clk; |
1793 | } |
1794 | disable_irq(irq: dp->irq); |
1795 | |
1796 | return dp; |
1797 | |
1798 | err_disable_clk: |
1799 | clk_disable_unprepare(clk: dp->clock); |
1800 | return ERR_PTR(error: ret); |
1801 | } |
1802 | EXPORT_SYMBOL_GPL(analogix_dp_probe); |
1803 | |
1804 | int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev) |
1805 | { |
1806 | int ret; |
1807 | |
1808 | dp->drm_dev = drm_dev; |
1809 | dp->encoder = dp->plat_data->encoder; |
1810 | |
1811 | dp->aux.name = "DP-AUX" ; |
1812 | dp->aux.transfer = analogix_dpaux_transfer; |
1813 | dp->aux.dev = dp->dev; |
1814 | dp->aux.drm_dev = drm_dev; |
1815 | |
1816 | ret = drm_dp_aux_register(aux: &dp->aux); |
1817 | if (ret) |
1818 | return ret; |
1819 | |
1820 | pm_runtime_use_autosuspend(dev: dp->dev); |
1821 | pm_runtime_set_autosuspend_delay(dev: dp->dev, delay: 100); |
1822 | pm_runtime_enable(dev: dp->dev); |
1823 | |
1824 | ret = analogix_dp_create_bridge(drm_dev, dp); |
1825 | if (ret) { |
1826 | DRM_ERROR("failed to create bridge (%d)\n" , ret); |
1827 | goto err_disable_pm_runtime; |
1828 | } |
1829 | |
1830 | return 0; |
1831 | |
1832 | err_disable_pm_runtime: |
1833 | pm_runtime_dont_use_autosuspend(dev: dp->dev); |
1834 | pm_runtime_disable(dev: dp->dev); |
1835 | drm_dp_aux_unregister(aux: &dp->aux); |
1836 | |
1837 | return ret; |
1838 | } |
1839 | EXPORT_SYMBOL_GPL(analogix_dp_bind); |
1840 | |
1841 | void analogix_dp_unbind(struct analogix_dp_device *dp) |
1842 | { |
1843 | analogix_dp_bridge_disable(bridge: dp->bridge); |
1844 | dp->connector.funcs->destroy(&dp->connector); |
1845 | |
1846 | if (dp->plat_data->panel) { |
1847 | if (drm_panel_unprepare(panel: dp->plat_data->panel)) |
1848 | DRM_ERROR("failed to turnoff the panel\n" ); |
1849 | } |
1850 | |
1851 | drm_dp_aux_unregister(aux: &dp->aux); |
1852 | pm_runtime_dont_use_autosuspend(dev: dp->dev); |
1853 | pm_runtime_disable(dev: dp->dev); |
1854 | } |
1855 | EXPORT_SYMBOL_GPL(analogix_dp_unbind); |
1856 | |
1857 | void analogix_dp_remove(struct analogix_dp_device *dp) |
1858 | { |
1859 | clk_disable_unprepare(clk: dp->clock); |
1860 | } |
1861 | EXPORT_SYMBOL_GPL(analogix_dp_remove); |
1862 | |
1863 | #ifdef CONFIG_PM |
1864 | int analogix_dp_suspend(struct analogix_dp_device *dp) |
1865 | { |
1866 | clk_disable_unprepare(clk: dp->clock); |
1867 | return 0; |
1868 | } |
1869 | EXPORT_SYMBOL_GPL(analogix_dp_suspend); |
1870 | |
1871 | int analogix_dp_resume(struct analogix_dp_device *dp) |
1872 | { |
1873 | int ret; |
1874 | |
1875 | ret = clk_prepare_enable(clk: dp->clock); |
1876 | if (ret < 0) { |
1877 | DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n" , ret); |
1878 | return ret; |
1879 | } |
1880 | |
1881 | return 0; |
1882 | } |
1883 | EXPORT_SYMBOL_GPL(analogix_dp_resume); |
1884 | #endif |
1885 | |
1886 | int analogix_dp_start_crc(struct drm_connector *connector) |
1887 | { |
1888 | struct analogix_dp_device *dp = to_dp(connector); |
1889 | |
1890 | if (!connector->state->crtc) { |
1891 | DRM_ERROR("Connector %s doesn't currently have a CRTC.\n" , |
1892 | connector->name); |
1893 | return -EINVAL; |
1894 | } |
1895 | |
1896 | return drm_dp_start_crc(aux: &dp->aux, crtc: connector->state->crtc); |
1897 | } |
1898 | EXPORT_SYMBOL_GPL(analogix_dp_start_crc); |
1899 | |
1900 | int analogix_dp_stop_crc(struct drm_connector *connector) |
1901 | { |
1902 | struct analogix_dp_device *dp = to_dp(connector); |
1903 | |
1904 | return drm_dp_stop_crc(aux: &dp->aux); |
1905 | } |
1906 | EXPORT_SYMBOL_GPL(analogix_dp_stop_crc); |
1907 | |
1908 | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>" ); |
1909 | MODULE_DESCRIPTION("Analogix DP Core Driver" ); |
1910 | MODULE_LICENSE("GPL v2" ); |
1911 | |