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, ®); 3696f920c07SWyon Bi dp->link_train.link_rate = reg; 3706f920c07SWyon Bi analogix_dp_get_lane_count(dp, ®); 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