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
analogix_dp_write(struct analogix_dp_device * dp,u32 reg,u32 val)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
analogix_dp_read(struct analogix_dp_device * dp,u32 reg)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
analogix_dp_enable_video_mute(struct analogix_dp_device * dp,bool enable)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
analogix_dp_stop_video(struct analogix_dp_device * dp)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
analogix_dp_set_lane_map(struct analogix_dp_device * dp)751f59ac36SWyon Bi static void analogix_dp_set_lane_map(struct analogix_dp_device *dp)
766f920c07SWyon Bi {
771f59ac36SWyon Bi u32 i, reg = 0;
786f920c07SWyon Bi
791f59ac36SWyon Bi for (i = 0; i < dp->video_info.max_lane_count; i++)
801f59ac36SWyon 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
analogix_dp_init_analog_param(struct analogix_dp_device * dp)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
analogix_dp_init_interrupt(struct analogix_dp_device * dp)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
analogix_dp_reset(struct analogix_dp_device * dp)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
1601f59ac36SWyon 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
analogix_dp_swreset(struct analogix_dp_device * dp)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
analogix_dp_config_interrupt(struct analogix_dp_device * dp)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
analogix_dp_mute_hpd_interrupt(struct analogix_dp_device * dp)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
analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device * dp)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
analogix_dp_get_pll_lock_status(struct analogix_dp_device * dp)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
analogix_dp_set_pll_power_down(struct analogix_dp_device * dp,bool enable)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
analogix_dp_set_analog_power_down(struct analogix_dp_device * dp,enum analog_power_block block,bool enable)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
analogix_dp_init_analog_func(struct analogix_dp_device * dp)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
analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device * dp)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
analogix_dp_init_hpd(struct analogix_dp_device * dp)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
analogix_dp_force_hpd(struct analogix_dp_device * dp)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
analogix_dp_get_irq_type(struct analogix_dp_device * dp)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
analogix_dp_reset_aux(struct analogix_dp_device * dp)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
analogix_dp_init_aux(struct analogix_dp_device * dp)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
analogix_dp_detect(struct analogix_dp_device * dp)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
analogix_dp_enable_sw_function(struct analogix_dp_device * dp)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
analogix_dp_get_plug_in_status(struct analogix_dp_device * dp)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
analogix_dp_start_aux_transaction(struct analogix_dp_device * dp)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
analogix_dp_select_i2c_device(struct analogix_dp_device * dp,unsigned int device_addr,unsigned int reg_addr)5656f920c07SWyon Bi int analogix_dp_select_i2c_device(struct analogix_dp_device *dp,
5666f920c07SWyon Bi unsigned int device_addr,
5676f920c07SWyon Bi unsigned int reg_addr)
5686f920c07SWyon Bi {
5696f920c07SWyon Bi u32 reg;
5706f920c07SWyon Bi int retval;
5716f920c07SWyon Bi
5726f920c07SWyon Bi /* Set EDID device address */
5736f920c07SWyon Bi reg = device_addr;
57452db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_7_0, reg);
57552db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_15_8, 0x0);
57652db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_19_16, 0x0);
5776f920c07SWyon Bi
5786f920c07SWyon Bi /* Set offset from base address of EDID device */
57952db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_BUF_DATA_0, reg_addr);
5806f920c07SWyon Bi
5816f920c07SWyon Bi /*
5826f920c07SWyon Bi * Set I2C transaction and write address
5836f920c07SWyon Bi * If bit 3 is 1, DisplayPort transaction.
5846f920c07SWyon Bi * If Bit 3 is 0, I2C transaction.
5856f920c07SWyon Bi */
5866f920c07SWyon Bi reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
5876f920c07SWyon Bi AUX_TX_COMM_WRITE;
58852db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_1, reg);
5896f920c07SWyon Bi
5906f920c07SWyon Bi /* Start AUX transaction */
5916f920c07SWyon Bi retval = analogix_dp_start_aux_transaction(dp);
5926f920c07SWyon Bi if (retval < 0)
5936f920c07SWyon Bi return retval;
5946f920c07SWyon Bi
5956f920c07SWyon Bi return 0;
5966f920c07SWyon Bi }
5976f920c07SWyon Bi
analogix_dp_read_byte_from_i2c(struct analogix_dp_device * dp,unsigned int device_addr,unsigned int reg_addr,unsigned int * data)5986f920c07SWyon Bi int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp,
5996f920c07SWyon Bi unsigned int device_addr,
6006f920c07SWyon Bi unsigned int reg_addr,
6016f920c07SWyon Bi unsigned int *data)
6026f920c07SWyon Bi {
6036f920c07SWyon Bi u32 reg;
6046f920c07SWyon Bi int i;
6056f920c07SWyon Bi int retval;
6066f920c07SWyon Bi
6076f920c07SWyon Bi for (i = 0; i < 3; i++) {
6086f920c07SWyon Bi /* Clear AUX CH data buffer */
6096f920c07SWyon Bi reg = BUF_CLR;
61052db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_BUFFER_DATA_CTL, reg);
6116f920c07SWyon Bi
6126f920c07SWyon Bi /* Select EDID device */
6136f920c07SWyon Bi retval = analogix_dp_select_i2c_device(dp, device_addr,
6146f920c07SWyon Bi reg_addr);
6156f920c07SWyon Bi if (retval != 0)
6166f920c07SWyon Bi continue;
6176f920c07SWyon Bi
6186f920c07SWyon Bi /*
6196f920c07SWyon Bi * Set I2C transaction and read data
6206f920c07SWyon Bi * If bit 3 is 1, DisplayPort transaction.
6216f920c07SWyon Bi * If Bit 3 is 0, I2C transaction.
6226f920c07SWyon Bi */
6236f920c07SWyon Bi reg = AUX_TX_COMM_I2C_TRANSACTION |
6246f920c07SWyon Bi AUX_TX_COMM_READ;
62552db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_1, reg);
6266f920c07SWyon Bi
6276f920c07SWyon Bi /* Start AUX transaction */
6286f920c07SWyon Bi retval = analogix_dp_start_aux_transaction(dp);
6296f920c07SWyon Bi if (retval == 0)
6306f920c07SWyon Bi break;
6316f920c07SWyon Bi }
6326f920c07SWyon Bi
6336f920c07SWyon Bi /* Read data */
6346f920c07SWyon Bi if (retval == 0)
63552db8715SWyon Bi *data = analogix_dp_read(dp, ANALOGIX_DP_BUF_DATA_0);
6366f920c07SWyon Bi
6376f920c07SWyon Bi return retval;
6386f920c07SWyon Bi }
6396f920c07SWyon Bi
analogix_dp_read_bytes_from_i2c(struct analogix_dp_device * dp,unsigned int device_addr,unsigned int reg_addr,unsigned int count,unsigned char edid[])6406f920c07SWyon Bi int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp,
6416f920c07SWyon Bi unsigned int device_addr,
6426f920c07SWyon Bi unsigned int reg_addr,
6436f920c07SWyon Bi unsigned int count,
6446f920c07SWyon Bi unsigned char edid[])
6456f920c07SWyon Bi {
6466f920c07SWyon Bi u32 reg;
6476f920c07SWyon Bi unsigned int i, j;
6486f920c07SWyon Bi unsigned int cur_data_idx;
6496f920c07SWyon Bi unsigned int defer = 0;
6506f920c07SWyon Bi int retval = 0;
6516f920c07SWyon Bi
6526f920c07SWyon Bi for (i = 0; i < count; i += 16) {
6536f920c07SWyon Bi for (j = 0; j < 3; j++) {
6546f920c07SWyon Bi /* Clear AUX CH data buffer */
6556f920c07SWyon Bi reg = BUF_CLR;
65652db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_BUFFER_DATA_CTL, reg);
6576f920c07SWyon Bi
6586f920c07SWyon Bi /* Set normal AUX CH command */
65952db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_AUX_CH_CTL_2);
6606f920c07SWyon Bi reg &= ~ADDR_ONLY;
66152db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_2, reg);
6626f920c07SWyon Bi
6636f920c07SWyon Bi /*
6646f920c07SWyon Bi * If Rx sends defer, Tx sends only reads
6656f920c07SWyon Bi * request without sending address
6666f920c07SWyon Bi */
6676f920c07SWyon Bi if (!defer)
6686f920c07SWyon Bi retval = analogix_dp_select_i2c_device(dp,
6696f920c07SWyon Bi device_addr, reg_addr + i);
6706f920c07SWyon Bi else
6716f920c07SWyon Bi defer = 0;
6726f920c07SWyon Bi
6736f920c07SWyon Bi if (retval == 0) {
6746f920c07SWyon Bi /*
6756f920c07SWyon Bi * Set I2C transaction and write data
6766f920c07SWyon Bi * If bit 3 is 1, DisplayPort transaction.
6776f920c07SWyon Bi * If Bit 3 is 0, I2C transaction.
6786f920c07SWyon Bi */
6796f920c07SWyon Bi reg = AUX_LENGTH(16) |
6806f920c07SWyon Bi AUX_TX_COMM_I2C_TRANSACTION |
6816f920c07SWyon Bi AUX_TX_COMM_READ;
68252db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_1,
68352db8715SWyon Bi reg);
6846f920c07SWyon Bi
6856f920c07SWyon Bi /* Start AUX transaction */
6866f920c07SWyon Bi retval = analogix_dp_start_aux_transaction(dp);
6876f920c07SWyon Bi if (retval == 0)
6886f920c07SWyon Bi break;
6896f920c07SWyon Bi }
6906f920c07SWyon Bi /* Check if Rx sends defer */
69152db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_AUX_RX_COMM);
6926f920c07SWyon Bi if (reg == AUX_RX_COMM_AUX_DEFER ||
6936f920c07SWyon Bi reg == AUX_RX_COMM_I2C_DEFER) {
6946f920c07SWyon Bi dev_dbg(dp->dev, "Defer: %d\n\n", reg);
6956f920c07SWyon Bi defer = 1;
6966f920c07SWyon Bi }
6976f920c07SWyon Bi }
6986f920c07SWyon Bi
6996f920c07SWyon Bi for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
70052db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_BUF_DATA_0
7016f920c07SWyon Bi + 4 * cur_data_idx);
7026f920c07SWyon Bi edid[i + cur_data_idx] = (unsigned char)reg;
7036f920c07SWyon Bi }
7046f920c07SWyon Bi }
7056f920c07SWyon Bi
7066f920c07SWyon Bi return retval;
7076f920c07SWyon Bi }
7086f920c07SWyon Bi
analogix_dp_ssc_supported(struct analogix_dp_device * dp)709699c29a5SWyon Bi bool analogix_dp_ssc_supported(struct analogix_dp_device *dp)
710699c29a5SWyon Bi {
711699c29a5SWyon Bi /* Check if SSC is supported by both sides */
712699c29a5SWyon Bi return dp->plat_data.ssc && dp->link_train.ssc;
713699c29a5SWyon Bi }
714699c29a5SWyon Bi
analogix_dp_set_link_bandwidth(struct analogix_dp_device * dp,u32 bwtype)7156f920c07SWyon Bi void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype)
7166f920c07SWyon Bi {
717699c29a5SWyon Bi union phy_configure_opts phy_cfg;
7187adc0066SWyon Bi u32 status;
719a6285d17SWyon Bi int ret;
7206f920c07SWyon Bi
7217adc0066SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_LINK_BW_SET, bwtype);
722a6285d17SWyon Bi
723699c29a5SWyon Bi phy_cfg.dp.lanes = dp->link_train.lane_count;
724699c29a5SWyon Bi phy_cfg.dp.link_rate =
725699c29a5SWyon Bi drm_dp_bw_code_to_link_rate(dp->link_train.link_rate) / 100;
726699c29a5SWyon Bi phy_cfg.dp.ssc = analogix_dp_ssc_supported(dp);
727699c29a5SWyon Bi phy_cfg.dp.set_lanes = false;
728699c29a5SWyon Bi phy_cfg.dp.set_rate = true;
729699c29a5SWyon Bi phy_cfg.dp.set_voltages = false;
730699c29a5SWyon Bi ret = generic_phy_configure(&dp->phy, &phy_cfg);
731699c29a5SWyon Bi if (ret) {
732699c29a5SWyon Bi dev_err(dp->dev, "%s: phy_configure() failed: %d\n",
733699c29a5SWyon Bi __func__, ret);
734699c29a5SWyon Bi return;
735699c29a5SWyon Bi }
736699c29a5SWyon Bi
737a6285d17SWyon Bi ret = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, status,
738a6285d17SWyon Bi status != PLL_UNLOCKED,
739a6285d17SWyon Bi 120 * DP_TIMEOUT_LOOP_COUNT);
740a6285d17SWyon Bi if (ret) {
741a6285d17SWyon Bi dev_err(dp->dev, "Wait for pll lock failed %d\n", ret);
742a6285d17SWyon Bi return;
743a6285d17SWyon Bi }
7446f920c07SWyon Bi }
7456f920c07SWyon Bi
analogix_dp_get_link_bandwidth(struct analogix_dp_device * dp,u32 * bwtype)7466f920c07SWyon Bi void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype)
7476f920c07SWyon Bi {
7486f920c07SWyon Bi u32 reg;
7496f920c07SWyon Bi
75052db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_LINK_BW_SET);
7516f920c07SWyon Bi *bwtype = reg;
7526f920c07SWyon Bi }
7536f920c07SWyon Bi
analogix_dp_set_lane_count(struct analogix_dp_device * dp,u32 count)7546f920c07SWyon Bi void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count)
7556f920c07SWyon Bi {
756699c29a5SWyon Bi union phy_configure_opts phy_cfg;
7576f920c07SWyon Bi u32 reg;
758699c29a5SWyon Bi int ret;
7596f920c07SWyon Bi
7606f920c07SWyon Bi reg = count;
76152db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_LANE_COUNT_SET, reg);
762699c29a5SWyon Bi
763699c29a5SWyon Bi phy_cfg.dp.lanes = dp->link_train.lane_count;
764699c29a5SWyon Bi phy_cfg.dp.set_lanes = true;
765699c29a5SWyon Bi phy_cfg.dp.set_rate = false;
766699c29a5SWyon Bi phy_cfg.dp.set_voltages = false;
767699c29a5SWyon Bi ret = generic_phy_configure(&dp->phy, &phy_cfg);
768699c29a5SWyon Bi if (ret) {
769699c29a5SWyon Bi dev_err(dp->dev, "%s: phy_configure() failed: %d\n",
770699c29a5SWyon Bi __func__, ret);
771699c29a5SWyon Bi return;
772699c29a5SWyon Bi }
7736f920c07SWyon Bi }
7746f920c07SWyon Bi
analogix_dp_get_lane_count(struct analogix_dp_device * dp,u32 * count)7756f920c07SWyon Bi void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count)
7766f920c07SWyon Bi {
7776f920c07SWyon Bi u32 reg;
7786f920c07SWyon Bi
77952db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_LANE_COUNT_SET);
7806f920c07SWyon Bi *count = reg;
7816f920c07SWyon Bi }
7826f920c07SWyon Bi
analogix_dp_set_lane_link_training(struct analogix_dp_device * dp)783253c2dc8SWyon Bi void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp)
784253c2dc8SWyon Bi {
785699c29a5SWyon Bi union phy_configure_opts phy_cfg;
786253c2dc8SWyon Bi u8 lane;
787699c29a5SWyon Bi int ret;
788253c2dc8SWyon Bi
789699c29a5SWyon Bi for (lane = 0; lane < dp->link_train.lane_count; lane++) {
790699c29a5SWyon Bi u8 training_lane = dp->link_train.training_lane[lane];
791699c29a5SWyon Bi u8 vs, pe;
792699c29a5SWyon Bi
793253c2dc8SWyon Bi analogix_dp_write(dp,
794253c2dc8SWyon Bi ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane,
795253c2dc8SWyon Bi dp->link_train.training_lane[lane]);
796699c29a5SWyon Bi
797d63e2d24SWyon Bi vs = (training_lane & DP_TRAIN_VOLTAGE_SWING_MASK) >>
798d63e2d24SWyon Bi DP_TRAIN_VOLTAGE_SWING_SHIFT;
799d63e2d24SWyon Bi pe = (training_lane & DP_TRAIN_PRE_EMPHASIS_MASK) >>
800d63e2d24SWyon Bi DP_TRAIN_PRE_EMPHASIS_SHIFT;
801699c29a5SWyon Bi phy_cfg.dp.voltage[lane] = vs;
802699c29a5SWyon Bi phy_cfg.dp.pre[lane] = pe;
803699c29a5SWyon Bi }
804699c29a5SWyon Bi
805699c29a5SWyon Bi phy_cfg.dp.lanes = dp->link_train.lane_count;
8067adc0066SWyon Bi phy_cfg.dp.link_rate =
8077adc0066SWyon Bi drm_dp_bw_code_to_link_rate(dp->link_train.link_rate) / 100;
808699c29a5SWyon Bi phy_cfg.dp.set_lanes = false;
809699c29a5SWyon Bi phy_cfg.dp.set_rate = false;
810699c29a5SWyon Bi phy_cfg.dp.set_voltages = true;
811699c29a5SWyon Bi ret = generic_phy_configure(&dp->phy, &phy_cfg);
812699c29a5SWyon Bi if (ret) {
813699c29a5SWyon Bi dev_err(dp->dev, "%s: phy_configure() failed: %d\n",
814699c29a5SWyon Bi __func__, ret);
815699c29a5SWyon Bi return;
816699c29a5SWyon Bi }
817253c2dc8SWyon Bi }
818253c2dc8SWyon Bi
analogix_dp_get_lane_link_training(struct analogix_dp_device * dp,u8 lane)819253c2dc8SWyon Bi u32 analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, u8 lane)
820253c2dc8SWyon Bi {
821253c2dc8SWyon Bi return analogix_dp_read(dp,
822253c2dc8SWyon Bi ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane);
823253c2dc8SWyon Bi }
824253c2dc8SWyon Bi
analogix_dp_enable_enhanced_mode(struct analogix_dp_device * dp,bool enable)8256f920c07SWyon Bi void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp,
8266f920c07SWyon Bi bool enable)
8276f920c07SWyon Bi {
8286f920c07SWyon Bi u32 reg;
8296f920c07SWyon Bi
8306f920c07SWyon Bi if (enable) {
83152db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_4);
8326f920c07SWyon Bi reg |= ENHANCED;
83352db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_4, reg);
8346f920c07SWyon Bi } else {
83552db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_4);
8366f920c07SWyon Bi reg &= ~ENHANCED;
83752db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_4, reg);
8386f920c07SWyon Bi }
8396f920c07SWyon Bi }
8406f920c07SWyon Bi
analogix_dp_set_training_pattern(struct analogix_dp_device * dp,enum pattern_set pattern)8416f920c07SWyon Bi void analogix_dp_set_training_pattern(struct analogix_dp_device *dp,
8426f920c07SWyon Bi enum pattern_set pattern)
8436f920c07SWyon Bi {
8446f920c07SWyon Bi u32 reg;
8456f920c07SWyon Bi
8466f920c07SWyon Bi switch (pattern) {
8476f920c07SWyon Bi case PRBS7:
8486f920c07SWyon Bi reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
84952db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
8506f920c07SWyon Bi break;
8516f920c07SWyon Bi case D10_2:
8526f920c07SWyon Bi reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
85352db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
8546f920c07SWyon Bi break;
8556f920c07SWyon Bi case TRAINING_PTN1:
8566f920c07SWyon Bi reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
85752db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
8586f920c07SWyon Bi break;
8596f920c07SWyon Bi case TRAINING_PTN2:
8606f920c07SWyon Bi reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
86152db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
8626f920c07SWyon Bi break;
8637adc0066SWyon Bi case TRAINING_PTN3:
8647adc0066SWyon Bi reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN3;
8657adc0066SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
8667adc0066SWyon Bi break;
8676f920c07SWyon Bi case DP_NONE:
8686f920c07SWyon Bi reg = SCRAMBLING_ENABLE |
8696f920c07SWyon Bi LINK_QUAL_PATTERN_SET_DISABLE |
8706f920c07SWyon Bi SW_TRAINING_PATTERN_SET_NORMAL;
87152db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
8726f920c07SWyon Bi break;
8736f920c07SWyon Bi default:
8746f920c07SWyon Bi break;
8756f920c07SWyon Bi }
8766f920c07SWyon Bi }
8776f920c07SWyon Bi
analogix_dp_reset_macro(struct analogix_dp_device * dp)8786f920c07SWyon Bi void analogix_dp_reset_macro(struct analogix_dp_device *dp)
8796f920c07SWyon Bi {
8806f920c07SWyon Bi u32 reg;
8816f920c07SWyon Bi
88252db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_PHY_TEST);
8836f920c07SWyon Bi reg |= MACRO_RST;
88452db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_PHY_TEST, reg);
8856f920c07SWyon Bi
8866f920c07SWyon Bi /* 10 us is the minimum reset time. */
8876f920c07SWyon Bi udelay(20);
8886f920c07SWyon Bi
8896f920c07SWyon Bi reg &= ~MACRO_RST;
89052db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_PHY_TEST, reg);
8916f920c07SWyon Bi }
8926f920c07SWyon Bi
analogix_dp_init_video(struct analogix_dp_device * dp)8936f920c07SWyon Bi void analogix_dp_init_video(struct analogix_dp_device *dp)
8946f920c07SWyon Bi {
8956f920c07SWyon Bi u32 reg;
8966f920c07SWyon Bi
8976f920c07SWyon Bi reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
89852db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_STA_1, reg);
8996f920c07SWyon Bi
9006f920c07SWyon Bi reg = 0x0;
90152db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_1, reg);
9026f920c07SWyon Bi
9036f920c07SWyon Bi reg = CHA_CRI(4) | CHA_CTRL;
90452db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_2, reg);
9056f920c07SWyon Bi
906ae5256b5SWyon Bi if (dp->video_info.force_stream_valid) {
907e9cac7f1SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_3);
908e9cac7f1SWyon Bi reg |= VALID_CTRL | F_VALID;
90952db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_3, reg);
910ae5256b5SWyon Bi }
9116f920c07SWyon Bi
9126f920c07SWyon Bi reg = VID_HRES_TH(2) | VID_VRES_TH(0);
91352db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_8, reg);
9146f920c07SWyon Bi }
9156f920c07SWyon Bi
analogix_dp_set_video_color_format(struct analogix_dp_device * dp)9166f920c07SWyon Bi void analogix_dp_set_video_color_format(struct analogix_dp_device *dp)
9176f920c07SWyon Bi {
9186f920c07SWyon Bi u32 reg;
9196f920c07SWyon Bi
9206f920c07SWyon Bi /* Configure the input color depth, color space, dynamic range */
9216f920c07SWyon Bi reg = (dp->video_info.dynamic_range << IN_D_RANGE_SHIFT) |
9226f920c07SWyon Bi (dp->video_info.color_depth << IN_BPC_SHIFT) |
9236f920c07SWyon Bi (dp->video_info.color_space << IN_COLOR_F_SHIFT);
92452db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_2, reg);
9256f920c07SWyon Bi
9266f920c07SWyon Bi /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
92752db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_3);
9286f920c07SWyon Bi reg &= ~IN_YC_COEFFI_MASK;
9296f920c07SWyon Bi if (dp->video_info.ycbcr_coeff)
9306f920c07SWyon Bi reg |= IN_YC_COEFFI_ITU709;
9316f920c07SWyon Bi else
9326f920c07SWyon Bi reg |= IN_YC_COEFFI_ITU601;
93352db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_3, reg);
9346f920c07SWyon Bi }
9356f920c07SWyon Bi
analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device * dp)9366f920c07SWyon Bi int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp)
9376f920c07SWyon Bi {
9386f920c07SWyon Bi u32 reg;
9396f920c07SWyon Bi
94052db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_1);
94152db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_1, reg);
9426f920c07SWyon Bi
94352db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_1);
9446f920c07SWyon Bi
9456f920c07SWyon Bi if (!(reg & DET_STA))
9466f920c07SWyon Bi return -EINVAL;
9476f920c07SWyon Bi
94852db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_2);
94952db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_2, reg);
9506f920c07SWyon Bi
95152db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_2);
9526f920c07SWyon Bi
9536f920c07SWyon Bi if (reg & CHA_STA)
9546f920c07SWyon Bi return -EINVAL;
9556f920c07SWyon Bi
9566f920c07SWyon Bi return 0;
9576f920c07SWyon Bi }
9586f920c07SWyon Bi
analogix_dp_set_video_cr_mn(struct analogix_dp_device * dp,enum clock_recovery_m_value_type type,u32 m_value,u32 n_value)9596f920c07SWyon Bi void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp,
9606f920c07SWyon Bi enum clock_recovery_m_value_type type,
9616f920c07SWyon Bi u32 m_value, u32 n_value)
9626f920c07SWyon Bi {
9636f920c07SWyon Bi u32 reg;
9646f920c07SWyon Bi
9656f920c07SWyon Bi if (type == REGISTER_M) {
96652db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_4);
9676f920c07SWyon Bi reg |= FIX_M_VID;
96852db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_4, reg);
9696f920c07SWyon Bi reg = m_value & 0xff;
97052db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_M_VID_0, reg);
9716f920c07SWyon Bi reg = (m_value >> 8) & 0xff;
97252db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_M_VID_1, reg);
9736f920c07SWyon Bi reg = (m_value >> 16) & 0xff;
97452db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_M_VID_2, reg);
9756f920c07SWyon Bi
9766f920c07SWyon Bi reg = n_value & 0xff;
97752db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_N_VID_0, reg);
9786f920c07SWyon Bi reg = (n_value >> 8) & 0xff;
97952db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_N_VID_1, reg);
9806f920c07SWyon Bi reg = (n_value >> 16) & 0xff;
98152db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_N_VID_2, reg);
9826f920c07SWyon Bi } else {
98352db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_4);
9846f920c07SWyon Bi reg &= ~FIX_M_VID;
98552db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_4, reg);
9866f920c07SWyon Bi
98752db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_N_VID_0, 0x00);
98852db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_N_VID_1, 0x80);
98952db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_N_VID_2, 0x00);
9906f920c07SWyon Bi }
9916f920c07SWyon Bi }
9926f920c07SWyon Bi
analogix_dp_set_video_timing_mode(struct analogix_dp_device * dp,u32 type)9936f920c07SWyon Bi void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type)
9946f920c07SWyon Bi {
9956f920c07SWyon Bi u32 reg;
9966f920c07SWyon Bi
9976f920c07SWyon Bi if (type == VIDEO_TIMING_FROM_CAPTURE) {
99852db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_10);
9996f920c07SWyon Bi reg &= ~FORMAT_SEL;
100052db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_10, reg);
10016f920c07SWyon Bi } else {
100252db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_10);
10036f920c07SWyon Bi reg |= FORMAT_SEL;
100452db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_10, reg);
10056f920c07SWyon Bi }
10066f920c07SWyon Bi }
10076f920c07SWyon Bi
analogix_dp_enable_video_master(struct analogix_dp_device * dp,bool enable)10086f920c07SWyon Bi void analogix_dp_enable_video_master(struct analogix_dp_device *dp, bool enable)
10096f920c07SWyon Bi {
10106f920c07SWyon Bi u32 reg;
10116f920c07SWyon Bi
10126f920c07SWyon Bi if (enable) {
101352db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_SOC_GENERAL_CTL);
10146f920c07SWyon Bi reg &= ~VIDEO_MODE_MASK;
10156f920c07SWyon Bi reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
101652db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_SOC_GENERAL_CTL, reg);
10176f920c07SWyon Bi } else {
101852db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_SOC_GENERAL_CTL);
10196f920c07SWyon Bi reg &= ~VIDEO_MODE_MASK;
10206f920c07SWyon Bi reg |= VIDEO_MODE_SLAVE_MODE;
102152db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_SOC_GENERAL_CTL, reg);
10226f920c07SWyon Bi }
10236f920c07SWyon Bi }
10246f920c07SWyon Bi
analogix_dp_start_video(struct analogix_dp_device * dp)10256f920c07SWyon Bi void analogix_dp_start_video(struct analogix_dp_device *dp)
10266f920c07SWyon Bi {
10276f920c07SWyon Bi u32 reg;
10286f920c07SWyon Bi
102952db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_1);
10306f920c07SWyon Bi reg |= VIDEO_EN;
103152db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_1, reg);
10326f920c07SWyon Bi }
10336f920c07SWyon Bi
analogix_dp_is_video_stream_on(struct analogix_dp_device * dp)10346f920c07SWyon Bi int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp)
10356f920c07SWyon Bi {
10366f920c07SWyon Bi u32 reg;
10376f920c07SWyon Bi
103852db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_3);
103952db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_3, reg);
10406f920c07SWyon Bi
104152db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_3);
10426f920c07SWyon Bi if (!(reg & STRM_VALID))
10436f920c07SWyon Bi return -EINVAL;
10446f920c07SWyon Bi
10456f920c07SWyon Bi return 0;
10466f920c07SWyon Bi }
10476f920c07SWyon Bi
analogix_dp_config_video_slave_mode(struct analogix_dp_device * dp)10486f920c07SWyon Bi void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp)
10496f920c07SWyon Bi {
10506f920c07SWyon Bi u32 reg;
10516f920c07SWyon Bi
105252db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_FUNC_EN_1);
10536f920c07SWyon Bi reg &= ~(MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N);
10546f920c07SWyon Bi reg |= MASTER_VID_FUNC_EN_N;
105552db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_FUNC_EN_1, reg);
10566f920c07SWyon Bi
105752db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_10);
10586f920c07SWyon Bi reg &= ~INTERACE_SCAN_CFG;
10596f920c07SWyon Bi reg |= (dp->video_info.interlaced << 2);
106052db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_10, reg);
10616f920c07SWyon Bi
106252db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_10);
10636f920c07SWyon Bi reg &= ~VSYNC_POLARITY_CFG;
10646f920c07SWyon Bi reg |= (dp->video_info.v_sync_polarity << 1);
106552db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_10, reg);
10666f920c07SWyon Bi
106752db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_10);
10686f920c07SWyon Bi reg &= ~HSYNC_POLARITY_CFG;
10696f920c07SWyon Bi reg |= (dp->video_info.h_sync_polarity << 0);
107052db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_10, reg);
10716f920c07SWyon Bi
10726f920c07SWyon Bi reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
107352db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_SOC_GENERAL_CTL, reg);
10746f920c07SWyon Bi }
10756f920c07SWyon Bi
analogix_dp_enable_scrambling(struct analogix_dp_device * dp)10766f920c07SWyon Bi void analogix_dp_enable_scrambling(struct analogix_dp_device *dp)
10776f920c07SWyon Bi {
10786f920c07SWyon Bi u32 reg;
10796f920c07SWyon Bi
108052db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_TRAINING_PTN_SET);
10816f920c07SWyon Bi reg &= ~SCRAMBLING_DISABLE;
108252db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
10836f920c07SWyon Bi }
10846f920c07SWyon Bi
analogix_dp_disable_scrambling(struct analogix_dp_device * dp)10856f920c07SWyon Bi void analogix_dp_disable_scrambling(struct analogix_dp_device *dp)
10866f920c07SWyon Bi {
10876f920c07SWyon Bi u32 reg;
10886f920c07SWyon Bi
108952db8715SWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_TRAINING_PTN_SET);
10906f920c07SWyon Bi reg |= SCRAMBLING_DISABLE;
109152db8715SWyon Bi analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg);
10926f920c07SWyon Bi }
10930b8cf90dSWyon Bi
analogix_dp_set_video_format(struct analogix_dp_device * dp,const struct drm_display_mode * mode)10940b8cf90dSWyon Bi void analogix_dp_set_video_format(struct analogix_dp_device *dp,
10950b8cf90dSWyon Bi const struct drm_display_mode *mode)
10960b8cf90dSWyon Bi {
10970b8cf90dSWyon Bi unsigned int hsw, hfp, hbp, vsw, vfp, vbp;
10980b8cf90dSWyon Bi
1099e9cac7f1SWyon Bi dp->video_info.interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
1100c7dcfb21SWyon Bi
1101c7dcfb21SWyon Bi if (dp->plat_data.subdev_type == RK3588_EDP) {
1102c7dcfb21SWyon Bi dp->video_info.v_sync_polarity = true;
1103c7dcfb21SWyon Bi dp->video_info.h_sync_polarity = true;
1104c7dcfb21SWyon Bi } else {
1105e9cac7f1SWyon Bi dp->video_info.v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
1106e9cac7f1SWyon Bi dp->video_info.h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
1107c7dcfb21SWyon Bi }
1108e9cac7f1SWyon Bi
11090b8cf90dSWyon Bi hsw = mode->hsync_end - mode->hsync_start;
11100b8cf90dSWyon Bi hfp = mode->hsync_start - mode->hdisplay;
11110b8cf90dSWyon Bi hbp = mode->htotal - mode->hsync_end;
11120b8cf90dSWyon Bi vsw = mode->vsync_end - mode->vsync_start;
11130b8cf90dSWyon Bi vfp = mode->vsync_start - mode->vdisplay;
11140b8cf90dSWyon Bi vbp = mode->vtotal - mode->vsync_end;
11150b8cf90dSWyon Bi
11160b8cf90dSWyon Bi /* Set Video Format Parameters */
11170b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_TOTAL_LINE_CFG_L,
11180b8cf90dSWyon Bi TOTAL_LINE_CFG_L(mode->vtotal));
11190b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_TOTAL_LINE_CFG_H,
11200b8cf90dSWyon Bi TOTAL_LINE_CFG_H(mode->vtotal >> 8));
11210b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_ACTIVE_LINE_CFG_L,
11220b8cf90dSWyon Bi ACTIVE_LINE_CFG_L(mode->vdisplay));
11230b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_ACTIVE_LINE_CFG_H,
11240b8cf90dSWyon Bi ACTIVE_LINE_CFG_H(mode->vdisplay >> 8));
11250b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_V_F_PORCH_CFG,
11260b8cf90dSWyon Bi V_F_PORCH_CFG(vfp));
11270b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_V_SYNC_WIDTH_CFG,
11280b8cf90dSWyon Bi V_SYNC_WIDTH_CFG(vsw));
11290b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_V_B_PORCH_CFG,
11300b8cf90dSWyon Bi V_B_PORCH_CFG(vbp));
11310b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_TOTAL_PIXEL_CFG_L,
11320b8cf90dSWyon Bi TOTAL_PIXEL_CFG_L(mode->htotal));
11330b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_TOTAL_PIXEL_CFG_H,
11340b8cf90dSWyon Bi TOTAL_PIXEL_CFG_H(mode->htotal >> 8));
11350b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_ACTIVE_PIXEL_CFG_L,
11360b8cf90dSWyon Bi ACTIVE_PIXEL_CFG_L(mode->hdisplay));
11370b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_ACTIVE_PIXEL_CFG_H,
11380b8cf90dSWyon Bi ACTIVE_PIXEL_CFG_H(mode->hdisplay >> 8));
11390b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_H_F_PORCH_CFG_L,
11400b8cf90dSWyon Bi H_F_PORCH_CFG_L(hfp));
11410b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_H_F_PORCH_CFG_H,
11420b8cf90dSWyon Bi H_F_PORCH_CFG_H(hfp >> 8));
11430b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_H_SYNC_CFG_L,
11440b8cf90dSWyon Bi H_SYNC_CFG_L(hsw));
11450b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_H_SYNC_CFG_H,
11460b8cf90dSWyon Bi H_SYNC_CFG_H(hsw >> 8));
11470b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_H_B_PORCH_CFG_L,
11480b8cf90dSWyon Bi H_B_PORCH_CFG_L(hbp));
11490b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_H_B_PORCH_CFG_H,
11500b8cf90dSWyon Bi H_B_PORCH_CFG_H(hbp >> 8));
11510b8cf90dSWyon Bi }
11520b8cf90dSWyon Bi
analogix_dp_video_bist_enable(struct analogix_dp_device * dp)11530b8cf90dSWyon Bi void analogix_dp_video_bist_enable(struct analogix_dp_device *dp)
11540b8cf90dSWyon Bi {
11550b8cf90dSWyon Bi u32 reg;
11560b8cf90dSWyon Bi
11570b8cf90dSWyon Bi /* Enable Video BIST */
11580b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_4, BIST_EN);
11590b8cf90dSWyon Bi
11600b8cf90dSWyon Bi /*
11610b8cf90dSWyon Bi * Note that if BIST_EN is set to 1, F_SEL must be cleared to 0
11620b8cf90dSWyon Bi * although video format information comes from registers set by user.
11630b8cf90dSWyon Bi */
11640b8cf90dSWyon Bi reg = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_10);
11650b8cf90dSWyon Bi reg &= ~FORMAT_SEL;
11660b8cf90dSWyon Bi analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_10, reg);
11670b8cf90dSWyon Bi }
116858df3976SDamon Ding
116958df3976SDamon Ding enum {
117058df3976SDamon Ding AUX_STATUS_OK,
117158df3976SDamon Ding AUX_STATUS_NACK_ERROR,
117258df3976SDamon Ding AUX_STATUS_TIMEOUT_ERROR,
117358df3976SDamon Ding AUX_STATUS_UNKNOWN_ERROR,
117458df3976SDamon Ding AUX_STATUS_MUCH_DEFER_ERROR,
117558df3976SDamon Ding AUX_STATUS_TX_SHORT_ERROR,
117658df3976SDamon Ding AUX_STATUS_RX_SHORT_ERROR,
117758df3976SDamon Ding AUX_STATUS_NACK_WITHOUT_M_ERROR,
117858df3976SDamon Ding AUX_STATUS_I2C_NACK_ERROR
117958df3976SDamon Ding };
118058df3976SDamon Ding
analogix_dp_aux_transfer(struct drm_dp_aux * aux,struct drm_dp_aux_msg * msg)118158df3976SDamon Ding ssize_t analogix_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
118258df3976SDamon Ding {
118358df3976SDamon Ding struct analogix_dp_device *dp = dev_get_priv(aux->dev);
118458df3976SDamon Ding u32 reg;
118558df3976SDamon Ding u8 *buffer = msg->buffer;
118658df3976SDamon Ding unsigned int i;
118758df3976SDamon Ding int num_transferred = 0;
118858df3976SDamon Ding int ret;
118958df3976SDamon Ding
119058df3976SDamon Ding /* Buffer size of AUX CH is 16 bytes */
119158df3976SDamon Ding if (WARN_ON(msg->size > 16))
119258df3976SDamon Ding return -E2BIG;
119358df3976SDamon Ding
119458df3976SDamon Ding /* Clear AUX CH data buffer */
119558df3976SDamon Ding reg = BUF_CLR;
119658df3976SDamon Ding analogix_dp_write(dp, ANALOGIX_DP_BUFFER_DATA_CTL, reg);
119758df3976SDamon Ding
119858df3976SDamon Ding switch (msg->request & ~DP_AUX_I2C_MOT) {
119958df3976SDamon Ding case DP_AUX_I2C_WRITE:
120058df3976SDamon Ding reg = AUX_TX_COMM_WRITE | AUX_TX_COMM_I2C_TRANSACTION;
120158df3976SDamon Ding if (msg->request & DP_AUX_I2C_MOT)
120258df3976SDamon Ding reg |= AUX_TX_COMM_MOT;
120358df3976SDamon Ding break;
120458df3976SDamon Ding
120558df3976SDamon Ding case DP_AUX_I2C_READ:
120658df3976SDamon Ding reg = AUX_TX_COMM_READ | AUX_TX_COMM_I2C_TRANSACTION;
120758df3976SDamon Ding if (msg->request & DP_AUX_I2C_MOT)
120858df3976SDamon Ding reg |= AUX_TX_COMM_MOT;
120958df3976SDamon Ding break;
121058df3976SDamon Ding
121158df3976SDamon Ding case DP_AUX_NATIVE_WRITE:
121258df3976SDamon Ding reg = AUX_TX_COMM_WRITE | AUX_TX_COMM_DP_TRANSACTION;
121358df3976SDamon Ding break;
121458df3976SDamon Ding
121558df3976SDamon Ding case DP_AUX_NATIVE_READ:
121658df3976SDamon Ding reg = AUX_TX_COMM_READ | AUX_TX_COMM_DP_TRANSACTION;
121758df3976SDamon Ding break;
121858df3976SDamon Ding
121958df3976SDamon Ding default:
122058df3976SDamon Ding return -EINVAL;
122158df3976SDamon Ding }
122258df3976SDamon Ding
122358df3976SDamon Ding reg |= AUX_LENGTH(msg->size);
122458df3976SDamon Ding analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_1, reg);
122558df3976SDamon Ding
122658df3976SDamon Ding /* Select DPCD device address */
122758df3976SDamon Ding reg = AUX_ADDR_7_0(msg->address);
122858df3976SDamon Ding analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_7_0, reg);
122958df3976SDamon Ding reg = AUX_ADDR_15_8(msg->address);
123058df3976SDamon Ding analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_15_8, reg);
123158df3976SDamon Ding reg = AUX_ADDR_19_16(msg->address);
123258df3976SDamon Ding analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_19_16, reg);
123358df3976SDamon Ding
123458df3976SDamon Ding if (!(msg->request & DP_AUX_I2C_READ)) {
123558df3976SDamon Ding for (i = 0; i < msg->size; i++) {
123658df3976SDamon Ding reg = buffer[i];
123758df3976SDamon Ding analogix_dp_write(dp, ANALOGIX_DP_BUF_DATA_0 + 4 * i,
123858df3976SDamon Ding reg);
123958df3976SDamon Ding num_transferred++;
124058df3976SDamon Ding }
124158df3976SDamon Ding }
124258df3976SDamon Ding
124358df3976SDamon Ding /* Enable AUX CH operation */
124458df3976SDamon Ding reg = AUX_EN;
124558df3976SDamon Ding
124658df3976SDamon Ding /* Zero-sized messages specify address-only transactions. */
124758df3976SDamon Ding if (msg->size < 1)
124858df3976SDamon Ding reg |= ADDR_ONLY;
124958df3976SDamon Ding
125058df3976SDamon Ding analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_2, reg);
125158df3976SDamon Ding
125258df3976SDamon Ding ret = readx_poll_timeout(readl, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2,
125358df3976SDamon Ding reg, !(reg & AUX_EN), 500 * 1000);
125458df3976SDamon Ding if (ret) {
125558df3976SDamon Ding dev_err(dp->dev, "AUX CH enable timeout!\n");
125658df3976SDamon Ding goto aux_error;
125758df3976SDamon Ding }
125858df3976SDamon Ding
125958df3976SDamon Ding /* TODO: Wait for an interrupt instead of looping? */
126058df3976SDamon Ding /* Is AUX CH command reply received? */
126158df3976SDamon Ding ret = readx_poll_timeout(readl, dp->reg_base + ANALOGIX_DP_INT_STA,
126258df3976SDamon Ding reg, reg & RPLY_RECEIV, 20 * 1000);
126358df3976SDamon Ding if (ret) {
126458df3976SDamon Ding dev_err(dp->dev, "AUX CH cmd reply timeout!\n");
126558df3976SDamon Ding goto aux_error;
126658df3976SDamon Ding }
126758df3976SDamon Ding
126858df3976SDamon Ding /* Clear interrupt source for AUX CH command reply */
126958df3976SDamon Ding analogix_dp_write(dp, ANALOGIX_DP_INT_STA, RPLY_RECEIV);
127058df3976SDamon Ding
127158df3976SDamon Ding reg = analogix_dp_read(dp, ANALOGIX_DP_AUX_CH_STA);
127258df3976SDamon Ding if ((reg & AUX_STATUS_MASK) == AUX_STATUS_TIMEOUT_ERROR)
127358df3976SDamon Ding return -ETIMEDOUT;
127458df3976SDamon Ding
127558df3976SDamon Ding if (msg->request & DP_AUX_I2C_READ) {
127658df3976SDamon Ding size_t buf_data_count;
127758df3976SDamon Ding
127858df3976SDamon Ding reg = analogix_dp_read(dp, ANALOGIX_DP_BUFFER_DATA_CTL);
127958df3976SDamon Ding buf_data_count = BUF_DATA_COUNT(reg);
128058df3976SDamon Ding
128158df3976SDamon Ding if (buf_data_count != msg->size)
128258df3976SDamon Ding return -EBUSY;
128358df3976SDamon Ding
128458df3976SDamon Ding for (i = 0; i < msg->size; i++) {
128558df3976SDamon Ding reg = analogix_dp_read(dp, ANALOGIX_DP_BUF_DATA_0 +
128658df3976SDamon Ding 4 * i);
128758df3976SDamon Ding buffer[i] = (unsigned char)reg;
128858df3976SDamon Ding num_transferred++;
128958df3976SDamon Ding }
129058df3976SDamon Ding }
129158df3976SDamon Ding
129258df3976SDamon Ding /* Check if Rx sends defer */
129358df3976SDamon Ding reg = analogix_dp_read(dp, ANALOGIX_DP_AUX_RX_COMM);
129458df3976SDamon Ding if (reg == AUX_RX_COMM_AUX_DEFER)
129558df3976SDamon Ding msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
129658df3976SDamon Ding else if (reg == AUX_RX_COMM_I2C_DEFER)
129758df3976SDamon Ding msg->reply = DP_AUX_I2C_REPLY_DEFER;
129858df3976SDamon Ding else if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_WRITE ||
129958df3976SDamon Ding (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_READ)
130058df3976SDamon Ding msg->reply = DP_AUX_I2C_REPLY_ACK;
130158df3976SDamon Ding else if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_WRITE ||
130258df3976SDamon Ding (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ)
130358df3976SDamon Ding msg->reply = DP_AUX_NATIVE_REPLY_ACK;
130458df3976SDamon Ding
130558df3976SDamon Ding return (num_transferred == msg->size) ? num_transferred : -EBUSY;
130658df3976SDamon Ding
130758df3976SDamon Ding aux_error:
130858df3976SDamon Ding /* if aux err happen, reset aux */
130958df3976SDamon Ding analogix_dp_init_aux(dp);
131058df3976SDamon Ding
131158df3976SDamon Ding return -EREMOTEIO;
131258df3976SDamon Ding }
1313*fc275078SDamon Ding
analogix_dp_enable_assr_mode(struct analogix_dp_device * dp,bool enable)1314*fc275078SDamon Ding void analogix_dp_enable_assr_mode(struct analogix_dp_device *dp, bool enable)
1315*fc275078SDamon Ding {
1316*fc275078SDamon Ding u32 reg;
1317*fc275078SDamon Ding
1318*fc275078SDamon Ding if (enable) {
1319*fc275078SDamon Ding reg = analogix_dp_read(dp, ANALOGIX_DP_LINK_POLICY);
1320*fc275078SDamon Ding reg |= ALTERNATE_SR_ENABLE;
1321*fc275078SDamon Ding analogix_dp_write(dp, ANALOGIX_DP_LINK_POLICY, reg);
1322*fc275078SDamon Ding } else {
1323*fc275078SDamon Ding reg = analogix_dp_read(dp, ANALOGIX_DP_LINK_POLICY);
1324*fc275078SDamon Ding reg &= ~ALTERNATE_SR_ENABLE;
1325*fc275078SDamon Ding analogix_dp_write(dp, ANALOGIX_DP_LINK_POLICY, reg);
1326*fc275078SDamon Ding }
1327*fc275078SDamon Ding }
1328*fc275078SDamon Ding
analogix_dp_get_assr_mode(struct analogix_dp_device * dp)1329*fc275078SDamon Ding bool analogix_dp_get_assr_mode(struct analogix_dp_device *dp)
1330*fc275078SDamon Ding {
1331*fc275078SDamon Ding u32 reg;
1332*fc275078SDamon Ding
1333*fc275078SDamon Ding reg = analogix_dp_read(dp, ANALOGIX_DP_LINK_POLICY);
1334*fc275078SDamon Ding
1335*fc275078SDamon Ding return !!(reg & ALTERNATE_SR_ENABLE);
1336*fc275078SDamon Ding }
1337