]>
Commit | Line | Data |
---|---|---|
e9474be4 | 1 | /* |
3424e3a4 | 2 | * Analogix DP (Display port) core register interface driver. |
e9474be4 JH |
3 | * |
4 | * Copyright (C) 2012 Samsung Electronics Co., Ltd. | |
5 | * Author: Jingoo Han <jg1.han@samsung.com> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2 of the License, or (at your | |
10 | * option) any later version. | |
11 | */ | |
12 | ||
13 | #include <linux/device.h> | |
14 | #include <linux/io.h> | |
15 | #include <linux/delay.h> | |
b8b52471 | 16 | #include <linux/gpio.h> |
e9474be4 | 17 | |
bcec20fd YY |
18 | #include <drm/bridge/analogix_dp.h> |
19 | ||
3424e3a4 YY |
20 | #include "analogix_dp_core.h" |
21 | #include "analogix_dp_reg.h" | |
e9474be4 | 22 | |
c30ffb90 SP |
23 | #define COMMON_INT_MASK_1 0 |
24 | #define COMMON_INT_MASK_2 0 | |
25 | #define COMMON_INT_MASK_3 0 | |
26 | #define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG) | |
27 | #define INT_STA_MASK INT_HPD | |
e9474be4 | 28 | |
3424e3a4 | 29 | void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable) |
e9474be4 JH |
30 | { |
31 | u32 reg; | |
32 | ||
33 | if (enable) { | |
092f8994 | 34 | reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); |
e9474be4 | 35 | reg |= HDCP_VIDEO_MUTE; |
092f8994 | 36 | writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); |
e9474be4 | 37 | } else { |
092f8994 | 38 | reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); |
e9474be4 | 39 | reg &= ~HDCP_VIDEO_MUTE; |
092f8994 | 40 | writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); |
e9474be4 JH |
41 | } |
42 | } | |
43 | ||
3424e3a4 | 44 | void analogix_dp_stop_video(struct analogix_dp_device *dp) |
e9474be4 JH |
45 | { |
46 | u32 reg; | |
47 | ||
092f8994 | 48 | reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); |
e9474be4 | 49 | reg &= ~VIDEO_EN; |
092f8994 | 50 | writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); |
e9474be4 JH |
51 | } |
52 | ||
3424e3a4 | 53 | void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable) |
e9474be4 JH |
54 | { |
55 | u32 reg; | |
56 | ||
57 | if (enable) | |
58 | reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 | | |
bcbb7033 | 59 | LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3; |
e9474be4 JH |
60 | else |
61 | reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 | | |
bcbb7033 | 62 | LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0; |
e9474be4 | 63 | |
092f8994 | 64 | writel(reg, dp->reg_base + ANALOGIX_DP_LANE_MAP); |
e9474be4 JH |
65 | } |
66 | ||
3424e3a4 | 67 | void analogix_dp_init_analog_param(struct analogix_dp_device *dp) |
8affaf5c JH |
68 | { |
69 | u32 reg; | |
70 | ||
71 | reg = TX_TERMINAL_CTRL_50_OHM; | |
092f8994 | 72 | writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_1); |
8affaf5c JH |
73 | |
74 | reg = SEL_24M | TX_DVDD_BIT_1_0625V; | |
092f8994 | 75 | writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_2); |
8affaf5c | 76 | |
bcec20fd YY |
77 | if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP)) { |
78 | writel(REF_CLK_24M, dp->reg_base + ANALOGIX_DP_PLL_REG_1); | |
79 | writel(0x95, dp->reg_base + ANALOGIX_DP_PLL_REG_2); | |
80 | writel(0x40, dp->reg_base + ANALOGIX_DP_PLL_REG_3); | |
81 | writel(0x58, dp->reg_base + ANALOGIX_DP_PLL_REG_4); | |
82 | writel(0x22, dp->reg_base + ANALOGIX_DP_PLL_REG_5); | |
83 | } | |
84 | ||
8affaf5c | 85 | reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO; |
092f8994 | 86 | writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_3); |
8affaf5c JH |
87 | |
88 | reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM | | |
5fdc62ca | 89 | TX_CUR1_2X | TX_CUR_16_MA; |
092f8994 | 90 | writel(reg, dp->reg_base + ANALOGIX_DP_PLL_FILTER_CTL_1); |
8affaf5c JH |
91 | |
92 | reg = CH3_AMP_400_MV | CH2_AMP_400_MV | | |
93 | CH1_AMP_400_MV | CH0_AMP_400_MV; | |
092f8994 | 94 | writel(reg, dp->reg_base + ANALOGIX_DP_TX_AMP_TUNING_CTL); |
8affaf5c JH |
95 | } |
96 | ||
3424e3a4 | 97 | void analogix_dp_init_interrupt(struct analogix_dp_device *dp) |
e9474be4 JH |
98 | { |
99 | /* Set interrupt pin assertion polarity as high */ | |
092f8994 | 100 | writel(INT_POL1 | INT_POL0, dp->reg_base + ANALOGIX_DP_INT_CTL); |
e9474be4 JH |
101 | |
102 | /* Clear pending regisers */ | |
092f8994 HS |
103 | writel(0xff, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1); |
104 | writel(0x4f, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_2); | |
105 | writel(0xe0, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_3); | |
106 | writel(0xe7, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4); | |
107 | writel(0x63, dp->reg_base + ANALOGIX_DP_INT_STA); | |
e9474be4 JH |
108 | |
109 | /* 0:mask,1: unmask */ | |
092f8994 HS |
110 | writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1); |
111 | writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2); | |
112 | writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3); | |
113 | writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4); | |
114 | writel(0x00, dp->reg_base + ANALOGIX_DP_INT_STA_MASK); | |
e9474be4 JH |
115 | } |
116 | ||
3424e3a4 | 117 | void analogix_dp_reset(struct analogix_dp_device *dp) |
e9474be4 JH |
118 | { |
119 | u32 reg; | |
120 | ||
3424e3a4 YY |
121 | analogix_dp_stop_video(dp); |
122 | analogix_dp_enable_video_mute(dp, 0); | |
e9474be4 JH |
123 | |
124 | reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N | | |
125 | AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N | | |
126 | HDCP_FUNC_EN_N | SW_FUNC_EN_N; | |
092f8994 | 127 | writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1); |
e9474be4 JH |
128 | |
129 | reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N | | |
130 | SERDES_FIFO_FUNC_EN_N | | |
131 | LS_CLK_DOMAIN_FUNC_EN_N; | |
092f8994 | 132 | writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); |
e9474be4 | 133 | |
a2c81bc1 | 134 | usleep_range(20, 30); |
e9474be4 | 135 | |
3424e3a4 | 136 | analogix_dp_lane_swap(dp, 0); |
e9474be4 | 137 | |
092f8994 HS |
138 | writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_1); |
139 | writel(0x40, dp->reg_base + ANALOGIX_DP_SYS_CTL_2); | |
140 | writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); | |
141 | writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); | |
e9474be4 | 142 | |
092f8994 HS |
143 | writel(0x0, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); |
144 | writel(0x0, dp->reg_base + ANALOGIX_DP_HDCP_CTL); | |
e9474be4 | 145 | |
092f8994 HS |
146 | writel(0x5e, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_L); |
147 | writel(0x1a, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_H); | |
e9474be4 | 148 | |
092f8994 | 149 | writel(0x10, dp->reg_base + ANALOGIX_DP_LINK_DEBUG_CTL); |
e9474be4 | 150 | |
092f8994 | 151 | writel(0x0, dp->reg_base + ANALOGIX_DP_PHY_TEST); |
e9474be4 | 152 | |
092f8994 HS |
153 | writel(0x0, dp->reg_base + ANALOGIX_DP_VIDEO_FIFO_THRD); |
154 | writel(0x20, dp->reg_base + ANALOGIX_DP_AUDIO_MARGIN); | |
e9474be4 | 155 | |
092f8994 HS |
156 | writel(0x4, dp->reg_base + ANALOGIX_DP_M_VID_GEN_FILTER_TH); |
157 | writel(0x2, dp->reg_base + ANALOGIX_DP_M_AUD_GEN_FILTER_TH); | |
e9474be4 | 158 | |
092f8994 | 159 | writel(0x00000101, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); |
e9474be4 JH |
160 | } |
161 | ||
3424e3a4 | 162 | void analogix_dp_swreset(struct analogix_dp_device *dp) |
24db03a8 | 163 | { |
092f8994 | 164 | writel(RESET_DP_TX, dp->reg_base + ANALOGIX_DP_TX_SW_RESET); |
24db03a8 JH |
165 | } |
166 | ||
3424e3a4 | 167 | void analogix_dp_config_interrupt(struct analogix_dp_device *dp) |
e9474be4 JH |
168 | { |
169 | u32 reg; | |
170 | ||
171 | /* 0: mask, 1: unmask */ | |
172 | reg = COMMON_INT_MASK_1; | |
092f8994 | 173 | writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1); |
e9474be4 JH |
174 | |
175 | reg = COMMON_INT_MASK_2; | |
092f8994 | 176 | writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2); |
e9474be4 JH |
177 | |
178 | reg = COMMON_INT_MASK_3; | |
092f8994 | 179 | writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3); |
e9474be4 JH |
180 | |
181 | reg = COMMON_INT_MASK_4; | |
092f8994 | 182 | writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4); |
e9474be4 JH |
183 | |
184 | reg = INT_STA_MASK; | |
092f8994 | 185 | writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK); |
e9474be4 JH |
186 | } |
187 | ||
3424e3a4 | 188 | enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp) |
e9474be4 JH |
189 | { |
190 | u32 reg; | |
191 | ||
092f8994 | 192 | reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL); |
e9474be4 JH |
193 | if (reg & PLL_LOCK) |
194 | return PLL_LOCKED; | |
195 | else | |
196 | return PLL_UNLOCKED; | |
197 | } | |
198 | ||
3424e3a4 | 199 | void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable) |
e9474be4 JH |
200 | { |
201 | u32 reg; | |
202 | ||
203 | if (enable) { | |
092f8994 | 204 | reg = readl(dp->reg_base + ANALOGIX_DP_PLL_CTL); |
e9474be4 | 205 | reg |= DP_PLL_PD; |
092f8994 | 206 | writel(reg, dp->reg_base + ANALOGIX_DP_PLL_CTL); |
e9474be4 | 207 | } else { |
092f8994 | 208 | reg = readl(dp->reg_base + ANALOGIX_DP_PLL_CTL); |
e9474be4 | 209 | reg &= ~DP_PLL_PD; |
092f8994 | 210 | writel(reg, dp->reg_base + ANALOGIX_DP_PLL_CTL); |
e9474be4 JH |
211 | } |
212 | } | |
213 | ||
3424e3a4 | 214 | void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, |
bcbb7033 YY |
215 | enum analog_power_block block, |
216 | bool enable) | |
e9474be4 JH |
217 | { |
218 | u32 reg; | |
bcec20fd YY |
219 | u32 phy_pd_addr = ANALOGIX_DP_PHY_PD; |
220 | ||
221 | if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP)) | |
222 | phy_pd_addr = ANALOGIX_DP_PD; | |
e9474be4 JH |
223 | |
224 | switch (block) { | |
225 | case AUX_BLOCK: | |
226 | if (enable) { | |
bcec20fd | 227 | reg = readl(dp->reg_base + phy_pd_addr); |
e9474be4 | 228 | reg |= AUX_PD; |
bcec20fd | 229 | writel(reg, dp->reg_base + phy_pd_addr); |
e9474be4 | 230 | } else { |
bcec20fd | 231 | reg = readl(dp->reg_base + phy_pd_addr); |
e9474be4 | 232 | reg &= ~AUX_PD; |
bcec20fd | 233 | writel(reg, dp->reg_base + phy_pd_addr); |
e9474be4 JH |
234 | } |
235 | break; | |
236 | case CH0_BLOCK: | |
237 | if (enable) { | |
bcec20fd | 238 | reg = readl(dp->reg_base + phy_pd_addr); |
e9474be4 | 239 | reg |= CH0_PD; |
bcec20fd | 240 | writel(reg, dp->reg_base + phy_pd_addr); |
e9474be4 | 241 | } else { |
bcec20fd | 242 | reg = readl(dp->reg_base + phy_pd_addr); |
e9474be4 | 243 | reg &= ~CH0_PD; |
bcec20fd | 244 | writel(reg, dp->reg_base + phy_pd_addr); |
e9474be4 JH |
245 | } |
246 | break; | |
247 | case CH1_BLOCK: | |
248 | if (enable) { | |
bcec20fd | 249 | reg = readl(dp->reg_base + phy_pd_addr); |
e9474be4 | 250 | reg |= CH1_PD; |
bcec20fd | 251 | writel(reg, dp->reg_base + phy_pd_addr); |
e9474be4 | 252 | } else { |
bcec20fd | 253 | reg = readl(dp->reg_base + phy_pd_addr); |
e9474be4 | 254 | reg &= ~CH1_PD; |
bcec20fd | 255 | writel(reg, dp->reg_base + phy_pd_addr); |
e9474be4 JH |
256 | } |
257 | break; | |
258 | case CH2_BLOCK: | |
259 | if (enable) { | |
bcec20fd | 260 | reg = readl(dp->reg_base + phy_pd_addr); |
e9474be4 | 261 | reg |= CH2_PD; |
bcec20fd | 262 | writel(reg, dp->reg_base + phy_pd_addr); |
e9474be4 | 263 | } else { |
bcec20fd | 264 | reg = readl(dp->reg_base + phy_pd_addr); |
e9474be4 | 265 | reg &= ~CH2_PD; |
bcec20fd | 266 | writel(reg, dp->reg_base + phy_pd_addr); |
e9474be4 JH |
267 | } |
268 | break; | |
269 | case CH3_BLOCK: | |
270 | if (enable) { | |
bcec20fd | 271 | reg = readl(dp->reg_base + phy_pd_addr); |
e9474be4 | 272 | reg |= CH3_PD; |
bcec20fd | 273 | writel(reg, dp->reg_base + phy_pd_addr); |
e9474be4 | 274 | } else { |
bcec20fd | 275 | reg = readl(dp->reg_base + phy_pd_addr); |
e9474be4 | 276 | reg &= ~CH3_PD; |
bcec20fd | 277 | writel(reg, dp->reg_base + phy_pd_addr); |
e9474be4 JH |
278 | } |
279 | break; | |
280 | case ANALOG_TOTAL: | |
281 | if (enable) { | |
bcec20fd | 282 | reg = readl(dp->reg_base + phy_pd_addr); |
e9474be4 | 283 | reg |= DP_PHY_PD; |
bcec20fd | 284 | writel(reg, dp->reg_base + phy_pd_addr); |
e9474be4 | 285 | } else { |
bcec20fd | 286 | reg = readl(dp->reg_base + phy_pd_addr); |
e9474be4 | 287 | reg &= ~DP_PHY_PD; |
bcec20fd | 288 | writel(reg, dp->reg_base + phy_pd_addr); |
e9474be4 JH |
289 | } |
290 | break; | |
291 | case POWER_ALL: | |
292 | if (enable) { | |
293 | reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD | | |
294 | CH1_PD | CH0_PD; | |
bcec20fd | 295 | writel(reg, dp->reg_base + phy_pd_addr); |
e9474be4 | 296 | } else { |
bcec20fd | 297 | writel(0x00, dp->reg_base + phy_pd_addr); |
e9474be4 JH |
298 | } |
299 | break; | |
300 | default: | |
301 | break; | |
302 | } | |
303 | } | |
304 | ||
3424e3a4 | 305 | void analogix_dp_init_analog_func(struct analogix_dp_device *dp) |
e9474be4 JH |
306 | { |
307 | u32 reg; | |
b5cfeed6 | 308 | int timeout_loop = 0; |
e9474be4 | 309 | |
3424e3a4 | 310 | analogix_dp_set_analog_power_down(dp, POWER_ALL, 0); |
e9474be4 JH |
311 | |
312 | reg = PLL_LOCK_CHG; | |
092f8994 | 313 | writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1); |
e9474be4 | 314 | |
092f8994 | 315 | reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL); |
e9474be4 | 316 | reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL); |
092f8994 | 317 | writel(reg, dp->reg_base + ANALOGIX_DP_DEBUG_CTL); |
e9474be4 JH |
318 | |
319 | /* Power up PLL */ | |
3424e3a4 YY |
320 | if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { |
321 | analogix_dp_set_pll_power_down(dp, 0); | |
e9474be4 | 322 | |
3424e3a4 | 323 | while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { |
b5cfeed6 JH |
324 | timeout_loop++; |
325 | if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { | |
326 | dev_err(dp->dev, "failed to get pll lock status\n"); | |
327 | return; | |
328 | } | |
329 | usleep_range(10, 20); | |
330 | } | |
331 | } | |
332 | ||
e9474be4 | 333 | /* Enable Serdes FIFO function and Link symbol clock domain module */ |
092f8994 | 334 | reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); |
e9474be4 JH |
335 | reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N |
336 | | AUX_FUNC_EN_N); | |
092f8994 | 337 | writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); |
e9474be4 JH |
338 | } |
339 | ||
3424e3a4 | 340 | void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp) |
e9474be4 JH |
341 | { |
342 | u32 reg; | |
343 | ||
b8b52471 AB |
344 | if (gpio_is_valid(dp->hpd_gpio)) |
345 | return; | |
346 | ||
e9474be4 | 347 | reg = HOTPLUG_CHG | HPD_LOST | PLUG; |
092f8994 | 348 | writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4); |
e9474be4 JH |
349 | |
350 | reg = INT_HPD; | |
092f8994 | 351 | writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA); |
c30ffb90 SP |
352 | } |
353 | ||
3424e3a4 | 354 | void analogix_dp_init_hpd(struct analogix_dp_device *dp) |
c30ffb90 SP |
355 | { |
356 | u32 reg; | |
357 | ||
b8b52471 AB |
358 | if (gpio_is_valid(dp->hpd_gpio)) |
359 | return; | |
360 | ||
3424e3a4 | 361 | analogix_dp_clear_hotplug_interrupts(dp); |
e9474be4 | 362 | |
092f8994 | 363 | reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); |
e9474be4 | 364 | reg &= ~(F_HPD | HPD_CTRL); |
092f8994 | 365 | writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); |
e9474be4 JH |
366 | } |
367 | ||
3424e3a4 | 368 | enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp) |
c30ffb90 SP |
369 | { |
370 | u32 reg; | |
371 | ||
b8b52471 AB |
372 | if (gpio_is_valid(dp->hpd_gpio)) { |
373 | reg = gpio_get_value(dp->hpd_gpio); | |
374 | if (reg) | |
375 | return DP_IRQ_TYPE_HP_CABLE_IN; | |
376 | else | |
377 | return DP_IRQ_TYPE_HP_CABLE_OUT; | |
378 | } else { | |
379 | /* Parse hotplug interrupt status register */ | |
092f8994 | 380 | reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4); |
c30ffb90 | 381 | |
b8b52471 AB |
382 | if (reg & PLUG) |
383 | return DP_IRQ_TYPE_HP_CABLE_IN; | |
c30ffb90 | 384 | |
b8b52471 AB |
385 | if (reg & HPD_LOST) |
386 | return DP_IRQ_TYPE_HP_CABLE_OUT; | |
c30ffb90 | 387 | |
b8b52471 AB |
388 | if (reg & HOTPLUG_CHG) |
389 | return DP_IRQ_TYPE_HP_CHANGE; | |
c30ffb90 | 390 | |
b8b52471 AB |
391 | return DP_IRQ_TYPE_UNKNOWN; |
392 | } | |
c30ffb90 SP |
393 | } |
394 | ||
3424e3a4 | 395 | void analogix_dp_reset_aux(struct analogix_dp_device *dp) |
e9474be4 JH |
396 | { |
397 | u32 reg; | |
398 | ||
399 | /* Disable AUX channel module */ | |
092f8994 | 400 | reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); |
e9474be4 | 401 | reg |= AUX_FUNC_EN_N; |
092f8994 | 402 | writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); |
e9474be4 JH |
403 | } |
404 | ||
3424e3a4 | 405 | void analogix_dp_init_aux(struct analogix_dp_device *dp) |
e9474be4 JH |
406 | { |
407 | u32 reg; | |
408 | ||
409 | /* Clear inerrupts related to AUX channel */ | |
410 | reg = RPLY_RECEIV | AUX_ERR; | |
092f8994 | 411 | writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA); |
e9474be4 | 412 | |
3424e3a4 | 413 | analogix_dp_reset_aux(dp); |
e9474be4 JH |
414 | |
415 | /* Disable AUX transaction H/W retry */ | |
bcec20fd YY |
416 | if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP)) |
417 | reg = AUX_BIT_PERIOD_EXPECTED_DELAY(0) | | |
418 | AUX_HW_RETRY_COUNT_SEL(3) | | |
419 | AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; | |
420 | else | |
421 | reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | | |
422 | AUX_HW_RETRY_COUNT_SEL(0) | | |
423 | AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; | |
092f8994 | 424 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_HW_RETRY_CTL); |
e9474be4 JH |
425 | |
426 | /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */ | |
427 | reg = DEFER_CTRL_EN | DEFER_COUNT(1); | |
092f8994 | 428 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_DEFER_CTL); |
e9474be4 JH |
429 | |
430 | /* Enable AUX channel module */ | |
092f8994 | 431 | reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); |
e9474be4 | 432 | reg &= ~AUX_FUNC_EN_N; |
092f8994 | 433 | writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); |
e9474be4 JH |
434 | } |
435 | ||
3424e3a4 | 436 | int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp) |
e9474be4 JH |
437 | { |
438 | u32 reg; | |
439 | ||
b8b52471 AB |
440 | if (gpio_is_valid(dp->hpd_gpio)) { |
441 | if (gpio_get_value(dp->hpd_gpio)) | |
442 | return 0; | |
443 | } else { | |
092f8994 | 444 | reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); |
b8b52471 AB |
445 | if (reg & HPD_STATUS) |
446 | return 0; | |
447 | } | |
e9474be4 JH |
448 | |
449 | return -EINVAL; | |
450 | } | |
451 | ||
3424e3a4 | 452 | void analogix_dp_enable_sw_function(struct analogix_dp_device *dp) |
e9474be4 JH |
453 | { |
454 | u32 reg; | |
455 | ||
092f8994 | 456 | reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1); |
e9474be4 | 457 | reg &= ~SW_FUNC_EN_N; |
092f8994 | 458 | writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1); |
e9474be4 JH |
459 | } |
460 | ||
3424e3a4 | 461 | int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp) |
e9474be4 JH |
462 | { |
463 | int reg; | |
464 | int retval = 0; | |
bada5537 | 465 | int timeout_loop = 0; |
e9474be4 JH |
466 | |
467 | /* Enable AUX CH operation */ | |
092f8994 | 468 | reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); |
e9474be4 | 469 | reg |= AUX_EN; |
092f8994 | 470 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); |
e9474be4 JH |
471 | |
472 | /* Is AUX CH command reply received? */ | |
092f8994 | 473 | reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA); |
bada5537 JH |
474 | while (!(reg & RPLY_RECEIV)) { |
475 | timeout_loop++; | |
476 | if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { | |
477 | dev_err(dp->dev, "AUX CH command reply failed!\n"); | |
478 | return -ETIMEDOUT; | |
479 | } | |
092f8994 | 480 | reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA); |
bada5537 JH |
481 | usleep_range(10, 11); |
482 | } | |
e9474be4 JH |
483 | |
484 | /* Clear interrupt source for AUX CH command reply */ | |
092f8994 | 485 | writel(RPLY_RECEIV, dp->reg_base + ANALOGIX_DP_INT_STA); |
e9474be4 JH |
486 | |
487 | /* Clear interrupt source for AUX CH access error */ | |
092f8994 | 488 | reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA); |
e9474be4 | 489 | if (reg & AUX_ERR) { |
092f8994 | 490 | writel(AUX_ERR, dp->reg_base + ANALOGIX_DP_INT_STA); |
e9474be4 JH |
491 | return -EREMOTEIO; |
492 | } | |
493 | ||
494 | /* Check AUX CH error access status */ | |
092f8994 | 495 | reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA); |
e9474be4 JH |
496 | if ((reg & AUX_STATUS_MASK) != 0) { |
497 | dev_err(dp->dev, "AUX CH error happens: %d\n\n", | |
498 | reg & AUX_STATUS_MASK); | |
499 | return -EREMOTEIO; | |
500 | } | |
501 | ||
502 | return retval; | |
503 | } | |
504 | ||
3424e3a4 | 505 | int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp, |
bcbb7033 YY |
506 | unsigned int reg_addr, |
507 | unsigned char data) | |
e9474be4 JH |
508 | { |
509 | u32 reg; | |
510 | int i; | |
511 | int retval; | |
512 | ||
513 | for (i = 0; i < 3; i++) { | |
514 | /* Clear AUX CH data buffer */ | |
515 | reg = BUF_CLR; | |
092f8994 | 516 | writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); |
e9474be4 JH |
517 | |
518 | /* Select DPCD device address */ | |
519 | reg = AUX_ADDR_7_0(reg_addr); | |
092f8994 | 520 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); |
e9474be4 | 521 | reg = AUX_ADDR_15_8(reg_addr); |
092f8994 | 522 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); |
e9474be4 | 523 | reg = AUX_ADDR_19_16(reg_addr); |
092f8994 | 524 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16); |
e9474be4 JH |
525 | |
526 | /* Write data buffer */ | |
527 | reg = (unsigned int)data; | |
092f8994 | 528 | writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0); |
e9474be4 JH |
529 | |
530 | /* | |
531 | * Set DisplayPort transaction and write 1 byte | |
532 | * If bit 3 is 1, DisplayPort transaction. | |
533 | * If Bit 3 is 0, I2C transaction. | |
534 | */ | |
535 | reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE; | |
092f8994 | 536 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); |
e9474be4 JH |
537 | |
538 | /* Start AUX transaction */ | |
3424e3a4 | 539 | retval = analogix_dp_start_aux_transaction(dp); |
e9474be4 JH |
540 | if (retval == 0) |
541 | break; | |
bcbb7033 YY |
542 | |
543 | dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); | |
e9474be4 JH |
544 | } |
545 | ||
546 | return retval; | |
547 | } | |
548 | ||
3424e3a4 | 549 | int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp, |
bcbb7033 YY |
550 | unsigned int reg_addr, |
551 | unsigned char *data) | |
e9474be4 JH |
552 | { |
553 | u32 reg; | |
554 | int i; | |
555 | int retval; | |
556 | ||
99f54152 | 557 | for (i = 0; i < 3; i++) { |
e9474be4 JH |
558 | /* Clear AUX CH data buffer */ |
559 | reg = BUF_CLR; | |
092f8994 | 560 | writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); |
e9474be4 JH |
561 | |
562 | /* Select DPCD device address */ | |
563 | reg = AUX_ADDR_7_0(reg_addr); | |
092f8994 | 564 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); |
e9474be4 | 565 | reg = AUX_ADDR_15_8(reg_addr); |
092f8994 | 566 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); |
e9474be4 | 567 | reg = AUX_ADDR_19_16(reg_addr); |
092f8994 | 568 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16); |
e9474be4 JH |
569 | |
570 | /* | |
571 | * Set DisplayPort transaction and read 1 byte | |
572 | * If bit 3 is 1, DisplayPort transaction. | |
573 | * If Bit 3 is 0, I2C transaction. | |
574 | */ | |
575 | reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ; | |
092f8994 | 576 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); |
e9474be4 JH |
577 | |
578 | /* Start AUX transaction */ | |
3424e3a4 | 579 | retval = analogix_dp_start_aux_transaction(dp); |
e9474be4 JH |
580 | if (retval == 0) |
581 | break; | |
bcbb7033 YY |
582 | |
583 | dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); | |
e9474be4 JH |
584 | } |
585 | ||
586 | /* Read data buffer */ | |
092f8994 | 587 | reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0); |
e9474be4 JH |
588 | *data = (unsigned char)(reg & 0xff); |
589 | ||
590 | return retval; | |
591 | } | |
592 | ||
3424e3a4 | 593 | int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp, |
bcbb7033 YY |
594 | unsigned int reg_addr, |
595 | unsigned int count, | |
596 | unsigned char data[]) | |
e9474be4 JH |
597 | { |
598 | u32 reg; | |
599 | unsigned int start_offset; | |
600 | unsigned int cur_data_count; | |
601 | unsigned int cur_data_idx; | |
602 | int i; | |
603 | int retval = 0; | |
604 | ||
605 | /* Clear AUX CH data buffer */ | |
606 | reg = BUF_CLR; | |
092f8994 | 607 | writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); |
e9474be4 JH |
608 | |
609 | start_offset = 0; | |
610 | while (start_offset < count) { | |
611 | /* Buffer size of AUX CH is 16 * 4bytes */ | |
612 | if ((count - start_offset) > 16) | |
613 | cur_data_count = 16; | |
614 | else | |
615 | cur_data_count = count - start_offset; | |
616 | ||
99f54152 | 617 | for (i = 0; i < 3; i++) { |
e9474be4 JH |
618 | /* Select DPCD device address */ |
619 | reg = AUX_ADDR_7_0(reg_addr + start_offset); | |
092f8994 | 620 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); |
e9474be4 | 621 | reg = AUX_ADDR_15_8(reg_addr + start_offset); |
092f8994 | 622 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); |
e9474be4 | 623 | reg = AUX_ADDR_19_16(reg_addr + start_offset); |
092f8994 | 624 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16); |
e9474be4 JH |
625 | |
626 | for (cur_data_idx = 0; cur_data_idx < cur_data_count; | |
627 | cur_data_idx++) { | |
628 | reg = data[start_offset + cur_data_idx]; | |
bcbb7033 YY |
629 | writel(reg, dp->reg_base + |
630 | ANALOGIX_DP_BUF_DATA_0 + | |
631 | 4 * cur_data_idx); | |
e9474be4 JH |
632 | } |
633 | ||
634 | /* | |
635 | * Set DisplayPort transaction and write | |
636 | * If bit 3 is 1, DisplayPort transaction. | |
637 | * If Bit 3 is 0, I2C transaction. | |
638 | */ | |
639 | reg = AUX_LENGTH(cur_data_count) | | |
640 | AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE; | |
092f8994 | 641 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); |
e9474be4 JH |
642 | |
643 | /* Start AUX transaction */ | |
3424e3a4 | 644 | retval = analogix_dp_start_aux_transaction(dp); |
e9474be4 JH |
645 | if (retval == 0) |
646 | break; | |
bcbb7033 YY |
647 | |
648 | dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", | |
649 | __func__); | |
e9474be4 JH |
650 | } |
651 | ||
652 | start_offset += cur_data_count; | |
653 | } | |
654 | ||
655 | return retval; | |
656 | } | |
657 | ||
3424e3a4 | 658 | int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp, |
bcbb7033 YY |
659 | unsigned int reg_addr, |
660 | unsigned int count, | |
661 | unsigned char data[]) | |
e9474be4 JH |
662 | { |
663 | u32 reg; | |
664 | unsigned int start_offset; | |
665 | unsigned int cur_data_count; | |
666 | unsigned int cur_data_idx; | |
667 | int i; | |
668 | int retval = 0; | |
669 | ||
670 | /* Clear AUX CH data buffer */ | |
671 | reg = BUF_CLR; | |
092f8994 | 672 | writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); |
e9474be4 JH |
673 | |
674 | start_offset = 0; | |
675 | while (start_offset < count) { | |
676 | /* Buffer size of AUX CH is 16 * 4bytes */ | |
677 | if ((count - start_offset) > 16) | |
678 | cur_data_count = 16; | |
679 | else | |
680 | cur_data_count = count - start_offset; | |
681 | ||
682 | /* AUX CH Request Transaction process */ | |
99f54152 | 683 | for (i = 0; i < 3; i++) { |
e9474be4 JH |
684 | /* Select DPCD device address */ |
685 | reg = AUX_ADDR_7_0(reg_addr + start_offset); | |
092f8994 | 686 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); |
e9474be4 | 687 | reg = AUX_ADDR_15_8(reg_addr + start_offset); |
092f8994 | 688 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); |
e9474be4 | 689 | reg = AUX_ADDR_19_16(reg_addr + start_offset); |
092f8994 | 690 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16); |
e9474be4 JH |
691 | |
692 | /* | |
693 | * Set DisplayPort transaction and read | |
694 | * If bit 3 is 1, DisplayPort transaction. | |
695 | * If Bit 3 is 0, I2C transaction. | |
696 | */ | |
697 | reg = AUX_LENGTH(cur_data_count) | | |
698 | AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ; | |
092f8994 | 699 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); |
e9474be4 JH |
700 | |
701 | /* Start AUX transaction */ | |
3424e3a4 | 702 | retval = analogix_dp_start_aux_transaction(dp); |
e9474be4 JH |
703 | if (retval == 0) |
704 | break; | |
bcbb7033 YY |
705 | |
706 | dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", | |
707 | __func__); | |
e9474be4 JH |
708 | } |
709 | ||
710 | for (cur_data_idx = 0; cur_data_idx < cur_data_count; | |
711 | cur_data_idx++) { | |
092f8994 | 712 | reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 |
e9474be4 JH |
713 | + 4 * cur_data_idx); |
714 | data[start_offset + cur_data_idx] = | |
715 | (unsigned char)reg; | |
716 | } | |
717 | ||
718 | start_offset += cur_data_count; | |
719 | } | |
720 | ||
721 | return retval; | |
722 | } | |
723 | ||
3424e3a4 | 724 | int analogix_dp_select_i2c_device(struct analogix_dp_device *dp, |
bcbb7033 YY |
725 | unsigned int device_addr, |
726 | unsigned int reg_addr) | |
e9474be4 JH |
727 | { |
728 | u32 reg; | |
729 | int retval; | |
730 | ||
731 | /* Set EDID device address */ | |
732 | reg = device_addr; | |
092f8994 HS |
733 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); |
734 | writel(0x0, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); | |
735 | writel(0x0, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16); | |
e9474be4 JH |
736 | |
737 | /* Set offset from base address of EDID device */ | |
092f8994 | 738 | writel(reg_addr, dp->reg_base + ANALOGIX_DP_BUF_DATA_0); |
e9474be4 JH |
739 | |
740 | /* | |
741 | * Set I2C transaction and write address | |
742 | * If bit 3 is 1, DisplayPort transaction. | |
743 | * If Bit 3 is 0, I2C transaction. | |
744 | */ | |
745 | reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT | | |
746 | AUX_TX_COMM_WRITE; | |
092f8994 | 747 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); |
e9474be4 JH |
748 | |
749 | /* Start AUX transaction */ | |
3424e3a4 | 750 | retval = analogix_dp_start_aux_transaction(dp); |
e9474be4 | 751 | if (retval != 0) |
8fefbb75 | 752 | dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); |
e9474be4 JH |
753 | |
754 | return retval; | |
755 | } | |
756 | ||
3424e3a4 | 757 | int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp, |
bcbb7033 YY |
758 | unsigned int device_addr, |
759 | unsigned int reg_addr, | |
760 | unsigned int *data) | |
e9474be4 JH |
761 | { |
762 | u32 reg; | |
763 | int i; | |
764 | int retval; | |
765 | ||
99f54152 | 766 | for (i = 0; i < 3; i++) { |
e9474be4 JH |
767 | /* Clear AUX CH data buffer */ |
768 | reg = BUF_CLR; | |
092f8994 | 769 | writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); |
e9474be4 JH |
770 | |
771 | /* Select EDID device */ | |
bcbb7033 YY |
772 | retval = analogix_dp_select_i2c_device(dp, device_addr, |
773 | reg_addr); | |
99f54152 | 774 | if (retval != 0) |
e9474be4 | 775 | continue; |
e9474be4 JH |
776 | |
777 | /* | |
778 | * Set I2C transaction and read data | |
779 | * If bit 3 is 1, DisplayPort transaction. | |
780 | * If Bit 3 is 0, I2C transaction. | |
781 | */ | |
782 | reg = AUX_TX_COMM_I2C_TRANSACTION | | |
783 | AUX_TX_COMM_READ; | |
092f8994 | 784 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); |
e9474be4 JH |
785 | |
786 | /* Start AUX transaction */ | |
3424e3a4 | 787 | retval = analogix_dp_start_aux_transaction(dp); |
e9474be4 JH |
788 | if (retval == 0) |
789 | break; | |
bcbb7033 YY |
790 | |
791 | dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); | |
e9474be4 JH |
792 | } |
793 | ||
794 | /* Read data */ | |
795 | if (retval == 0) | |
092f8994 | 796 | *data = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0); |
e9474be4 JH |
797 | |
798 | return retval; | |
799 | } | |
800 | ||
3424e3a4 | 801 | int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp, |
bcbb7033 YY |
802 | unsigned int device_addr, |
803 | unsigned int reg_addr, | |
804 | unsigned int count, | |
805 | unsigned char edid[]) | |
e9474be4 JH |
806 | { |
807 | u32 reg; | |
808 | unsigned int i, j; | |
809 | unsigned int cur_data_idx; | |
810 | unsigned int defer = 0; | |
811 | int retval = 0; | |
812 | ||
813 | for (i = 0; i < count; i += 16) { | |
99f54152 | 814 | for (j = 0; j < 3; j++) { |
e9474be4 JH |
815 | /* Clear AUX CH data buffer */ |
816 | reg = BUF_CLR; | |
092f8994 | 817 | writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); |
e9474be4 JH |
818 | |
819 | /* Set normal AUX CH command */ | |
092f8994 | 820 | reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); |
e9474be4 | 821 | reg &= ~ADDR_ONLY; |
092f8994 | 822 | writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); |
e9474be4 JH |
823 | |
824 | /* | |
825 | * If Rx sends defer, Tx sends only reads | |
ff0c2642 | 826 | * request without sending address |
e9474be4 JH |
827 | */ |
828 | if (!defer) | |
3424e3a4 | 829 | retval = analogix_dp_select_i2c_device(dp, |
e9474be4 JH |
830 | device_addr, reg_addr + i); |
831 | else | |
832 | defer = 0; | |
833 | ||
834 | if (retval == 0) { | |
835 | /* | |
836 | * Set I2C transaction and write data | |
837 | * If bit 3 is 1, DisplayPort transaction. | |
838 | * If Bit 3 is 0, I2C transaction. | |
839 | */ | |
840 | reg = AUX_LENGTH(16) | | |
841 | AUX_TX_COMM_I2C_TRANSACTION | | |
842 | AUX_TX_COMM_READ; | |
843 | writel(reg, dp->reg_base + | |
092f8994 | 844 | ANALOGIX_DP_AUX_CH_CTL_1); |
e9474be4 JH |
845 | |
846 | /* Start AUX transaction */ | |
3424e3a4 | 847 | retval = analogix_dp_start_aux_transaction(dp); |
e9474be4 JH |
848 | if (retval == 0) |
849 | break; | |
bcbb7033 YY |
850 | |
851 | dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", | |
852 | __func__); | |
e9474be4 JH |
853 | } |
854 | /* Check if Rx sends defer */ | |
092f8994 | 855 | reg = readl(dp->reg_base + ANALOGIX_DP_AUX_RX_COMM); |
e9474be4 | 856 | if (reg == AUX_RX_COMM_AUX_DEFER || |
bcbb7033 | 857 | reg == AUX_RX_COMM_I2C_DEFER) { |
e9474be4 JH |
858 | dev_err(dp->dev, "Defer: %d\n\n", reg); |
859 | defer = 1; | |
860 | } | |
861 | } | |
862 | ||
863 | for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) { | |
092f8994 | 864 | reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 |
e9474be4 JH |
865 | + 4 * cur_data_idx); |
866 | edid[i + cur_data_idx] = (unsigned char)reg; | |
867 | } | |
868 | } | |
869 | ||
870 | return retval; | |
871 | } | |
872 | ||
3424e3a4 | 873 | void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype) |
e9474be4 JH |
874 | { |
875 | u32 reg; | |
876 | ||
877 | reg = bwtype; | |
40fc7ce7 | 878 | if ((bwtype == DP_LINK_BW_2_7) || (bwtype == DP_LINK_BW_1_62)) |
092f8994 | 879 | writel(reg, dp->reg_base + ANALOGIX_DP_LINK_BW_SET); |
e9474be4 JH |
880 | } |
881 | ||
3424e3a4 | 882 | void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype) |
e9474be4 JH |
883 | { |
884 | u32 reg; | |
885 | ||
092f8994 | 886 | reg = readl(dp->reg_base + ANALOGIX_DP_LINK_BW_SET); |
e9474be4 JH |
887 | *bwtype = reg; |
888 | } | |
889 | ||
3424e3a4 | 890 | void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count) |
e9474be4 JH |
891 | { |
892 | u32 reg; | |
893 | ||
894 | reg = count; | |
092f8994 | 895 | writel(reg, dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET); |
e9474be4 JH |
896 | } |
897 | ||
3424e3a4 | 898 | void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count) |
e9474be4 JH |
899 | { |
900 | u32 reg; | |
901 | ||
092f8994 | 902 | reg = readl(dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET); |
e9474be4 JH |
903 | *count = reg; |
904 | } | |
905 | ||
bcbb7033 YY |
906 | void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, |
907 | bool enable) | |
e9474be4 JH |
908 | { |
909 | u32 reg; | |
910 | ||
911 | if (enable) { | |
092f8994 | 912 | reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); |
e9474be4 | 913 | reg |= ENHANCED; |
092f8994 | 914 | writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); |
e9474be4 | 915 | } else { |
092f8994 | 916 | reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); |
e9474be4 | 917 | reg &= ~ENHANCED; |
092f8994 | 918 | writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); |
e9474be4 JH |
919 | } |
920 | } | |
921 | ||
3424e3a4 | 922 | void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, |
bcbb7033 | 923 | enum pattern_set pattern) |
e9474be4 JH |
924 | { |
925 | u32 reg; | |
926 | ||
927 | switch (pattern) { | |
928 | case PRBS7: | |
929 | reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7; | |
092f8994 | 930 | writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); |
e9474be4 JH |
931 | break; |
932 | case D10_2: | |
933 | reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2; | |
092f8994 | 934 | writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); |
e9474be4 JH |
935 | break; |
936 | case TRAINING_PTN1: | |
937 | reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1; | |
092f8994 | 938 | writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); |
e9474be4 JH |
939 | break; |
940 | case TRAINING_PTN2: | |
941 | reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2; | |
092f8994 | 942 | writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); |
e9474be4 JH |
943 | break; |
944 | case DP_NONE: | |
945 | reg = SCRAMBLING_ENABLE | | |
946 | LINK_QUAL_PATTERN_SET_DISABLE | | |
947 | SW_TRAINING_PATTERN_SET_NORMAL; | |
092f8994 | 948 | writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); |
e9474be4 JH |
949 | break; |
950 | default: | |
951 | break; | |
952 | } | |
953 | } | |
954 | ||
bcbb7033 YY |
955 | void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp, |
956 | u32 level) | |
e9474be4 JH |
957 | { |
958 | u32 reg; | |
959 | ||
092f8994 | 960 | reg = readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); |
e3c02009 JH |
961 | reg &= ~PRE_EMPHASIS_SET_MASK; |
962 | reg |= level << PRE_EMPHASIS_SET_SHIFT; | |
092f8994 | 963 | writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); |
e9474be4 JH |
964 | } |
965 | ||
bcbb7033 YY |
966 | void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp, |
967 | u32 level) | |
e9474be4 JH |
968 | { |
969 | u32 reg; | |
970 | ||
092f8994 | 971 | reg = readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); |
e3c02009 JH |
972 | reg &= ~PRE_EMPHASIS_SET_MASK; |
973 | reg |= level << PRE_EMPHASIS_SET_SHIFT; | |
092f8994 | 974 | writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); |
e9474be4 JH |
975 | } |
976 | ||
bcbb7033 YY |
977 | void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp, |
978 | u32 level) | |
e9474be4 JH |
979 | { |
980 | u32 reg; | |
981 | ||
092f8994 | 982 | reg = readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); |
e3c02009 JH |
983 | reg &= ~PRE_EMPHASIS_SET_MASK; |
984 | reg |= level << PRE_EMPHASIS_SET_SHIFT; | |
092f8994 | 985 | writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); |
e9474be4 JH |
986 | } |
987 | ||
bcbb7033 YY |
988 | void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp, |
989 | u32 level) | |
e9474be4 JH |
990 | { |
991 | u32 reg; | |
992 | ||
092f8994 | 993 | reg = readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); |
e3c02009 JH |
994 | reg &= ~PRE_EMPHASIS_SET_MASK; |
995 | reg |= level << PRE_EMPHASIS_SET_SHIFT; | |
092f8994 | 996 | writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); |
e9474be4 JH |
997 | } |
998 | ||
3424e3a4 | 999 | void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp, |
bcbb7033 | 1000 | u32 training_lane) |
e9474be4 JH |
1001 | { |
1002 | u32 reg; | |
1003 | ||
1004 | reg = training_lane; | |
092f8994 | 1005 | writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); |
e9474be4 JH |
1006 | } |
1007 | ||
3424e3a4 | 1008 | void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp, |
bcbb7033 | 1009 | u32 training_lane) |
e9474be4 JH |
1010 | { |
1011 | u32 reg; | |
1012 | ||
1013 | reg = training_lane; | |
092f8994 | 1014 | writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); |
e9474be4 JH |
1015 | } |
1016 | ||
3424e3a4 YY |
1017 | void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp, |
1018 | u32 training_lane) | |
e9474be4 JH |
1019 | { |
1020 | u32 reg; | |
1021 | ||
1022 | reg = training_lane; | |
092f8994 | 1023 | writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); |
e9474be4 JH |
1024 | } |
1025 | ||
3424e3a4 | 1026 | void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp, |
bcbb7033 | 1027 | u32 training_lane) |
e9474be4 JH |
1028 | { |
1029 | u32 reg; | |
1030 | ||
1031 | reg = training_lane; | |
092f8994 | 1032 | writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); |
e9474be4 JH |
1033 | } |
1034 | ||
3424e3a4 | 1035 | u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp) |
e9474be4 JH |
1036 | { |
1037 | u32 reg; | |
1038 | ||
092f8994 | 1039 | reg = readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); |
e9474be4 JH |
1040 | return reg; |
1041 | } | |
1042 | ||
3424e3a4 | 1043 | u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp) |
e9474be4 JH |
1044 | { |
1045 | u32 reg; | |
1046 | ||
092f8994 | 1047 | reg = readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); |
e9474be4 JH |
1048 | return reg; |
1049 | } | |
1050 | ||
3424e3a4 | 1051 | u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp) |
e9474be4 JH |
1052 | { |
1053 | u32 reg; | |
1054 | ||
092f8994 | 1055 | reg = readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); |
e9474be4 JH |
1056 | return reg; |
1057 | } | |
1058 | ||
3424e3a4 | 1059 | u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp) |
e9474be4 JH |
1060 | { |
1061 | u32 reg; | |
1062 | ||
092f8994 | 1063 | reg = readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); |
e9474be4 JH |
1064 | return reg; |
1065 | } | |
1066 | ||
3424e3a4 | 1067 | void analogix_dp_reset_macro(struct analogix_dp_device *dp) |
e9474be4 JH |
1068 | { |
1069 | u32 reg; | |
1070 | ||
092f8994 | 1071 | reg = readl(dp->reg_base + ANALOGIX_DP_PHY_TEST); |
e9474be4 | 1072 | reg |= MACRO_RST; |
092f8994 | 1073 | writel(reg, dp->reg_base + ANALOGIX_DP_PHY_TEST); |
e9474be4 JH |
1074 | |
1075 | /* 10 us is the minimum reset time. */ | |
a2c81bc1 | 1076 | usleep_range(10, 20); |
e9474be4 JH |
1077 | |
1078 | reg &= ~MACRO_RST; | |
092f8994 | 1079 | writel(reg, dp->reg_base + ANALOGIX_DP_PHY_TEST); |
e9474be4 JH |
1080 | } |
1081 | ||
3424e3a4 | 1082 | void analogix_dp_init_video(struct analogix_dp_device *dp) |
e9474be4 JH |
1083 | { |
1084 | u32 reg; | |
1085 | ||
1086 | reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG; | |
092f8994 | 1087 | writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1); |
e9474be4 JH |
1088 | |
1089 | reg = 0x0; | |
092f8994 | 1090 | writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_1); |
e9474be4 JH |
1091 | |
1092 | reg = CHA_CRI(4) | CHA_CTRL; | |
092f8994 | 1093 | writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_2); |
e9474be4 JH |
1094 | |
1095 | reg = 0x0; | |
092f8994 | 1096 | writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); |
e9474be4 JH |
1097 | |
1098 | reg = VID_HRES_TH(2) | VID_VRES_TH(0); | |
092f8994 | 1099 | writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_8); |
e9474be4 JH |
1100 | } |
1101 | ||
3424e3a4 | 1102 | void analogix_dp_set_video_color_format(struct analogix_dp_device *dp) |
e9474be4 JH |
1103 | { |
1104 | u32 reg; | |
1105 | ||
1106 | /* Configure the input color depth, color space, dynamic range */ | |
793ce4eb YY |
1107 | reg = (dp->video_info.dynamic_range << IN_D_RANGE_SHIFT) | |
1108 | (dp->video_info.color_depth << IN_BPC_SHIFT) | | |
1109 | (dp->video_info.color_space << IN_COLOR_F_SHIFT); | |
092f8994 | 1110 | writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_2); |
e9474be4 JH |
1111 | |
1112 | /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */ | |
092f8994 | 1113 | reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3); |
e9474be4 | 1114 | reg &= ~IN_YC_COEFFI_MASK; |
793ce4eb | 1115 | if (dp->video_info.ycbcr_coeff) |
e9474be4 JH |
1116 | reg |= IN_YC_COEFFI_ITU709; |
1117 | else | |
1118 | reg |= IN_YC_COEFFI_ITU601; | |
092f8994 | 1119 | writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3); |
e9474be4 JH |
1120 | } |
1121 | ||
3424e3a4 | 1122 | int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp) |
e9474be4 JH |
1123 | { |
1124 | u32 reg; | |
1125 | ||
092f8994 HS |
1126 | reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_1); |
1127 | writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_1); | |
e9474be4 | 1128 | |
092f8994 | 1129 | reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_1); |
e9474be4 JH |
1130 | |
1131 | if (!(reg & DET_STA)) { | |
1132 | dev_dbg(dp->dev, "Input stream clock not detected.\n"); | |
1133 | return -EINVAL; | |
1134 | } | |
1135 | ||
092f8994 HS |
1136 | reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_2); |
1137 | writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_2); | |
e9474be4 | 1138 | |
092f8994 | 1139 | reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_2); |
e9474be4 JH |
1140 | dev_dbg(dp->dev, "wait SYS_CTL_2.\n"); |
1141 | ||
1142 | if (reg & CHA_STA) { | |
1143 | dev_dbg(dp->dev, "Input stream clk is changing\n"); | |
1144 | return -EINVAL; | |
1145 | } | |
1146 | ||
1147 | return 0; | |
1148 | } | |
1149 | ||
3424e3a4 | 1150 | void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp, |
bcbb7033 YY |
1151 | enum clock_recovery_m_value_type type, |
1152 | u32 m_value, u32 n_value) | |
e9474be4 JH |
1153 | { |
1154 | u32 reg; | |
1155 | ||
1156 | if (type == REGISTER_M) { | |
092f8994 | 1157 | reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); |
e9474be4 | 1158 | reg |= FIX_M_VID; |
092f8994 | 1159 | writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); |
e9474be4 | 1160 | reg = m_value & 0xff; |
092f8994 | 1161 | writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_0); |
e9474be4 | 1162 | reg = (m_value >> 8) & 0xff; |
092f8994 | 1163 | writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_1); |
e9474be4 | 1164 | reg = (m_value >> 16) & 0xff; |
092f8994 | 1165 | writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_2); |
e9474be4 JH |
1166 | |
1167 | reg = n_value & 0xff; | |
092f8994 | 1168 | writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_0); |
e9474be4 | 1169 | reg = (n_value >> 8) & 0xff; |
092f8994 | 1170 | writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_1); |
e9474be4 | 1171 | reg = (n_value >> 16) & 0xff; |
092f8994 | 1172 | writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_2); |
e9474be4 | 1173 | } else { |
092f8994 | 1174 | reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); |
e9474be4 | 1175 | reg &= ~FIX_M_VID; |
092f8994 | 1176 | writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); |
e9474be4 | 1177 | |
092f8994 HS |
1178 | writel(0x00, dp->reg_base + ANALOGIX_DP_N_VID_0); |
1179 | writel(0x80, dp->reg_base + ANALOGIX_DP_N_VID_1); | |
1180 | writel(0x00, dp->reg_base + ANALOGIX_DP_N_VID_2); | |
e9474be4 JH |
1181 | } |
1182 | } | |
1183 | ||
3424e3a4 | 1184 | void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type) |
e9474be4 JH |
1185 | { |
1186 | u32 reg; | |
1187 | ||
1188 | if (type == VIDEO_TIMING_FROM_CAPTURE) { | |
092f8994 | 1189 | reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); |
e9474be4 | 1190 | reg &= ~FORMAT_SEL; |
092f8994 | 1191 | writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); |
e9474be4 | 1192 | } else { |
092f8994 | 1193 | reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); |
e9474be4 | 1194 | reg |= FORMAT_SEL; |
092f8994 | 1195 | writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); |
e9474be4 JH |
1196 | } |
1197 | } | |
1198 | ||
3424e3a4 | 1199 | void analogix_dp_enable_video_master(struct analogix_dp_device *dp, bool enable) |
e9474be4 JH |
1200 | { |
1201 | u32 reg; | |
1202 | ||
1203 | if (enable) { | |
092f8994 | 1204 | reg = readl(dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); |
e9474be4 JH |
1205 | reg &= ~VIDEO_MODE_MASK; |
1206 | reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE; | |
092f8994 | 1207 | writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); |
e9474be4 | 1208 | } else { |
092f8994 | 1209 | reg = readl(dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); |
e9474be4 JH |
1210 | reg &= ~VIDEO_MODE_MASK; |
1211 | reg |= VIDEO_MODE_SLAVE_MODE; | |
092f8994 | 1212 | writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); |
e9474be4 JH |
1213 | } |
1214 | } | |
1215 | ||
3424e3a4 | 1216 | void analogix_dp_start_video(struct analogix_dp_device *dp) |
e9474be4 JH |
1217 | { |
1218 | u32 reg; | |
1219 | ||
092f8994 | 1220 | reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); |
e9474be4 | 1221 | reg |= VIDEO_EN; |
092f8994 | 1222 | writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); |
e9474be4 JH |
1223 | } |
1224 | ||
3424e3a4 | 1225 | int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp) |
e9474be4 JH |
1226 | { |
1227 | u32 reg; | |
1228 | ||
092f8994 HS |
1229 | reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); |
1230 | writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); | |
e9474be4 | 1231 | |
092f8994 | 1232 | reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); |
e9474be4 JH |
1233 | if (!(reg & STRM_VALID)) { |
1234 | dev_dbg(dp->dev, "Input video stream is not detected.\n"); | |
1235 | return -EINVAL; | |
1236 | } | |
1237 | ||
1238 | return 0; | |
1239 | } | |
1240 | ||
3424e3a4 | 1241 | void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp) |
e9474be4 JH |
1242 | { |
1243 | u32 reg; | |
1244 | ||
092f8994 | 1245 | reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1); |
bcbb7033 | 1246 | reg &= ~(MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N); |
e9474be4 | 1247 | reg |= MASTER_VID_FUNC_EN_N; |
092f8994 | 1248 | writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1); |
e9474be4 | 1249 | |
092f8994 | 1250 | reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); |
e9474be4 | 1251 | reg &= ~INTERACE_SCAN_CFG; |
793ce4eb | 1252 | reg |= (dp->video_info.interlaced << 2); |
092f8994 | 1253 | writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); |
e9474be4 | 1254 | |
092f8994 | 1255 | reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); |
e9474be4 | 1256 | reg &= ~VSYNC_POLARITY_CFG; |
793ce4eb | 1257 | reg |= (dp->video_info.v_sync_polarity << 1); |
092f8994 | 1258 | writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); |
e9474be4 | 1259 | |
092f8994 | 1260 | reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); |
e9474be4 | 1261 | reg &= ~HSYNC_POLARITY_CFG; |
793ce4eb | 1262 | reg |= (dp->video_info.h_sync_polarity << 0); |
092f8994 | 1263 | writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); |
e9474be4 JH |
1264 | |
1265 | reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE; | |
092f8994 | 1266 | writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); |
e9474be4 JH |
1267 | } |
1268 | ||
3424e3a4 | 1269 | void analogix_dp_enable_scrambling(struct analogix_dp_device *dp) |
e9474be4 JH |
1270 | { |
1271 | u32 reg; | |
1272 | ||
092f8994 | 1273 | reg = readl(dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); |
e9474be4 | 1274 | reg &= ~SCRAMBLING_DISABLE; |
092f8994 | 1275 | writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); |
e9474be4 JH |
1276 | } |
1277 | ||
3424e3a4 | 1278 | void analogix_dp_disable_scrambling(struct analogix_dp_device *dp) |
e9474be4 JH |
1279 | { |
1280 | u32 reg; | |
1281 | ||
092f8994 | 1282 | reg = readl(dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); |
e9474be4 | 1283 | reg |= SCRAMBLING_DISABLE; |
092f8994 | 1284 | writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); |
e9474be4 | 1285 | } |