xref: /rk3399_rockchip-uboot/drivers/video/drm/analogix_dp.c (revision 1f59ac367d60d6dee358a5a4e197227035dbb2d4)
16f920c07SWyon Bi /*
26f920c07SWyon Bi  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
36f920c07SWyon Bi  *
46f920c07SWyon Bi  * SPDX-License-Identifier:	GPL-2.0+
56f920c07SWyon Bi  */
66f920c07SWyon Bi 
76f920c07SWyon Bi #include <config.h>
86f920c07SWyon Bi #include <common.h>
96f920c07SWyon Bi #include <errno.h>
106f920c07SWyon Bi #include <malloc.h>
116f920c07SWyon Bi #include <asm/unaligned.h>
126f920c07SWyon Bi #include <asm/io.h>
136f920c07SWyon Bi #include <dm/device.h>
14cb17ca6cSSandy Huang #include <dm/of_access.h>
156f920c07SWyon Bi #include <dm/read.h>
167adc0066SWyon Bi #include <linux/bitfield.h>
176f920c07SWyon Bi #include <linux/list.h>
186f920c07SWyon Bi #include <syscon.h>
196f920c07SWyon Bi #include <asm/arch-rockchip/clock.h>
206f920c07SWyon Bi #include <asm/gpio.h>
216f920c07SWyon Bi 
226f920c07SWyon Bi #include "rockchip_display.h"
236f920c07SWyon Bi #include "rockchip_crtc.h"
246f920c07SWyon Bi #include "rockchip_connector.h"
258ae84ec5SWyon Bi #include "rockchip_panel.h"
266f920c07SWyon Bi #include "analogix_dp.h"
276f920c07SWyon Bi 
287adc0066SWyon Bi #define RK3588_GRF_VO1_CON0	0x0000
297adc0066SWyon Bi #define EDP_MODE		BIT(0)
307adc0066SWyon Bi #define RK3588_GRF_VO1_CON1	0x0004
317adc0066SWyon Bi 
326f920c07SWyon Bi /**
336f920c07SWyon Bi  * struct rockchip_dp_chip_data - splite the grf setting of kind of chips
346f920c07SWyon Bi  * @lcdsel_grf_reg: grf register offset of lcdc select
356f920c07SWyon Bi  * @lcdsel_big: reg value of selecting vop big for eDP
366f920c07SWyon Bi  * @lcdsel_lit: reg value of selecting vop little for eDP
37699c29a5SWyon Bi  * @chip_type: specific chip type
38699c29a5SWyon Bi  * @ssc: check if SSC is supported by source
396f920c07SWyon Bi  */
406f920c07SWyon Bi struct rockchip_dp_chip_data {
416f920c07SWyon Bi 	u32	lcdsel_grf_reg;
426f920c07SWyon Bi 	u32	lcdsel_big;
436f920c07SWyon Bi 	u32	lcdsel_lit;
446f920c07SWyon Bi 	u32	chip_type;
45699c29a5SWyon Bi 	bool    ssc;
467adc0066SWyon Bi 
477adc0066SWyon Bi 	u32 max_link_rate;
487adc0066SWyon Bi 	u32 max_lane_count;
496f920c07SWyon Bi };
506f920c07SWyon Bi 
516f920c07SWyon Bi static void
526f920c07SWyon Bi analogix_dp_enable_rx_to_enhanced_mode(struct analogix_dp_device *dp,
536f920c07SWyon Bi 				       bool enable)
546f920c07SWyon Bi {
556f920c07SWyon Bi 	u8 data;
566f920c07SWyon Bi 
576f920c07SWyon Bi 	analogix_dp_read_byte_from_dpcd(dp, DP_LANE_COUNT_SET, &data);
586f920c07SWyon Bi 
596f920c07SWyon Bi 	if (enable)
606f920c07SWyon Bi 		analogix_dp_write_byte_to_dpcd(dp, DP_LANE_COUNT_SET,
616f920c07SWyon Bi 					       DP_LANE_COUNT_ENHANCED_FRAME_EN |
626f920c07SWyon Bi 					       DPCD_LANE_COUNT_SET(data));
636f920c07SWyon Bi 	else
646f920c07SWyon Bi 		analogix_dp_write_byte_to_dpcd(dp, DP_LANE_COUNT_SET,
656f920c07SWyon Bi 					       DPCD_LANE_COUNT_SET(data));
666f920c07SWyon Bi }
676f920c07SWyon Bi 
686f920c07SWyon Bi static int analogix_dp_is_enhanced_mode_available(struct analogix_dp_device *dp)
696f920c07SWyon Bi {
706f920c07SWyon Bi 	u8 data;
716f920c07SWyon Bi 	int retval;
726f920c07SWyon Bi 
736f920c07SWyon Bi 	analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data);
746f920c07SWyon Bi 	retval = DPCD_ENHANCED_FRAME_CAP(data);
756f920c07SWyon Bi 
766f920c07SWyon Bi 	return retval;
776f920c07SWyon Bi }
786f920c07SWyon Bi 
796f920c07SWyon Bi static void analogix_dp_set_enhanced_mode(struct analogix_dp_device *dp)
806f920c07SWyon Bi {
816f920c07SWyon Bi 	u8 data;
826f920c07SWyon Bi 
836f920c07SWyon Bi 	data = analogix_dp_is_enhanced_mode_available(dp);
846f920c07SWyon Bi 	analogix_dp_enable_rx_to_enhanced_mode(dp, data);
856f920c07SWyon Bi 	analogix_dp_enable_enhanced_mode(dp, data);
866f920c07SWyon Bi }
876f920c07SWyon Bi 
886f920c07SWyon Bi static void analogix_dp_training_pattern_dis(struct analogix_dp_device *dp)
896f920c07SWyon Bi {
906f920c07SWyon Bi 	analogix_dp_set_training_pattern(dp, DP_NONE);
916f920c07SWyon Bi 
926f920c07SWyon Bi 	analogix_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET,
936f920c07SWyon Bi 				       DP_TRAINING_PATTERN_DISABLE);
946f920c07SWyon Bi }
956f920c07SWyon Bi 
966f920c07SWyon Bi static int analogix_dp_link_start(struct analogix_dp_device *dp)
976f920c07SWyon Bi {
986f920c07SWyon Bi 	u8 buf[4];
99a6285d17SWyon Bi 	int lane, lane_count, retval;
1006f920c07SWyon Bi 
1016f920c07SWyon Bi 	lane_count = dp->link_train.lane_count;
1026f920c07SWyon Bi 
1036f920c07SWyon Bi 	dp->link_train.lt_state = CLOCK_RECOVERY;
1046f920c07SWyon Bi 	dp->link_train.eq_loop = 0;
1056f920c07SWyon Bi 
1066f920c07SWyon Bi 	for (lane = 0; lane < lane_count; lane++)
1076f920c07SWyon Bi 		dp->link_train.cr_loop[lane] = 0;
1086f920c07SWyon Bi 
1096f920c07SWyon Bi 	/* Set link rate and count as you want to establish*/
1106f920c07SWyon Bi 	analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
1116f920c07SWyon Bi 	analogix_dp_set_lane_count(dp, dp->link_train.lane_count);
1126f920c07SWyon Bi 
1136f920c07SWyon Bi 	/* Setup RX configuration */
1146f920c07SWyon Bi 	buf[0] = dp->link_train.link_rate;
1156f920c07SWyon Bi 	buf[1] = dp->link_train.lane_count;
1166f920c07SWyon Bi 	retval = analogix_dp_write_bytes_to_dpcd(dp, DP_LINK_BW_SET, 2, buf);
1176f920c07SWyon Bi 	if (retval)
1186f920c07SWyon Bi 		return retval;
1196f920c07SWyon Bi 
120699c29a5SWyon Bi 	/* Spread AMP if required, enable 8b/10b coding */
121699c29a5SWyon Bi 	buf[0] = analogix_dp_ssc_supported(dp) ? DP_SPREAD_AMP_0_5 : 0;
122699c29a5SWyon Bi 	buf[1] = DP_SET_ANSI_8B10B;
123699c29a5SWyon Bi 	retval = analogix_dp_write_bytes_to_dpcd(dp, DP_DOWNSPREAD_CTRL,
124699c29a5SWyon Bi 						 2, buf);
125699c29a5SWyon Bi 	if (retval < 0)
126699c29a5SWyon Bi 		return retval;
127699c29a5SWyon Bi 
128253c2dc8SWyon Bi 	/* Set TX voltage-swing and pre-emphasis to minimum */
1296f920c07SWyon Bi 	for (lane = 0; lane < lane_count; lane++)
130253c2dc8SWyon Bi 		dp->link_train.training_lane[lane] =
131253c2dc8SWyon Bi 				DP_TRAIN_VOLTAGE_SWING_LEVEL_0 |
132253c2dc8SWyon Bi 				DP_TRAIN_PRE_EMPH_LEVEL_0;
133253c2dc8SWyon Bi 	analogix_dp_set_lane_link_training(dp);
1346f920c07SWyon Bi 
1356f920c07SWyon Bi 	/* Set training pattern 1 */
1366f920c07SWyon Bi 	analogix_dp_set_training_pattern(dp, TRAINING_PTN1);
1376f920c07SWyon Bi 
1386f920c07SWyon Bi 	/* Set RX training pattern */
1396f920c07SWyon Bi 	retval = analogix_dp_write_byte_to_dpcd(dp,
1406f920c07SWyon Bi 			DP_TRAINING_PATTERN_SET,
1416f920c07SWyon Bi 			DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_1);
1426f920c07SWyon Bi 	if (retval)
1436f920c07SWyon Bi 		return retval;
1446f920c07SWyon Bi 
1456f920c07SWyon Bi 	for (lane = 0; lane < lane_count; lane++)
1466f920c07SWyon Bi 		buf[lane] = DP_TRAIN_PRE_EMPH_LEVEL_0 |
1476f920c07SWyon Bi 			    DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
1486f920c07SWyon Bi 
1496f920c07SWyon Bi 	retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET,
1506f920c07SWyon Bi 						 lane_count, buf);
1516f920c07SWyon Bi 
1526f920c07SWyon Bi 	return retval;
1536f920c07SWyon Bi }
1546f920c07SWyon Bi 
1556f920c07SWyon Bi static unsigned char analogix_dp_get_lane_status(u8 link_status[2], int lane)
1566f920c07SWyon Bi {
1576f920c07SWyon Bi 	int shift = (lane & 1) * 4;
1586f920c07SWyon Bi 	u8 link_value = link_status[lane >> 1];
1596f920c07SWyon Bi 
1606f920c07SWyon Bi 	return (link_value >> shift) & 0xf;
1616f920c07SWyon Bi }
1626f920c07SWyon Bi 
1636f920c07SWyon Bi static int analogix_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
1646f920c07SWyon Bi {
1656f920c07SWyon Bi 	int lane;
1666f920c07SWyon Bi 	u8 lane_status;
1676f920c07SWyon Bi 
1686f920c07SWyon Bi 	for (lane = 0; lane < lane_count; lane++) {
1696f920c07SWyon Bi 		lane_status = analogix_dp_get_lane_status(link_status, lane);
1706f920c07SWyon Bi 		if ((lane_status & DP_LANE_CR_DONE) == 0)
1716f920c07SWyon Bi 			return -EINVAL;
1726f920c07SWyon Bi 	}
1736f920c07SWyon Bi 	return 0;
1746f920c07SWyon Bi }
1756f920c07SWyon Bi 
1766f920c07SWyon Bi static int analogix_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
1776f920c07SWyon Bi 				     int lane_count)
1786f920c07SWyon Bi {
1796f920c07SWyon Bi 	int lane;
1806f920c07SWyon Bi 	u8 lane_status;
1816f920c07SWyon Bi 
1826f920c07SWyon Bi 	if ((link_align & DP_INTERLANE_ALIGN_DONE) == 0)
1836f920c07SWyon Bi 		return -EINVAL;
1846f920c07SWyon Bi 
1856f920c07SWyon Bi 	for (lane = 0; lane < lane_count; lane++) {
1866f920c07SWyon Bi 		lane_status = analogix_dp_get_lane_status(link_status, lane);
1876f920c07SWyon Bi 		lane_status &= DP_CHANNEL_EQ_BITS;
1886f920c07SWyon Bi 		if (lane_status != DP_CHANNEL_EQ_BITS)
1896f920c07SWyon Bi 			return -EINVAL;
1906f920c07SWyon Bi 	}
1916f920c07SWyon Bi 
1926f920c07SWyon Bi 	return 0;
1936f920c07SWyon Bi }
1946f920c07SWyon Bi 
1956f920c07SWyon Bi static unsigned char
1966f920c07SWyon Bi analogix_dp_get_adjust_request_voltage(u8 adjust_request[2], int lane)
1976f920c07SWyon Bi {
1986f920c07SWyon Bi 	int shift = (lane & 1) * 4;
1996f920c07SWyon Bi 	u8 link_value = adjust_request[lane >> 1];
2006f920c07SWyon Bi 
2016f920c07SWyon Bi 	return (link_value >> shift) & 0x3;
2026f920c07SWyon Bi }
2036f920c07SWyon Bi 
2046f920c07SWyon Bi static unsigned char analogix_dp_get_adjust_request_pre_emphasis(
2056f920c07SWyon Bi 					u8 adjust_request[2],
2066f920c07SWyon Bi 					int lane)
2076f920c07SWyon Bi {
2086f920c07SWyon Bi 	int shift = (lane & 1) * 4;
2096f920c07SWyon Bi 	u8 link_value = adjust_request[lane >> 1];
2106f920c07SWyon Bi 
2116f920c07SWyon Bi 	return ((link_value >> shift) & 0xc) >> 2;
2126f920c07SWyon Bi }
2136f920c07SWyon Bi 
2146f920c07SWyon Bi static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp)
2156f920c07SWyon Bi {
2166f920c07SWyon Bi 	analogix_dp_training_pattern_dis(dp);
2176f920c07SWyon Bi 	analogix_dp_set_enhanced_mode(dp);
2186f920c07SWyon Bi 
2196f920c07SWyon Bi 	dp->link_train.lt_state = FAILED;
2206f920c07SWyon Bi }
2216f920c07SWyon Bi 
2226f920c07SWyon Bi static void analogix_dp_get_adjust_training_lane(struct analogix_dp_device *dp,
2236f920c07SWyon Bi 						 u8 adjust_request[2])
2246f920c07SWyon Bi {
2256f920c07SWyon Bi 	int lane, lane_count;
2266f920c07SWyon Bi 	u8 voltage_swing, pre_emphasis, training_lane;
2276f920c07SWyon Bi 
2286f920c07SWyon Bi 	lane_count = dp->link_train.lane_count;
2296f920c07SWyon Bi 	for (lane = 0; lane < lane_count; lane++) {
2306f920c07SWyon Bi 		voltage_swing = analogix_dp_get_adjust_request_voltage(
2316f920c07SWyon Bi 						adjust_request, lane);
2326f920c07SWyon Bi 		pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis(
2336f920c07SWyon Bi 						adjust_request, lane);
2346f920c07SWyon Bi 		training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
2356f920c07SWyon Bi 				DPCD_PRE_EMPHASIS_SET(pre_emphasis);
2366f920c07SWyon Bi 
2376f920c07SWyon Bi 		if (voltage_swing == VOLTAGE_LEVEL_3)
2386f920c07SWyon Bi 			training_lane |= DP_TRAIN_MAX_SWING_REACHED;
2396f920c07SWyon Bi 		if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
2406f920c07SWyon Bi 			training_lane |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
2416f920c07SWyon Bi 
2426f920c07SWyon Bi 		dp->link_train.training_lane[lane] = training_lane;
2436f920c07SWyon Bi 	}
2446f920c07SWyon Bi }
2456f920c07SWyon Bi 
2467adc0066SWyon Bi static bool analogix_dp_tps3_supported(struct analogix_dp_device *dp)
2477adc0066SWyon Bi {
2487adc0066SWyon Bi 	bool source_tps3_supported, sink_tps3_supported;
2497adc0066SWyon Bi 	u8 dpcd = 0;
2507adc0066SWyon Bi 
2517adc0066SWyon Bi 	source_tps3_supported =
2527adc0066SWyon Bi 		dp->video_info.max_link_rate == DP_LINK_BW_5_4;
2537adc0066SWyon Bi 	analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &dpcd);
2547adc0066SWyon Bi 	sink_tps3_supported = dpcd & DP_TPS3_SUPPORTED;
2557adc0066SWyon Bi 
2567adc0066SWyon Bi 	return source_tps3_supported && sink_tps3_supported;
2577adc0066SWyon Bi }
2587adc0066SWyon Bi 
2596f920c07SWyon Bi static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
2606f920c07SWyon Bi {
2616f920c07SWyon Bi 	int lane, lane_count, retval;
2626f920c07SWyon Bi 	u8 voltage_swing, pre_emphasis, training_lane;
2636f920c07SWyon Bi 	u8 link_status[2], adjust_request[2];
2647adc0066SWyon Bi 	u8 training_pattern = TRAINING_PTN2;
2656f920c07SWyon Bi 
2661a00cf6eSWyon Bi 	drm_dp_link_train_clock_recovery_delay(dp->dpcd);
2676f920c07SWyon Bi 
2686f920c07SWyon Bi 	lane_count = dp->link_train.lane_count;
2696f920c07SWyon Bi 
2706f920c07SWyon Bi 	retval =  analogix_dp_read_bytes_from_dpcd(dp,
2716f920c07SWyon Bi 			DP_LANE0_1_STATUS, 2, link_status);
2726f920c07SWyon Bi 	if (retval)
2736f920c07SWyon Bi 		return retval;
2746f920c07SWyon Bi 
2756f920c07SWyon Bi 	if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) {
2767adc0066SWyon Bi 		if (analogix_dp_tps3_supported(dp))
2777adc0066SWyon Bi 			training_pattern = TRAINING_PTN3;
2787adc0066SWyon Bi 
2797adc0066SWyon Bi 		/* set training pattern for EQ */
2807adc0066SWyon Bi 		analogix_dp_set_training_pattern(dp, training_pattern);
2816f920c07SWyon Bi 
2826f920c07SWyon Bi 		retval = analogix_dp_write_byte_to_dpcd(dp,
2836f920c07SWyon Bi 				DP_TRAINING_PATTERN_SET,
2847adc0066SWyon Bi 				(training_pattern == TRAINING_PTN3 ?
2857adc0066SWyon Bi 				 DP_TRAINING_PATTERN_3 : DP_TRAINING_PATTERN_2));
2866f920c07SWyon Bi 		if (retval)
2876f920c07SWyon Bi 			return retval;
2886f920c07SWyon Bi 
2896f920c07SWyon Bi 		dev_info(dp->dev, "Link Training Clock Recovery success\n");
2906f920c07SWyon Bi 		dp->link_train.lt_state = EQUALIZER_TRAINING;
29110d706d5SWyon Bi 
29210d706d5SWyon Bi 		return 0;
2936f920c07SWyon Bi 	} else {
29410d706d5SWyon Bi 		retval = analogix_dp_read_bytes_from_dpcd(dp,
29510d706d5SWyon Bi 				DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
29610d706d5SWyon Bi 		if (retval)
29710d706d5SWyon Bi 			return retval;
29810d706d5SWyon Bi 
2996f920c07SWyon Bi 		for (lane = 0; lane < lane_count; lane++) {
3006f920c07SWyon Bi 			training_lane = analogix_dp_get_lane_link_training(
3016f920c07SWyon Bi 							dp, lane);
3026f920c07SWyon Bi 			voltage_swing = analogix_dp_get_adjust_request_voltage(
3036f920c07SWyon Bi 							adjust_request, lane);
3046f920c07SWyon Bi 			pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis(
3056f920c07SWyon Bi 							adjust_request, lane);
3066f920c07SWyon Bi 
3076f920c07SWyon Bi 			if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
3086f920c07SWyon Bi 					voltage_swing &&
3096f920c07SWyon Bi 			    DPCD_PRE_EMPHASIS_GET(training_lane) ==
3106f920c07SWyon Bi 					pre_emphasis)
3116f920c07SWyon Bi 				dp->link_train.cr_loop[lane]++;
3126f920c07SWyon Bi 
3136f920c07SWyon Bi 			if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
3146f920c07SWyon Bi 			    voltage_swing == VOLTAGE_LEVEL_3 ||
3156f920c07SWyon Bi 			    pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
3166f920c07SWyon Bi 				dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
3176f920c07SWyon Bi 					dp->link_train.cr_loop[lane],
3186f920c07SWyon Bi 					voltage_swing, pre_emphasis);
3196f920c07SWyon Bi 				analogix_dp_reduce_link_rate(dp);
3206f920c07SWyon Bi 				return -EIO;
3216f920c07SWyon Bi 			}
3226f920c07SWyon Bi 		}
3236f920c07SWyon Bi 	}
3246f920c07SWyon Bi 
3256f920c07SWyon Bi 	analogix_dp_get_adjust_training_lane(dp, adjust_request);
326253c2dc8SWyon Bi 	analogix_dp_set_lane_link_training(dp);
3276f920c07SWyon Bi 
3286f920c07SWyon Bi 	retval = analogix_dp_write_bytes_to_dpcd(dp,
3296f920c07SWyon Bi 			DP_TRAINING_LANE0_SET, lane_count,
3306f920c07SWyon Bi 			dp->link_train.training_lane);
3316f920c07SWyon Bi 	if (retval)
3326f920c07SWyon Bi 		return retval;
3336f920c07SWyon Bi 
3346f920c07SWyon Bi 	return retval;
3356f920c07SWyon Bi }
3366f920c07SWyon Bi 
3376f920c07SWyon Bi static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
3386f920c07SWyon Bi {
339253c2dc8SWyon Bi 	int lane_count, retval;
3406f920c07SWyon Bi 	u32 reg;
3416f920c07SWyon Bi 	u8 link_align, link_status[2], adjust_request[2];
3426f920c07SWyon Bi 
3431a00cf6eSWyon Bi 	drm_dp_link_train_channel_eq_delay(dp->dpcd);
3446f920c07SWyon Bi 
3456f920c07SWyon Bi 	lane_count = dp->link_train.lane_count;
3466f920c07SWyon Bi 
3476f920c07SWyon Bi 	retval = analogix_dp_read_bytes_from_dpcd(dp,
3486f920c07SWyon Bi 			DP_LANE0_1_STATUS, 2, link_status);
3496f920c07SWyon Bi 	if (retval)
3506f920c07SWyon Bi 		return retval;
3516f920c07SWyon Bi 
3526f920c07SWyon Bi 	if (analogix_dp_clock_recovery_ok(link_status, lane_count)) {
3536f920c07SWyon Bi 		analogix_dp_reduce_link_rate(dp);
3546f920c07SWyon Bi 		return -EIO;
3556f920c07SWyon Bi 	}
3566f920c07SWyon Bi 
3576f920c07SWyon Bi 	retval = analogix_dp_read_byte_from_dpcd(dp,
3586f920c07SWyon Bi 			DP_LANE_ALIGN_STATUS_UPDATED, &link_align);
3596f920c07SWyon Bi 	if (retval)
3606f920c07SWyon Bi 		return retval;
3616f920c07SWyon Bi 
3626f920c07SWyon Bi 	if (!analogix_dp_channel_eq_ok(link_status, link_align, lane_count)) {
3636f920c07SWyon Bi 		/* traing pattern Set to Normal */
3646f920c07SWyon Bi 		analogix_dp_training_pattern_dis(dp);
3656f920c07SWyon Bi 
3666f920c07SWyon Bi 		printf("Link Training success!\n");
3676f920c07SWyon Bi 
3686f920c07SWyon Bi 		analogix_dp_get_link_bandwidth(dp, &reg);
3696f920c07SWyon Bi 		dp->link_train.link_rate = reg;
3706f920c07SWyon Bi 		analogix_dp_get_lane_count(dp, &reg);
3716f920c07SWyon Bi 		dp->link_train.lane_count = reg;
3726f920c07SWyon Bi 
3736f920c07SWyon Bi 		printf("final link rate = 0x%.2x, lane count = 0x%.2x\n",
3746f920c07SWyon Bi 		       dp->link_train.link_rate, dp->link_train.lane_count);
3756f920c07SWyon Bi 
3766f920c07SWyon Bi 		/* set enhanced mode if available */
3776f920c07SWyon Bi 		analogix_dp_set_enhanced_mode(dp);
3786f920c07SWyon Bi 		dp->link_train.lt_state = FINISHED;
3796f920c07SWyon Bi 
3806f920c07SWyon Bi 		return 0;
3816f920c07SWyon Bi 	}
3826f920c07SWyon Bi 
3836f920c07SWyon Bi 	/* not all locked */
3846f920c07SWyon Bi 	dp->link_train.eq_loop++;
3856f920c07SWyon Bi 
3866f920c07SWyon Bi 	if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
3876f920c07SWyon Bi 		dev_dbg(dp->dev, "EQ Max loop\n");
3886f920c07SWyon Bi 		analogix_dp_reduce_link_rate(dp);
3896f920c07SWyon Bi 		return -EIO;
3906f920c07SWyon Bi 	}
3916f920c07SWyon Bi 
39210d706d5SWyon Bi 	retval = analogix_dp_read_bytes_from_dpcd(dp,
39310d706d5SWyon Bi 			DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
39410d706d5SWyon Bi 	if (retval)
39510d706d5SWyon Bi 		return retval;
39610d706d5SWyon Bi 
39710d706d5SWyon Bi 	analogix_dp_get_adjust_training_lane(dp, adjust_request);
398253c2dc8SWyon Bi 	analogix_dp_set_lane_link_training(dp);
3996f920c07SWyon Bi 
4006f920c07SWyon Bi 	retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET,
4016f920c07SWyon Bi 			lane_count, dp->link_train.training_lane);
4026f920c07SWyon Bi 
4036f920c07SWyon Bi 	return retval;
4046f920c07SWyon Bi }
4056f920c07SWyon Bi 
4066f920c07SWyon Bi static void analogix_dp_get_max_rx_bandwidth(struct analogix_dp_device *dp,
4076f920c07SWyon Bi 					     u8 *bandwidth)
4086f920c07SWyon Bi {
4096f920c07SWyon Bi 	u8 data;
4106f920c07SWyon Bi 
4116f920c07SWyon Bi 	/*
4126f920c07SWyon Bi 	 * For DP rev.1.1, Maximum link rate of Main Link lanes
4136f920c07SWyon Bi 	 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
4146f920c07SWyon Bi 	 * For DP rev.1.2, Maximum link rate of Main Link lanes
4156f920c07SWyon Bi 	 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps, 0x14 = 5.4Gbps
4166f920c07SWyon Bi 	 */
4176f920c07SWyon Bi 	analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data);
4186f920c07SWyon Bi 	*bandwidth = data;
4196f920c07SWyon Bi }
4206f920c07SWyon Bi 
4216f920c07SWyon Bi static void analogix_dp_get_max_rx_lane_count(struct analogix_dp_device *dp,
4226f920c07SWyon Bi 					      u8 *lane_count)
4236f920c07SWyon Bi {
4246f920c07SWyon Bi 	u8 data;
4256f920c07SWyon Bi 
4266f920c07SWyon Bi 	/*
4276f920c07SWyon Bi 	 * For DP rev.1.1, Maximum number of Main Link lanes
4286f920c07SWyon Bi 	 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
4296f920c07SWyon Bi 	 */
4306f920c07SWyon Bi 	analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data);
4316f920c07SWyon Bi 	*lane_count = DPCD_MAX_LANE_COUNT(data);
4326f920c07SWyon Bi }
4336f920c07SWyon Bi 
4346f920c07SWyon Bi static int analogix_dp_init_training(struct analogix_dp_device *dp,
4356f920c07SWyon Bi 				     enum link_lane_count_type max_lane,
4366f920c07SWyon Bi 				     int max_rate)
4376f920c07SWyon Bi {
438699c29a5SWyon Bi 	u8 dpcd;
439699c29a5SWyon Bi 
4406f920c07SWyon Bi 	/*
4416f920c07SWyon Bi 	 * MACRO_RST must be applied after the PLL_LOCK to avoid
4426f920c07SWyon Bi 	 * the DP inter pair skew issue for at least 10 us
4436f920c07SWyon Bi 	 */
4446f920c07SWyon Bi 	analogix_dp_reset_macro(dp);
4456f920c07SWyon Bi 
4466f920c07SWyon Bi 	/* Initialize by reading RX's DPCD */
4476f920c07SWyon Bi 	analogix_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
4486f920c07SWyon Bi 	analogix_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
4496f920c07SWyon Bi 
4506f920c07SWyon Bi 	if ((dp->link_train.link_rate != DP_LINK_BW_1_62) &&
4516f920c07SWyon Bi 	    (dp->link_train.link_rate != DP_LINK_BW_2_7) &&
4526f920c07SWyon Bi 	    (dp->link_train.link_rate != DP_LINK_BW_5_4)) {
4536f920c07SWyon Bi 		dev_err(dp->dev, "failed to get Rx Max Link Rate\n");
4546f920c07SWyon Bi 		return -ENODEV;
4556f920c07SWyon Bi 	}
4566f920c07SWyon Bi 
4576f920c07SWyon Bi 	if (dp->link_train.lane_count == 0) {
4586f920c07SWyon Bi 		dev_err(dp->dev, "failed to get Rx Max Lane Count\n");
4596f920c07SWyon Bi 		return -ENODEV;
4606f920c07SWyon Bi 	}
4616f920c07SWyon Bi 
4626f920c07SWyon Bi 	/* Setup TX lane count & rate */
4636f920c07SWyon Bi 	if (dp->link_train.lane_count > max_lane)
4646f920c07SWyon Bi 		dp->link_train.lane_count = max_lane;
4656f920c07SWyon Bi 	if (dp->link_train.link_rate > max_rate)
4666f920c07SWyon Bi 		dp->link_train.link_rate = max_rate;
4676f920c07SWyon Bi 
468699c29a5SWyon Bi 	analogix_dp_read_byte_from_dpcd(dp, DP_MAX_DOWNSPREAD, &dpcd);
469699c29a5SWyon Bi 	dp->link_train.ssc = !!(dpcd & DP_MAX_DOWNSPREAD_0_5);
470699c29a5SWyon Bi 
4716f920c07SWyon Bi 	/* All DP analog module power up */
4726f920c07SWyon Bi 	analogix_dp_set_analog_power_down(dp, POWER_ALL, 0);
4736f920c07SWyon Bi 
4746f920c07SWyon Bi 	return 0;
4756f920c07SWyon Bi }
4766f920c07SWyon Bi 
4776f920c07SWyon Bi static int analogix_dp_sw_link_training(struct analogix_dp_device *dp)
4786f920c07SWyon Bi {
4796f920c07SWyon Bi 	int retval = 0, training_finished = 0;
4806f920c07SWyon Bi 
4816f920c07SWyon Bi 	dp->link_train.lt_state = START;
4826f920c07SWyon Bi 
4836f920c07SWyon Bi 	/* Process here */
4846f920c07SWyon Bi 	while (!retval && !training_finished) {
4856f920c07SWyon Bi 		switch (dp->link_train.lt_state) {
4866f920c07SWyon Bi 		case START:
4876f920c07SWyon Bi 			retval = analogix_dp_link_start(dp);
4886f920c07SWyon Bi 			if (retval)
4896f920c07SWyon Bi 				dev_err(dp->dev, "LT link start failed!\n");
4906f920c07SWyon Bi 			break;
4916f920c07SWyon Bi 		case CLOCK_RECOVERY:
4926f920c07SWyon Bi 			retval = analogix_dp_process_clock_recovery(dp);
4936f920c07SWyon Bi 			if (retval)
4946f920c07SWyon Bi 				dev_err(dp->dev, "LT CR failed!\n");
4956f920c07SWyon Bi 			break;
4966f920c07SWyon Bi 		case EQUALIZER_TRAINING:
4976f920c07SWyon Bi 			retval = analogix_dp_process_equalizer_training(dp);
4986f920c07SWyon Bi 			if (retval)
4996f920c07SWyon Bi 				dev_err(dp->dev, "LT EQ failed!\n");
5006f920c07SWyon Bi 			break;
5016f920c07SWyon Bi 		case FINISHED:
5026f920c07SWyon Bi 			training_finished = 1;
5036f920c07SWyon Bi 			break;
5046f920c07SWyon Bi 		case FAILED:
5056f920c07SWyon Bi 			return -EREMOTEIO;
5066f920c07SWyon Bi 		}
5076f920c07SWyon Bi 	}
5086f920c07SWyon Bi 
5096f920c07SWyon Bi 	return retval;
5106f920c07SWyon Bi }
5116f920c07SWyon Bi 
5126f920c07SWyon Bi static int analogix_dp_set_link_train(struct analogix_dp_device *dp,
5136f920c07SWyon Bi 				      u32 count, u32 bwtype)
5146f920c07SWyon Bi {
51521069358SWyon Bi 	int i, ret;
5166f920c07SWyon Bi 
51721069358SWyon Bi 	for (i = 0; i < 5; i++) {
5186f920c07SWyon Bi 		ret = analogix_dp_init_training(dp, count, bwtype);
5196f920c07SWyon Bi 		if (ret < 0) {
5206f920c07SWyon Bi 			dev_err(dp->dev, "failed to init training\n");
5216f920c07SWyon Bi 			return ret;
5226f920c07SWyon Bi 		}
5236f920c07SWyon Bi 
5246f920c07SWyon Bi 		ret = analogix_dp_sw_link_training(dp);
52521069358SWyon Bi 		if (!ret)
52621069358SWyon Bi 			break;
5276f920c07SWyon Bi 	}
5286f920c07SWyon Bi 
52921069358SWyon Bi 	return ret;
5306f920c07SWyon Bi }
5316f920c07SWyon Bi 
5326f920c07SWyon Bi static int analogix_dp_config_video(struct analogix_dp_device *dp)
5336f920c07SWyon Bi {
5346f920c07SWyon Bi 	int timeout_loop = 0;
5356f920c07SWyon Bi 	int done_count = 0;
5366f920c07SWyon Bi 
5376f920c07SWyon Bi 	analogix_dp_config_video_slave_mode(dp);
5386f920c07SWyon Bi 
5396f920c07SWyon Bi 	analogix_dp_set_video_color_format(dp);
5406f920c07SWyon Bi 
5416f920c07SWyon Bi 	if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
5426f920c07SWyon Bi 		dev_err(dp->dev, "PLL is not locked yet.\n");
5436f920c07SWyon Bi 		return -EINVAL;
5446f920c07SWyon Bi 	}
5456f920c07SWyon Bi 
5466f920c07SWyon Bi 	for (;;) {
5476f920c07SWyon Bi 		timeout_loop++;
5486f920c07SWyon Bi 		if (analogix_dp_is_slave_video_stream_clock_on(dp) == 0)
5496f920c07SWyon Bi 			break;
5506f920c07SWyon Bi 		if (timeout_loop > DP_TIMEOUT_LOOP_COUNT) {
5516f920c07SWyon Bi 			dev_err(dp->dev, "Timeout of video streamclk ok\n");
5526f920c07SWyon Bi 			return -ETIMEDOUT;
5536f920c07SWyon Bi 		}
5546f920c07SWyon Bi 
5556f920c07SWyon Bi 		udelay(2);
5566f920c07SWyon Bi 	}
5576f920c07SWyon Bi 
5586f920c07SWyon Bi 	/* Set to use the register calculated M/N video */
5596f920c07SWyon Bi 	analogix_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
5606f920c07SWyon Bi 
5616f920c07SWyon Bi 	/* For video bist, Video timing must be generated by register */
5626f920c07SWyon Bi 	analogix_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
5636f920c07SWyon Bi 
5646f920c07SWyon Bi 	/* Disable video mute */
5656f920c07SWyon Bi 	analogix_dp_enable_video_mute(dp, 0);
5666f920c07SWyon Bi 
5676f920c07SWyon Bi 	/* Configure video slave mode */
5686f920c07SWyon Bi 	analogix_dp_enable_video_master(dp, 0);
5696f920c07SWyon Bi 
5706f920c07SWyon Bi 	/* Enable video input */
5716f920c07SWyon Bi 	analogix_dp_start_video(dp);
5726f920c07SWyon Bi 
5736f920c07SWyon Bi 	timeout_loop = 0;
5746f920c07SWyon Bi 
5756f920c07SWyon Bi 	for (;;) {
5766f920c07SWyon Bi 		timeout_loop++;
5776f920c07SWyon Bi 		if (analogix_dp_is_video_stream_on(dp) == 0) {
5786f920c07SWyon Bi 			done_count++;
5796f920c07SWyon Bi 			if (done_count > 10)
5806f920c07SWyon Bi 				break;
5816f920c07SWyon Bi 		} else if (done_count) {
5826f920c07SWyon Bi 			done_count = 0;
5836f920c07SWyon Bi 		}
5846f920c07SWyon Bi 		if (timeout_loop > DP_TIMEOUT_LOOP_COUNT) {
5856f920c07SWyon Bi 			dev_err(dp->dev, "Timeout of video streamclk ok\n");
5866f920c07SWyon Bi 			return -ETIMEDOUT;
5876f920c07SWyon Bi 		}
5886f920c07SWyon Bi 
5896f920c07SWyon Bi 		udelay(1001);
5906f920c07SWyon Bi 	}
5916f920c07SWyon Bi 
5926f920c07SWyon Bi 	return 0;
5936f920c07SWyon Bi }
5946f920c07SWyon Bi 
5956f920c07SWyon Bi static void analogix_dp_enable_scramble(struct analogix_dp_device *dp,
5966f920c07SWyon Bi 					bool enable)
5976f920c07SWyon Bi {
5986f920c07SWyon Bi 	u8 data;
5996f920c07SWyon Bi 
6006f920c07SWyon Bi 	if (enable) {
6016f920c07SWyon Bi 		analogix_dp_enable_scrambling(dp);
6026f920c07SWyon Bi 
6036f920c07SWyon Bi 		analogix_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET,
6046f920c07SWyon Bi 						&data);
6056f920c07SWyon Bi 		analogix_dp_write_byte_to_dpcd(dp,
6066f920c07SWyon Bi 			DP_TRAINING_PATTERN_SET,
6076f920c07SWyon Bi 			(u8)(data & ~DP_LINK_SCRAMBLING_DISABLE));
6086f920c07SWyon Bi 	} else {
6096f920c07SWyon Bi 		analogix_dp_disable_scrambling(dp);
6106f920c07SWyon Bi 
6116f920c07SWyon Bi 		analogix_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET,
6126f920c07SWyon Bi 						&data);
6136f920c07SWyon Bi 		analogix_dp_write_byte_to_dpcd(dp,
6146f920c07SWyon Bi 			DP_TRAINING_PATTERN_SET,
6156f920c07SWyon Bi 			(u8)(data | DP_LINK_SCRAMBLING_DISABLE));
6166f920c07SWyon Bi 	}
6176f920c07SWyon Bi }
6186f920c07SWyon Bi 
6196f920c07SWyon Bi static void analogix_dp_init_dp(struct analogix_dp_device *dp)
6206f920c07SWyon Bi {
6216f920c07SWyon Bi 	analogix_dp_reset(dp);
6226f920c07SWyon Bi 
6236f920c07SWyon Bi 	analogix_dp_swreset(dp);
6246f920c07SWyon Bi 
6256f920c07SWyon Bi 	analogix_dp_init_analog_param(dp);
6266f920c07SWyon Bi 	analogix_dp_init_interrupt(dp);
6276f920c07SWyon Bi 
6286f920c07SWyon Bi 	/* SW defined function Normal operation */
6296f920c07SWyon Bi 	analogix_dp_enable_sw_function(dp);
6306f920c07SWyon Bi 
6316f920c07SWyon Bi 	analogix_dp_config_interrupt(dp);
6326f920c07SWyon Bi 	analogix_dp_init_analog_func(dp);
6336f920c07SWyon Bi 
6346f920c07SWyon Bi 	analogix_dp_init_hpd(dp);
6356f920c07SWyon Bi 	analogix_dp_init_aux(dp);
6366f920c07SWyon Bi }
6376f920c07SWyon Bi 
6386f920c07SWyon Bi static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data)
6396f920c07SWyon Bi {
6406f920c07SWyon Bi 	int i;
6416f920c07SWyon Bi 	unsigned char sum = 0;
6426f920c07SWyon Bi 
6436f920c07SWyon Bi 	for (i = 0; i < EDID_BLOCK_LENGTH; i++)
6446f920c07SWyon Bi 		sum = sum + edid_data[i];
6456f920c07SWyon Bi 
6466f920c07SWyon Bi 	return sum;
6476f920c07SWyon Bi }
6486f920c07SWyon Bi 
6496f920c07SWyon Bi static int analogix_dp_read_edid(struct analogix_dp_device *dp)
6506f920c07SWyon Bi {
6516f920c07SWyon Bi 	unsigned char *edid = dp->edid;
6526f920c07SWyon Bi 	unsigned int extend_block = 0;
6536f920c07SWyon Bi 	unsigned char test_vector;
6546f920c07SWyon Bi 	int retval;
6556f920c07SWyon Bi 
6566f920c07SWyon Bi 	/*
6576f920c07SWyon Bi 	 * EDID device address is 0x50.
6586f920c07SWyon Bi 	 * However, if necessary, you must have set upper address
6596f920c07SWyon Bi 	 * into E-EDID in I2C device, 0x30.
6606f920c07SWyon Bi 	 */
6616f920c07SWyon Bi 
6626f920c07SWyon Bi 	/* Read Extension Flag, Number of 128-byte EDID extension blocks */
6636f920c07SWyon Bi 	retval = analogix_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
6646f920c07SWyon Bi 						EDID_EXTENSION_FLAG,
6656f920c07SWyon Bi 						&extend_block);
6666f920c07SWyon Bi 	if (retval)
6676f920c07SWyon Bi 		return retval;
6686f920c07SWyon Bi 
6696f920c07SWyon Bi 	if (extend_block > 0) {
6706f920c07SWyon Bi 		debug("EDID data includes a single extension!\n");
6716f920c07SWyon Bi 
6726f920c07SWyon Bi 		/* Read EDID data */
6736f920c07SWyon Bi 		retval = analogix_dp_read_bytes_from_i2c(dp,
6746f920c07SWyon Bi 						I2C_EDID_DEVICE_ADDR,
6756f920c07SWyon Bi 						EDID_HEADER_PATTERN,
6766f920c07SWyon Bi 						EDID_BLOCK_LENGTH,
6776f920c07SWyon Bi 						&edid[EDID_HEADER_PATTERN]);
6786f920c07SWyon Bi 		if (retval < 0)
6796f920c07SWyon Bi 			return retval;
6806f920c07SWyon Bi 
6816f920c07SWyon Bi 		if (analogix_dp_calc_edid_check_sum(edid))
6826f920c07SWyon Bi 			return -EINVAL;
6836f920c07SWyon Bi 
6846f920c07SWyon Bi 		/* Read additional EDID data */
6856f920c07SWyon Bi 		retval = analogix_dp_read_bytes_from_i2c(dp,
6866f920c07SWyon Bi 				I2C_EDID_DEVICE_ADDR,
6876f920c07SWyon Bi 				EDID_BLOCK_LENGTH,
6886f920c07SWyon Bi 				EDID_BLOCK_LENGTH,
6896f920c07SWyon Bi 				&edid[EDID_BLOCK_LENGTH]);
6906f920c07SWyon Bi 		if (retval < 0)
6916f920c07SWyon Bi 			return retval;
6926f920c07SWyon Bi 
6936f920c07SWyon Bi 		if (analogix_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]))
6946f920c07SWyon Bi 			return -EINVAL;
6956f920c07SWyon Bi 
6966f920c07SWyon Bi 		analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST,
6976f920c07SWyon Bi 						&test_vector);
6986f920c07SWyon Bi 		if (test_vector & DP_TEST_LINK_EDID_READ) {
6996f920c07SWyon Bi 			analogix_dp_write_byte_to_dpcd(dp,
7006f920c07SWyon Bi 				DP_TEST_EDID_CHECKSUM,
7016f920c07SWyon Bi 				edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
7026f920c07SWyon Bi 			analogix_dp_write_byte_to_dpcd(dp,
7036f920c07SWyon Bi 				DP_TEST_RESPONSE,
7046f920c07SWyon Bi 				DP_TEST_EDID_CHECKSUM_WRITE);
7056f920c07SWyon Bi 		}
7066f920c07SWyon Bi 	} else {
7076f920c07SWyon Bi 		dev_info(dp->dev,
7086f920c07SWyon Bi 			 "EDID data does not include any extensions.\n");
7096f920c07SWyon Bi 
7106f920c07SWyon Bi 		/* Read EDID data */
7116f920c07SWyon Bi 		retval = analogix_dp_read_bytes_from_i2c(dp,
7126f920c07SWyon Bi 				I2C_EDID_DEVICE_ADDR, EDID_HEADER_PATTERN,
7136f920c07SWyon Bi 				EDID_BLOCK_LENGTH, &edid[EDID_HEADER_PATTERN]);
7146f920c07SWyon Bi 		if (retval < 0)
7156f920c07SWyon Bi 			return retval;
7166f920c07SWyon Bi 
7176f920c07SWyon Bi 		if (analogix_dp_calc_edid_check_sum(edid))
7186f920c07SWyon Bi 			return -EINVAL;
7196f920c07SWyon Bi 
7206f920c07SWyon Bi 		analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST,
7216f920c07SWyon Bi 						&test_vector);
7226f920c07SWyon Bi 		if (test_vector & DP_TEST_LINK_EDID_READ) {
7236f920c07SWyon Bi 			analogix_dp_write_byte_to_dpcd(dp,
7246f920c07SWyon Bi 				DP_TEST_EDID_CHECKSUM, edid[EDID_CHECKSUM]);
7256f920c07SWyon Bi 			analogix_dp_write_byte_to_dpcd(dp,
7266f920c07SWyon Bi 				DP_TEST_RESPONSE, DP_TEST_EDID_CHECKSUM_WRITE);
7276f920c07SWyon Bi 		}
7286f920c07SWyon Bi 	}
7296f920c07SWyon Bi 
7306f920c07SWyon Bi 	return 0;
7316f920c07SWyon Bi }
7326f920c07SWyon Bi 
7336f920c07SWyon Bi static int analogix_dp_handle_edid(struct analogix_dp_device *dp)
7346f920c07SWyon Bi {
7356f920c07SWyon Bi 	u8 buf[12];
7366f920c07SWyon Bi 	int i, try = 5;
7376f920c07SWyon Bi 	int retval;
7386f920c07SWyon Bi 
7396f920c07SWyon Bi retry:
7406f920c07SWyon Bi 	/* Read DPCD DP_DPCD_REV~RECEIVE_PORT1_CAP_1 */
7416f920c07SWyon Bi 	retval = analogix_dp_read_bytes_from_dpcd(dp, DP_DPCD_REV, 12, buf);
7426f920c07SWyon Bi 
7436f920c07SWyon Bi 	if (retval && try--) {
7446f920c07SWyon Bi 		mdelay(10);
7456f920c07SWyon Bi 		goto retry;
7466f920c07SWyon Bi 	}
7476f920c07SWyon Bi 
7486f920c07SWyon Bi 	if (retval)
7496f920c07SWyon Bi 		return retval;
7506f920c07SWyon Bi 
7516f920c07SWyon Bi 	/* Read EDID */
7526f920c07SWyon Bi 	for (i = 0; i < 3; i++) {
7536f920c07SWyon Bi 		retval = analogix_dp_read_edid(dp);
7546f920c07SWyon Bi 		if (!retval)
7556f920c07SWyon Bi 			break;
7566f920c07SWyon Bi 	}
7576f920c07SWyon Bi 
7586f920c07SWyon Bi 	return retval;
7596f920c07SWyon Bi }
7606f920c07SWyon Bi 
76158c17f51SSandy Huang static int analogix_dp_connector_pre_init(struct display_state *state)
76258c17f51SSandy Huang {
76358c17f51SSandy Huang 	struct connector_state *conn_state = &state->conn_state;
76458c17f51SSandy Huang 
76558c17f51SSandy Huang 	conn_state->type = DRM_MODE_CONNECTOR_eDP;
76658c17f51SSandy Huang 
76758c17f51SSandy Huang 	return 0;
76858c17f51SSandy Huang }
76958c17f51SSandy Huang 
7706f920c07SWyon Bi static int analogix_dp_connector_init(struct display_state *state)
7716f920c07SWyon Bi {
7726f920c07SWyon Bi 	struct connector_state *conn_state = &state->conn_state;
7736f920c07SWyon Bi 	struct analogix_dp_device *dp = dev_get_priv(conn_state->dev);
7746f920c07SWyon Bi 
7757adc0066SWyon Bi 	conn_state->output_if |= dp->id ? VOP_OUTPUT_IF_eDP1 : VOP_OUTPUT_IF_eDP0;
7766f920c07SWyon Bi 	conn_state->output_mode = ROCKCHIP_OUT_MODE_AAAA;
7776f920c07SWyon Bi 	conn_state->color_space = V4L2_COLORSPACE_DEFAULT;
7786f920c07SWyon Bi 
779699c29a5SWyon Bi 	reset_assert_bulk(&dp->resets);
780dddde95bSWyon Bi 	udelay(1);
781699c29a5SWyon Bi 	reset_deassert_bulk(&dp->resets);
782dddde95bSWyon Bi 
783cb17ca6cSSandy Huang 	conn_state->disp_info  = rockchip_get_disp_info(conn_state->type, dp->id);
7847adc0066SWyon Bi 	generic_phy_set_mode(&dp->phy, PHY_MODE_DP);
785699c29a5SWyon Bi 	generic_phy_power_on(&dp->phy);
7866f920c07SWyon Bi 	analogix_dp_init_dp(dp);
7876f920c07SWyon Bi 
7886f920c07SWyon Bi 	return 0;
7896f920c07SWyon Bi }
7906f920c07SWyon Bi 
7916f920c07SWyon Bi static int analogix_dp_connector_get_edid(struct display_state *state)
7926f920c07SWyon Bi {
7936f920c07SWyon Bi 	struct connector_state *conn_state = &state->conn_state;
7946f920c07SWyon Bi 	struct analogix_dp_device *dp = dev_get_priv(conn_state->dev);
7956f920c07SWyon Bi 	int ret;
7966f920c07SWyon Bi 
7976f920c07SWyon Bi 	ret = analogix_dp_handle_edid(dp);
7986f920c07SWyon Bi 	if (ret) {
7996f920c07SWyon Bi 		dev_err(dp->dev, "failed to get edid\n");
8006f920c07SWyon Bi 		return ret;
8016f920c07SWyon Bi 	}
8026f920c07SWyon Bi 
8036f920c07SWyon Bi 	memcpy(&conn_state->edid, &dp->edid, sizeof(dp->edid));
8046f920c07SWyon Bi 
8056f920c07SWyon Bi 	return 0;
8066f920c07SWyon Bi }
8076f920c07SWyon Bi 
808d3e70420SWyon Bi static int analogix_dp_link_power_up(struct analogix_dp_device *dp)
809d3e70420SWyon Bi {
810d3e70420SWyon Bi 	u8 value;
811d3e70420SWyon Bi 	int ret;
812d3e70420SWyon Bi 
813d3e70420SWyon Bi 	if (dp->dpcd[DP_DPCD_REV] < 0x11)
814d3e70420SWyon Bi 		return 0;
815d3e70420SWyon Bi 
816d3e70420SWyon Bi 	ret = analogix_dp_read_byte_from_dpcd(dp, DP_SET_POWER, &value);
817d3e70420SWyon Bi 	if (ret < 0)
818d3e70420SWyon Bi 		return ret;
819d3e70420SWyon Bi 
820d3e70420SWyon Bi 	value &= ~DP_SET_POWER_MASK;
821d3e70420SWyon Bi 	value |= DP_SET_POWER_D0;
822d3e70420SWyon Bi 
823d3e70420SWyon Bi 	ret = analogix_dp_write_byte_to_dpcd(dp, DP_SET_POWER, value);
824d3e70420SWyon Bi 	if (ret < 0)
825d3e70420SWyon Bi 		return ret;
826d3e70420SWyon Bi 
827d3e70420SWyon Bi 	mdelay(1);
828d3e70420SWyon Bi 
829d3e70420SWyon Bi 	return 0;
830d3e70420SWyon Bi }
831d3e70420SWyon Bi 
832d3e70420SWyon Bi static int analogix_dp_link_power_down(struct analogix_dp_device *dp)
833d3e70420SWyon Bi {
834d3e70420SWyon Bi 	u8 value;
835d3e70420SWyon Bi 	int ret;
836d3e70420SWyon Bi 
837d3e70420SWyon Bi 	if (dp->dpcd[DP_DPCD_REV] < 0x11)
838d3e70420SWyon Bi 		return 0;
839d3e70420SWyon Bi 
840d3e70420SWyon Bi 	ret = analogix_dp_read_byte_from_dpcd(dp, DP_SET_POWER, &value);
841d3e70420SWyon Bi 	if (ret < 0)
842d3e70420SWyon Bi 		return ret;
843d3e70420SWyon Bi 
844d3e70420SWyon Bi 	value &= ~DP_SET_POWER_MASK;
845d3e70420SWyon Bi 	value |= DP_SET_POWER_D3;
846d3e70420SWyon Bi 
847d3e70420SWyon Bi 	ret = analogix_dp_write_byte_to_dpcd(dp, DP_SET_POWER, value);
848d3e70420SWyon Bi 	if (ret < 0)
849d3e70420SWyon Bi 		return ret;
850d3e70420SWyon Bi 
851d3e70420SWyon Bi 	return 0;
852d3e70420SWyon Bi }
853d3e70420SWyon Bi 
8546f920c07SWyon Bi static int analogix_dp_connector_enable(struct display_state *state)
8556f920c07SWyon Bi {
8566f920c07SWyon Bi 	struct connector_state *conn_state = &state->conn_state;
8576f920c07SWyon Bi 	struct crtc_state *crtc_state = &state->crtc_state;
8586f920c07SWyon Bi 	const struct rockchip_connector *connector = conn_state->connector;
8596f920c07SWyon Bi 	const struct rockchip_dp_chip_data *pdata = connector->data;
8606f920c07SWyon Bi 	struct analogix_dp_device *dp = dev_get_priv(conn_state->dev);
8612a74799bSJianqun Xu 	struct video_info *video = &dp->video_info;
8626f920c07SWyon Bi 	u32 val;
8636f920c07SWyon Bi 	int ret;
8646f920c07SWyon Bi 
865699c29a5SWyon Bi 	if (pdata->lcdsel_grf_reg) {
8666f920c07SWyon Bi 		if (crtc_state->crtc_id)
8676f920c07SWyon Bi 			val = pdata->lcdsel_lit;
8686f920c07SWyon Bi 		else
8696f920c07SWyon Bi 			val = pdata->lcdsel_big;
8706f920c07SWyon Bi 
8717adc0066SWyon Bi 		regmap_write(dp->grf, pdata->lcdsel_grf_reg, val);
8726f920c07SWyon Bi 	}
8736f920c07SWyon Bi 
8747adc0066SWyon Bi 	if (pdata->chip_type == RK3588_EDP)
8757adc0066SWyon Bi 		regmap_write(dp->grf, dp->id ? RK3588_GRF_VO1_CON1 : RK3588_GRF_VO1_CON0,
8767adc0066SWyon Bi 			     EDP_MODE << 16 | FIELD_PREP(EDP_MODE, 1));
8777adc0066SWyon Bi 
8782a74799bSJianqun Xu 	switch (conn_state->bpc) {
8792a74799bSJianqun Xu 	case 12:
8802a74799bSJianqun Xu 		video->color_depth = COLOR_12;
8812a74799bSJianqun Xu 		break;
8822a74799bSJianqun Xu 	case 10:
8832a74799bSJianqun Xu 		video->color_depth = COLOR_10;
8842a74799bSJianqun Xu 		break;
8852a74799bSJianqun Xu 	case 6:
8862a74799bSJianqun Xu 		video->color_depth = COLOR_6;
8872a74799bSJianqun Xu 		break;
8882a74799bSJianqun Xu 	case 8:
8892a74799bSJianqun Xu 	default:
8902a74799bSJianqun Xu 		video->color_depth = COLOR_8;
8912a74799bSJianqun Xu 		break;
8922a74799bSJianqun Xu 	}
8932a74799bSJianqun Xu 
8941a00cf6eSWyon Bi 	ret = analogix_dp_read_bytes_from_dpcd(dp, DP_DPCD_REV,
8951a00cf6eSWyon Bi 					       DP_RECEIVER_CAP_SIZE, dp->dpcd);
8961a00cf6eSWyon Bi 	if (ret) {
8971a00cf6eSWyon Bi 		dev_err(dp->dev, "failed to read dpcd caps: %d\n", ret);
8981a00cf6eSWyon Bi 		return ret;
8991a00cf6eSWyon Bi 	}
9001a00cf6eSWyon Bi 
901d3e70420SWyon Bi 	ret = analogix_dp_link_power_up(dp);
902d3e70420SWyon Bi 	if (ret) {
903d3e70420SWyon Bi 		dev_err(dp->dev, "failed to power up link: %d\n", ret);
904d3e70420SWyon Bi 		return ret;
905d3e70420SWyon Bi 	}
906d3e70420SWyon Bi 
9076f920c07SWyon Bi 	ret = analogix_dp_set_link_train(dp, dp->video_info.max_lane_count,
9086f920c07SWyon Bi 					 dp->video_info.max_link_rate);
9096f920c07SWyon Bi 	if (ret) {
9106f920c07SWyon Bi 		dev_err(dp->dev, "unable to do link train\n");
9116f920c07SWyon Bi 		return ret;
9126f920c07SWyon Bi 	}
9136f920c07SWyon Bi 
9146f920c07SWyon Bi 	analogix_dp_enable_scramble(dp, 1);
9156f920c07SWyon Bi 	analogix_dp_enable_rx_to_enhanced_mode(dp, 1);
9166f920c07SWyon Bi 	analogix_dp_enable_enhanced_mode(dp, 1);
9176f920c07SWyon Bi 
9186f920c07SWyon Bi 	analogix_dp_init_video(dp);
9190b8cf90dSWyon Bi 	analogix_dp_set_video_format(dp, &conn_state->mode);
9200b8cf90dSWyon Bi 
9210b8cf90dSWyon Bi 	if (dp->video_bist_enable)
9220b8cf90dSWyon Bi 		analogix_dp_video_bist_enable(dp);
9230b8cf90dSWyon Bi 
9246f920c07SWyon Bi 	ret = analogix_dp_config_video(dp);
9256f920c07SWyon Bi 	if (ret) {
9266f920c07SWyon Bi 		dev_err(dp->dev, "unable to config video\n");
9276f920c07SWyon Bi 		return ret;
9286f920c07SWyon Bi 	}
9296f920c07SWyon Bi 
9306f920c07SWyon Bi 	return 0;
9316f920c07SWyon Bi }
9326f920c07SWyon Bi 
9336f920c07SWyon Bi static int analogix_dp_connector_disable(struct display_state *state)
9346f920c07SWyon Bi {
9357adc0066SWyon Bi 	struct connector_state *conn_state = &state->conn_state;
9367adc0066SWyon Bi 	const struct rockchip_connector *connector = conn_state->connector;
9377adc0066SWyon Bi 	const struct rockchip_dp_chip_data *pdata = connector->data;
9387adc0066SWyon Bi 	struct analogix_dp_device *dp = dev_get_priv(conn_state->dev);
9397adc0066SWyon Bi 
940d3e70420SWyon Bi 	if (!analogix_dp_get_plug_in_status(dp))
941d3e70420SWyon Bi 		analogix_dp_link_power_down(dp);
942d3e70420SWyon Bi 
9437adc0066SWyon Bi 	if (pdata->chip_type == RK3588_EDP)
9447adc0066SWyon Bi 		regmap_write(dp->grf, dp->id ? RK3588_GRF_VO1_CON1 : RK3588_GRF_VO1_CON0,
9457adc0066SWyon Bi 			     EDP_MODE << 16 | FIELD_PREP(EDP_MODE, 0));
9466f920c07SWyon Bi 
9476f920c07SWyon Bi 	return 0;
9486f920c07SWyon Bi }
9496f920c07SWyon Bi 
950d90a0d9fSWyon Bi static int analogix_dp_connector_detect(struct display_state *state)
951d90a0d9fSWyon Bi {
952d90a0d9fSWyon Bi 	struct connector_state *conn_state = &state->conn_state;
9538ae84ec5SWyon Bi 	struct panel_state *panel_state = &state->panel_state;
954d90a0d9fSWyon Bi 	struct analogix_dp_device *dp = dev_get_priv(conn_state->dev);
9558ae84ec5SWyon Bi 	int ret;
956d90a0d9fSWyon Bi 
9578ae84ec5SWyon Bi 	if (panel_state->panel)
9588ae84ec5SWyon Bi 		rockchip_panel_prepare(panel_state->panel);
9598ae84ec5SWyon Bi 
9608ae84ec5SWyon Bi 	if (!analogix_dp_detect(dp))
9618ae84ec5SWyon Bi 		goto unprepare_panel;
9628ae84ec5SWyon Bi 
9638ae84ec5SWyon Bi 	ret = analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE,
9648ae84ec5SWyon Bi 					      &dp->link_train.link_rate);
9658ae84ec5SWyon Bi 	if (ret < 0) {
9668ae84ec5SWyon Bi 		dev_err(dp->dev, "failed to read link rate: %d\n", ret);
9678ae84ec5SWyon Bi 		goto unprepare_panel;
9688ae84ec5SWyon Bi 	}
9698ae84ec5SWyon Bi 
9708ae84ec5SWyon Bi 	ret = analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT,
9718ae84ec5SWyon Bi 					      &dp->link_train.lane_count);
9728ae84ec5SWyon Bi 	if (ret < 0) {
9738ae84ec5SWyon Bi 		dev_err(dp->dev, "failed to read lane count: %d\n", ret);
9748ae84ec5SWyon Bi 		goto unprepare_panel;
9758ae84ec5SWyon Bi 	}
9768ae84ec5SWyon Bi 
9778ae84ec5SWyon Bi 	return true;
9788ae84ec5SWyon Bi 
9798ae84ec5SWyon Bi unprepare_panel:
9808ae84ec5SWyon Bi 	if (panel_state->panel)
9818ae84ec5SWyon Bi 		rockchip_panel_unprepare(panel_state->panel);
9828ae84ec5SWyon Bi 	return false;
983d90a0d9fSWyon Bi }
984d90a0d9fSWyon Bi 
9856f920c07SWyon Bi static const struct rockchip_connector_funcs analogix_dp_connector_funcs = {
98658c17f51SSandy Huang 	.pre_init = analogix_dp_connector_pre_init,
9876f920c07SWyon Bi 	.init = analogix_dp_connector_init,
9886f920c07SWyon Bi 	.get_edid = analogix_dp_connector_get_edid,
9896f920c07SWyon Bi 	.enable = analogix_dp_connector_enable,
9906f920c07SWyon Bi 	.disable = analogix_dp_connector_disable,
991d90a0d9fSWyon Bi 	.detect = analogix_dp_connector_detect,
9926f920c07SWyon Bi };
9936f920c07SWyon Bi 
994*1f59ac36SWyon Bi static int analogix_dp_parse_dt(struct analogix_dp_device *dp)
995*1f59ac36SWyon Bi {
996*1f59ac36SWyon Bi 	struct udevice *dev = dp->dev;
997*1f59ac36SWyon Bi 	int len;
998*1f59ac36SWyon Bi 	u32 num_lanes;
999*1f59ac36SWyon Bi 	int ret;
1000*1f59ac36SWyon Bi 
1001*1f59ac36SWyon Bi 	dp->force_hpd = dev_read_bool(dev, "force-hpd");
1002*1f59ac36SWyon Bi 	dp->video_bist_enable = dev_read_bool(dev, "analogix,video-bist-enable");
1003*1f59ac36SWyon Bi 
1004*1f59ac36SWyon Bi 	if (dev_read_prop(dev, "data-lanes", &len)) {
1005*1f59ac36SWyon Bi 		num_lanes = len / sizeof(u32);
1006*1f59ac36SWyon Bi 		if (num_lanes < 1 || num_lanes > 4 || num_lanes == 3) {
1007*1f59ac36SWyon Bi 			dev_err(dev, "bad number of data lanes\n");
1008*1f59ac36SWyon Bi 			return -EINVAL;
1009*1f59ac36SWyon Bi 		}
1010*1f59ac36SWyon Bi 
1011*1f59ac36SWyon Bi 		ret = dev_read_u32_array(dev, "data-lanes", dp->lane_map,
1012*1f59ac36SWyon Bi 					 num_lanes);
1013*1f59ac36SWyon Bi 		if (ret)
1014*1f59ac36SWyon Bi 			return ret;
1015*1f59ac36SWyon Bi 
1016*1f59ac36SWyon Bi 		dp->video_info.max_lane_count = num_lanes;
1017*1f59ac36SWyon Bi 	} else {
1018*1f59ac36SWyon Bi 		dp->lane_map[0] = 0;
1019*1f59ac36SWyon Bi 		dp->lane_map[1] = 1;
1020*1f59ac36SWyon Bi 		dp->lane_map[2] = 2;
1021*1f59ac36SWyon Bi 		dp->lane_map[3] = 3;
1022*1f59ac36SWyon Bi 	}
1023*1f59ac36SWyon Bi 
1024*1f59ac36SWyon Bi 	return 0;
1025*1f59ac36SWyon Bi }
1026*1f59ac36SWyon Bi 
10276f920c07SWyon Bi static int analogix_dp_probe(struct udevice *dev)
10286f920c07SWyon Bi {
10296f920c07SWyon Bi 	struct analogix_dp_device *dp = dev_get_priv(dev);
10306f920c07SWyon Bi 	const struct rockchip_connector *connector =
10316f920c07SWyon Bi 		(const struct rockchip_connector *)dev_get_driver_data(dev);
10326f920c07SWyon Bi 	const struct rockchip_dp_chip_data *pdata = connector->data;
10337adc0066SWyon Bi 	struct udevice *syscon;
10346f920c07SWyon Bi 	int ret;
10356f920c07SWyon Bi 
10366f920c07SWyon Bi 	dp->reg_base = dev_read_addr_ptr(dev);
10376f920c07SWyon Bi 
1038cb17ca6cSSandy Huang 	dp->id = of_alias_get_id(ofnode_to_np(dev->node), "edp");
1039cb17ca6cSSandy Huang 	if (dp->id < 0)
1040cb17ca6cSSandy Huang 		dp->id = 0;
10417adc0066SWyon Bi 
10427adc0066SWyon Bi 	ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,grf",
10437adc0066SWyon Bi 					   &syscon);
10447adc0066SWyon Bi 	if (!ret) {
10457adc0066SWyon Bi 		dp->grf = syscon_get_regmap(syscon);
10467adc0066SWyon Bi 		if (!dp->grf)
10477adc0066SWyon Bi 			return -ENODEV;
10487adc0066SWyon Bi 	}
10497adc0066SWyon Bi 
1050699c29a5SWyon Bi 	ret = reset_get_bulk(dev, &dp->resets);
1051dddde95bSWyon Bi 	if (ret) {
1052dddde95bSWyon Bi 		dev_err(dev, "failed to get reset control: %d\n", ret);
1053dddde95bSWyon Bi 		return ret;
1054dddde95bSWyon Bi 	}
1055dddde95bSWyon Bi 
10566f920c07SWyon Bi 	ret = gpio_request_by_name(dev, "hpd-gpios", 0, &dp->hpd_gpio,
10576f920c07SWyon Bi 				   GPIOD_IS_IN);
10586f920c07SWyon Bi 	if (ret && ret != -ENOENT) {
10596f920c07SWyon Bi 		dev_err(dev, "failed to get hpd GPIO: %d\n", ret);
10606f920c07SWyon Bi 		return ret;
10616f920c07SWyon Bi 	}
10626f920c07SWyon Bi 
1063699c29a5SWyon Bi 	generic_phy_get_by_name(dev, "dp", &dp->phy);
1064699c29a5SWyon Bi 
10656f920c07SWyon Bi 	dp->plat_data.dev_type = ROCKCHIP_DP;
10666f920c07SWyon Bi 	dp->plat_data.subdev_type = pdata->chip_type;
1067699c29a5SWyon Bi 	dp->plat_data.ssc = pdata->ssc;
10687adc0066SWyon Bi 
10697adc0066SWyon Bi 	dp->video_info.max_link_rate = pdata->max_link_rate;
10707adc0066SWyon Bi 	dp->video_info.max_lane_count = pdata->max_lane_count;
10716f920c07SWyon Bi 
10726f920c07SWyon Bi 	dp->dev = dev;
10736f920c07SWyon Bi 
1074*1f59ac36SWyon Bi 	ret = analogix_dp_parse_dt(dp);
1075*1f59ac36SWyon Bi 	if (ret) {
1076*1f59ac36SWyon Bi 		dev_err(dev, "failed to parse DT: %d\n", ret);
1077*1f59ac36SWyon Bi 		return ret;
1078*1f59ac36SWyon Bi 	}
1079*1f59ac36SWyon Bi 
10806f920c07SWyon Bi 	return 0;
10816f920c07SWyon Bi }
10826f920c07SWyon Bi 
10836f920c07SWyon Bi static const struct rockchip_dp_chip_data rk3288_edp_platform_data = {
10846f920c07SWyon Bi 	.lcdsel_grf_reg = 0x025c,
10856f920c07SWyon Bi 	.lcdsel_big = 0 | BIT(21),
10866f920c07SWyon Bi 	.lcdsel_lit = BIT(5) | BIT(21),
10876f920c07SWyon Bi 	.chip_type = RK3288_DP,
10887adc0066SWyon Bi 
10897adc0066SWyon Bi 	.max_link_rate = DP_LINK_BW_2_7,
10907adc0066SWyon Bi 	.max_lane_count = 4,
10916f920c07SWyon Bi };
10926f920c07SWyon Bi 
10936f920c07SWyon Bi static const struct rockchip_connector rk3288_edp_driver_data = {
10946f920c07SWyon Bi 	 .funcs = &analogix_dp_connector_funcs,
10956f920c07SWyon Bi 	 .data = &rk3288_edp_platform_data,
10966f920c07SWyon Bi };
10976f920c07SWyon Bi 
10986f920c07SWyon Bi static const struct rockchip_dp_chip_data rk3368_edp_platform_data = {
10996f920c07SWyon Bi 	.chip_type = RK3368_EDP,
11007adc0066SWyon Bi 
11017adc0066SWyon Bi 	.max_link_rate = DP_LINK_BW_2_7,
11027adc0066SWyon Bi 	.max_lane_count = 4,
11036f920c07SWyon Bi };
11046f920c07SWyon Bi 
11056f920c07SWyon Bi static const struct rockchip_connector rk3368_edp_driver_data = {
11066f920c07SWyon Bi 	 .funcs = &analogix_dp_connector_funcs,
11076f920c07SWyon Bi 	 .data = &rk3368_edp_platform_data,
11086f920c07SWyon Bi };
11096f920c07SWyon Bi 
11106f920c07SWyon Bi static const struct rockchip_dp_chip_data rk3399_edp_platform_data = {
11116f920c07SWyon Bi 	.lcdsel_grf_reg = 0x6250,
11126f920c07SWyon Bi 	.lcdsel_big = 0 | BIT(21),
11136f920c07SWyon Bi 	.lcdsel_lit = BIT(5) | BIT(21),
11146f920c07SWyon Bi 	.chip_type = RK3399_EDP,
11157adc0066SWyon Bi 
11167adc0066SWyon Bi 	.max_link_rate = DP_LINK_BW_2_7,
11177adc0066SWyon Bi 	.max_lane_count = 4,
11186f920c07SWyon Bi };
11196f920c07SWyon Bi 
11206f920c07SWyon Bi static const struct rockchip_connector rk3399_edp_driver_data = {
11216f920c07SWyon Bi 	 .funcs = &analogix_dp_connector_funcs,
11226f920c07SWyon Bi 	 .data = &rk3399_edp_platform_data,
11236f920c07SWyon Bi };
11246f920c07SWyon Bi 
1125699c29a5SWyon Bi static const struct rockchip_dp_chip_data rk3568_edp_platform_data = {
1126699c29a5SWyon Bi 	.chip_type = RK3568_EDP,
1127699c29a5SWyon Bi 	.ssc = true,
11287adc0066SWyon Bi 
11297adc0066SWyon Bi 	.max_link_rate = DP_LINK_BW_2_7,
11307adc0066SWyon Bi 	.max_lane_count = 4,
1131699c29a5SWyon Bi };
1132699c29a5SWyon Bi 
1133699c29a5SWyon Bi static const struct rockchip_connector rk3568_edp_driver_data = {
1134699c29a5SWyon Bi 	 .funcs = &analogix_dp_connector_funcs,
1135699c29a5SWyon Bi 	 .data = &rk3568_edp_platform_data,
1136699c29a5SWyon Bi };
1137699c29a5SWyon Bi 
11387adc0066SWyon Bi static const struct rockchip_dp_chip_data rk3588_edp_platform_data = {
11397adc0066SWyon Bi 	.chip_type = RK3588_EDP,
11407adc0066SWyon Bi 	.ssc = true,
11417adc0066SWyon Bi 
11427adc0066SWyon Bi 	.max_link_rate = DP_LINK_BW_5_4,
11437adc0066SWyon Bi 	.max_lane_count = 4,
11447adc0066SWyon Bi };
11457adc0066SWyon Bi 
11467adc0066SWyon Bi static const struct rockchip_connector rk3588_edp_driver_data = {
11477adc0066SWyon Bi 	 .funcs = &analogix_dp_connector_funcs,
11487adc0066SWyon Bi 	 .data = &rk3588_edp_platform_data,
11497adc0066SWyon Bi };
11507adc0066SWyon Bi 
11516f920c07SWyon Bi static const struct udevice_id analogix_dp_ids[] = {
11526f920c07SWyon Bi 	{
11536f920c07SWyon Bi 		.compatible = "rockchip,rk3288-dp",
11546f920c07SWyon Bi 		.data = (ulong)&rk3288_edp_driver_data,
11556f920c07SWyon Bi 	}, {
11566f920c07SWyon Bi 		.compatible = "rockchip,rk3368-edp",
11576f920c07SWyon Bi 		.data = (ulong)&rk3368_edp_driver_data,
11586f920c07SWyon Bi 	}, {
11596f920c07SWyon Bi 		.compatible = "rockchip,rk3399-edp",
11606f920c07SWyon Bi 		.data = (ulong)&rk3399_edp_driver_data,
1161699c29a5SWyon Bi 	}, {
1162699c29a5SWyon Bi 		.compatible = "rockchip,rk3568-edp",
1163699c29a5SWyon Bi 		.data = (ulong)&rk3568_edp_driver_data,
11647adc0066SWyon Bi 	}, {
11657adc0066SWyon Bi 		.compatible = "rockchip,rk3588-edp",
11667adc0066SWyon Bi 		.data = (ulong)&rk3588_edp_driver_data,
11676f920c07SWyon Bi 	},
11686f920c07SWyon Bi 	{}
11696f920c07SWyon Bi };
11706f920c07SWyon Bi 
11716f920c07SWyon Bi U_BOOT_DRIVER(analogix_dp) = {
11726f920c07SWyon Bi 	.name = "analogix_dp",
11736f920c07SWyon Bi 	.id = UCLASS_DISPLAY,
11746f920c07SWyon Bi 	.of_match = analogix_dp_ids,
11756f920c07SWyon Bi 	.probe = analogix_dp_probe,
11766f920c07SWyon Bi 	.priv_auto_alloc_size = sizeof(struct analogix_dp_device),
11776f920c07SWyon Bi };
1178