1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2015 Broadcom
4 * Copyright (c) 2014 The Linux Foundation. All rights reserved.
5 * Copyright (C) 2013 Red Hat
6 * Author: Rob Clark <robdclark@gmail.com>
7 */
8
9 #include "vc4_hdmi.h"
10 #include "vc4_regs.h"
11 #include "vc4_hdmi_regs.h"
12
13 #define VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB BIT(5)
14 #define VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB BIT(4)
15 #define VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET BIT(3)
16 #define VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET BIT(2)
17 #define VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET BIT(1)
18 #define VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET BIT(0)
19
20 #define VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN BIT(4)
21
22 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_SHIFT 29
23 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_MASK VC4_MASK(31, 29)
24 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_SHIFT 24
25 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_MASK VC4_MASK(28, 24)
26 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_SHIFT 21
27 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_MASK VC4_MASK(23, 21)
28 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_SHIFT 16
29 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_MASK VC4_MASK(20, 16)
30 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_SHIFT 13
31 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_MASK VC4_MASK(15, 13)
32 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_SHIFT 8
33 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_MASK VC4_MASK(12, 8)
34 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_SHIFT 5
35 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_MASK VC4_MASK(7, 5)
36 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_SHIFT 0
37 #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_MASK VC4_MASK(4, 0)
38
39 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_SHIFT 15
40 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_MASK VC4_MASK(19, 15)
41 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_SHIFT 10
42 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_MASK VC4_MASK(14, 10)
43 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_SHIFT 5
44 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_MASK VC4_MASK(9, 5)
45 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_SHIFT 0
46 #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_MASK VC4_MASK(4, 0)
47
48 #define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_SHIFT 16
49 #define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_MASK VC4_MASK(19, 16)
50 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_SHIFT 12
51 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_MASK VC4_MASK(15, 12)
52 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_SHIFT 8
53 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_MASK VC4_MASK(11, 8)
54 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_SHIFT 4
55 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_MASK VC4_MASK(7, 4)
56 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_SHIFT 0
57 #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_MASK VC4_MASK(3, 0)
58
59 #define VC4_HDMI_TX_PHY_CTL_3_RP_SHIFT 17
60 #define VC4_HDMI_TX_PHY_CTL_3_RP_MASK VC4_MASK(19, 17)
61 #define VC4_HDMI_TX_PHY_CTL_3_RZ_SHIFT 12
62 #define VC4_HDMI_TX_PHY_CTL_3_RZ_MASK VC4_MASK(16, 12)
63 #define VC4_HDMI_TX_PHY_CTL_3_CP1_SHIFT 10
64 #define VC4_HDMI_TX_PHY_CTL_3_CP1_MASK VC4_MASK(11, 10)
65 #define VC4_HDMI_TX_PHY_CTL_3_CP_SHIFT 8
66 #define VC4_HDMI_TX_PHY_CTL_3_CP_MASK VC4_MASK(9, 8)
67 #define VC4_HDMI_TX_PHY_CTL_3_CZ_SHIFT 6
68 #define VC4_HDMI_TX_PHY_CTL_3_CZ_MASK VC4_MASK(7, 6)
69 #define VC4_HDMI_TX_PHY_CTL_3_ICP_SHIFT 0
70 #define VC4_HDMI_TX_PHY_CTL_3_ICP_MASK VC4_MASK(5, 0)
71
72 #define VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE BIT(13)
73 #define VC4_HDMI_TX_PHY_PLL_CTL_0_VC_RANGE_EN BIT(12)
74 #define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_LOW BIT(11)
75 #define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_HIGH BIT(10)
76 #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_SHIFT 9
77 #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_MASK VC4_MASK(9, 9)
78 #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_FB_DIV2 BIT(8)
79 #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_POST_DIV2 BIT(7)
80 #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN BIT(6)
81 #define VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK BIT(5)
82
83 #define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_SHIFT 16
84 #define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_MASK VC4_MASK(27, 16)
85 #define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_SHIFT 14
86 #define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_MASK VC4_MASK(15, 14)
87 #define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE BIT(13)
88 #define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_SHIFT 11
89 #define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_MASK VC4_MASK(12, 11)
90
91 #define VC4_HDMI_TX_PHY_CLK_DIV_VCO_SHIFT 8
92 #define VC4_HDMI_TX_PHY_CLK_DIV_VCO_MASK VC4_MASK(15, 8)
93
94 #define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_SHIFT 0
95 #define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_MASK VC4_MASK(3, 0)
96
97 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_MASK VC4_MASK(13, 12)
98 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_SHIFT 12
99 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_MASK VC4_MASK(9, 8)
100 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_SHIFT 8
101 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_MASK VC4_MASK(5, 4)
102 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_SHIFT 4
103 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_MASK VC4_MASK(1, 0)
104 #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_SHIFT 0
105
106 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK VC4_MASK(27, 0)
107 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_SHIFT 0
108
109 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK VC4_MASK(27, 0)
110 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_SHIFT 0
111
112 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_MASK VC4_MASK(31, 16)
113 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_SHIFT 16
114 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_MASK VC4_MASK(15, 0)
115 #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_SHIFT 0
116
117 #define VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS BIT(19)
118 #define VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR BIT(17)
119 #define VC4_HDMI_RM_CONTROL_FREE_RUN BIT(4)
120
121 #define VC4_HDMI_RM_OFFSET_ONLY BIT(31)
122 #define VC4_HDMI_RM_OFFSET_OFFSET_SHIFT 0
123 #define VC4_HDMI_RM_OFFSET_OFFSET_MASK VC4_MASK(30, 0)
124
125 #define VC4_HDMI_RM_FORMAT_SHIFT_SHIFT 24
126 #define VC4_HDMI_RM_FORMAT_SHIFT_MASK VC4_MASK(25, 24)
127
128 #define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_BG_PWRUP BIT(8)
129 #define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_LDO_PWRUP BIT(7)
130 #define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_BIAS_PWRUP BIT(6)
131 #define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_RNDGEN_PWRUP BIT(4)
132 #define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_CK_PWRUP BIT(3)
133 #define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_2_PWRUP BIT(2)
134 #define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_1_PWRUP BIT(1)
135 #define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_0_PWRUP BIT(0)
136
137 #define VC6_HDMI_TX_PHY_PLL_REFCLK_REFCLK_SEL_CMOS BIT(13)
138 #define VC6_HDMI_TX_PHY_PLL_REFCLK_REFFRQ_MASK VC4_MASK(9, 0)
139
140 #define VC6_HDMI_TX_PHY_PLL_POST_KDIV_CLK0_SEL_MASK VC4_MASK(3, 2)
141 #define VC6_HDMI_TX_PHY_PLL_POST_KDIV_KDIV_MASK VC4_MASK(1, 0)
142
143 #define VC6_HDMI_TX_PHY_PLL_VCOCLK_DIV_VCODIV_EN BIT(10)
144 #define VC6_HDMI_TX_PHY_PLL_VCOCLK_DIV_VCODIV_MASK VC4_MASK(9, 0)
145
146 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL_MASK VC4_MASK(31, 28)
147 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE_MASK VC4_MASK(27, 27)
148 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL_MASK VC4_MASK(26, 26)
149 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN_MASK VC4_MASK(25, 25)
150 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL_MASK VC4_MASK(24, 23)
151 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN_MASK VC4_MASK(22, 22)
152 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL_MASK VC4_MASK(21, 21)
153 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN_MASK VC4_MASK(20, 20)
154 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL_MASK VC4_MASK(19, 18)
155 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN_MASK VC4_MASK(17, 17)
156 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN_MASK VC4_MASK(16, 16)
157 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL_MASK VC4_MASK(15, 12)
158 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN_MASK VC4_MASK(11, 11)
159 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT_MASK VC4_MASK(10, 8)
160 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT_MASK VC4_MASK(7, 5)
161 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING_MASK VC4_MASK(4, 3)
162 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING_MASK VC4_MASK(2, 1)
163 #define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN_MASK VC4_MASK(0, 0)
164
165 #define VC6_HDMI_TX_PHY_PLL_RESET_CTL_PLL_PLLPOST_RESETB BIT(1)
166 #define VC6_HDMI_TX_PHY_PLL_RESET_CTL_PLL_RESETB BIT(0)
167
168 #define VC6_HDMI_TX_PHY_PLL_POWERUP_CTL_PLL_PWRUP BIT(0)
169
170 #define OSCILLATOR_FREQUENCY 54000000
171
vc4_hdmi_phy_init(struct vc4_hdmi * vc4_hdmi,struct drm_connector_state * conn_state)172 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
173 struct drm_connector_state *conn_state)
174 {
175 unsigned long flags;
176
177 /* PHY should be in reset, like
178 * vc4_hdmi_encoder_disable() does.
179 */
180
181 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
182
183 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
184 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
185
186 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
187 }
188
vc4_hdmi_phy_disable(struct vc4_hdmi * vc4_hdmi)189 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
190 {
191 unsigned long flags;
192
193 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
194 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
195 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
196 }
197
vc4_hdmi_phy_rng_enable(struct vc4_hdmi * vc4_hdmi)198 void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
199 {
200 unsigned long flags;
201
202 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
203 HDMI_WRITE(HDMI_TX_PHY_CTL_0,
204 HDMI_READ(HDMI_TX_PHY_CTL_0) &
205 ~VC4_HDMI_TX_PHY_RNG_PWRDN);
206 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
207 }
208
vc4_hdmi_phy_rng_disable(struct vc4_hdmi * vc4_hdmi)209 void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
210 {
211 unsigned long flags;
212
213 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
214 HDMI_WRITE(HDMI_TX_PHY_CTL_0,
215 HDMI_READ(HDMI_TX_PHY_CTL_0) |
216 VC4_HDMI_TX_PHY_RNG_PWRDN);
217 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
218 }
219
220 static unsigned long long
phy_get_vco_freq(unsigned long long clock,u8 * vco_sel,u8 * vco_div)221 phy_get_vco_freq(unsigned long long clock, u8 *vco_sel, u8 *vco_div)
222 {
223 unsigned long long vco_freq = clock;
224 unsigned int _vco_div = 0;
225 unsigned int _vco_sel = 0;
226
227 while (vco_freq < 3000000000ULL) {
228 _vco_div++;
229 vco_freq = clock * _vco_div * 10;
230 }
231
232 if (vco_freq > 4500000000ULL)
233 _vco_sel = 1;
234
235 *vco_sel = _vco_sel;
236 *vco_div = _vco_div;
237
238 return vco_freq;
239 }
240
phy_get_cp_current(unsigned long vco_freq)241 static u8 phy_get_cp_current(unsigned long vco_freq)
242 {
243 if (vco_freq < 3700000000ULL)
244 return 0x1c;
245
246 return 0x18;
247 }
248
phy_get_rm_offset(unsigned long long vco_freq)249 static u32 phy_get_rm_offset(unsigned long long vco_freq)
250 {
251 unsigned long long fref = OSCILLATOR_FREQUENCY;
252 u64 offset = 0;
253
254 /* RM offset is stored as 9.22 format */
255 offset = vco_freq * 2;
256 offset = offset << 22;
257 do_div(offset, fref);
258 offset >>= 2;
259
260 return offset;
261 }
262
phy_get_vco_gain(unsigned long long vco_freq)263 static u8 phy_get_vco_gain(unsigned long long vco_freq)
264 {
265 if (vco_freq < 3350000000ULL)
266 return 0xf;
267
268 if (vco_freq < 3700000000ULL)
269 return 0xc;
270
271 if (vco_freq < 4050000000ULL)
272 return 0x6;
273
274 if (vco_freq < 4800000000ULL)
275 return 0x5;
276
277 if (vco_freq < 5200000000ULL)
278 return 0x7;
279
280 return 0x2;
281 }
282
283 struct phy_lane_settings {
284 struct {
285 u8 preemphasis;
286 u8 main_driver;
287 } amplitude;
288
289 u8 res_sel_data;
290 u8 term_res_sel_data;
291 };
292
293 struct phy_settings {
294 unsigned long long min_rate;
295 unsigned long long max_rate;
296 struct phy_lane_settings channel[3];
297 struct phy_lane_settings clock;
298 };
299
300 static const struct phy_settings vc5_hdmi_phy_settings[] = {
301 {
302 0, 50000000,
303 {
304 {{0x0, 0x0A}, 0x12, 0x0},
305 {{0x0, 0x0A}, 0x12, 0x0},
306 {{0x0, 0x0A}, 0x12, 0x0}
307 },
308 {{0x0, 0x0A}, 0x18, 0x0},
309 },
310 {
311 50000001, 75000000,
312 {
313 {{0x0, 0x09}, 0x12, 0x0},
314 {{0x0, 0x09}, 0x12, 0x0},
315 {{0x0, 0x09}, 0x12, 0x0}
316 },
317 {{0x0, 0x0C}, 0x18, 0x3},
318 },
319 {
320 75000001, 165000000,
321 {
322 {{0x0, 0x09}, 0x12, 0x0},
323 {{0x0, 0x09}, 0x12, 0x0},
324 {{0x0, 0x09}, 0x12, 0x0}
325 },
326 {{0x0, 0x0C}, 0x18, 0x3},
327 },
328 {
329 165000001, 250000000,
330 {
331 {{0x0, 0x0F}, 0x12, 0x1},
332 {{0x0, 0x0F}, 0x12, 0x1},
333 {{0x0, 0x0F}, 0x12, 0x1}
334 },
335 {{0x0, 0x0C}, 0x18, 0x3},
336 },
337 {
338 250000001, 340000000,
339 {
340 {{0x2, 0x0D}, 0x12, 0x1},
341 {{0x2, 0x0D}, 0x12, 0x1},
342 {{0x2, 0x0D}, 0x12, 0x1}
343 },
344 {{0x0, 0x0C}, 0x18, 0xF},
345 },
346 {
347 340000001, 450000000,
348 {
349 {{0x0, 0x1B}, 0x12, 0xF},
350 {{0x0, 0x1B}, 0x12, 0xF},
351 {{0x0, 0x1B}, 0x12, 0xF}
352 },
353 {{0x0, 0x0A}, 0x12, 0xF},
354 },
355 {
356 450000001, 600000000,
357 {
358 {{0x0, 0x1C}, 0x12, 0xF},
359 {{0x0, 0x1C}, 0x12, 0xF},
360 {{0x0, 0x1C}, 0x12, 0xF}
361 },
362 {{0x0, 0x0B}, 0x13, 0xF},
363 },
364 };
365
phy_get_settings(unsigned long long tmds_rate)366 static const struct phy_settings *phy_get_settings(unsigned long long tmds_rate)
367 {
368 unsigned int count = ARRAY_SIZE(vc5_hdmi_phy_settings);
369 unsigned int i;
370
371 for (i = 0; i < count; i++) {
372 const struct phy_settings *s = &vc5_hdmi_phy_settings[i];
373
374 if (tmds_rate >= s->min_rate && tmds_rate <= s->max_rate)
375 return s;
376 }
377
378 /*
379 * If the pixel clock exceeds our max setting, try the max
380 * setting anyway.
381 */
382 return &vc5_hdmi_phy_settings[count - 1];
383 }
384
385 static const struct phy_lane_settings *
phy_get_channel_settings(enum vc4_hdmi_phy_channel chan,unsigned long long tmds_rate)386 phy_get_channel_settings(enum vc4_hdmi_phy_channel chan,
387 unsigned long long tmds_rate)
388 {
389 const struct phy_settings *settings = phy_get_settings(tmds_rate);
390
391 if (chan == PHY_LANE_CK)
392 return &settings->clock;
393
394 return &settings->channel[chan];
395 }
396
vc5_hdmi_reset_phy(struct vc4_hdmi * vc4_hdmi)397 static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
398 {
399 lockdep_assert_held(&vc4_hdmi->hw_lock);
400
401 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x0f);
402 HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10));
403 }
404
vc5_hdmi_phy_init(struct vc4_hdmi * vc4_hdmi,struct drm_connector_state * conn_state)405 void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
406 struct drm_connector_state *conn_state)
407 {
408 const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings;
409 const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
410 unsigned long long pixel_freq = conn_state->hdmi.tmds_char_rate;
411 unsigned long long vco_freq;
412 unsigned char word_sel;
413 unsigned long flags;
414 u8 vco_sel, vco_div;
415
416 vco_freq = phy_get_vco_freq(pixel_freq, &vco_sel, &vco_div);
417
418 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
419
420 vc5_hdmi_reset_phy(vc4_hdmi);
421
422 HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
423 VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
424
425 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
426 HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
427 ~VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET &
428 ~VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET &
429 ~VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET &
430 ~VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET);
431
432 HDMI_WRITE(HDMI_RM_CONTROL,
433 HDMI_READ(HDMI_RM_CONTROL) |
434 VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS |
435 VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR |
436 VC4_HDMI_RM_CONTROL_FREE_RUN);
437
438 HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
439 (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1) &
440 ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK) |
441 VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT));
442
443 HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
444 (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2) &
445 ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK) |
446 VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT));
447
448 HDMI_WRITE(HDMI_RM_OFFSET,
449 VC4_SET_FIELD(phy_get_rm_offset(vco_freq),
450 VC4_HDMI_RM_OFFSET_OFFSET) |
451 VC4_HDMI_RM_OFFSET_ONLY);
452
453 HDMI_WRITE(HDMI_TX_PHY_CLK_DIV,
454 VC4_SET_FIELD(vco_div, VC4_HDMI_TX_PHY_CLK_DIV_VCO));
455
456 HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
457 VC4_SET_FIELD(0xe147, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD) |
458 VC4_SET_FIELD(0xe14, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD));
459
460 HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_0,
461 VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK |
462 VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN |
463 VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE |
464 VC4_SET_FIELD(vco_sel, VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL));
465
466 HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_1,
467 HDMI_READ(HDMI_TX_PHY_PLL_CTL_1) |
468 VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE |
469 VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL) |
470 VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY) |
471 VC4_SET_FIELD(0x8a, VC4_HDMI_TX_PHY_PLL_CTL_1_CPP));
472
473 HDMI_WRITE(HDMI_RM_FORMAT,
474 HDMI_READ(HDMI_RM_FORMAT) |
475 VC4_SET_FIELD(2, VC4_HDMI_RM_FORMAT_SHIFT));
476
477 HDMI_WRITE(HDMI_TX_PHY_PLL_CFG,
478 HDMI_READ(HDMI_TX_PHY_PLL_CFG) |
479 VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CFG_PDIV));
480
481 if (pixel_freq >= 340000000)
482 word_sel = 3;
483 else
484 word_sel = 0;
485 HDMI_WRITE(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, word_sel);
486
487 HDMI_WRITE(HDMI_TX_PHY_CTL_3,
488 VC4_SET_FIELD(phy_get_cp_current(vco_freq),
489 VC4_HDMI_TX_PHY_CTL_3_ICP) |
490 VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP) |
491 VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP1) |
492 VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_CTL_3_CZ) |
493 VC4_SET_FIELD(4, VC4_HDMI_TX_PHY_CTL_3_RP) |
494 VC4_SET_FIELD(6, VC4_HDMI_TX_PHY_CTL_3_RZ));
495
496 chan0_settings =
497 phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_0],
498 pixel_freq);
499 chan1_settings =
500 phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_1],
501 pixel_freq);
502 chan2_settings =
503 phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_2],
504 pixel_freq);
505 clock_settings =
506 phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_CK],
507 pixel_freq);
508
509 HDMI_WRITE(HDMI_TX_PHY_CTL_0,
510 VC4_SET_FIELD(chan0_settings->amplitude.preemphasis,
511 VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP) |
512 VC4_SET_FIELD(chan0_settings->amplitude.main_driver,
513 VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV) |
514 VC4_SET_FIELD(chan1_settings->amplitude.preemphasis,
515 VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP) |
516 VC4_SET_FIELD(chan1_settings->amplitude.main_driver,
517 VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV) |
518 VC4_SET_FIELD(chan2_settings->amplitude.preemphasis,
519 VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP) |
520 VC4_SET_FIELD(chan2_settings->amplitude.main_driver,
521 VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV) |
522 VC4_SET_FIELD(clock_settings->amplitude.preemphasis,
523 VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP) |
524 VC4_SET_FIELD(clock_settings->amplitude.main_driver,
525 VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV));
526
527 HDMI_WRITE(HDMI_TX_PHY_CTL_1,
528 HDMI_READ(HDMI_TX_PHY_CTL_1) |
529 VC4_SET_FIELD(chan0_settings->res_sel_data,
530 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0) |
531 VC4_SET_FIELD(chan1_settings->res_sel_data,
532 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1) |
533 VC4_SET_FIELD(chan2_settings->res_sel_data,
534 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2) |
535 VC4_SET_FIELD(clock_settings->res_sel_data,
536 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK));
537
538 HDMI_WRITE(HDMI_TX_PHY_CTL_2,
539 VC4_SET_FIELD(chan0_settings->term_res_sel_data,
540 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0) |
541 VC4_SET_FIELD(chan1_settings->term_res_sel_data,
542 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1) |
543 VC4_SET_FIELD(chan2_settings->term_res_sel_data,
544 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2) |
545 VC4_SET_FIELD(clock_settings->term_res_sel_data,
546 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK) |
547 VC4_SET_FIELD(phy_get_vco_gain(vco_freq),
548 VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN));
549
550 HDMI_WRITE(HDMI_TX_PHY_CHANNEL_SWAP,
551 VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_0],
552 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL) |
553 VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_1],
554 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL) |
555 VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_2],
556 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL) |
557 VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_CK],
558 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL));
559
560 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
561 HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
562 ~(VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
563 VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB));
564
565 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
566 HDMI_READ(HDMI_TX_PHY_RESET_CTL) |
567 VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
568 VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB);
569
570 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
571 }
572
vc5_hdmi_phy_disable(struct vc4_hdmi * vc4_hdmi)573 void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
574 {
575 unsigned long flags;
576
577 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
578 vc5_hdmi_reset_phy(vc4_hdmi);
579 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
580 }
581
vc5_hdmi_phy_rng_enable(struct vc4_hdmi * vc4_hdmi)582 void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
583 {
584 unsigned long flags;
585
586 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
587 HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
588 HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) &
589 ~VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
590 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
591 }
592
vc5_hdmi_phy_rng_disable(struct vc4_hdmi * vc4_hdmi)593 void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
594 {
595 unsigned long flags;
596
597 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
598 HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
599 HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) |
600 VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
601 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
602 }
603
604 #define VC6_VCO_MIN_FREQ (8ULL * 1000 * 1000 * 1000)
605 #define VC6_VCO_MAX_FREQ (12ULL * 1000 * 1000 * 1000)
606
607 static unsigned long long
vc6_phy_get_vco_freq(unsigned long long tmds_rate,unsigned int * vco_div)608 vc6_phy_get_vco_freq(unsigned long long tmds_rate, unsigned int *vco_div)
609 {
610 unsigned int min_div;
611 unsigned int max_div;
612 unsigned int div;
613
614 div = 0;
615 while (tmds_rate * div * 10 < VC6_VCO_MIN_FREQ)
616 div++;
617 min_div = div;
618
619 while (tmds_rate * (div + 1) * 10 < VC6_VCO_MAX_FREQ)
620 div++;
621 max_div = div;
622
623 div = min_div + (max_div - min_div) / 2;
624
625 *vco_div = div;
626 return tmds_rate * div * 10;
627 }
628
629 struct vc6_phy_lane_settings {
630 unsigned int ext_current_ctl:4;
631 unsigned int ffe_enable:1;
632 unsigned int slew_rate_ctl:1;
633 unsigned int ffe_post_tap_en:1;
634 unsigned int ldmos_bias_ctl:2;
635 unsigned int com_mode_ldmos_en:1;
636 unsigned int edge_sel:1;
637 unsigned int ext_current_src_hs_en:1;
638 unsigned int term_ctl:2;
639 unsigned int ext_current_src_en:1;
640 unsigned int int_current_src_en:1;
641 unsigned int int_current_ctl:4;
642 unsigned int int_current_src_hs_en:1;
643 unsigned int main_tap_current_select:3;
644 unsigned int post_tap_current_select:3;
645 unsigned int slew_ctl_slow_loading:2;
646 unsigned int slew_ctl_slow_driving:2;
647 unsigned int ffe_pre_tap_en:1;
648 };
649
650 struct vc6_phy_settings {
651 unsigned long long min_rate;
652 unsigned long long max_rate;
653 struct vc6_phy_lane_settings channel[3];
654 struct vc6_phy_lane_settings clock;
655 };
656
657 static const struct vc6_phy_settings vc6_hdmi_phy_settings[] = {
658 {
659 0, 222000000,
660 {
661 {
662 /* 200mA */
663 .ext_current_ctl = 8,
664
665 /* 0.85V */
666 .ldmos_bias_ctl = 1,
667
668 /* Enable External Current Source */
669 .ext_current_src_en = 1,
670
671 /* 200mA */
672 .int_current_ctl = 8,
673
674 /* 17.6 mA */
675 .main_tap_current_select = 7,
676 },
677 {
678 /* 200mA */
679 .ext_current_ctl = 8,
680
681 /* 0.85V */
682 .ldmos_bias_ctl = 1,
683
684 /* Enable External Current Source */
685 .ext_current_src_en = 1,
686
687 /* 200mA */
688 .int_current_ctl = 8,
689
690 /* 17.6 mA */
691 .main_tap_current_select = 7,
692 },
693 {
694 /* 200mA */
695 .ext_current_ctl = 8,
696
697 /* 0.85V */
698 .ldmos_bias_ctl = 1,
699
700 /* Enable External Current Source */
701 .ext_current_src_en = 1,
702
703 /* 200mA */
704 .int_current_ctl = 8,
705
706 /* 17.6 mA */
707 .main_tap_current_select = 7,
708 },
709 },
710 {
711 /* 200mA */
712 .ext_current_ctl = 8,
713
714 /* 0.85V */
715 .ldmos_bias_ctl = 1,
716
717 /* Enable External Current Source */
718 .ext_current_src_en = 1,
719
720 /* 200mA */
721 .int_current_ctl = 8,
722
723 /* 17.6 mA */
724 .main_tap_current_select = 7,
725 },
726 },
727 {
728 222000001, 297000000,
729 {
730 {
731 /* 200mA and 180mA ?! */
732 .ext_current_ctl = 12,
733
734 /* 0.85V */
735 .ldmos_bias_ctl = 1,
736
737 /* 100 Ohm */
738 .term_ctl = 1,
739
740 /* Enable External Current Source */
741 .ext_current_src_en = 1,
742
743 /* Enable Internal Current Source */
744 .int_current_src_en = 1,
745 },
746 {
747 /* 200mA and 180mA ?! */
748 .ext_current_ctl = 12,
749
750 /* 0.85V */
751 .ldmos_bias_ctl = 1,
752
753 /* 100 Ohm */
754 .term_ctl = 1,
755
756 /* Enable External Current Source */
757 .ext_current_src_en = 1,
758
759 /* Enable Internal Current Source */
760 .int_current_src_en = 1,
761 },
762 {
763 /* 200mA and 180mA ?! */
764 .ext_current_ctl = 12,
765
766 /* 0.85V */
767 .ldmos_bias_ctl = 1,
768
769 /* 100 Ohm */
770 .term_ctl = 1,
771
772 /* Enable External Current Source */
773 .ext_current_src_en = 1,
774
775 /* Enable Internal Current Source */
776 .int_current_src_en = 1,
777 },
778 },
779 {
780 /* 200mA and 180mA ?! */
781 .ext_current_ctl = 12,
782
783 /* 0.85V */
784 .ldmos_bias_ctl = 1,
785
786 /* 100 Ohm */
787 .term_ctl = 1,
788
789 /* Enable External Current Source */
790 .ext_current_src_en = 1,
791
792 /* Enable Internal Current Source */
793 .int_current_src_en = 1,
794
795 /* Internal Current Source Half Swing Enable*/
796 .int_current_src_hs_en = 1,
797 },
798 },
799 {
800 297000001, 597000044,
801 {
802 {
803 /* 200mA */
804 .ext_current_ctl = 8,
805
806 /* Normal Slew Rate Control */
807 .slew_rate_ctl = 1,
808
809 /* 0.85V */
810 .ldmos_bias_ctl = 1,
811
812 /* 50 Ohms */
813 .term_ctl = 3,
814
815 /* Enable External Current Source */
816 .ext_current_src_en = 1,
817
818 /* Enable Internal Current Source */
819 .int_current_src_en = 1,
820
821 /* 200mA */
822 .int_current_ctl = 8,
823
824 /* 17.6 mA */
825 .main_tap_current_select = 7,
826 },
827 {
828 /* 200mA */
829 .ext_current_ctl = 8,
830
831 /* Normal Slew Rate Control */
832 .slew_rate_ctl = 1,
833
834 /* 0.85V */
835 .ldmos_bias_ctl = 1,
836
837 /* 50 Ohms */
838 .term_ctl = 3,
839
840 /* Enable External Current Source */
841 .ext_current_src_en = 1,
842
843 /* Enable Internal Current Source */
844 .int_current_src_en = 1,
845
846 /* 200mA */
847 .int_current_ctl = 8,
848
849 /* 17.6 mA */
850 .main_tap_current_select = 7,
851 },
852 {
853 /* 200mA */
854 .ext_current_ctl = 8,
855
856 /* Normal Slew Rate Control */
857 .slew_rate_ctl = 1,
858
859 /* 0.85V */
860 .ldmos_bias_ctl = 1,
861
862 /* 50 Ohms */
863 .term_ctl = 3,
864
865 /* Enable External Current Source */
866 .ext_current_src_en = 1,
867
868 /* Enable Internal Current Source */
869 .int_current_src_en = 1,
870
871 /* 200mA */
872 .int_current_ctl = 8,
873
874 /* 17.6 mA */
875 .main_tap_current_select = 7,
876 },
877 },
878 {
879 /* 200mA */
880 .ext_current_ctl = 8,
881
882 /* Normal Slew Rate Control */
883 .slew_rate_ctl = 1,
884
885 /* 0.85V */
886 .ldmos_bias_ctl = 1,
887
888 /* External Current Source Half Swing Enable*/
889 .ext_current_src_hs_en = 1,
890
891 /* 50 Ohms */
892 .term_ctl = 3,
893
894 /* Enable External Current Source */
895 .ext_current_src_en = 1,
896
897 /* Enable Internal Current Source */
898 .int_current_src_en = 1,
899
900 /* 200mA */
901 .int_current_ctl = 8,
902
903 /* Internal Current Source Half Swing Enable*/
904 .int_current_src_hs_en = 1,
905
906 /* 17.6 mA */
907 .main_tap_current_select = 7,
908 },
909 },
910 };
911
912 static const struct vc6_phy_settings *
vc6_phy_get_settings(unsigned long long tmds_rate)913 vc6_phy_get_settings(unsigned long long tmds_rate)
914 {
915 unsigned int count = ARRAY_SIZE(vc6_hdmi_phy_settings);
916 unsigned int i;
917
918 for (i = 0; i < count; i++) {
919 const struct vc6_phy_settings *s = &vc6_hdmi_phy_settings[i];
920
921 if (tmds_rate >= s->min_rate && tmds_rate <= s->max_rate)
922 return s;
923 }
924
925 /*
926 * If the pixel clock exceeds our max setting, try the max
927 * setting anyway.
928 */
929 return &vc6_hdmi_phy_settings[count - 1];
930 }
931
932 static const struct vc6_phy_lane_settings *
vc6_phy_get_channel_settings(enum vc4_hdmi_phy_channel chan,unsigned long long tmds_rate)933 vc6_phy_get_channel_settings(enum vc4_hdmi_phy_channel chan,
934 unsigned long long tmds_rate)
935 {
936 const struct vc6_phy_settings *settings = vc6_phy_get_settings(tmds_rate);
937
938 if (chan == PHY_LANE_CK)
939 return &settings->clock;
940
941 return &settings->channel[chan];
942 }
943
vc6_hdmi_reset_phy(struct vc4_hdmi * vc4_hdmi)944 static void vc6_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
945 {
946 lockdep_assert_held(&vc4_hdmi->hw_lock);
947
948 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
949 HDMI_WRITE(HDMI_TX_PHY_POWERUP_CTL, 0);
950 }
951
vc6_hdmi_phy_init(struct vc4_hdmi * vc4_hdmi,struct drm_connector_state * conn_state)952 void vc6_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
953 struct drm_connector_state *conn_state)
954 {
955 const struct vc6_phy_lane_settings *chan0_settings;
956 const struct vc6_phy_lane_settings *chan1_settings;
957 const struct vc6_phy_lane_settings *chan2_settings;
958 const struct vc6_phy_lane_settings *clock_settings;
959 const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
960 unsigned long long pixel_freq = conn_state->hdmi.tmds_char_rate;
961 unsigned long long vco_freq;
962 unsigned char word_sel;
963 unsigned long flags;
964 unsigned int vco_div;
965
966 vco_freq = vc6_phy_get_vco_freq(pixel_freq, &vco_div);
967
968 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
969
970 vc6_hdmi_reset_phy(vc4_hdmi);
971
972 HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_0, 0x810c6000);
973 HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_1, 0x00b8c451);
974 HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_2, 0x46402e31);
975 HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_3, 0x00b8c005);
976 HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_4, 0x42410261);
977 HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_5, 0xcc021001);
978 HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_6, 0xc8301c80);
979 HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_7, 0xb0804444);
980 HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_8, 0xf80f8000);
981
982 HDMI_WRITE(HDMI_TX_PHY_PLL_REFCLK,
983 VC6_HDMI_TX_PHY_PLL_REFCLK_REFCLK_SEL_CMOS |
984 VC4_SET_FIELD(54, VC6_HDMI_TX_PHY_PLL_REFCLK_REFFRQ));
985
986 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x7f);
987
988 HDMI_WRITE(HDMI_RM_OFFSET,
989 VC4_HDMI_RM_OFFSET_ONLY |
990 VC4_SET_FIELD(phy_get_rm_offset(vco_freq),
991 VC4_HDMI_RM_OFFSET_OFFSET));
992
993 HDMI_WRITE(HDMI_TX_PHY_PLL_VCOCLK_DIV,
994 VC6_HDMI_TX_PHY_PLL_VCOCLK_DIV_VCODIV_EN |
995 VC4_SET_FIELD(vco_div,
996 VC6_HDMI_TX_PHY_PLL_VCOCLK_DIV_VCODIV));
997
998 HDMI_WRITE(HDMI_TX_PHY_PLL_CFG,
999 VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CFG_PDIV));
1000
1001 HDMI_WRITE(HDMI_TX_PHY_PLL_POST_KDIV,
1002 VC4_SET_FIELD(2, VC6_HDMI_TX_PHY_PLL_POST_KDIV_CLK0_SEL) |
1003 VC4_SET_FIELD(1, VC6_HDMI_TX_PHY_PLL_POST_KDIV_KDIV));
1004
1005 chan0_settings =
1006 vc6_phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_0],
1007 pixel_freq);
1008 HDMI_WRITE(HDMI_TX_PHY_CTL_0,
1009 VC4_SET_FIELD(chan0_settings->ext_current_ctl,
1010 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL) |
1011 VC4_SET_FIELD(chan0_settings->ffe_enable,
1012 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE) |
1013 VC4_SET_FIELD(chan0_settings->slew_rate_ctl,
1014 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL) |
1015 VC4_SET_FIELD(chan0_settings->ffe_post_tap_en,
1016 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN) |
1017 VC4_SET_FIELD(chan0_settings->ldmos_bias_ctl,
1018 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL) |
1019 VC4_SET_FIELD(chan0_settings->com_mode_ldmos_en,
1020 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN) |
1021 VC4_SET_FIELD(chan0_settings->edge_sel,
1022 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL) |
1023 VC4_SET_FIELD(chan0_settings->ext_current_src_hs_en,
1024 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN) |
1025 VC4_SET_FIELD(chan0_settings->term_ctl,
1026 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL) |
1027 VC4_SET_FIELD(chan0_settings->ext_current_src_en,
1028 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN) |
1029 VC4_SET_FIELD(chan0_settings->int_current_src_en,
1030 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN) |
1031 VC4_SET_FIELD(chan0_settings->int_current_ctl,
1032 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL) |
1033 VC4_SET_FIELD(chan0_settings->int_current_src_hs_en,
1034 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN) |
1035 VC4_SET_FIELD(chan0_settings->main_tap_current_select,
1036 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT) |
1037 VC4_SET_FIELD(chan0_settings->post_tap_current_select,
1038 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT) |
1039 VC4_SET_FIELD(chan0_settings->slew_ctl_slow_loading,
1040 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING) |
1041 VC4_SET_FIELD(chan0_settings->slew_ctl_slow_driving,
1042 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING) |
1043 VC4_SET_FIELD(chan0_settings->ffe_pre_tap_en,
1044 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN));
1045
1046 chan1_settings =
1047 vc6_phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_1],
1048 pixel_freq);
1049 HDMI_WRITE(HDMI_TX_PHY_CTL_1,
1050 VC4_SET_FIELD(chan1_settings->ext_current_ctl,
1051 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL) |
1052 VC4_SET_FIELD(chan1_settings->ffe_enable,
1053 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE) |
1054 VC4_SET_FIELD(chan1_settings->slew_rate_ctl,
1055 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL) |
1056 VC4_SET_FIELD(chan1_settings->ffe_post_tap_en,
1057 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN) |
1058 VC4_SET_FIELD(chan1_settings->ldmos_bias_ctl,
1059 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL) |
1060 VC4_SET_FIELD(chan1_settings->com_mode_ldmos_en,
1061 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN) |
1062 VC4_SET_FIELD(chan1_settings->edge_sel,
1063 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL) |
1064 VC4_SET_FIELD(chan1_settings->ext_current_src_hs_en,
1065 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN) |
1066 VC4_SET_FIELD(chan1_settings->term_ctl,
1067 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL) |
1068 VC4_SET_FIELD(chan1_settings->ext_current_src_en,
1069 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN) |
1070 VC4_SET_FIELD(chan1_settings->int_current_src_en,
1071 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN) |
1072 VC4_SET_FIELD(chan1_settings->int_current_ctl,
1073 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL) |
1074 VC4_SET_FIELD(chan1_settings->int_current_src_hs_en,
1075 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN) |
1076 VC4_SET_FIELD(chan1_settings->main_tap_current_select,
1077 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT) |
1078 VC4_SET_FIELD(chan1_settings->post_tap_current_select,
1079 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT) |
1080 VC4_SET_FIELD(chan1_settings->slew_ctl_slow_loading,
1081 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING) |
1082 VC4_SET_FIELD(chan1_settings->slew_ctl_slow_driving,
1083 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING) |
1084 VC4_SET_FIELD(chan1_settings->ffe_pre_tap_en,
1085 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN));
1086
1087 chan2_settings =
1088 vc6_phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_2],
1089 pixel_freq);
1090 HDMI_WRITE(HDMI_TX_PHY_CTL_2,
1091 VC4_SET_FIELD(chan2_settings->ext_current_ctl,
1092 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL) |
1093 VC4_SET_FIELD(chan2_settings->ffe_enable,
1094 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE) |
1095 VC4_SET_FIELD(chan2_settings->slew_rate_ctl,
1096 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL) |
1097 VC4_SET_FIELD(chan2_settings->ffe_post_tap_en,
1098 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN) |
1099 VC4_SET_FIELD(chan2_settings->ldmos_bias_ctl,
1100 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL) |
1101 VC4_SET_FIELD(chan2_settings->com_mode_ldmos_en,
1102 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN) |
1103 VC4_SET_FIELD(chan2_settings->edge_sel,
1104 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL) |
1105 VC4_SET_FIELD(chan2_settings->ext_current_src_hs_en,
1106 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN) |
1107 VC4_SET_FIELD(chan2_settings->term_ctl,
1108 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL) |
1109 VC4_SET_FIELD(chan2_settings->ext_current_src_en,
1110 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN) |
1111 VC4_SET_FIELD(chan2_settings->int_current_src_en,
1112 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN) |
1113 VC4_SET_FIELD(chan2_settings->int_current_ctl,
1114 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL) |
1115 VC4_SET_FIELD(chan2_settings->int_current_src_hs_en,
1116 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN) |
1117 VC4_SET_FIELD(chan2_settings->main_tap_current_select,
1118 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT) |
1119 VC4_SET_FIELD(chan2_settings->post_tap_current_select,
1120 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT) |
1121 VC4_SET_FIELD(chan2_settings->slew_ctl_slow_loading,
1122 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING) |
1123 VC4_SET_FIELD(chan2_settings->slew_ctl_slow_driving,
1124 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING) |
1125 VC4_SET_FIELD(chan2_settings->ffe_pre_tap_en,
1126 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN));
1127
1128 clock_settings =
1129 vc6_phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_CK],
1130 pixel_freq);
1131 HDMI_WRITE(HDMI_TX_PHY_CTL_CK,
1132 VC4_SET_FIELD(clock_settings->ext_current_ctl,
1133 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL) |
1134 VC4_SET_FIELD(clock_settings->ffe_enable,
1135 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE) |
1136 VC4_SET_FIELD(clock_settings->slew_rate_ctl,
1137 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL) |
1138 VC4_SET_FIELD(clock_settings->ffe_post_tap_en,
1139 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN) |
1140 VC4_SET_FIELD(clock_settings->ldmos_bias_ctl,
1141 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL) |
1142 VC4_SET_FIELD(clock_settings->com_mode_ldmos_en,
1143 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN) |
1144 VC4_SET_FIELD(clock_settings->edge_sel,
1145 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL) |
1146 VC4_SET_FIELD(clock_settings->ext_current_src_hs_en,
1147 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN) |
1148 VC4_SET_FIELD(clock_settings->term_ctl,
1149 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL) |
1150 VC4_SET_FIELD(clock_settings->ext_current_src_en,
1151 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN) |
1152 VC4_SET_FIELD(clock_settings->int_current_src_en,
1153 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN) |
1154 VC4_SET_FIELD(clock_settings->int_current_ctl,
1155 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL) |
1156 VC4_SET_FIELD(clock_settings->int_current_src_hs_en,
1157 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN) |
1158 VC4_SET_FIELD(clock_settings->main_tap_current_select,
1159 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT) |
1160 VC4_SET_FIELD(clock_settings->post_tap_current_select,
1161 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT) |
1162 VC4_SET_FIELD(clock_settings->slew_ctl_slow_loading,
1163 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING) |
1164 VC4_SET_FIELD(clock_settings->slew_ctl_slow_driving,
1165 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING) |
1166 VC4_SET_FIELD(clock_settings->ffe_pre_tap_en,
1167 VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN));
1168
1169 if (pixel_freq >= 340000000)
1170 word_sel = 3;
1171 else
1172 word_sel = 0;
1173 HDMI_WRITE(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, word_sel);
1174
1175 HDMI_WRITE(HDMI_TX_PHY_POWERUP_CTL,
1176 VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_BG_PWRUP |
1177 VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_LDO_PWRUP |
1178 VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_BIAS_PWRUP |
1179 VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_CK_PWRUP |
1180 VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_2_PWRUP |
1181 VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_1_PWRUP |
1182 VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_0_PWRUP);
1183
1184 HDMI_WRITE(HDMI_TX_PHY_PLL_POWERUP_CTL,
1185 VC6_HDMI_TX_PHY_PLL_POWERUP_CTL_PLL_PWRUP);
1186
1187 HDMI_WRITE(HDMI_TX_PHY_PLL_RESET_CTL,
1188 HDMI_READ(HDMI_TX_PHY_PLL_RESET_CTL) &
1189 ~VC6_HDMI_TX_PHY_PLL_RESET_CTL_PLL_RESETB);
1190
1191 HDMI_WRITE(HDMI_TX_PHY_PLL_RESET_CTL,
1192 HDMI_READ(HDMI_TX_PHY_PLL_RESET_CTL) |
1193 VC6_HDMI_TX_PHY_PLL_RESET_CTL_PLL_RESETB);
1194
1195 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
1196 }
1197
vc6_hdmi_phy_disable(struct vc4_hdmi * vc4_hdmi)1198 void vc6_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
1199 {
1200 }
1201