xref: /rk3399_rockchip-uboot/drivers/video/drm/analogix_dp_reg.c (revision 1f59ac367d60d6dee358a5a4e197227035dbb2d4)
16f920c07SWyon Bi /*
26f920c07SWyon Bi  * Analogix DP (Display port) core register interface driver.
36f920c07SWyon Bi  *
46f920c07SWyon Bi  * Copyright (C) 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
56f920c07SWyon Bi  * Copyright (C) 2012 Samsung Electronics Co., Ltd.
66f920c07SWyon Bi  * Author: Jingoo Han <jg1.han@samsung.com>
76f920c07SWyon Bi  *
86f920c07SWyon Bi  * This program is free software; you can redistribute it and/or modify it
96f920c07SWyon Bi  * under the terms of the GNU General Public License as published by the
106f920c07SWyon Bi  * Free Software Foundation; either version 2 of the License, or (at your
116f920c07SWyon Bi  * option) any later version.
126f920c07SWyon Bi  */
136f920c07SWyon Bi 
146f920c07SWyon Bi #include <config.h>
156f920c07SWyon Bi #include <common.h>
166f920c07SWyon Bi #include <errno.h>
176f920c07SWyon Bi #include <malloc.h>
186f920c07SWyon Bi #include <asm/unaligned.h>
196f920c07SWyon Bi #include <linux/list.h>
206f920c07SWyon Bi #include <dm/device.h>
216f920c07SWyon Bi #include <syscon.h>
226f920c07SWyon Bi #include <asm/io.h>
236f920c07SWyon Bi #include <asm/gpio.h>
24a6285d17SWyon Bi #include <linux/iopoll.h>
256f920c07SWyon Bi 
266f920c07SWyon Bi #include "rockchip_display.h"
276f920c07SWyon Bi #include "rockchip_crtc.h"
286f920c07SWyon Bi #include "rockchip_connector.h"
296f920c07SWyon Bi #include "analogix_dp.h"
306f920c07SWyon Bi 
316f920c07SWyon Bi #define COMMON_INT_MASK_1	0
326f920c07SWyon Bi #define COMMON_INT_MASK_2	0
336f920c07SWyon Bi #define COMMON_INT_MASK_3	0
346f920c07SWyon Bi #define COMMON_INT_MASK_4	(HOTPLUG_CHG | HPD_LOST | PLUG)
356f920c07SWyon Bi #define INT_STA_MASK		INT_HPD
366f920c07SWyon Bi 
3752db8715SWyon Bi static void analogix_dp_write(struct analogix_dp_device *dp, u32 reg, u32 val)
3852db8715SWyon Bi {
3952db8715SWyon Bi 	readl(dp->reg_base);
4052db8715SWyon Bi 	writel(val, dp->reg_base + reg);
4152db8715SWyon Bi 	writel(val, dp->reg_base + reg);
4252db8715SWyon Bi }
4352db8715SWyon Bi 
4452db8715SWyon Bi static u32 analogix_dp_read(struct analogix_dp_device *dp, u32 reg)
4552db8715SWyon Bi {
4652db8715SWyon Bi 	readl(dp->reg_base + reg);
4752db8715SWyon Bi 
4852db8715SWyon Bi 	return readl(dp->reg_base + reg);
4952db8715SWyon Bi }
5052db8715SWyon Bi 
516f920c07SWyon Bi void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable)
526f920c07SWyon Bi {
536f920c07SWyon Bi 	u32 reg;
546f920c07SWyon Bi 
556f920c07SWyon Bi 	if (enable) {
5652db8715SWyon Bi 		reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_1);
576f920c07SWyon Bi 		reg |= HDCP_VIDEO_MUTE;
5852db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_1, reg);
596f920c07SWyon Bi 	} else {
6052db8715SWyon Bi 		reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_1);
616f920c07SWyon Bi 		reg &= ~HDCP_VIDEO_MUTE;
6252db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_1, reg);
636f920c07SWyon Bi 	}
646f920c07SWyon Bi }
656f920c07SWyon Bi 
666f920c07SWyon Bi void analogix_dp_stop_video(struct analogix_dp_device *dp)
676f920c07SWyon Bi {
686f920c07SWyon Bi 	u32 reg;
696f920c07SWyon Bi 
7052db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_1);
716f920c07SWyon Bi 	reg &= ~VIDEO_EN;
7252db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_1, reg);
736f920c07SWyon Bi }
746f920c07SWyon Bi 
75*1f59ac36SWyon Bi static void analogix_dp_set_lane_map(struct analogix_dp_device *dp)
766f920c07SWyon Bi {
77*1f59ac36SWyon Bi 	u32 i, reg = 0;
786f920c07SWyon Bi 
79*1f59ac36SWyon Bi 	for (i = 0; i < dp->video_info.max_lane_count; i++)
80*1f59ac36SWyon Bi 		reg |= dp->lane_map[i] << (2 * i);
816f920c07SWyon Bi 
8252db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_LANE_MAP, reg);
836f920c07SWyon Bi }
846f920c07SWyon Bi 
856f920c07SWyon Bi void analogix_dp_init_analog_param(struct analogix_dp_device *dp)
866f920c07SWyon Bi {
876f920c07SWyon Bi 	u32 reg;
886f920c07SWyon Bi 
896f920c07SWyon Bi 	reg = TX_TERMINAL_CTRL_50_OHM;
9052db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_1, reg);
916f920c07SWyon Bi 
926f920c07SWyon Bi 	reg = SEL_24M | TX_DVDD_BIT_1_0625V;
9352db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_2, reg);
946f920c07SWyon Bi 
956f920c07SWyon Bi 	if (dp->plat_data.dev_type == ROCKCHIP_DP) {
966f920c07SWyon Bi 		reg = REF_CLK_24M;
976f920c07SWyon Bi 		if (dp->plat_data.subdev_type == RK3288_DP ||
986f920c07SWyon Bi 		    dp->plat_data.subdev_type == RK3368_EDP)
996f920c07SWyon Bi 			reg ^= REF_CLK_MASK;
1006f920c07SWyon Bi 
10152db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_PLL_REG_1, reg);
1029f415b59SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_PLL_REG_2, 0x99);
10352db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_PLL_REG_3, 0x40);
10452db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_PLL_REG_4, 0x58);
10552db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_PLL_REG_5, 0x22);
1069f415b59SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_BIAS, 0x44);
1076f920c07SWyon Bi 	}
1086f920c07SWyon Bi 
1096f920c07SWyon Bi 	reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
11052db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_3, reg);
1116f920c07SWyon Bi 
1126f920c07SWyon Bi 	reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
1136f920c07SWyon Bi 		TX_CUR1_2X | TX_CUR_16_MA;
11452db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_PLL_FILTER_CTL_1, reg);
1156f920c07SWyon Bi 
1166f920c07SWyon Bi 	reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
1176f920c07SWyon Bi 		CH1_AMP_400_MV | CH0_AMP_400_MV;
11852db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_TX_AMP_TUNING_CTL, reg);
1196f920c07SWyon Bi }
1206f920c07SWyon Bi 
1216f920c07SWyon Bi void analogix_dp_init_interrupt(struct analogix_dp_device *dp)
1226f920c07SWyon Bi {
1236f920c07SWyon Bi 	/* Set interrupt pin assertion polarity as high */
12452db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_INT_CTL, INT_POL1 | INT_POL0);
1256f920c07SWyon Bi 
1266f920c07SWyon Bi 	/* Clear pending regisers */
12752db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_STA_1, 0xff);
12852db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_STA_2, 0x4f);
12952db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_STA_3, 0xe0);
13052db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_STA_4, 0xe7);
13152db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_INT_STA, 0x63);
1326f920c07SWyon Bi 
1336f920c07SWyon Bi 	/* 0:mask,1: unmask */
13452db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_1, 0x00);
13552db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_2, 0x00);
13652db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_3, 0x00);
13752db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_4, 0x00);
13852db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_INT_STA_MASK, 0x00);
1396f920c07SWyon Bi }
1406f920c07SWyon Bi 
1416f920c07SWyon Bi void analogix_dp_reset(struct analogix_dp_device *dp)
1426f920c07SWyon Bi {
1436f920c07SWyon Bi 	u32 reg;
1446f920c07SWyon Bi 
1456f920c07SWyon Bi 	analogix_dp_stop_video(dp);
1466f920c07SWyon Bi 	analogix_dp_enable_video_mute(dp, 0);
1476f920c07SWyon Bi 
1486f920c07SWyon Bi 	reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
1496f920c07SWyon Bi 		AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
1506f920c07SWyon Bi 		HDCP_FUNC_EN_N | SW_FUNC_EN_N;
15152db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_FUNC_EN_1, reg);
1526f920c07SWyon Bi 
1536f920c07SWyon Bi 	reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
1546f920c07SWyon Bi 		SERDES_FIFO_FUNC_EN_N |
1556f920c07SWyon Bi 		LS_CLK_DOMAIN_FUNC_EN_N;
15652db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_FUNC_EN_2, reg);
1576f920c07SWyon Bi 
1586f920c07SWyon Bi 	udelay(30);
1596f920c07SWyon Bi 
160*1f59ac36SWyon Bi 	analogix_dp_set_lane_map(dp);
1616f920c07SWyon Bi 
16252db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_1, 0x0);
16352db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_2, 0x40);
16452db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_3, 0x0);
16552db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_4, 0x0);
1666f920c07SWyon Bi 
16752db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_PKT_SEND_CTL, 0x0);
16852db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_HDCP_CTL, 0x0);
1696f920c07SWyon Bi 
17052db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_HPD_DEGLITCH_L, 0x5e);
17152db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_HPD_DEGLITCH_H, 0x1a);
1726f920c07SWyon Bi 
17352db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_LINK_DEBUG_CTL, 0x10);
1746f920c07SWyon Bi 
17552db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_PHY_TEST, 0x0);
1766f920c07SWyon Bi 
17752db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_VIDEO_FIFO_THRD, 0x0);
17852db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_AUDIO_MARGIN, 0x20);
1796f920c07SWyon Bi 
18052db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_M_VID_GEN_FILTER_TH, 0x4);
18152db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_M_AUD_GEN_FILTER_TH, 0x2);
1826f920c07SWyon Bi 
18352db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_SOC_GENERAL_CTL, 0x00000101);
1846f920c07SWyon Bi }
1856f920c07SWyon Bi 
1866f920c07SWyon Bi void analogix_dp_swreset(struct analogix_dp_device *dp)
1876f920c07SWyon Bi {
18852db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_TX_SW_RESET, RESET_DP_TX);
1896f920c07SWyon Bi }
1906f920c07SWyon Bi 
1916f920c07SWyon Bi void analogix_dp_config_interrupt(struct analogix_dp_device *dp)
1926f920c07SWyon Bi {
1936f920c07SWyon Bi 	u32 reg;
1946f920c07SWyon Bi 
1956f920c07SWyon Bi 	/* 0: mask, 1: unmask */
1966f920c07SWyon Bi 	reg = COMMON_INT_MASK_1;
19752db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_1, reg);
1986f920c07SWyon Bi 
1996f920c07SWyon Bi 	reg = COMMON_INT_MASK_2;
20052db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_2, reg);
2016f920c07SWyon Bi 
2026f920c07SWyon Bi 	reg = COMMON_INT_MASK_3;
20352db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_3, reg);
2046f920c07SWyon Bi 
2056f920c07SWyon Bi 	reg = COMMON_INT_MASK_4;
20652db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_4, reg);
2076f920c07SWyon Bi 
2086f920c07SWyon Bi 	reg = INT_STA_MASK;
20952db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_INT_STA_MASK, reg);
2106f920c07SWyon Bi }
2116f920c07SWyon Bi 
2126f920c07SWyon Bi void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp)
2136f920c07SWyon Bi {
2146f920c07SWyon Bi 	u32 reg;
2156f920c07SWyon Bi 
2166f920c07SWyon Bi 	/* 0: mask, 1: unmask */
21752db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_COMMON_INT_MASK_4);
2186f920c07SWyon Bi 	reg &= ~COMMON_INT_MASK_4;
21952db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_4, reg);
2206f920c07SWyon Bi 
22152db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_INT_STA_MASK);
2226f920c07SWyon Bi 	reg &= ~INT_STA_MASK;
22352db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_INT_STA_MASK, reg);
2246f920c07SWyon Bi }
2256f920c07SWyon Bi 
2266f920c07SWyon Bi void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp)
2276f920c07SWyon Bi {
2286f920c07SWyon Bi 	u32 reg;
2296f920c07SWyon Bi 
2306f920c07SWyon Bi 	/* 0: mask, 1: unmask */
2316f920c07SWyon Bi 	reg = COMMON_INT_MASK_4;
23252db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_4, reg);
2336f920c07SWyon Bi 
2346f920c07SWyon Bi 	reg = INT_STA_MASK;
23552db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_INT_STA_MASK, reg);
2366f920c07SWyon Bi }
2376f920c07SWyon Bi 
2386f920c07SWyon Bi enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp)
2396f920c07SWyon Bi {
2406f920c07SWyon Bi 	u32 reg;
2416f920c07SWyon Bi 
24252db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_DEBUG_CTL);
2436f920c07SWyon Bi 	if (reg & PLL_LOCK)
2446f920c07SWyon Bi 		return PLL_LOCKED;
2456f920c07SWyon Bi 	else
2466f920c07SWyon Bi 		return PLL_UNLOCKED;
2476f920c07SWyon Bi }
2486f920c07SWyon Bi 
2496f920c07SWyon Bi void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable)
2506f920c07SWyon Bi {
2516f920c07SWyon Bi 	u32 reg;
2526f920c07SWyon Bi 
2536f920c07SWyon Bi 	if (enable) {
25452db8715SWyon Bi 		reg = analogix_dp_read(dp, ANALOGIX_DP_PLL_CTL);
2556f920c07SWyon Bi 		reg |= DP_PLL_PD;
25652db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_PLL_CTL, reg);
2576f920c07SWyon Bi 	} else {
25852db8715SWyon Bi 		reg = analogix_dp_read(dp, ANALOGIX_DP_PLL_CTL);
2596f920c07SWyon Bi 		reg &= ~DP_PLL_PD;
26052db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_PLL_CTL, reg);
2616f920c07SWyon Bi 	}
2626f920c07SWyon Bi }
2636f920c07SWyon Bi 
2646f920c07SWyon Bi void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp,
2656f920c07SWyon Bi 				       enum analog_power_block block,
2666f920c07SWyon Bi 				       bool enable)
2676f920c07SWyon Bi {
2686f920c07SWyon Bi 	u32 reg;
2696f920c07SWyon Bi 	u32 phy_pd_addr = ANALOGIX_DP_PHY_PD;
2706f920c07SWyon Bi 
2716f920c07SWyon Bi 	if (dp->plat_data.dev_type == ROCKCHIP_DP)
2726f920c07SWyon Bi 		phy_pd_addr = ANALOGIX_DP_PD;
2736f920c07SWyon Bi 
2746f920c07SWyon Bi 	switch (block) {
2756f920c07SWyon Bi 	case AUX_BLOCK:
2766f920c07SWyon Bi 		if (enable) {
27752db8715SWyon Bi 			reg = analogix_dp_read(dp, phy_pd_addr);
2786f920c07SWyon Bi 			reg |= AUX_PD;
27952db8715SWyon Bi 			analogix_dp_write(dp, phy_pd_addr, reg);
2806f920c07SWyon Bi 		} else {
28152db8715SWyon Bi 			reg = analogix_dp_read(dp, phy_pd_addr);
2826f920c07SWyon Bi 			reg &= ~AUX_PD;
28352db8715SWyon Bi 			analogix_dp_write(dp, phy_pd_addr, reg);
2846f920c07SWyon Bi 		}
2856f920c07SWyon Bi 		break;
2866f920c07SWyon Bi 	case CH0_BLOCK:
2876f920c07SWyon Bi 		if (enable) {
28852db8715SWyon Bi 			reg = analogix_dp_read(dp, phy_pd_addr);
2896f920c07SWyon Bi 			reg |= CH0_PD;
29052db8715SWyon Bi 			analogix_dp_write(dp, phy_pd_addr, reg);
2916f920c07SWyon Bi 		} else {
29252db8715SWyon Bi 			reg = analogix_dp_read(dp, phy_pd_addr);
2936f920c07SWyon Bi 			reg &= ~CH0_PD;
29452db8715SWyon Bi 			analogix_dp_write(dp, phy_pd_addr, reg);
2956f920c07SWyon Bi 		}
2966f920c07SWyon Bi 		break;
2976f920c07SWyon Bi 	case CH1_BLOCK:
2986f920c07SWyon Bi 		if (enable) {
29952db8715SWyon Bi 			reg = analogix_dp_read(dp, phy_pd_addr);
3006f920c07SWyon Bi 			reg |= CH1_PD;
30152db8715SWyon Bi 			analogix_dp_write(dp, phy_pd_addr, reg);
3026f920c07SWyon Bi 		} else {
30352db8715SWyon Bi 			reg = analogix_dp_read(dp, phy_pd_addr);
3046f920c07SWyon Bi 			reg &= ~CH1_PD;
30552db8715SWyon Bi 			analogix_dp_write(dp, phy_pd_addr, reg);
3066f920c07SWyon Bi 		}
3076f920c07SWyon Bi 		break;
3086f920c07SWyon Bi 	case CH2_BLOCK:
3096f920c07SWyon Bi 		if (enable) {
31052db8715SWyon Bi 			reg = analogix_dp_read(dp, phy_pd_addr);
3116f920c07SWyon Bi 			reg |= CH2_PD;
31252db8715SWyon Bi 			analogix_dp_write(dp, phy_pd_addr, reg);
3136f920c07SWyon Bi 		} else {
31452db8715SWyon Bi 			reg = analogix_dp_read(dp, phy_pd_addr);
3156f920c07SWyon Bi 			reg &= ~CH2_PD;
31652db8715SWyon Bi 			analogix_dp_write(dp, phy_pd_addr, reg);
3176f920c07SWyon Bi 		}
3186f920c07SWyon Bi 		break;
3196f920c07SWyon Bi 	case CH3_BLOCK:
3206f920c07SWyon Bi 		if (enable) {
32152db8715SWyon Bi 			reg = analogix_dp_read(dp, phy_pd_addr);
3226f920c07SWyon Bi 			reg |= CH3_PD;
32352db8715SWyon Bi 			analogix_dp_write(dp, phy_pd_addr, reg);
3246f920c07SWyon Bi 		} else {
32552db8715SWyon Bi 			reg = analogix_dp_read(dp, phy_pd_addr);
3266f920c07SWyon Bi 			reg &= ~CH3_PD;
32752db8715SWyon Bi 			analogix_dp_write(dp, phy_pd_addr, reg);
3286f920c07SWyon Bi 		}
3296f920c07SWyon Bi 		break;
3306f920c07SWyon Bi 	case ANALOG_TOTAL:
3316f920c07SWyon Bi 		if (enable) {
33252db8715SWyon Bi 			reg = analogix_dp_read(dp, phy_pd_addr);
3336f920c07SWyon Bi 			reg |= DP_PHY_PD;
33452db8715SWyon Bi 			analogix_dp_write(dp, phy_pd_addr, reg);
3356f920c07SWyon Bi 		} else {
33652db8715SWyon Bi 			reg = analogix_dp_read(dp, phy_pd_addr);
3376f920c07SWyon Bi 			reg &= ~DP_PHY_PD;
33852db8715SWyon Bi 			analogix_dp_write(dp, phy_pd_addr, reg);
3396f920c07SWyon Bi 		}
3406f920c07SWyon Bi 		break;
3416f920c07SWyon Bi 	case POWER_ALL:
3426f920c07SWyon Bi 		if (enable) {
3436f920c07SWyon Bi 			reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
3446f920c07SWyon Bi 				CH1_PD | CH0_PD;
34552db8715SWyon Bi 			analogix_dp_write(dp, phy_pd_addr, reg);
3466f920c07SWyon Bi 		} else {
34752db8715SWyon Bi 			analogix_dp_write(dp, phy_pd_addr, 0x00);
3486f920c07SWyon Bi 		}
3496f920c07SWyon Bi 		break;
3506f920c07SWyon Bi 	default:
3516f920c07SWyon Bi 		break;
3526f920c07SWyon Bi 	}
3536f920c07SWyon Bi }
3546f920c07SWyon Bi 
3556f920c07SWyon Bi void analogix_dp_init_analog_func(struct analogix_dp_device *dp)
3566f920c07SWyon Bi {
3576f920c07SWyon Bi 	u32 reg;
3586f920c07SWyon Bi 
3596f920c07SWyon Bi 	analogix_dp_set_analog_power_down(dp, POWER_ALL, 0);
3606f920c07SWyon Bi 
3616f920c07SWyon Bi 	reg = PLL_LOCK_CHG;
36252db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_STA_1, reg);
3636f920c07SWyon Bi 
36452db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_DEBUG_CTL);
3656f920c07SWyon Bi 	reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
36652db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_DEBUG_CTL, reg);
3676f920c07SWyon Bi 
3686f920c07SWyon Bi 	/* Power up PLL */
3696f920c07SWyon Bi 	analogix_dp_set_pll_power_down(dp, 0);
3706f920c07SWyon Bi 
3716f920c07SWyon Bi 	/* Enable Serdes FIFO function and Link symbol clock domain module */
37252db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_FUNC_EN_2);
3736f920c07SWyon Bi 	reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
3746f920c07SWyon Bi 		| AUX_FUNC_EN_N);
37552db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_FUNC_EN_2, reg);
3766f920c07SWyon Bi }
3776f920c07SWyon Bi 
3786f920c07SWyon Bi void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp)
3796f920c07SWyon Bi {
3806f920c07SWyon Bi 	u32 reg;
3816f920c07SWyon Bi 
3826f920c07SWyon Bi 	if (dm_gpio_is_valid(&dp->hpd_gpio))
3836f920c07SWyon Bi 		return;
3846f920c07SWyon Bi 
3856f920c07SWyon Bi 	reg = HOTPLUG_CHG | HPD_LOST | PLUG;
38652db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_STA_4, reg);
3876f920c07SWyon Bi 
3886f920c07SWyon Bi 	reg = INT_HPD;
38952db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_INT_STA, reg);
3906f920c07SWyon Bi }
3916f920c07SWyon Bi 
3926f920c07SWyon Bi void analogix_dp_init_hpd(struct analogix_dp_device *dp)
3936f920c07SWyon Bi {
3946f920c07SWyon Bi 	u32 reg;
3956f920c07SWyon Bi 
3966f920c07SWyon Bi 	if (dm_gpio_is_valid(&dp->hpd_gpio))
3976f920c07SWyon Bi 		return;
3986f920c07SWyon Bi 
3996f920c07SWyon Bi 	analogix_dp_clear_hotplug_interrupts(dp);
4006f920c07SWyon Bi 
40152db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_3);
4026f920c07SWyon Bi 	reg &= ~(F_HPD | HPD_CTRL);
40352db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_3, reg);
4046f920c07SWyon Bi }
4056f920c07SWyon Bi 
4066f920c07SWyon Bi void analogix_dp_force_hpd(struct analogix_dp_device *dp)
4076f920c07SWyon Bi {
4086f920c07SWyon Bi 	u32 reg;
4096f920c07SWyon Bi 
41052db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_3);
41152db8715SWyon Bi 	reg |= (F_HPD | HPD_CTRL);
41252db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_3, reg);
4136f920c07SWyon Bi }
4146f920c07SWyon Bi 
4156f920c07SWyon Bi enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp)
4166f920c07SWyon Bi {
4176f920c07SWyon Bi 	u32 reg;
4186f920c07SWyon Bi 
4196f920c07SWyon Bi 	if (dm_gpio_is_valid(&dp->hpd_gpio)) {
4206f920c07SWyon Bi 		reg = dm_gpio_get_value(&dp->hpd_gpio);
4216f920c07SWyon Bi 		if (reg)
4226f920c07SWyon Bi 			return DP_IRQ_TYPE_HP_CABLE_IN;
4236f920c07SWyon Bi 		else
4246f920c07SWyon Bi 			return DP_IRQ_TYPE_HP_CABLE_OUT;
4256f920c07SWyon Bi 	} else {
4266f920c07SWyon Bi 		/* Parse hotplug interrupt status register */
42752db8715SWyon Bi 		reg = analogix_dp_read(dp, ANALOGIX_DP_COMMON_INT_STA_4);
4286f920c07SWyon Bi 
4296f920c07SWyon Bi 		if (reg & PLUG)
4306f920c07SWyon Bi 			return DP_IRQ_TYPE_HP_CABLE_IN;
4316f920c07SWyon Bi 
4326f920c07SWyon Bi 		if (reg & HPD_LOST)
4336f920c07SWyon Bi 			return DP_IRQ_TYPE_HP_CABLE_OUT;
4346f920c07SWyon Bi 
4356f920c07SWyon Bi 		if (reg & HOTPLUG_CHG)
4366f920c07SWyon Bi 			return DP_IRQ_TYPE_HP_CHANGE;
4376f920c07SWyon Bi 
4386f920c07SWyon Bi 		return DP_IRQ_TYPE_UNKNOWN;
4396f920c07SWyon Bi 	}
4406f920c07SWyon Bi }
4416f920c07SWyon Bi 
4426f920c07SWyon Bi void analogix_dp_reset_aux(struct analogix_dp_device *dp)
4436f920c07SWyon Bi {
4446f920c07SWyon Bi 	u32 reg;
4456f920c07SWyon Bi 
4466f920c07SWyon Bi 	/* Disable AUX channel module */
44752db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_FUNC_EN_2);
4486f920c07SWyon Bi 	reg |= AUX_FUNC_EN_N;
44952db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_FUNC_EN_2, reg);
4506f920c07SWyon Bi }
4516f920c07SWyon Bi 
4526f920c07SWyon Bi void analogix_dp_init_aux(struct analogix_dp_device *dp)
4536f920c07SWyon Bi {
4546f920c07SWyon Bi 	u32 reg;
4556f920c07SWyon Bi 
4566f920c07SWyon Bi 	/* Clear inerrupts related to AUX channel */
4576f920c07SWyon Bi 	reg = RPLY_RECEIV | AUX_ERR;
45852db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_INT_STA, reg);
4596f920c07SWyon Bi 
4606f920c07SWyon Bi 	analogix_dp_reset_aux(dp);
4616f920c07SWyon Bi 
4626f920c07SWyon Bi 	/* Disable AUX transaction H/W retry */
4636f920c07SWyon Bi 	if (dp->plat_data.dev_type == ROCKCHIP_DP)
4646f920c07SWyon Bi 		reg = AUX_BIT_PERIOD_EXPECTED_DELAY(0) |
4656f920c07SWyon Bi 		      AUX_HW_RETRY_COUNT_SEL(3) |
4666f920c07SWyon Bi 		      AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
4676f920c07SWyon Bi 	else
4686f920c07SWyon Bi 		reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) |
4696f920c07SWyon Bi 		      AUX_HW_RETRY_COUNT_SEL(0) |
4706f920c07SWyon Bi 		      AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
47152db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_AUX_HW_RETRY_CTL, reg);
4726f920c07SWyon Bi 
4736f920c07SWyon Bi 	/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
4746f920c07SWyon Bi 	reg = DEFER_CTRL_EN | DEFER_COUNT(1);
47552db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_DEFER_CTL, reg);
4766f920c07SWyon Bi 
4776f920c07SWyon Bi 	/* Enable AUX channel module */
47852db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_FUNC_EN_2);
4796f920c07SWyon Bi 	reg &= ~AUX_FUNC_EN_N;
48052db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_FUNC_EN_2, reg);
4816f920c07SWyon Bi }
4826f920c07SWyon Bi 
483d90a0d9fSWyon Bi int analogix_dp_detect(struct analogix_dp_device *dp)
4846f920c07SWyon Bi {
4856f920c07SWyon Bi 	u32 reg;
4866f920c07SWyon Bi 
487d90a0d9fSWyon Bi 	if (dm_gpio_is_valid(&dp->hpd_gpio))
488d90a0d9fSWyon Bi 		return dm_gpio_get_value(&dp->hpd_gpio);
489d90a0d9fSWyon Bi 
490d90a0d9fSWyon Bi 	if (dp->force_hpd)
491d90a0d9fSWyon Bi 		analogix_dp_force_hpd(dp);
492d90a0d9fSWyon Bi 
49352db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_3);
4946f920c07SWyon Bi 	if (reg & HPD_STATUS)
495d90a0d9fSWyon Bi 		return 1;
4966f920c07SWyon Bi 
497d90a0d9fSWyon Bi 	return 0;
4986f920c07SWyon Bi }
4996f920c07SWyon Bi 
5006f920c07SWyon Bi void analogix_dp_enable_sw_function(struct analogix_dp_device *dp)
5016f920c07SWyon Bi {
5026f920c07SWyon Bi 	u32 reg;
5036f920c07SWyon Bi 
50452db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_FUNC_EN_1);
5056f920c07SWyon Bi 	reg &= ~SW_FUNC_EN_N;
50652db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_FUNC_EN_1, reg);
5076f920c07SWyon Bi }
5086f920c07SWyon Bi 
509d3e70420SWyon Bi int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp)
510d3e70420SWyon Bi {
511d3e70420SWyon Bi 	u32 reg;
512d3e70420SWyon Bi 
513d3e70420SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_3);
514d3e70420SWyon Bi 	if (reg & HPD_STATUS)
515d3e70420SWyon Bi 		return 0;
516d3e70420SWyon Bi 
517d3e70420SWyon Bi 	return -EINVAL;
518d3e70420SWyon Bi }
519d3e70420SWyon Bi 
5206f920c07SWyon Bi int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp)
5216f920c07SWyon Bi {
5226f920c07SWyon Bi 	int reg;
5236f920c07SWyon Bi 	int retval = 0;
5246f920c07SWyon Bi 	int timeout_loop = 0;
5256f920c07SWyon Bi 
5266f920c07SWyon Bi 	/* Enable AUX CH operation */
52752db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_AUX_CH_CTL_2);
5286f920c07SWyon Bi 	reg |= AUX_EN;
52952db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_2, reg);
5306f920c07SWyon Bi 
5316f920c07SWyon Bi 	/* Is AUX CH command reply received? */
53252db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_INT_STA);
5336f920c07SWyon Bi 	while (!(reg & RPLY_RECEIV)) {
5346f920c07SWyon Bi 		timeout_loop++;
5356f920c07SWyon Bi 		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
5366f920c07SWyon Bi 			dev_err(dp->dev, "AUX CH command reply failed!\n");
5376f920c07SWyon Bi 			return -ETIMEDOUT;
5386f920c07SWyon Bi 		}
5396f920c07SWyon Bi 
54052db8715SWyon Bi 		reg = analogix_dp_read(dp, ANALOGIX_DP_INT_STA);
5416f920c07SWyon Bi 		udelay(11);
5426f920c07SWyon Bi 	}
5436f920c07SWyon Bi 
5446f920c07SWyon Bi 	/* Clear interrupt source for AUX CH command reply */
54552db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_INT_STA, reg);
5466f920c07SWyon Bi 
5476f920c07SWyon Bi 	/* Clear interrupt source for AUX CH access error */
54852db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_INT_STA);
5496f920c07SWyon Bi 	if (reg & AUX_ERR) {
55052db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_INT_STA, AUX_ERR);
5516f920c07SWyon Bi 		return -EREMOTEIO;
5526f920c07SWyon Bi 	}
5536f920c07SWyon Bi 
5546f920c07SWyon Bi 	/* Check AUX CH error access status */
55552db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_AUX_CH_STA);
5566f920c07SWyon Bi 	if ((reg & AUX_STATUS_MASK) != 0) {
5576f920c07SWyon Bi 		dev_err(dp->dev,
5586f920c07SWyon Bi 			"AUX CH error happens: %d\n", reg & AUX_STATUS_MASK);
5596f920c07SWyon Bi 		return -EREMOTEIO;
5606f920c07SWyon Bi 	}
5616f920c07SWyon Bi 
5626f920c07SWyon Bi 	return retval;
5636f920c07SWyon Bi }
5646f920c07SWyon Bi 
5656f920c07SWyon Bi int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp,
5666f920c07SWyon Bi 				   unsigned int reg_addr,
5676f920c07SWyon Bi 				   unsigned char data)
5686f920c07SWyon Bi {
5696f920c07SWyon Bi 	u32 reg;
5706f920c07SWyon Bi 	int i;
5716f920c07SWyon Bi 	int retval;
5726f920c07SWyon Bi 
5736f920c07SWyon Bi 	for (i = 0; i < 3; i++) {
5746f920c07SWyon Bi 		/* Clear AUX CH data buffer */
5756f920c07SWyon Bi 		reg = BUF_CLR;
57652db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_BUFFER_DATA_CTL, reg);
5776f920c07SWyon Bi 
5786f920c07SWyon Bi 		/* Select DPCD device address */
5796f920c07SWyon Bi 		reg = AUX_ADDR_7_0(reg_addr);
58052db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_7_0, reg);
5816f920c07SWyon Bi 		reg = AUX_ADDR_15_8(reg_addr);
58252db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_15_8, reg);
5836f920c07SWyon Bi 		reg = AUX_ADDR_19_16(reg_addr);
58452db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_19_16, reg);
5856f920c07SWyon Bi 
5866f920c07SWyon Bi 		/* Write data buffer */
5876f920c07SWyon Bi 		reg = (unsigned int)data;
58852db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_BUF_DATA_0, reg);
5896f920c07SWyon Bi 
5906f920c07SWyon Bi 		/*
5916f920c07SWyon Bi 		 * Set DisplayPort transaction and write 1 byte
5926f920c07SWyon Bi 		 * If bit 3 is 1, DisplayPort transaction.
5936f920c07SWyon Bi 		 * If Bit 3 is 0, I2C transaction.
5946f920c07SWyon Bi 		 */
5956f920c07SWyon Bi 		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
59652db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_1, reg);
5976f920c07SWyon Bi 
5986f920c07SWyon Bi 		/* Start AUX transaction */
5996f920c07SWyon Bi 		retval = analogix_dp_start_aux_transaction(dp);
6006f920c07SWyon Bi 		if (retval == 0)
6016f920c07SWyon Bi 			break;
6026f920c07SWyon Bi 	}
6036f920c07SWyon Bi 
6046f920c07SWyon Bi 	return retval;
6056f920c07SWyon Bi }
6066f920c07SWyon Bi 
6076f920c07SWyon Bi int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp,
6086f920c07SWyon Bi 				    unsigned int reg_addr,
6096f920c07SWyon Bi 				    unsigned char *data)
6106f920c07SWyon Bi {
6116f920c07SWyon Bi 	u32 reg;
6126f920c07SWyon Bi 	int i;
6136f920c07SWyon Bi 	int retval;
6146f920c07SWyon Bi 
6156f920c07SWyon Bi 	for (i = 0; i < 3; i++) {
6166f920c07SWyon Bi 		/* Clear AUX CH data buffer */
6176f920c07SWyon Bi 		reg = BUF_CLR;
61852db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_BUFFER_DATA_CTL, reg);
6196f920c07SWyon Bi 
6206f920c07SWyon Bi 		/* Select DPCD device address */
6216f920c07SWyon Bi 		reg = AUX_ADDR_7_0(reg_addr);
62252db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_7_0, reg);
6236f920c07SWyon Bi 		reg = AUX_ADDR_15_8(reg_addr);
62452db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_15_8, reg);
6256f920c07SWyon Bi 		reg = AUX_ADDR_19_16(reg_addr);
62652db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_19_16, reg);
6276f920c07SWyon Bi 
6286f920c07SWyon Bi 		/*
6296f920c07SWyon Bi 		 * Set DisplayPort transaction and read 1 byte
6306f920c07SWyon Bi 		 * If bit 3 is 1, DisplayPort transaction.
6316f920c07SWyon Bi 		 * If Bit 3 is 0, I2C transaction.
6326f920c07SWyon Bi 		 */
6336f920c07SWyon Bi 		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
63452db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_1, reg);
6356f920c07SWyon Bi 
6366f920c07SWyon Bi 		/* Start AUX transaction */
6376f920c07SWyon Bi 		retval = analogix_dp_start_aux_transaction(dp);
6386f920c07SWyon Bi 		if (retval == 0)
6396f920c07SWyon Bi 			break;
6406f920c07SWyon Bi 	}
6416f920c07SWyon Bi 
6426f920c07SWyon Bi 	/* Read data buffer */
64352db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_BUF_DATA_0);
6446f920c07SWyon Bi 	*data = (unsigned char)(reg & 0xff);
6456f920c07SWyon Bi 
6466f920c07SWyon Bi 	return retval;
6476f920c07SWyon Bi }
6486f920c07SWyon Bi 
6496f920c07SWyon Bi int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp,
6506f920c07SWyon Bi 				    unsigned int reg_addr,
6516f920c07SWyon Bi 				    unsigned int count,
6526f920c07SWyon Bi 				    unsigned char data[])
6536f920c07SWyon Bi {
6546f920c07SWyon Bi 	u32 reg;
6556f920c07SWyon Bi 	unsigned int start_offset;
6566f920c07SWyon Bi 	unsigned int cur_data_count;
6576f920c07SWyon Bi 	unsigned int cur_data_idx;
6586f920c07SWyon Bi 	int i;
6596f920c07SWyon Bi 	int retval = 0;
6606f920c07SWyon Bi 
6616f920c07SWyon Bi 	/* Clear AUX CH data buffer */
6626f920c07SWyon Bi 	reg = BUF_CLR;
66352db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_BUFFER_DATA_CTL, reg);
6646f920c07SWyon Bi 
6656f920c07SWyon Bi 	start_offset = 0;
6666f920c07SWyon Bi 	while (start_offset < count) {
6676f920c07SWyon Bi 		/* Buffer size of AUX CH is 16 * 4bytes */
6686f920c07SWyon Bi 		if ((count - start_offset) > 16)
6696f920c07SWyon Bi 			cur_data_count = 16;
6706f920c07SWyon Bi 		else
6716f920c07SWyon Bi 			cur_data_count = count - start_offset;
6726f920c07SWyon Bi 
6736f920c07SWyon Bi 		for (i = 0; i < 3; i++) {
6746f920c07SWyon Bi 			/* Select DPCD device address */
6756f920c07SWyon Bi 			reg = AUX_ADDR_7_0(reg_addr + start_offset);
67652db8715SWyon Bi 			analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_7_0, reg);
6776f920c07SWyon Bi 			reg = AUX_ADDR_15_8(reg_addr + start_offset);
67852db8715SWyon Bi 			analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_15_8, reg);
6796f920c07SWyon Bi 			reg = AUX_ADDR_19_16(reg_addr + start_offset);
68052db8715SWyon Bi 			analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_19_16, reg);
6816f920c07SWyon Bi 
6826f920c07SWyon Bi 			for (cur_data_idx = 0; cur_data_idx < cur_data_count;
6836f920c07SWyon Bi 			     cur_data_idx++) {
6846f920c07SWyon Bi 				reg = data[start_offset + cur_data_idx];
68552db8715SWyon Bi 				analogix_dp_write(dp, ANALOGIX_DP_BUF_DATA_0 +
68652db8715SWyon Bi 				       4 * cur_data_idx, reg);
6876f920c07SWyon Bi 			}
6886f920c07SWyon Bi 
6896f920c07SWyon Bi 			/*
6906f920c07SWyon Bi 			 * Set DisplayPort transaction and write
6916f920c07SWyon Bi 			 * If bit 3 is 1, DisplayPort transaction.
6926f920c07SWyon Bi 			 * If Bit 3 is 0, I2C transaction.
6936f920c07SWyon Bi 			 */
6946f920c07SWyon Bi 			reg = AUX_LENGTH(cur_data_count) |
6956f920c07SWyon Bi 				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
69652db8715SWyon Bi 			analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_1, reg);
6976f920c07SWyon Bi 
6986f920c07SWyon Bi 			/* Start AUX transaction */
6996f920c07SWyon Bi 			retval = analogix_dp_start_aux_transaction(dp);
7006f920c07SWyon Bi 			if (retval == 0)
7016f920c07SWyon Bi 				break;
7026f920c07SWyon Bi 		}
7036f920c07SWyon Bi 
7046f920c07SWyon Bi 		start_offset += cur_data_count;
7056f920c07SWyon Bi 	}
7066f920c07SWyon Bi 
7076f920c07SWyon Bi 	return retval;
7086f920c07SWyon Bi }
7096f920c07SWyon Bi 
7106f920c07SWyon Bi int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp,
7116f920c07SWyon Bi 				     unsigned int reg_addr,
7126f920c07SWyon Bi 				     unsigned int count,
7136f920c07SWyon Bi 				     unsigned char data[])
7146f920c07SWyon Bi {
7156f920c07SWyon Bi 	u32 reg;
7166f920c07SWyon Bi 	unsigned int start_offset;
7176f920c07SWyon Bi 	unsigned int cur_data_count;
7186f920c07SWyon Bi 	unsigned int cur_data_idx;
7196f920c07SWyon Bi 	int i;
7206f920c07SWyon Bi 	int retval = 0;
7216f920c07SWyon Bi 
7226f920c07SWyon Bi 	/* Clear AUX CH data buffer */
7236f920c07SWyon Bi 	reg = BUF_CLR;
72452db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_BUFFER_DATA_CTL, reg);
7256f920c07SWyon Bi 
7266f920c07SWyon Bi 	start_offset = 0;
7276f920c07SWyon Bi 	while (start_offset < count) {
7286f920c07SWyon Bi 		/* Buffer size of AUX CH is 16 * 4bytes */
7296f920c07SWyon Bi 		if ((count - start_offset) > 16)
7306f920c07SWyon Bi 			cur_data_count = 16;
7316f920c07SWyon Bi 		else
7326f920c07SWyon Bi 			cur_data_count = count - start_offset;
7336f920c07SWyon Bi 
7346f920c07SWyon Bi 		/* AUX CH Request Transaction process */
7356f920c07SWyon Bi 		for (i = 0; i < 3; i++) {
7366f920c07SWyon Bi 			/* Select DPCD device address */
7376f920c07SWyon Bi 			reg = AUX_ADDR_7_0(reg_addr + start_offset);
73852db8715SWyon Bi 			analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_7_0, reg);
7396f920c07SWyon Bi 			reg = AUX_ADDR_15_8(reg_addr + start_offset);
74052db8715SWyon Bi 			analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_15_8, reg);
7416f920c07SWyon Bi 			reg = AUX_ADDR_19_16(reg_addr + start_offset);
74252db8715SWyon Bi 			analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_19_16, reg);
7436f920c07SWyon Bi 
7446f920c07SWyon Bi 			/*
7456f920c07SWyon Bi 			 * Set DisplayPort transaction and read
7466f920c07SWyon Bi 			 * If bit 3 is 1, DisplayPort transaction.
7476f920c07SWyon Bi 			 * If Bit 3 is 0, I2C transaction.
7486f920c07SWyon Bi 			 */
7496f920c07SWyon Bi 			reg = AUX_LENGTH(cur_data_count) |
7506f920c07SWyon Bi 				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
75152db8715SWyon Bi 			analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_1, reg);
7526f920c07SWyon Bi 
7536f920c07SWyon Bi 			/* Start AUX transaction */
7546f920c07SWyon Bi 			retval = analogix_dp_start_aux_transaction(dp);
7556f920c07SWyon Bi 			if (retval == 0)
7566f920c07SWyon Bi 				break;
7576f920c07SWyon Bi 		}
7586f920c07SWyon Bi 
7596f920c07SWyon Bi 		for (cur_data_idx = 0; cur_data_idx < cur_data_count;
7606f920c07SWyon Bi 		    cur_data_idx++) {
76152db8715SWyon Bi 			reg = analogix_dp_read(dp, ANALOGIX_DP_BUF_DATA_0
7626f920c07SWyon Bi 						 + 4 * cur_data_idx);
7636f920c07SWyon Bi 			data[start_offset + cur_data_idx] =
7646f920c07SWyon Bi 				(unsigned char)reg;
7656f920c07SWyon Bi 		}
7666f920c07SWyon Bi 
7676f920c07SWyon Bi 		start_offset += cur_data_count;
7686f920c07SWyon Bi 	}
7696f920c07SWyon Bi 
7706f920c07SWyon Bi 	return retval;
7716f920c07SWyon Bi }
7726f920c07SWyon Bi 
7736f920c07SWyon Bi int analogix_dp_select_i2c_device(struct analogix_dp_device *dp,
7746f920c07SWyon Bi 				  unsigned int device_addr,
7756f920c07SWyon Bi 				  unsigned int reg_addr)
7766f920c07SWyon Bi {
7776f920c07SWyon Bi 	u32 reg;
7786f920c07SWyon Bi 	int retval;
7796f920c07SWyon Bi 
7806f920c07SWyon Bi 	/* Set EDID device address */
7816f920c07SWyon Bi 	reg = device_addr;
78252db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_7_0, reg);
78352db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_15_8, 0x0);
78452db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_19_16, 0x0);
7856f920c07SWyon Bi 
7866f920c07SWyon Bi 	/* Set offset from base address of EDID device */
78752db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_BUF_DATA_0, reg_addr);
7886f920c07SWyon Bi 
7896f920c07SWyon Bi 	/*
7906f920c07SWyon Bi 	 * Set I2C transaction and write address
7916f920c07SWyon Bi 	 * If bit 3 is 1, DisplayPort transaction.
7926f920c07SWyon Bi 	 * If Bit 3 is 0, I2C transaction.
7936f920c07SWyon Bi 	 */
7946f920c07SWyon Bi 	reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
7956f920c07SWyon Bi 		AUX_TX_COMM_WRITE;
79652db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_1, reg);
7976f920c07SWyon Bi 
7986f920c07SWyon Bi 	/* Start AUX transaction */
7996f920c07SWyon Bi 	retval = analogix_dp_start_aux_transaction(dp);
8006f920c07SWyon Bi 	if (retval < 0)
8016f920c07SWyon Bi 		return retval;
8026f920c07SWyon Bi 
8036f920c07SWyon Bi 	return 0;
8046f920c07SWyon Bi }
8056f920c07SWyon Bi 
8066f920c07SWyon Bi int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp,
8076f920c07SWyon Bi 				   unsigned int device_addr,
8086f920c07SWyon Bi 				   unsigned int reg_addr,
8096f920c07SWyon Bi 				   unsigned int *data)
8106f920c07SWyon Bi {
8116f920c07SWyon Bi 	u32 reg;
8126f920c07SWyon Bi 	int i;
8136f920c07SWyon Bi 	int retval;
8146f920c07SWyon Bi 
8156f920c07SWyon Bi 	for (i = 0; i < 3; i++) {
8166f920c07SWyon Bi 		/* Clear AUX CH data buffer */
8176f920c07SWyon Bi 		reg = BUF_CLR;
81852db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_BUFFER_DATA_CTL, reg);
8196f920c07SWyon Bi 
8206f920c07SWyon Bi 		/* Select EDID device */
8216f920c07SWyon Bi 		retval = analogix_dp_select_i2c_device(dp, device_addr,
8226f920c07SWyon Bi 						       reg_addr);
8236f920c07SWyon Bi 		if (retval != 0)
8246f920c07SWyon Bi 			continue;
8256f920c07SWyon Bi 
8266f920c07SWyon Bi 		/*
8276f920c07SWyon Bi 		 * Set I2C transaction and read data
8286f920c07SWyon Bi 		 * If bit 3 is 1, DisplayPort transaction.
8296f920c07SWyon Bi 		 * If Bit 3 is 0, I2C transaction.
8306f920c07SWyon Bi 		 */
8316f920c07SWyon Bi 		reg = AUX_TX_COMM_I2C_TRANSACTION |
8326f920c07SWyon Bi 			AUX_TX_COMM_READ;
83352db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_1, reg);
8346f920c07SWyon Bi 
8356f920c07SWyon Bi 		/* Start AUX transaction */
8366f920c07SWyon Bi 		retval = analogix_dp_start_aux_transaction(dp);
8376f920c07SWyon Bi 		if (retval == 0)
8386f920c07SWyon Bi 			break;
8396f920c07SWyon Bi 	}
8406f920c07SWyon Bi 
8416f920c07SWyon Bi 	/* Read data */
8426f920c07SWyon Bi 	if (retval == 0)
84352db8715SWyon Bi 		*data = analogix_dp_read(dp, ANALOGIX_DP_BUF_DATA_0);
8446f920c07SWyon Bi 
8456f920c07SWyon Bi 	return retval;
8466f920c07SWyon Bi }
8476f920c07SWyon Bi 
8486f920c07SWyon Bi int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp,
8496f920c07SWyon Bi 				    unsigned int device_addr,
8506f920c07SWyon Bi 				    unsigned int reg_addr,
8516f920c07SWyon Bi 				    unsigned int count,
8526f920c07SWyon Bi 				    unsigned char edid[])
8536f920c07SWyon Bi {
8546f920c07SWyon Bi 	u32 reg;
8556f920c07SWyon Bi 	unsigned int i, j;
8566f920c07SWyon Bi 	unsigned int cur_data_idx;
8576f920c07SWyon Bi 	unsigned int defer = 0;
8586f920c07SWyon Bi 	int retval = 0;
8596f920c07SWyon Bi 
8606f920c07SWyon Bi 	for (i = 0; i < count; i += 16) {
8616f920c07SWyon Bi 		for (j = 0; j < 3; j++) {
8626f920c07SWyon Bi 			/* Clear AUX CH data buffer */
8636f920c07SWyon Bi 			reg = BUF_CLR;
86452db8715SWyon Bi 			analogix_dp_write(dp, ANALOGIX_DP_BUFFER_DATA_CTL, reg);
8656f920c07SWyon Bi 
8666f920c07SWyon Bi 			/* Set normal AUX CH command */
86752db8715SWyon Bi 			reg = analogix_dp_read(dp, ANALOGIX_DP_AUX_CH_CTL_2);
8686f920c07SWyon Bi 			reg &= ~ADDR_ONLY;
86952db8715SWyon Bi 			analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_2, reg);
8706f920c07SWyon Bi 
8716f920c07SWyon Bi 			/*
8726f920c07SWyon Bi 			 * If Rx sends defer, Tx sends only reads
8736f920c07SWyon Bi 			 * request without sending address
8746f920c07SWyon Bi 			 */
8756f920c07SWyon Bi 			if (!defer)
8766f920c07SWyon Bi 				retval = analogix_dp_select_i2c_device(dp,
8776f920c07SWyon Bi 						device_addr, reg_addr + i);
8786f920c07SWyon Bi 			else
8796f920c07SWyon Bi 				defer = 0;
8806f920c07SWyon Bi 
8816f920c07SWyon Bi 			if (retval == 0) {
8826f920c07SWyon Bi 				/*
8836f920c07SWyon Bi 				 * Set I2C transaction and write data
8846f920c07SWyon Bi 				 * If bit 3 is 1, DisplayPort transaction.
8856f920c07SWyon Bi 				 * If Bit 3 is 0, I2C transaction.
8866f920c07SWyon Bi 				 */
8876f920c07SWyon Bi 				reg = AUX_LENGTH(16) |
8886f920c07SWyon Bi 					AUX_TX_COMM_I2C_TRANSACTION |
8896f920c07SWyon Bi 					AUX_TX_COMM_READ;
89052db8715SWyon Bi 				analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_1,
89152db8715SWyon Bi 						  reg);
8926f920c07SWyon Bi 
8936f920c07SWyon Bi 				/* Start AUX transaction */
8946f920c07SWyon Bi 				retval = analogix_dp_start_aux_transaction(dp);
8956f920c07SWyon Bi 				if (retval == 0)
8966f920c07SWyon Bi 					break;
8976f920c07SWyon Bi 			}
8986f920c07SWyon Bi 			/* Check if Rx sends defer */
89952db8715SWyon Bi 			reg = analogix_dp_read(dp, ANALOGIX_DP_AUX_RX_COMM);
9006f920c07SWyon Bi 			if (reg == AUX_RX_COMM_AUX_DEFER ||
9016f920c07SWyon Bi 			    reg == AUX_RX_COMM_I2C_DEFER) {
9026f920c07SWyon Bi 				dev_dbg(dp->dev, "Defer: %d\n\n", reg);
9036f920c07SWyon Bi 				defer = 1;
9046f920c07SWyon Bi 			}
9056f920c07SWyon Bi 		}
9066f920c07SWyon Bi 
9076f920c07SWyon Bi 		for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
90852db8715SWyon Bi 			reg = analogix_dp_read(dp, ANALOGIX_DP_BUF_DATA_0
9096f920c07SWyon Bi 						 + 4 * cur_data_idx);
9106f920c07SWyon Bi 			edid[i + cur_data_idx] = (unsigned char)reg;
9116f920c07SWyon Bi 		}
9126f920c07SWyon Bi 	}
9136f920c07SWyon Bi 
9146f920c07SWyon Bi 	return retval;
9156f920c07SWyon Bi }
9166f920c07SWyon Bi 
917699c29a5SWyon Bi bool analogix_dp_ssc_supported(struct analogix_dp_device *dp)
918699c29a5SWyon Bi {
919699c29a5SWyon Bi 	/* Check if SSC is supported by both sides */
920699c29a5SWyon Bi 	return dp->plat_data.ssc && dp->link_train.ssc;
921699c29a5SWyon Bi }
922699c29a5SWyon Bi 
9236f920c07SWyon Bi void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype)
9246f920c07SWyon Bi {
925699c29a5SWyon Bi 	union phy_configure_opts phy_cfg;
9267adc0066SWyon Bi 	u32 status;
927a6285d17SWyon Bi 	int ret;
9286f920c07SWyon Bi 
9297adc0066SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_LINK_BW_SET, bwtype);
930a6285d17SWyon Bi 
931699c29a5SWyon Bi 	phy_cfg.dp.lanes = dp->link_train.lane_count;
932699c29a5SWyon Bi 	phy_cfg.dp.link_rate =
933699c29a5SWyon Bi 		drm_dp_bw_code_to_link_rate(dp->link_train.link_rate) / 100;
934699c29a5SWyon Bi 	phy_cfg.dp.ssc = analogix_dp_ssc_supported(dp);
935699c29a5SWyon Bi 	phy_cfg.dp.set_lanes = false;
936699c29a5SWyon Bi 	phy_cfg.dp.set_rate = true;
937699c29a5SWyon Bi 	phy_cfg.dp.set_voltages = false;
938699c29a5SWyon Bi 	ret = generic_phy_configure(&dp->phy, &phy_cfg);
939699c29a5SWyon Bi 	if (ret) {
940699c29a5SWyon Bi 		dev_err(dp->dev, "%s: phy_configure() failed: %d\n",
941699c29a5SWyon Bi 			__func__, ret);
942699c29a5SWyon Bi 		return;
943699c29a5SWyon Bi 	}
944699c29a5SWyon Bi 
945a6285d17SWyon Bi 	ret = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, status,
946a6285d17SWyon Bi 				 status != PLL_UNLOCKED,
947a6285d17SWyon Bi 				 120 * DP_TIMEOUT_LOOP_COUNT);
948a6285d17SWyon Bi 	if (ret) {
949a6285d17SWyon Bi 		dev_err(dp->dev, "Wait for pll lock failed %d\n", ret);
950a6285d17SWyon Bi 		return;
951a6285d17SWyon Bi 	}
9526f920c07SWyon Bi }
9536f920c07SWyon Bi 
9546f920c07SWyon Bi void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype)
9556f920c07SWyon Bi {
9566f920c07SWyon Bi 	u32 reg;
9576f920c07SWyon Bi 
95852db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_LINK_BW_SET);
9596f920c07SWyon Bi 	*bwtype = reg;
9606f920c07SWyon Bi }
9616f920c07SWyon Bi 
9626f920c07SWyon Bi void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count)
9636f920c07SWyon Bi {
964699c29a5SWyon Bi 	union phy_configure_opts phy_cfg;
9656f920c07SWyon Bi 	u32 reg;
966699c29a5SWyon Bi 	int ret;
9676f920c07SWyon Bi 
9686f920c07SWyon Bi 	reg = count;
96952db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_LANE_COUNT_SET, reg);
970699c29a5SWyon Bi 
971699c29a5SWyon Bi 	phy_cfg.dp.lanes = dp->link_train.lane_count;
972699c29a5SWyon Bi 	phy_cfg.dp.set_lanes = true;
973699c29a5SWyon Bi 	phy_cfg.dp.set_rate = false;
974699c29a5SWyon Bi 	phy_cfg.dp.set_voltages = false;
975699c29a5SWyon Bi 	ret = generic_phy_configure(&dp->phy, &phy_cfg);
976699c29a5SWyon Bi 	if (ret) {
977699c29a5SWyon Bi 		dev_err(dp->dev, "%s: phy_configure() failed: %d\n",
978699c29a5SWyon Bi 			__func__, ret);
979699c29a5SWyon Bi 		return;
980699c29a5SWyon Bi 	}
9816f920c07SWyon Bi }
9826f920c07SWyon Bi 
9836f920c07SWyon Bi void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count)
9846f920c07SWyon Bi {
9856f920c07SWyon Bi 	u32 reg;
9866f920c07SWyon Bi 
98752db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_LANE_COUNT_SET);
9886f920c07SWyon Bi 	*count = reg;
9896f920c07SWyon Bi }
9906f920c07SWyon Bi 
991253c2dc8SWyon Bi void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp)
992253c2dc8SWyon Bi {
993699c29a5SWyon Bi 	union phy_configure_opts phy_cfg;
994253c2dc8SWyon Bi 	u8 lane;
995699c29a5SWyon Bi 	int ret;
996253c2dc8SWyon Bi 
997699c29a5SWyon Bi 	for (lane = 0; lane < dp->link_train.lane_count; lane++) {
998699c29a5SWyon Bi 		u8 training_lane = dp->link_train.training_lane[lane];
999699c29a5SWyon Bi 		u8 vs, pe;
1000699c29a5SWyon Bi 
1001253c2dc8SWyon Bi 		analogix_dp_write(dp,
1002253c2dc8SWyon Bi 				  ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane,
1003253c2dc8SWyon Bi 				  dp->link_train.training_lane[lane]);
1004699c29a5SWyon Bi 
1005d63e2d24SWyon Bi 		vs = (training_lane & DP_TRAIN_VOLTAGE_SWING_MASK) >>
1006d63e2d24SWyon Bi 		     DP_TRAIN_VOLTAGE_SWING_SHIFT;
1007d63e2d24SWyon Bi 		pe = (training_lane & DP_TRAIN_PRE_EMPHASIS_MASK) >>
1008d63e2d24SWyon Bi 		     DP_TRAIN_PRE_EMPHASIS_SHIFT;
1009699c29a5SWyon Bi 		phy_cfg.dp.voltage[lane] = vs;
1010699c29a5SWyon Bi 		phy_cfg.dp.pre[lane] = pe;
1011699c29a5SWyon Bi 	}
1012699c29a5SWyon Bi 
1013699c29a5SWyon Bi 	phy_cfg.dp.lanes = dp->link_train.lane_count;
10147adc0066SWyon Bi 	phy_cfg.dp.link_rate =
10157adc0066SWyon Bi 		drm_dp_bw_code_to_link_rate(dp->link_train.link_rate) / 100;
1016699c29a5SWyon Bi 	phy_cfg.dp.set_lanes = false;
1017699c29a5SWyon Bi 	phy_cfg.dp.set_rate = false;
1018699c29a5SWyon Bi 	phy_cfg.dp.set_voltages = true;
1019699c29a5SWyon Bi 	ret = generic_phy_configure(&dp->phy, &phy_cfg);
1020699c29a5SWyon Bi 	if (ret) {
1021699c29a5SWyon Bi 		dev_err(dp->dev, "%s: phy_configure() failed: %d\n",
1022699c29a5SWyon Bi 			__func__, ret);
1023699c29a5SWyon Bi 		return;
1024699c29a5SWyon Bi 	}
1025253c2dc8SWyon Bi }
1026253c2dc8SWyon Bi 
1027253c2dc8SWyon Bi u32 analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, u8 lane)
1028253c2dc8SWyon Bi {
1029253c2dc8SWyon Bi 	return analogix_dp_read(dp,
1030253c2dc8SWyon Bi 				ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane);
1031253c2dc8SWyon Bi }
1032253c2dc8SWyon Bi 
10336f920c07SWyon Bi void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp,
10346f920c07SWyon Bi 				      bool enable)
10356f920c07SWyon Bi {
10366f920c07SWyon Bi 	u32 reg;
10376f920c07SWyon Bi 
10386f920c07SWyon Bi 	if (enable) {
103952db8715SWyon Bi 		reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_4);
10406f920c07SWyon Bi 		reg |= ENHANCED;
104152db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_4, reg);
10426f920c07SWyon Bi 	} else {
104352db8715SWyon Bi 		reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_4);
10446f920c07SWyon Bi 		reg &= ~ENHANCED;
104552db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_4, reg);
10466f920c07SWyon Bi 	}
10476f920c07SWyon Bi }
10486f920c07SWyon Bi 
10496f920c07SWyon Bi void analogix_dp_set_training_pattern(struct analogix_dp_device *dp,
10506f920c07SWyon Bi 				      enum pattern_set pattern)
10516f920c07SWyon Bi {
10526f920c07SWyon Bi 	u32 reg;
10536f920c07SWyon Bi 
10546f920c07SWyon Bi 	switch (pattern) {
10556f920c07SWyon Bi 	case PRBS7:
10566f920c07SWyon Bi 		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
105752db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
10586f920c07SWyon Bi 		break;
10596f920c07SWyon Bi 	case D10_2:
10606f920c07SWyon Bi 		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
106152db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
10626f920c07SWyon Bi 		break;
10636f920c07SWyon Bi 	case TRAINING_PTN1:
10646f920c07SWyon Bi 		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
106552db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
10666f920c07SWyon Bi 		break;
10676f920c07SWyon Bi 	case TRAINING_PTN2:
10686f920c07SWyon Bi 		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
106952db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
10706f920c07SWyon Bi 		break;
10717adc0066SWyon Bi 	case TRAINING_PTN3:
10727adc0066SWyon Bi 		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN3;
10737adc0066SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
10747adc0066SWyon Bi 		break;
10756f920c07SWyon Bi 	case DP_NONE:
10766f920c07SWyon Bi 		reg = SCRAMBLING_ENABLE |
10776f920c07SWyon Bi 			LINK_QUAL_PATTERN_SET_DISABLE |
10786f920c07SWyon Bi 			SW_TRAINING_PATTERN_SET_NORMAL;
107952db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
10806f920c07SWyon Bi 		break;
10816f920c07SWyon Bi 	default:
10826f920c07SWyon Bi 		break;
10836f920c07SWyon Bi 	}
10846f920c07SWyon Bi }
10856f920c07SWyon Bi 
10866f920c07SWyon Bi void analogix_dp_reset_macro(struct analogix_dp_device *dp)
10876f920c07SWyon Bi {
10886f920c07SWyon Bi 	u32 reg;
10896f920c07SWyon Bi 
109052db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_PHY_TEST);
10916f920c07SWyon Bi 	reg |= MACRO_RST;
109252db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_PHY_TEST, reg);
10936f920c07SWyon Bi 
10946f920c07SWyon Bi 	/* 10 us is the minimum reset time. */
10956f920c07SWyon Bi 	udelay(20);
10966f920c07SWyon Bi 
10976f920c07SWyon Bi 	reg &= ~MACRO_RST;
109852db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_PHY_TEST, reg);
10996f920c07SWyon Bi }
11006f920c07SWyon Bi 
11016f920c07SWyon Bi void analogix_dp_init_video(struct analogix_dp_device *dp)
11026f920c07SWyon Bi {
11036f920c07SWyon Bi 	u32 reg;
11046f920c07SWyon Bi 
11056f920c07SWyon Bi 	reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
110652db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_STA_1, reg);
11076f920c07SWyon Bi 
11086f920c07SWyon Bi 	reg = 0x0;
110952db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_1, reg);
11106f920c07SWyon Bi 
11116f920c07SWyon Bi 	reg = CHA_CRI(4) | CHA_CTRL;
111252db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_2, reg);
11136f920c07SWyon Bi 
11146f920c07SWyon Bi 	reg = 0x0;
111552db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_3, reg);
11166f920c07SWyon Bi 
11176f920c07SWyon Bi 	reg = VID_HRES_TH(2) | VID_VRES_TH(0);
111852db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_8, reg);
11196f920c07SWyon Bi }
11206f920c07SWyon Bi 
11216f920c07SWyon Bi void analogix_dp_set_video_color_format(struct analogix_dp_device *dp)
11226f920c07SWyon Bi {
11236f920c07SWyon Bi 	u32 reg;
11246f920c07SWyon Bi 
11256f920c07SWyon Bi 	/* Configure the input color depth, color space, dynamic range */
11266f920c07SWyon Bi 	reg = (dp->video_info.dynamic_range << IN_D_RANGE_SHIFT) |
11276f920c07SWyon Bi 		(dp->video_info.color_depth << IN_BPC_SHIFT) |
11286f920c07SWyon Bi 		(dp->video_info.color_space << IN_COLOR_F_SHIFT);
112952db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_2, reg);
11306f920c07SWyon Bi 
11316f920c07SWyon Bi 	/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
113252db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_3);
11336f920c07SWyon Bi 	reg &= ~IN_YC_COEFFI_MASK;
11346f920c07SWyon Bi 	if (dp->video_info.ycbcr_coeff)
11356f920c07SWyon Bi 		reg |= IN_YC_COEFFI_ITU709;
11366f920c07SWyon Bi 	else
11376f920c07SWyon Bi 		reg |= IN_YC_COEFFI_ITU601;
113852db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_3, reg);
11396f920c07SWyon Bi }
11406f920c07SWyon Bi 
11416f920c07SWyon Bi int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp)
11426f920c07SWyon Bi {
11436f920c07SWyon Bi 	u32 reg;
11446f920c07SWyon Bi 
114552db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_1);
114652db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_1, reg);
11476f920c07SWyon Bi 
114852db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_1);
11496f920c07SWyon Bi 
11506f920c07SWyon Bi 	if (!(reg & DET_STA))
11516f920c07SWyon Bi 		return -EINVAL;
11526f920c07SWyon Bi 
115352db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_2);
115452db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_2, reg);
11556f920c07SWyon Bi 
115652db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_2);
11576f920c07SWyon Bi 
11586f920c07SWyon Bi 	if (reg & CHA_STA)
11596f920c07SWyon Bi 		return -EINVAL;
11606f920c07SWyon Bi 
11616f920c07SWyon Bi 	return 0;
11626f920c07SWyon Bi }
11636f920c07SWyon Bi 
11646f920c07SWyon Bi void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp,
11656f920c07SWyon Bi 				 enum clock_recovery_m_value_type type,
11666f920c07SWyon Bi 				 u32 m_value, u32 n_value)
11676f920c07SWyon Bi {
11686f920c07SWyon Bi 	u32 reg;
11696f920c07SWyon Bi 
11706f920c07SWyon Bi 	if (type == REGISTER_M) {
117152db8715SWyon Bi 		reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_4);
11726f920c07SWyon Bi 		reg |= FIX_M_VID;
117352db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_4, reg);
11746f920c07SWyon Bi 		reg = m_value & 0xff;
117552db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_M_VID_0, reg);
11766f920c07SWyon Bi 		reg = (m_value >> 8) & 0xff;
117752db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_M_VID_1, reg);
11786f920c07SWyon Bi 		reg = (m_value >> 16) & 0xff;
117952db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_M_VID_2, reg);
11806f920c07SWyon Bi 
11816f920c07SWyon Bi 		reg = n_value & 0xff;
118252db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_N_VID_0, reg);
11836f920c07SWyon Bi 		reg = (n_value >> 8) & 0xff;
118452db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_N_VID_1, reg);
11856f920c07SWyon Bi 		reg = (n_value >> 16) & 0xff;
118652db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_N_VID_2, reg);
11876f920c07SWyon Bi 	} else  {
118852db8715SWyon Bi 		reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_4);
11896f920c07SWyon Bi 		reg &= ~FIX_M_VID;
119052db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_4, reg);
11916f920c07SWyon Bi 
119252db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_N_VID_0, 0x00);
119352db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_N_VID_1, 0x80);
119452db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_N_VID_2, 0x00);
11956f920c07SWyon Bi 	}
11966f920c07SWyon Bi }
11976f920c07SWyon Bi 
11986f920c07SWyon Bi void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type)
11996f920c07SWyon Bi {
12006f920c07SWyon Bi 	u32 reg;
12016f920c07SWyon Bi 
12026f920c07SWyon Bi 	if (type == VIDEO_TIMING_FROM_CAPTURE) {
120352db8715SWyon Bi 		reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_10);
12046f920c07SWyon Bi 		reg &= ~FORMAT_SEL;
120552db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_10, reg);
12066f920c07SWyon Bi 	} else {
120752db8715SWyon Bi 		reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_10);
12086f920c07SWyon Bi 		reg |= FORMAT_SEL;
120952db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_10, reg);
12106f920c07SWyon Bi 	}
12116f920c07SWyon Bi }
12126f920c07SWyon Bi 
12136f920c07SWyon Bi void analogix_dp_enable_video_master(struct analogix_dp_device *dp, bool enable)
12146f920c07SWyon Bi {
12156f920c07SWyon Bi 	u32 reg;
12166f920c07SWyon Bi 
12176f920c07SWyon Bi 	if (enable) {
121852db8715SWyon Bi 		reg = analogix_dp_read(dp, ANALOGIX_DP_SOC_GENERAL_CTL);
12196f920c07SWyon Bi 		reg &= ~VIDEO_MODE_MASK;
12206f920c07SWyon Bi 		reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
122152db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_SOC_GENERAL_CTL, reg);
12226f920c07SWyon Bi 	} else {
122352db8715SWyon Bi 		reg = analogix_dp_read(dp, ANALOGIX_DP_SOC_GENERAL_CTL);
12246f920c07SWyon Bi 		reg &= ~VIDEO_MODE_MASK;
12256f920c07SWyon Bi 		reg |= VIDEO_MODE_SLAVE_MODE;
122652db8715SWyon Bi 		analogix_dp_write(dp, ANALOGIX_DP_SOC_GENERAL_CTL, reg);
12276f920c07SWyon Bi 	}
12286f920c07SWyon Bi }
12296f920c07SWyon Bi 
12306f920c07SWyon Bi void analogix_dp_start_video(struct analogix_dp_device *dp)
12316f920c07SWyon Bi {
12326f920c07SWyon Bi 	u32 reg;
12336f920c07SWyon Bi 
123452db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_1);
12356f920c07SWyon Bi 	reg |= VIDEO_EN;
123652db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_1, reg);
12376f920c07SWyon Bi }
12386f920c07SWyon Bi 
12396f920c07SWyon Bi int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp)
12406f920c07SWyon Bi {
12416f920c07SWyon Bi 	u32 reg;
12426f920c07SWyon Bi 
124352db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_3);
124452db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_3, reg);
12456f920c07SWyon Bi 
124652db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_3);
12476f920c07SWyon Bi 	if (!(reg & STRM_VALID))
12486f920c07SWyon Bi 		return -EINVAL;
12496f920c07SWyon Bi 
12506f920c07SWyon Bi 	return 0;
12516f920c07SWyon Bi }
12526f920c07SWyon Bi 
12536f920c07SWyon Bi void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp)
12546f920c07SWyon Bi {
12556f920c07SWyon Bi 	u32 reg;
12566f920c07SWyon Bi 
125752db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_FUNC_EN_1);
12586f920c07SWyon Bi 	reg &= ~(MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N);
12596f920c07SWyon Bi 	reg |= MASTER_VID_FUNC_EN_N;
126052db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_FUNC_EN_1, reg);
12616f920c07SWyon Bi 
126252db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_10);
12636f920c07SWyon Bi 	reg &= ~INTERACE_SCAN_CFG;
12646f920c07SWyon Bi 	reg |= (dp->video_info.interlaced << 2);
126552db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_10, reg);
12666f920c07SWyon Bi 
126752db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_10);
12686f920c07SWyon Bi 	reg &= ~VSYNC_POLARITY_CFG;
12696f920c07SWyon Bi 	reg |= (dp->video_info.v_sync_polarity << 1);
127052db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_10, reg);
12716f920c07SWyon Bi 
127252db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_10);
12736f920c07SWyon Bi 	reg &= ~HSYNC_POLARITY_CFG;
12746f920c07SWyon Bi 	reg |= (dp->video_info.h_sync_polarity << 0);
127552db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_10, reg);
12766f920c07SWyon Bi 
12776f920c07SWyon Bi 	reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
127852db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_SOC_GENERAL_CTL, reg);
12796f920c07SWyon Bi }
12806f920c07SWyon Bi 
12816f920c07SWyon Bi void analogix_dp_enable_scrambling(struct analogix_dp_device *dp)
12826f920c07SWyon Bi {
12836f920c07SWyon Bi 	u32 reg;
12846f920c07SWyon Bi 
128552db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_TRAINING_PTN_SET);
12866f920c07SWyon Bi 	reg &= ~SCRAMBLING_DISABLE;
128752db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
12886f920c07SWyon Bi }
12896f920c07SWyon Bi 
12906f920c07SWyon Bi void analogix_dp_disable_scrambling(struct analogix_dp_device *dp)
12916f920c07SWyon Bi {
12926f920c07SWyon Bi 	u32 reg;
12936f920c07SWyon Bi 
129452db8715SWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_TRAINING_PTN_SET);
12956f920c07SWyon Bi 	reg |= SCRAMBLING_DISABLE;
129652db8715SWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
12976f920c07SWyon Bi }
12980b8cf90dSWyon Bi 
12990b8cf90dSWyon Bi void analogix_dp_set_video_format(struct analogix_dp_device *dp,
13000b8cf90dSWyon Bi 				  const struct drm_display_mode *mode)
13010b8cf90dSWyon Bi {
13020b8cf90dSWyon Bi 	unsigned int hsw, hfp, hbp, vsw, vfp, vbp;
13030b8cf90dSWyon Bi 
13040b8cf90dSWyon Bi 	hsw = mode->hsync_end - mode->hsync_start;
13050b8cf90dSWyon Bi 	hfp = mode->hsync_start - mode->hdisplay;
13060b8cf90dSWyon Bi 	hbp = mode->htotal - mode->hsync_end;
13070b8cf90dSWyon Bi 	vsw = mode->vsync_end - mode->vsync_start;
13080b8cf90dSWyon Bi 	vfp = mode->vsync_start - mode->vdisplay;
13090b8cf90dSWyon Bi 	vbp = mode->vtotal - mode->vsync_end;
13100b8cf90dSWyon Bi 
13110b8cf90dSWyon Bi 	/* Set Video Format Parameters */
13120b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_TOTAL_LINE_CFG_L,
13130b8cf90dSWyon Bi 			  TOTAL_LINE_CFG_L(mode->vtotal));
13140b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_TOTAL_LINE_CFG_H,
13150b8cf90dSWyon Bi 			  TOTAL_LINE_CFG_H(mode->vtotal >> 8));
13160b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_ACTIVE_LINE_CFG_L,
13170b8cf90dSWyon Bi 			  ACTIVE_LINE_CFG_L(mode->vdisplay));
13180b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_ACTIVE_LINE_CFG_H,
13190b8cf90dSWyon Bi 			  ACTIVE_LINE_CFG_H(mode->vdisplay >> 8));
13200b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_V_F_PORCH_CFG,
13210b8cf90dSWyon Bi 			  V_F_PORCH_CFG(vfp));
13220b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_V_SYNC_WIDTH_CFG,
13230b8cf90dSWyon Bi 			  V_SYNC_WIDTH_CFG(vsw));
13240b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_V_B_PORCH_CFG,
13250b8cf90dSWyon Bi 			  V_B_PORCH_CFG(vbp));
13260b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_TOTAL_PIXEL_CFG_L,
13270b8cf90dSWyon Bi 			  TOTAL_PIXEL_CFG_L(mode->htotal));
13280b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_TOTAL_PIXEL_CFG_H,
13290b8cf90dSWyon Bi 			  TOTAL_PIXEL_CFG_H(mode->htotal >> 8));
13300b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_ACTIVE_PIXEL_CFG_L,
13310b8cf90dSWyon Bi 			  ACTIVE_PIXEL_CFG_L(mode->hdisplay));
13320b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_ACTIVE_PIXEL_CFG_H,
13330b8cf90dSWyon Bi 			  ACTIVE_PIXEL_CFG_H(mode->hdisplay >> 8));
13340b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_H_F_PORCH_CFG_L,
13350b8cf90dSWyon Bi 			  H_F_PORCH_CFG_L(hfp));
13360b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_H_F_PORCH_CFG_H,
13370b8cf90dSWyon Bi 			  H_F_PORCH_CFG_H(hfp >> 8));
13380b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_H_SYNC_CFG_L,
13390b8cf90dSWyon Bi 			  H_SYNC_CFG_L(hsw));
13400b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_H_SYNC_CFG_H,
13410b8cf90dSWyon Bi 			  H_SYNC_CFG_H(hsw >> 8));
13420b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_H_B_PORCH_CFG_L,
13430b8cf90dSWyon Bi 			  H_B_PORCH_CFG_L(hbp));
13440b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_H_B_PORCH_CFG_H,
13450b8cf90dSWyon Bi 			  H_B_PORCH_CFG_H(hbp >> 8));
13460b8cf90dSWyon Bi }
13470b8cf90dSWyon Bi 
13480b8cf90dSWyon Bi void analogix_dp_video_bist_enable(struct analogix_dp_device *dp)
13490b8cf90dSWyon Bi {
13500b8cf90dSWyon Bi 	u32 reg;
13510b8cf90dSWyon Bi 
13520b8cf90dSWyon Bi 	/* Enable Video BIST */
13530b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_4, BIST_EN);
13540b8cf90dSWyon Bi 
13550b8cf90dSWyon Bi 	/*
13560b8cf90dSWyon Bi 	 * Note that if BIST_EN is set to 1, F_SEL must be cleared to 0
13570b8cf90dSWyon Bi 	 * although video format information comes from registers set by user.
13580b8cf90dSWyon Bi 	 */
13590b8cf90dSWyon Bi 	reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_10);
13600b8cf90dSWyon Bi 	reg &= ~FORMAT_SEL;
13610b8cf90dSWyon Bi 	analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_10, reg);
13620b8cf90dSWyon Bi }
1363