]> Git Repo - linux.git/blob - drivers/gpu/drm/vc4/vc4_hdmi_phy.c
Merge tag 'for-linus' of https://github.com/openrisc/linux
[linux.git] / drivers / gpu / drm / vc4 / vc4_hdmi_phy.c
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 <[email protected]>
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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
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 *
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 *
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
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
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
1198 void vc6_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
1199 {
1200 }
This page took 0.109387 seconds and 4 git commands to generate.