2 * Samsung SoC DP (Display Port) interface driver.
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/slab.h>
16 #include <linux/err.h>
17 #include <linux/clk.h>
19 #include <linux/interrupt.h>
20 #include <linux/delay.h>
22 #include <video/exynos_dp.h>
26 #include "exynos_dp_core.h"
28 static int exynos_dp_init_dp(struct exynos_dp_device
*dp
)
32 /* SW defined function Normal operation */
33 exynos_dp_enable_sw_function(dp
);
35 exynos_dp_config_interrupt(dp
);
36 exynos_dp_init_analog_func(dp
);
38 exynos_dp_init_hpd(dp
);
39 exynos_dp_init_aux(dp
);
44 static int exynos_dp_detect_hpd(struct exynos_dp_device
*dp
)
48 exynos_dp_init_hpd(dp
);
52 while (exynos_dp_get_plug_in_status(dp
) != 0) {
54 if (DP_TIMEOUT_LOOP_COUNT
< timeout_loop
) {
55 dev_err(dp
->dev
, "failed to get hpd plug status\n");
64 static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data
)
67 unsigned char sum
= 0;
69 for (i
= 0; i
< EDID_BLOCK_LENGTH
; i
++)
70 sum
= sum
+ edid_data
[i
];
75 static int exynos_dp_read_edid(struct exynos_dp_device
*dp
)
77 unsigned char edid
[EDID_BLOCK_LENGTH
* 2];
78 unsigned int extend_block
= 0;
80 unsigned char test_vector
;
84 * EDID device address is 0x50.
85 * However, if necessary, you must have set upper address
86 * into E-EDID in I2C device, 0x30.
89 /* Read Extension Flag, Number of 128-byte EDID extension blocks */
90 exynos_dp_read_byte_from_i2c(dp
, I2C_EDID_DEVICE_ADDR
,
94 if (extend_block
> 0) {
95 dev_dbg(dp
->dev
, "EDID data includes a single extension!\n");
98 retval
= exynos_dp_read_bytes_from_i2c(dp
, I2C_EDID_DEVICE_ADDR
,
101 &edid
[EDID_HEADER_PATTERN
]);
103 dev_err(dp
->dev
, "EDID Read failed!\n");
106 sum
= exynos_dp_calc_edid_check_sum(edid
);
108 dev_err(dp
->dev
, "EDID bad checksum!\n");
112 /* Read additional EDID data */
113 retval
= exynos_dp_read_bytes_from_i2c(dp
,
114 I2C_EDID_DEVICE_ADDR
,
117 &edid
[EDID_BLOCK_LENGTH
]);
119 dev_err(dp
->dev
, "EDID Read failed!\n");
122 sum
= exynos_dp_calc_edid_check_sum(&edid
[EDID_BLOCK_LENGTH
]);
124 dev_err(dp
->dev
, "EDID bad checksum!\n");
128 exynos_dp_read_byte_from_dpcd(dp
, DPCD_ADDR_TEST_REQUEST
,
130 if (test_vector
& DPCD_TEST_EDID_READ
) {
131 exynos_dp_write_byte_to_dpcd(dp
,
132 DPCD_ADDR_TEST_EDID_CHECKSUM
,
133 edid
[EDID_BLOCK_LENGTH
+ EDID_CHECKSUM
]);
134 exynos_dp_write_byte_to_dpcd(dp
,
135 DPCD_ADDR_TEST_RESPONSE
,
136 DPCD_TEST_EDID_CHECKSUM_WRITE
);
139 dev_info(dp
->dev
, "EDID data does not include any extensions.\n");
142 retval
= exynos_dp_read_bytes_from_i2c(dp
,
143 I2C_EDID_DEVICE_ADDR
,
146 &edid
[EDID_HEADER_PATTERN
]);
148 dev_err(dp
->dev
, "EDID Read failed!\n");
151 sum
= exynos_dp_calc_edid_check_sum(edid
);
153 dev_err(dp
->dev
, "EDID bad checksum!\n");
157 exynos_dp_read_byte_from_dpcd(dp
,
158 DPCD_ADDR_TEST_REQUEST
,
160 if (test_vector
& DPCD_TEST_EDID_READ
) {
161 exynos_dp_write_byte_to_dpcd(dp
,
162 DPCD_ADDR_TEST_EDID_CHECKSUM
,
163 edid
[EDID_CHECKSUM
]);
164 exynos_dp_write_byte_to_dpcd(dp
,
165 DPCD_ADDR_TEST_RESPONSE
,
166 DPCD_TEST_EDID_CHECKSUM_WRITE
);
170 dev_err(dp
->dev
, "EDID Read success!\n");
174 static int exynos_dp_handle_edid(struct exynos_dp_device
*dp
)
180 /* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
181 exynos_dp_read_bytes_from_dpcd(dp
,
186 for (i
= 0; i
< 3; i
++) {
187 retval
= exynos_dp_read_edid(dp
);
195 static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device
*dp
,
200 exynos_dp_read_byte_from_dpcd(dp
, DPCD_ADDR_LANE_COUNT_SET
, &data
);
203 exynos_dp_write_byte_to_dpcd(dp
, DPCD_ADDR_LANE_COUNT_SET
,
204 DPCD_ENHANCED_FRAME_EN
|
205 DPCD_LANE_COUNT_SET(data
));
207 exynos_dp_write_byte_to_dpcd(dp
, DPCD_ADDR_LANE_COUNT_SET
,
208 DPCD_LANE_COUNT_SET(data
));
211 static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device
*dp
)
216 exynos_dp_read_byte_from_dpcd(dp
, DPCD_ADDR_MAX_LANE_COUNT
, &data
);
217 retval
= DPCD_ENHANCED_FRAME_CAP(data
);
222 static void exynos_dp_set_enhanced_mode(struct exynos_dp_device
*dp
)
226 data
= exynos_dp_is_enhanced_mode_available(dp
);
227 exynos_dp_enable_rx_to_enhanced_mode(dp
, data
);
228 exynos_dp_enable_enhanced_mode(dp
, data
);
231 static void exynos_dp_training_pattern_dis(struct exynos_dp_device
*dp
)
233 exynos_dp_set_training_pattern(dp
, DP_NONE
);
235 exynos_dp_write_byte_to_dpcd(dp
,
236 DPCD_ADDR_TRAINING_PATTERN_SET
,
237 DPCD_TRAINING_PATTERN_DISABLED
);
240 static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device
*dp
,
241 int pre_emphasis
, int lane
)
245 exynos_dp_set_lane0_pre_emphasis(dp
, pre_emphasis
);
248 exynos_dp_set_lane1_pre_emphasis(dp
, pre_emphasis
);
252 exynos_dp_set_lane2_pre_emphasis(dp
, pre_emphasis
);
256 exynos_dp_set_lane3_pre_emphasis(dp
, pre_emphasis
);
261 static void exynos_dp_link_start(struct exynos_dp_device
*dp
)
267 lane_count
= dp
->link_train
.lane_count
;
269 dp
->link_train
.lt_state
= CLOCK_RECOVERY
;
270 dp
->link_train
.eq_loop
= 0;
272 for (lane
= 0; lane
< lane_count
; lane
++)
273 dp
->link_train
.cr_loop
[lane
] = 0;
275 /* Set sink to D0 (Sink Not Ready) mode. */
276 exynos_dp_write_byte_to_dpcd(dp
, DPCD_ADDR_SINK_POWER_STATE
,
277 DPCD_SET_POWER_STATE_D0
);
279 /* Set link rate and count as you want to establish*/
280 exynos_dp_set_link_bandwidth(dp
, dp
->link_train
.link_rate
);
281 exynos_dp_set_lane_count(dp
, dp
->link_train
.lane_count
);
283 /* Setup RX configuration */
284 buf
[0] = dp
->link_train
.link_rate
;
285 buf
[1] = dp
->link_train
.lane_count
;
286 exynos_dp_write_bytes_to_dpcd(dp
, DPCD_ADDR_LINK_BW_SET
,
289 /* Set TX pre-emphasis to minimum */
290 for (lane
= 0; lane
< lane_count
; lane
++)
291 exynos_dp_set_lane_lane_pre_emphasis(dp
,
292 PRE_EMPHASIS_LEVEL_0
, lane
);
294 /* Set training pattern 1 */
295 exynos_dp_set_training_pattern(dp
, TRAINING_PTN1
);
297 /* Set RX training pattern */
298 buf
[0] = DPCD_SCRAMBLING_DISABLED
|
299 DPCD_TRAINING_PATTERN_1
;
300 exynos_dp_write_byte_to_dpcd(dp
,
301 DPCD_ADDR_TRAINING_PATTERN_SET
, buf
[0]);
303 for (lane
= 0; lane
< lane_count
; lane
++)
304 buf
[lane
] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0
|
305 DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0
;
306 exynos_dp_write_bytes_to_dpcd(dp
,
307 DPCD_ADDR_TRAINING_PATTERN_SET
,
311 static unsigned char exynos_dp_get_lane_status(u8 link_status
[6], int lane
)
313 int shift
= (lane
& 1) * 4;
314 u8 link_value
= link_status
[lane
>>1];
316 return (link_value
>> shift
) & 0xf;
319 static int exynos_dp_clock_recovery_ok(u8 link_status
[6], int lane_count
)
324 for (lane
= 0; lane
< lane_count
; lane
++) {
325 lane_status
= exynos_dp_get_lane_status(link_status
, lane
);
326 if ((lane_status
& DPCD_LANE_CR_DONE
) == 0)
332 static int exynos_dp_channel_eq_ok(u8 link_status
[6], int lane_count
)
338 lane_align
= link_status
[2];
339 if ((lane_align
== DPCD_INTERLANE_ALIGN_DONE
) == 0)
342 for (lane
= 0; lane
< lane_count
; lane
++) {
343 lane_status
= exynos_dp_get_lane_status(link_status
, lane
);
344 lane_status
&= DPCD_CHANNEL_EQ_BITS
;
345 if (lane_status
!= DPCD_CHANNEL_EQ_BITS
)
351 static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request
[2],
354 int shift
= (lane
& 1) * 4;
355 u8 link_value
= adjust_request
[lane
>>1];
357 return (link_value
>> shift
) & 0x3;
360 static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
361 u8 adjust_request
[2],
364 int shift
= (lane
& 1) * 4;
365 u8 link_value
= adjust_request
[lane
>>1];
367 return ((link_value
>> shift
) & 0xc) >> 2;
370 static void exynos_dp_set_lane_link_training(struct exynos_dp_device
*dp
,
371 u8 training_lane_set
, int lane
)
375 exynos_dp_set_lane0_link_training(dp
, training_lane_set
);
378 exynos_dp_set_lane1_link_training(dp
, training_lane_set
);
382 exynos_dp_set_lane2_link_training(dp
, training_lane_set
);
386 exynos_dp_set_lane3_link_training(dp
, training_lane_set
);
391 static unsigned int exynos_dp_get_lane_link_training(
392 struct exynos_dp_device
*dp
,
399 reg
= exynos_dp_get_lane0_link_training(dp
);
402 reg
= exynos_dp_get_lane1_link_training(dp
);
405 reg
= exynos_dp_get_lane2_link_training(dp
);
408 reg
= exynos_dp_get_lane3_link_training(dp
);
415 static void exynos_dp_reduce_link_rate(struct exynos_dp_device
*dp
)
417 if (dp
->link_train
.link_rate
== LINK_RATE_2_70GBPS
) {
418 /* set to reduced bit rate */
419 dp
->link_train
.link_rate
= LINK_RATE_1_62GBPS
;
420 dev_err(dp
->dev
, "set to bandwidth %.2x\n",
421 dp
->link_train
.link_rate
);
422 dp
->link_train
.lt_state
= START
;
424 exynos_dp_training_pattern_dis(dp
);
425 /* set enhanced mode if available */
426 exynos_dp_set_enhanced_mode(dp
);
427 dp
->link_train
.lt_state
= FAILED
;
431 static void exynos_dp_get_adjust_train(struct exynos_dp_device
*dp
,
432 u8 adjust_request
[2])
440 lane_count
= dp
->link_train
.lane_count
;
441 for (lane
= 0; lane
< lane_count
; lane
++) {
442 voltage_swing
= exynos_dp_get_adjust_request_voltage(
443 adjust_request
, lane
);
444 pre_emphasis
= exynos_dp_get_adjust_request_pre_emphasis(
445 adjust_request
, lane
);
446 training_lane
= DPCD_VOLTAGE_SWING_SET(voltage_swing
) |
447 DPCD_PRE_EMPHASIS_SET(pre_emphasis
);
449 if (voltage_swing
== VOLTAGE_LEVEL_3
||
450 pre_emphasis
== PRE_EMPHASIS_LEVEL_3
) {
451 training_lane
|= DPCD_MAX_SWING_REACHED
;
452 training_lane
|= DPCD_MAX_PRE_EMPHASIS_REACHED
;
454 dp
->link_train
.training_lane
[lane
] = training_lane
;
458 static int exynos_dp_check_max_cr_loop(struct exynos_dp_device
*dp
,
464 lane_count
= dp
->link_train
.lane_count
;
465 for (lane
= 0; lane
< lane_count
; lane
++) {
466 if (voltage_swing
== VOLTAGE_LEVEL_3
||
467 dp
->link_train
.cr_loop
[lane
] == MAX_CR_LOOP
)
473 static int exynos_dp_process_clock_recovery(struct exynos_dp_device
*dp
)
488 exynos_dp_read_bytes_from_dpcd(dp
, DPCD_ADDR_LANE0_1_STATUS
,
490 lane_count
= dp
->link_train
.lane_count
;
492 if (exynos_dp_clock_recovery_ok(link_status
, lane_count
) == 0) {
493 /* set training pattern 2 for EQ */
494 exynos_dp_set_training_pattern(dp
, TRAINING_PTN2
);
496 adjust_request
= link_status
+ (DPCD_ADDR_ADJUST_REQUEST_LANE0_1
497 - DPCD_ADDR_LANE0_1_STATUS
);
499 exynos_dp_get_adjust_train(dp
, adjust_request
);
501 buf
[0] = DPCD_SCRAMBLING_DISABLED
|
502 DPCD_TRAINING_PATTERN_2
;
503 exynos_dp_write_byte_to_dpcd(dp
,
504 DPCD_ADDR_TRAINING_LANE0_SET
,
507 for (lane
= 0; lane
< lane_count
; lane
++) {
508 exynos_dp_set_lane_link_training(dp
,
509 dp
->link_train
.training_lane
[lane
],
511 buf
[lane
] = dp
->link_train
.training_lane
[lane
];
512 exynos_dp_write_byte_to_dpcd(dp
,
513 DPCD_ADDR_TRAINING_LANE0_SET
+ lane
,
516 dp
->link_train
.lt_state
= EQUALIZER_TRAINING
;
518 exynos_dp_read_byte_from_dpcd(dp
,
519 DPCD_ADDR_ADJUST_REQUEST_LANE0_1
,
521 adjust_request
[0] = data
;
523 exynos_dp_read_byte_from_dpcd(dp
,
524 DPCD_ADDR_ADJUST_REQUEST_LANE2_3
,
526 adjust_request
[1] = data
;
528 for (lane
= 0; lane
< lane_count
; lane
++) {
529 training_lane
= exynos_dp_get_lane_link_training(
531 voltage_swing
= exynos_dp_get_adjust_request_voltage(
532 adjust_request
, lane
);
533 pre_emphasis
= exynos_dp_get_adjust_request_pre_emphasis(
534 adjust_request
, lane
);
535 if ((DPCD_VOLTAGE_SWING_GET(training_lane
) == voltage_swing
) &&
536 (DPCD_PRE_EMPHASIS_GET(training_lane
) == pre_emphasis
))
537 dp
->link_train
.cr_loop
[lane
]++;
538 dp
->link_train
.training_lane
[lane
] = training_lane
;
541 if (exynos_dp_check_max_cr_loop(dp
, voltage_swing
) != 0) {
542 exynos_dp_reduce_link_rate(dp
);
544 exynos_dp_get_adjust_train(dp
, adjust_request
);
546 for (lane
= 0; lane
< lane_count
; lane
++) {
547 exynos_dp_set_lane_link_training(dp
,
548 dp
->link_train
.training_lane
[lane
],
550 buf
[lane
] = dp
->link_train
.training_lane
[lane
];
551 exynos_dp_write_byte_to_dpcd(dp
,
552 DPCD_ADDR_TRAINING_LANE0_SET
+ lane
,
561 static int exynos_dp_process_equalizer_training(struct exynos_dp_device
*dp
)
573 exynos_dp_read_bytes_from_dpcd(dp
, DPCD_ADDR_LANE0_1_STATUS
,
575 lane_count
= dp
->link_train
.lane_count
;
577 if (exynos_dp_clock_recovery_ok(link_status
, lane_count
) == 0) {
578 adjust_request
= link_status
+ (DPCD_ADDR_ADJUST_REQUEST_LANE0_1
579 - DPCD_ADDR_LANE0_1_STATUS
);
581 if (exynos_dp_channel_eq_ok(link_status
, lane_count
) == 0) {
582 /* traing pattern Set to Normal */
583 exynos_dp_training_pattern_dis(dp
);
585 dev_info(dp
->dev
, "Link Training success!\n");
587 exynos_dp_get_link_bandwidth(dp
, ®
);
588 dp
->link_train
.link_rate
= reg
;
589 dev_dbg(dp
->dev
, "final bandwidth = %.2x\n",
590 dp
->link_train
.link_rate
);
592 exynos_dp_get_lane_count(dp
, ®
);
593 dp
->link_train
.lane_count
= reg
;
594 dev_dbg(dp
->dev
, "final lane count = %.2x\n",
595 dp
->link_train
.lane_count
);
596 /* set enhanced mode if available */
597 exynos_dp_set_enhanced_mode(dp
);
599 dp
->link_train
.lt_state
= FINISHED
;
602 dp
->link_train
.eq_loop
++;
604 if (dp
->link_train
.eq_loop
> MAX_EQ_LOOP
) {
605 exynos_dp_reduce_link_rate(dp
);
607 exynos_dp_get_adjust_train(dp
, adjust_request
);
609 for (lane
= 0; lane
< lane_count
; lane
++) {
610 exynos_dp_set_lane_link_training(dp
,
611 dp
->link_train
.training_lane
[lane
],
613 buf
[lane
] = dp
->link_train
.training_lane
[lane
];
614 exynos_dp_write_byte_to_dpcd(dp
,
615 DPCD_ADDR_TRAINING_LANE0_SET
+ lane
,
621 exynos_dp_reduce_link_rate(dp
);
627 static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device
*dp
,
633 * For DP rev.1.1, Maximum link rate of Main Link lanes
634 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
636 exynos_dp_read_byte_from_dpcd(dp
, DPCD_ADDR_MAX_LINK_RATE
, &data
);
640 static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device
*dp
,
646 * For DP rev.1.1, Maximum number of Main Link lanes
647 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
649 exynos_dp_read_byte_from_dpcd(dp
, DPCD_ADDR_MAX_LANE_COUNT
, &data
);
650 *lane_count
= DPCD_MAX_LANE_COUNT(data
);
653 static void exynos_dp_init_training(struct exynos_dp_device
*dp
,
654 enum link_lane_count_type max_lane
,
655 enum link_rate_type max_rate
)
658 * MACRO_RST must be applied after the PLL_LOCK to avoid
659 * the DP inter pair skew issue for at least 10 us
661 exynos_dp_reset_macro(dp
);
663 /* Initialize by reading RX's DPCD */
664 exynos_dp_get_max_rx_bandwidth(dp
, &dp
->link_train
.link_rate
);
665 exynos_dp_get_max_rx_lane_count(dp
, &dp
->link_train
.lane_count
);
667 if ((dp
->link_train
.link_rate
!= LINK_RATE_1_62GBPS
) &&
668 (dp
->link_train
.link_rate
!= LINK_RATE_2_70GBPS
)) {
669 dev_err(dp
->dev
, "Rx Max Link Rate is abnormal :%x !\n",
670 dp
->link_train
.link_rate
);
671 dp
->link_train
.link_rate
= LINK_RATE_1_62GBPS
;
674 if (dp
->link_train
.lane_count
== 0) {
675 dev_err(dp
->dev
, "Rx Max Lane count is abnormal :%x !\n",
676 dp
->link_train
.lane_count
);
677 dp
->link_train
.lane_count
= (u8
)LANE_COUNT1
;
680 /* Setup TX lane count & rate */
681 if (dp
->link_train
.lane_count
> max_lane
)
682 dp
->link_train
.lane_count
= max_lane
;
683 if (dp
->link_train
.link_rate
> max_rate
)
684 dp
->link_train
.link_rate
= max_rate
;
686 /* All DP analog module power up */
687 exynos_dp_set_analog_power_down(dp
, POWER_ALL
, 0);
690 static int exynos_dp_sw_link_training(struct exynos_dp_device
*dp
)
693 int training_finished
;
695 /* Turn off unnecessary lane */
696 if (dp
->link_train
.lane_count
== 1)
697 exynos_dp_set_analog_power_down(dp
, CH1_BLOCK
, 1);
699 training_finished
= 0;
701 dp
->link_train
.lt_state
= START
;
704 while (!training_finished
) {
705 switch (dp
->link_train
.lt_state
) {
707 exynos_dp_link_start(dp
);
710 exynos_dp_process_clock_recovery(dp
);
712 case EQUALIZER_TRAINING
:
713 exynos_dp_process_equalizer_training(dp
);
716 training_finished
= 1;
726 static int exynos_dp_set_link_train(struct exynos_dp_device
*dp
,
733 for (i
= 0; i
< DP_TIMEOUT_LOOP_COUNT
; i
++) {
734 exynos_dp_init_training(dp
, count
, bwtype
);
735 retval
= exynos_dp_sw_link_training(dp
);
745 static int exynos_dp_config_video(struct exynos_dp_device
*dp
,
746 struct video_info
*video_info
)
749 int timeout_loop
= 0;
752 exynos_dp_config_video_slave_mode(dp
, video_info
);
754 exynos_dp_set_video_color_format(dp
, video_info
->color_depth
,
755 video_info
->color_space
,
756 video_info
->dynamic_range
,
757 video_info
->ycbcr_coeff
);
759 if (exynos_dp_get_pll_lock_status(dp
) == PLL_UNLOCKED
) {
760 dev_err(dp
->dev
, "PLL is not locked yet.\n");
766 if (exynos_dp_is_slave_video_stream_clock_on(dp
) == 0)
768 if (DP_TIMEOUT_LOOP_COUNT
< timeout_loop
) {
769 dev_err(dp
->dev
, "Timeout of video streamclk ok\n");
776 /* Set to use the register calculated M/N video */
777 exynos_dp_set_video_cr_mn(dp
, CALCULATED_M
, 0, 0);
779 /* For video bist, Video timing must be generated by register */
780 exynos_dp_set_video_timing_mode(dp
, VIDEO_TIMING_FROM_CAPTURE
);
782 /* Disable video mute */
783 exynos_dp_enable_video_mute(dp
, 0);
785 /* Configure video slave mode */
786 exynos_dp_enable_video_master(dp
, 0);
789 exynos_dp_start_video(dp
);
795 if (exynos_dp_is_video_stream_on(dp
) == 0) {
799 } else if (done_count
) {
802 if (DP_TIMEOUT_LOOP_COUNT
< timeout_loop
) {
803 dev_err(dp
->dev
, "Timeout of video streamclk ok\n");
811 dev_err(dp
->dev
, "Video stream is not detected!\n");
816 static void exynos_dp_enable_scramble(struct exynos_dp_device
*dp
, bool enable
)
821 exynos_dp_enable_scrambling(dp
);
823 exynos_dp_read_byte_from_dpcd(dp
,
824 DPCD_ADDR_TRAINING_PATTERN_SET
,
826 exynos_dp_write_byte_to_dpcd(dp
,
827 DPCD_ADDR_TRAINING_PATTERN_SET
,
828 (u8
)(data
& ~DPCD_SCRAMBLING_DISABLED
));
830 exynos_dp_disable_scrambling(dp
);
832 exynos_dp_read_byte_from_dpcd(dp
,
833 DPCD_ADDR_TRAINING_PATTERN_SET
,
835 exynos_dp_write_byte_to_dpcd(dp
,
836 DPCD_ADDR_TRAINING_PATTERN_SET
,
837 (u8
)(data
| DPCD_SCRAMBLING_DISABLED
));
841 static irqreturn_t
exynos_dp_irq_handler(int irq
, void *arg
)
843 struct exynos_dp_device
*dp
= arg
;
845 dev_err(dp
->dev
, "exynos_dp_irq_handler\n");
849 static int __devinit
exynos_dp_probe(struct platform_device
*pdev
)
851 struct resource
*res
;
852 struct exynos_dp_device
*dp
;
853 struct exynos_dp_platdata
*pdata
;
857 pdata
= pdev
->dev
.platform_data
;
859 dev_err(&pdev
->dev
, "no platform data\n");
863 dp
= kzalloc(sizeof(struct exynos_dp_device
), GFP_KERNEL
);
865 dev_err(&pdev
->dev
, "no memory for device data\n");
869 dp
->dev
= &pdev
->dev
;
871 dp
->clock
= clk_get(&pdev
->dev
, "dp");
872 if (IS_ERR(dp
->clock
)) {
873 dev_err(&pdev
->dev
, "failed to get clock\n");
874 ret
= PTR_ERR(dp
->clock
);
878 clk_enable(dp
->clock
);
880 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
882 dev_err(&pdev
->dev
, "failed to get registers\n");
887 res
= request_mem_region(res
->start
, resource_size(res
),
888 dev_name(&pdev
->dev
));
890 dev_err(&pdev
->dev
, "failed to request registers region\n");
897 dp
->reg_base
= ioremap(res
->start
, resource_size(res
));
899 dev_err(&pdev
->dev
, "failed to ioremap\n");
904 dp
->irq
= platform_get_irq(pdev
, 0);
906 dev_err(&pdev
->dev
, "failed to get irq\n");
911 ret
= request_irq(dp
->irq
, exynos_dp_irq_handler
, 0,
914 dev_err(&pdev
->dev
, "failed to request irq\n");
918 dp
->video_info
= pdata
->video_info
;
922 exynos_dp_init_dp(dp
);
924 ret
= exynos_dp_detect_hpd(dp
);
926 dev_err(&pdev
->dev
, "unable to detect hpd\n");
930 exynos_dp_handle_edid(dp
);
932 ret
= exynos_dp_set_link_train(dp
, dp
->video_info
->lane_count
,
933 dp
->video_info
->link_rate
);
935 dev_err(&pdev
->dev
, "unable to do link train\n");
939 exynos_dp_enable_scramble(dp
, 1);
940 exynos_dp_enable_rx_to_enhanced_mode(dp
, 1);
941 exynos_dp_enable_enhanced_mode(dp
, 1);
943 exynos_dp_set_lane_count(dp
, dp
->video_info
->lane_count
);
944 exynos_dp_set_link_bandwidth(dp
, dp
->video_info
->link_rate
);
946 exynos_dp_init_video(dp
);
947 ret
= exynos_dp_config_video(dp
, dp
->video_info
);
949 dev_err(&pdev
->dev
, "unable to config video\n");
953 platform_set_drvdata(pdev
, dp
);
958 free_irq(dp
->irq
, dp
);
960 iounmap(dp
->reg_base
);
962 release_mem_region(res
->start
, resource_size(res
));
971 static int __devexit
exynos_dp_remove(struct platform_device
*pdev
)
973 struct exynos_dp_platdata
*pdata
= pdev
->dev
.platform_data
;
974 struct exynos_dp_device
*dp
= platform_get_drvdata(pdev
);
976 if (pdata
&& pdata
->phy_exit
)
979 free_irq(dp
->irq
, dp
);
980 iounmap(dp
->reg_base
);
982 clk_disable(dp
->clock
);
985 release_mem_region(dp
->res
->start
, resource_size(dp
->res
));
992 #ifdef CONFIG_PM_SLEEP
993 static int exynos_dp_suspend(struct device
*dev
)
995 struct platform_device
*pdev
= to_platform_device(dev
);
996 struct exynos_dp_platdata
*pdata
= pdev
->dev
.platform_data
;
997 struct exynos_dp_device
*dp
= platform_get_drvdata(pdev
);
999 if (pdata
&& pdata
->phy_exit
)
1002 clk_disable(dp
->clock
);
1007 static int exynos_dp_resume(struct device
*dev
)
1009 struct platform_device
*pdev
= to_platform_device(dev
);
1010 struct exynos_dp_platdata
*pdata
= pdev
->dev
.platform_data
;
1011 struct exynos_dp_device
*dp
= platform_get_drvdata(pdev
);
1013 if (pdata
&& pdata
->phy_init
)
1016 clk_enable(dp
->clock
);
1018 exynos_dp_init_dp(dp
);
1020 exynos_dp_detect_hpd(dp
);
1021 exynos_dp_handle_edid(dp
);
1023 exynos_dp_set_link_train(dp
, dp
->video_info
->lane_count
,
1024 dp
->video_info
->link_rate
);
1026 exynos_dp_enable_scramble(dp
, 1);
1027 exynos_dp_enable_rx_to_enhanced_mode(dp
, 1);
1028 exynos_dp_enable_enhanced_mode(dp
, 1);
1030 exynos_dp_set_lane_count(dp
, dp
->video_info
->lane_count
);
1031 exynos_dp_set_link_bandwidth(dp
, dp
->video_info
->link_rate
);
1033 exynos_dp_init_video(dp
);
1034 exynos_dp_config_video(dp
, dp
->video_info
);
1040 static const struct dev_pm_ops exynos_dp_pm_ops
= {
1041 SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend
, exynos_dp_resume
)
1044 static struct platform_driver exynos_dp_driver
= {
1045 .probe
= exynos_dp_probe
,
1046 .remove
= __devexit_p(exynos_dp_remove
),
1048 .name
= "exynos-dp",
1049 .owner
= THIS_MODULE
,
1050 .pm
= &exynos_dp_pm_ops
,
1054 module_platform_driver(exynos_dp_driver
);
1056 MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
1057 MODULE_DESCRIPTION("Samsung SoC DP Driver");
1058 MODULE_LICENSE("GPL");