treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 284
[linux-block.git] / drivers / gpu / drm / msm / hdmi / hdmi_phy_8996.c
CommitLineData
97fb5e8d 1// SPDX-License-Identifier: GPL-2.0-only
e17afdce
AT
2/*
3 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
e17afdce
AT
4 */
5
6#include <linux/clk-provider.h>
7
8#include "hdmi.h"
9
10#define HDMI_VCO_MAX_FREQ 12000000000UL
11#define HDMI_VCO_MIN_FREQ 8000000000UL
12
13#define HDMI_PCLK_MAX_FREQ 600000000
14#define HDMI_PCLK_MIN_FREQ 25000000
15
16#define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD 3400000000UL
17#define HDMI_DIG_FREQ_BIT_CLK_THRESHOLD 1500000000UL
18#define HDMI_MID_FREQ_BIT_CLK_THRESHOLD 750000000UL
19#define HDMI_CORECLK_DIV 5
20#define HDMI_DEFAULT_REF_CLOCK 19200000
21#define HDMI_PLL_CMP_CNT 1024
22
23#define HDMI_PLL_POLL_MAX_READS 100
24#define HDMI_PLL_POLL_TIMEOUT_US 150
25
26#define HDMI_NUM_TX_CHANNEL 4
27
28struct hdmi_pll_8996 {
29 struct platform_device *pdev;
30 struct clk_hw clk_hw;
31
32 /* pll mmio base */
33 void __iomem *mmio_qserdes_com;
34 /* tx channel base */
35 void __iomem *mmio_qserdes_tx[HDMI_NUM_TX_CHANNEL];
36};
37
38#define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8996, clk_hw)
39
40struct hdmi_8996_phy_pll_reg_cfg {
41 u32 tx_lx_lane_mode[HDMI_NUM_TX_CHANNEL];
42 u32 tx_lx_tx_band[HDMI_NUM_TX_CHANNEL];
43 u32 com_svs_mode_clk_sel;
44 u32 com_hsclk_sel;
45 u32 com_pll_cctrl_mode0;
46 u32 com_pll_rctrl_mode0;
47 u32 com_cp_ctrl_mode0;
48 u32 com_dec_start_mode0;
49 u32 com_div_frac_start1_mode0;
50 u32 com_div_frac_start2_mode0;
51 u32 com_div_frac_start3_mode0;
52 u32 com_integloop_gain0_mode0;
53 u32 com_integloop_gain1_mode0;
54 u32 com_lock_cmp_en;
55 u32 com_lock_cmp1_mode0;
56 u32 com_lock_cmp2_mode0;
57 u32 com_lock_cmp3_mode0;
58 u32 com_core_clk_en;
59 u32 com_coreclk_div;
60 u32 com_vco_tune_ctrl;
61
62 u32 tx_lx_tx_drv_lvl[HDMI_NUM_TX_CHANNEL];
63 u32 tx_lx_tx_emp_post1_lvl[HDMI_NUM_TX_CHANNEL];
64 u32 tx_lx_vmode_ctrl1[HDMI_NUM_TX_CHANNEL];
65 u32 tx_lx_vmode_ctrl2[HDMI_NUM_TX_CHANNEL];
66 u32 tx_lx_res_code_lane_tx[HDMI_NUM_TX_CHANNEL];
67 u32 tx_lx_hp_pd_enables[HDMI_NUM_TX_CHANNEL];
68
69 u32 phy_mode;
70};
71
72struct hdmi_8996_post_divider {
73 u64 vco_freq;
74 int hsclk_divsel;
75 int vco_ratio;
76 int tx_band_sel;
77 int half_rate_mode;
78};
79
80static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8996 *pll)
81{
82 return platform_get_drvdata(pll->pdev);
83}
84
85static inline void hdmi_pll_write(struct hdmi_pll_8996 *pll, int offset,
86 u32 data)
87{
88 msm_writel(data, pll->mmio_qserdes_com + offset);
89}
90
91static inline u32 hdmi_pll_read(struct hdmi_pll_8996 *pll, int offset)
92{
93 return msm_readl(pll->mmio_qserdes_com + offset);
94}
95
96static inline void hdmi_tx_chan_write(struct hdmi_pll_8996 *pll, int channel,
97 int offset, int data)
98{
99 msm_writel(data, pll->mmio_qserdes_tx[channel] + offset);
100}
101
102static inline u32 pll_get_cpctrl(u64 frac_start, unsigned long ref_clk,
103 bool gen_ssc)
104{
105 if ((frac_start != 0) || gen_ssc)
106 return (11000000 / (ref_clk / 20));
107
108 return 0x23;
109}
110
111static inline u32 pll_get_rctrl(u64 frac_start, bool gen_ssc)
112{
113 if ((frac_start != 0) || gen_ssc)
114 return 0x16;
115
116 return 0x10;
117}
118
119static inline u32 pll_get_cctrl(u64 frac_start, bool gen_ssc)
120{
121 if ((frac_start != 0) || gen_ssc)
122 return 0x28;
123
124 return 0x1;
125}
126
127static inline u32 pll_get_integloop_gain(u64 frac_start, u64 bclk, u32 ref_clk,
128 bool gen_ssc)
129{
130 int digclk_divsel = bclk >= HDMI_DIG_FREQ_BIT_CLK_THRESHOLD ? 1 : 2;
131 u64 base;
132
133 if ((frac_start != 0) || gen_ssc)
134 base = (64 * ref_clk) / HDMI_DEFAULT_REF_CLOCK;
135 else
136 base = (1022 * ref_clk) / 100;
137
138 base <<= digclk_divsel;
139
140 return (base <= 2046 ? base : 2046);
141}
142
143static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk)
144{
145 u64 dividend = HDMI_PLL_CMP_CNT * fdata;
146 u32 divisor = ref_clk * 10;
147 u32 rem;
148
149 rem = do_div(dividend, divisor);
150 if (rem > (divisor >> 1))
151 dividend++;
152
153 return dividend - 1;
154}
155
156static inline u64 pll_cmp_to_fdata(u32 pll_cmp, unsigned long ref_clk)
157{
158 u64 fdata = ((u64)pll_cmp) * ref_clk * 10;
159
160 do_div(fdata, HDMI_PLL_CMP_CNT);
161
162 return fdata;
163}
164
165static int pll_get_post_div(struct hdmi_8996_post_divider *pd, u64 bclk)
166{
167 int ratio[] = { 2, 3, 4, 5, 6, 9, 10, 12, 14, 15, 20, 21, 25, 28, 35 };
168 int hs_divsel[] = { 0, 4, 8, 12, 1, 5, 2, 9, 3, 13, 10, 7, 14, 11, 15 };
169 int tx_band_sel[] = { 0, 1, 2, 3 };
170 u64 vco_freq[60];
171 u64 vco, vco_optimal;
172 int half_rate_mode = 0;
173 int vco_optimal_index, vco_freq_index;
174 int i, j;
175
176retry:
177 vco_optimal = HDMI_VCO_MAX_FREQ;
178 vco_optimal_index = -1;
179 vco_freq_index = 0;
180 for (i = 0; i < 15; i++) {
181 for (j = 0; j < 4; j++) {
182 u32 ratio_mult = ratio[i] << tx_band_sel[j];
183
184 vco = bclk >> half_rate_mode;
185 vco *= ratio_mult;
186 vco_freq[vco_freq_index++] = vco;
187 }
188 }
189
190 for (i = 0; i < 60; i++) {
191 u64 vco_tmp = vco_freq[i];
192
193 if ((vco_tmp >= HDMI_VCO_MIN_FREQ) &&
194 (vco_tmp <= vco_optimal)) {
195 vco_optimal = vco_tmp;
196 vco_optimal_index = i;
197 }
198 }
199
200 if (vco_optimal_index == -1) {
201 if (!half_rate_mode) {
202 half_rate_mode = 1;
203 goto retry;
204 }
205 } else {
206 pd->vco_freq = vco_optimal;
207 pd->tx_band_sel = tx_band_sel[vco_optimal_index % 4];
208 pd->vco_ratio = ratio[vco_optimal_index / 4];
209 pd->hsclk_divsel = hs_divsel[vco_optimal_index / 4];
210
211 return 0;
212 }
213
214 return -EINVAL;
215}
216
217static int pll_calculate(unsigned long pix_clk, unsigned long ref_clk,
218 struct hdmi_8996_phy_pll_reg_cfg *cfg)
219{
220 struct hdmi_8996_post_divider pd;
221 u64 bclk;
222 u64 tmds_clk;
223 u64 dec_start;
224 u64 frac_start;
225 u64 fdata;
226 u32 pll_divisor;
227 u32 rem;
228 u32 cpctrl;
229 u32 rctrl;
230 u32 cctrl;
231 u32 integloop_gain;
232 u32 pll_cmp;
233 int i, ret;
234
235 /* bit clk = 10 * pix_clk */
236 bclk = ((u64)pix_clk) * 10;
237
238 if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD)
239 tmds_clk = pix_clk >> 2;
240 else
241 tmds_clk = pix_clk;
242
243 ret = pll_get_post_div(&pd, bclk);
244 if (ret)
245 return ret;
246
247 dec_start = pd.vco_freq;
248 pll_divisor = 4 * ref_clk;
249 do_div(dec_start, pll_divisor);
250
251 frac_start = pd.vco_freq * (1 << 20);
252
253 rem = do_div(frac_start, pll_divisor);
254 frac_start -= dec_start * (1 << 20);
255 if (rem > (pll_divisor >> 1))
256 frac_start++;
257
258 cpctrl = pll_get_cpctrl(frac_start, ref_clk, false);
259 rctrl = pll_get_rctrl(frac_start, false);
260 cctrl = pll_get_cctrl(frac_start, false);
261 integloop_gain = pll_get_integloop_gain(frac_start, bclk,
262 ref_clk, false);
263
264 fdata = pd.vco_freq;
265 do_div(fdata, pd.vco_ratio);
266
267 pll_cmp = pll_get_pll_cmp(fdata, ref_clk);
268
269 DBG("VCO freq: %llu", pd.vco_freq);
270 DBG("fdata: %llu", fdata);
271 DBG("pix_clk: %lu", pix_clk);
272 DBG("tmds clk: %llu", tmds_clk);
273 DBG("HSCLK_SEL: %d", pd.hsclk_divsel);
274 DBG("DEC_START: %llu", dec_start);
275 DBG("DIV_FRAC_START: %llu", frac_start);
276 DBG("PLL_CPCTRL: %u", cpctrl);
277 DBG("PLL_RCTRL: %u", rctrl);
278 DBG("PLL_CCTRL: %u", cctrl);
279 DBG("INTEGLOOP_GAIN: %u", integloop_gain);
280 DBG("TX_BAND: %d", pd.tx_band_sel);
281 DBG("PLL_CMP: %u", pll_cmp);
282
283 /* Convert these values to register specific values */
284 if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD)
285 cfg->com_svs_mode_clk_sel = 1;
286 else
287 cfg->com_svs_mode_clk_sel = 2;
288
289 cfg->com_hsclk_sel = (0x20 | pd.hsclk_divsel);
290 cfg->com_pll_cctrl_mode0 = cctrl;
291 cfg->com_pll_rctrl_mode0 = rctrl;
292 cfg->com_cp_ctrl_mode0 = cpctrl;
293 cfg->com_dec_start_mode0 = dec_start;
294 cfg->com_div_frac_start1_mode0 = (frac_start & 0xff);
295 cfg->com_div_frac_start2_mode0 = ((frac_start & 0xff00) >> 8);
296 cfg->com_div_frac_start3_mode0 = ((frac_start & 0xf0000) >> 16);
297 cfg->com_integloop_gain0_mode0 = (integloop_gain & 0xff);
298 cfg->com_integloop_gain1_mode0 = ((integloop_gain & 0xf00) >> 8);
299 cfg->com_lock_cmp1_mode0 = (pll_cmp & 0xff);
300 cfg->com_lock_cmp2_mode0 = ((pll_cmp & 0xff00) >> 8);
301 cfg->com_lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16);
302 cfg->com_lock_cmp_en = 0x0;
303 cfg->com_core_clk_en = 0x2c;
304 cfg->com_coreclk_div = HDMI_CORECLK_DIV;
305 cfg->phy_mode = (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x10 : 0x0;
306 cfg->com_vco_tune_ctrl = 0x0;
307
308 cfg->tx_lx_lane_mode[0] =
309 cfg->tx_lx_lane_mode[2] = 0x43;
310
311 cfg->tx_lx_hp_pd_enables[0] =
312 cfg->tx_lx_hp_pd_enables[1] =
313 cfg->tx_lx_hp_pd_enables[2] = 0x0c;
314 cfg->tx_lx_hp_pd_enables[3] = 0x3;
315
316 for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++)
317 cfg->tx_lx_tx_band[i] = pd.tx_band_sel + 4;
318
319 if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) {
320 cfg->tx_lx_tx_drv_lvl[0] =
321 cfg->tx_lx_tx_drv_lvl[1] =
322 cfg->tx_lx_tx_drv_lvl[2] = 0x25;
323 cfg->tx_lx_tx_drv_lvl[3] = 0x22;
324
325 cfg->tx_lx_tx_emp_post1_lvl[0] =
326 cfg->tx_lx_tx_emp_post1_lvl[1] =
327 cfg->tx_lx_tx_emp_post1_lvl[2] = 0x23;
328 cfg->tx_lx_tx_emp_post1_lvl[3] = 0x27;
329
330 cfg->tx_lx_vmode_ctrl1[0] =
331 cfg->tx_lx_vmode_ctrl1[1] =
332 cfg->tx_lx_vmode_ctrl1[2] =
333 cfg->tx_lx_vmode_ctrl1[3] = 0x00;
334
335 cfg->tx_lx_vmode_ctrl2[0] =
336 cfg->tx_lx_vmode_ctrl2[1] =
337 cfg->tx_lx_vmode_ctrl2[2] = 0x0D;
338
339 cfg->tx_lx_vmode_ctrl2[3] = 0x00;
340 } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) {
341 for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
342 cfg->tx_lx_tx_drv_lvl[i] = 0x25;
343 cfg->tx_lx_tx_emp_post1_lvl[i] = 0x23;
344 cfg->tx_lx_vmode_ctrl1[i] = 0x00;
345 }
346
347 cfg->tx_lx_vmode_ctrl2[0] =
348 cfg->tx_lx_vmode_ctrl2[1] =
349 cfg->tx_lx_vmode_ctrl2[2] = 0x0D;
350 cfg->tx_lx_vmode_ctrl2[3] = 0x00;
351 } else {
352 for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
353 cfg->tx_lx_tx_drv_lvl[i] = 0x20;
354 cfg->tx_lx_tx_emp_post1_lvl[i] = 0x20;
355 cfg->tx_lx_vmode_ctrl1[i] = 0x00;
356 cfg->tx_lx_vmode_ctrl2[i] = 0x0E;
357 }
358 }
359
360 DBG("com_svs_mode_clk_sel = 0x%x", cfg->com_svs_mode_clk_sel);
361 DBG("com_hsclk_sel = 0x%x", cfg->com_hsclk_sel);
362 DBG("com_lock_cmp_en = 0x%x", cfg->com_lock_cmp_en);
363 DBG("com_pll_cctrl_mode0 = 0x%x", cfg->com_pll_cctrl_mode0);
364 DBG("com_pll_rctrl_mode0 = 0x%x", cfg->com_pll_rctrl_mode0);
365 DBG("com_cp_ctrl_mode0 = 0x%x", cfg->com_cp_ctrl_mode0);
366 DBG("com_dec_start_mode0 = 0x%x", cfg->com_dec_start_mode0);
367 DBG("com_div_frac_start1_mode0 = 0x%x", cfg->com_div_frac_start1_mode0);
368 DBG("com_div_frac_start2_mode0 = 0x%x", cfg->com_div_frac_start2_mode0);
369 DBG("com_div_frac_start3_mode0 = 0x%x", cfg->com_div_frac_start3_mode0);
370 DBG("com_integloop_gain0_mode0 = 0x%x", cfg->com_integloop_gain0_mode0);
371 DBG("com_integloop_gain1_mode0 = 0x%x", cfg->com_integloop_gain1_mode0);
372 DBG("com_lock_cmp1_mode0 = 0x%x", cfg->com_lock_cmp1_mode0);
373 DBG("com_lock_cmp2_mode0 = 0x%x", cfg->com_lock_cmp2_mode0);
374 DBG("com_lock_cmp3_mode0 = 0x%x", cfg->com_lock_cmp3_mode0);
375 DBG("com_core_clk_en = 0x%x", cfg->com_core_clk_en);
376 DBG("com_coreclk_div = 0x%x", cfg->com_coreclk_div);
377 DBG("phy_mode = 0x%x", cfg->phy_mode);
378
379 DBG("tx_l0_lane_mode = 0x%x", cfg->tx_lx_lane_mode[0]);
380 DBG("tx_l2_lane_mode = 0x%x", cfg->tx_lx_lane_mode[2]);
381
382 for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
383 DBG("tx_l%d_tx_band = 0x%x", i, cfg->tx_lx_tx_band[i]);
384 DBG("tx_l%d_tx_drv_lvl = 0x%x", i, cfg->tx_lx_tx_drv_lvl[i]);
385 DBG("tx_l%d_tx_emp_post1_lvl = 0x%x", i,
386 cfg->tx_lx_tx_emp_post1_lvl[i]);
387 DBG("tx_l%d_vmode_ctrl1 = 0x%x", i, cfg->tx_lx_vmode_ctrl1[i]);
388 DBG("tx_l%d_vmode_ctrl2 = 0x%x", i, cfg->tx_lx_vmode_ctrl2[i]);
389 }
390
391 return 0;
392}
393
394static int hdmi_8996_pll_set_clk_rate(struct clk_hw *hw, unsigned long rate,
395 unsigned long parent_rate)
396{
397 struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
398 struct hdmi_phy *phy = pll_get_phy(pll);
399 struct hdmi_8996_phy_pll_reg_cfg cfg;
400 int i, ret;
401
402 memset(&cfg, 0x00, sizeof(cfg));
403
404 ret = pll_calculate(rate, parent_rate, &cfg);
405 if (ret) {
406 DRM_ERROR("PLL calculation failed\n");
407 return ret;
408 }
409
410 /* Initially shut down PHY */
411 DBG("Disabling PHY");
412 hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x0);
413 udelay(500);
414
415 /* Power up sequence */
416 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_CTRL, 0x04);
417
418 hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x1);
419 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_RESETSM_CNTRL, 0x20);
420 hdmi_phy_write(phy, REG_HDMI_8996_PHY_TX0_TX1_LANE_CTL, 0x0F);
421 hdmi_phy_write(phy, REG_HDMI_8996_PHY_TX2_TX3_LANE_CTL, 0x0F);
422
423 for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
424 hdmi_tx_chan_write(pll, i,
425 REG_HDMI_PHY_QSERDES_TX_LX_CLKBUF_ENABLE,
426 0x03);
427 hdmi_tx_chan_write(pll, i,
428 REG_HDMI_PHY_QSERDES_TX_LX_TX_BAND,
429 cfg.tx_lx_tx_band[i]);
430 hdmi_tx_chan_write(pll, i,
431 REG_HDMI_PHY_QSERDES_TX_LX_RESET_TSYNC_EN,
432 0x03);
433 }
434
435 hdmi_tx_chan_write(pll, 0, REG_HDMI_PHY_QSERDES_TX_LX_LANE_MODE,
436 cfg.tx_lx_lane_mode[0]);
437 hdmi_tx_chan_write(pll, 2, REG_HDMI_PHY_QSERDES_TX_LX_LANE_MODE,
438 cfg.tx_lx_lane_mode[2]);
439
440 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1E);
441 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x07);
442 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYSCLK_EN_SEL, 0x37);
443 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYS_CLK_CTRL, 0x02);
444 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CLK_ENABLE1, 0x0E);
445
446 /* Bypass VCO calibration */
447 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SVS_MODE_CLK_SEL,
448 cfg.com_svs_mode_clk_sel);
449
450 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_TRIM, 0x0F);
451 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_IVCO, 0x0F);
452 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_VCO_TUNE_CTRL,
453 cfg.com_vco_tune_ctrl);
454
455 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_CTRL, 0x06);
456
457 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CLK_SELECT, 0x30);
458 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_HSCLK_SEL,
459 cfg.com_hsclk_sel);
460 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP_EN,
461 cfg.com_lock_cmp_en);
462
463 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_CCTRL_MODE0,
464 cfg.com_pll_cctrl_mode0);
465 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_RCTRL_MODE0,
466 cfg.com_pll_rctrl_mode0);
467 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CP_CTRL_MODE0,
468 cfg.com_cp_ctrl_mode0);
469 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DEC_START_MODE0,
470 cfg.com_dec_start_mode0);
471 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START1_MODE0,
472 cfg.com_div_frac_start1_mode0);
473 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START2_MODE0,
474 cfg.com_div_frac_start2_mode0);
475 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START3_MODE0,
476 cfg.com_div_frac_start3_mode0);
477
478 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_INTEGLOOP_GAIN0_MODE0,
479 cfg.com_integloop_gain0_mode0);
480 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_INTEGLOOP_GAIN1_MODE0,
481 cfg.com_integloop_gain1_mode0);
482
483 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP1_MODE0,
484 cfg.com_lock_cmp1_mode0);
485 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP2_MODE0,
486 cfg.com_lock_cmp2_mode0);
487 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP3_MODE0,
488 cfg.com_lock_cmp3_mode0);
489
490 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_VCO_TUNE_MAP, 0x00);
491 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CORE_CLK_EN,
492 cfg.com_core_clk_en);
493 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CORECLK_DIV,
494 cfg.com_coreclk_div);
495 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CMN_CONFIG, 0x02);
496
497 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_RESCODE_DIV_NUM, 0x15);
498
499 /* TX lanes setup (TX 0/1/2/3) */
500 for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
501 hdmi_tx_chan_write(pll, i,
502 REG_HDMI_PHY_QSERDES_TX_LX_TX_DRV_LVL,
503 cfg.tx_lx_tx_drv_lvl[i]);
504 hdmi_tx_chan_write(pll, i,
505 REG_HDMI_PHY_QSERDES_TX_LX_TX_EMP_POST1_LVL,
506 cfg.tx_lx_tx_emp_post1_lvl[i]);
507 hdmi_tx_chan_write(pll, i,
508 REG_HDMI_PHY_QSERDES_TX_LX_VMODE_CTRL1,
509 cfg.tx_lx_vmode_ctrl1[i]);
510 hdmi_tx_chan_write(pll, i,
511 REG_HDMI_PHY_QSERDES_TX_LX_VMODE_CTRL2,
512 cfg.tx_lx_vmode_ctrl2[i]);
513 hdmi_tx_chan_write(pll, i,
514 REG_HDMI_PHY_QSERDES_TX_LX_TX_DRV_LVL_OFFSET,
515 0x00);
516 hdmi_tx_chan_write(pll, i,
517 REG_HDMI_PHY_QSERDES_TX_LX_RES_CODE_LANE_OFFSET,
518 0x00);
519 hdmi_tx_chan_write(pll, i,
520 REG_HDMI_PHY_QSERDES_TX_LX_TRAN_DRVR_EMP_EN,
521 0x03);
522 hdmi_tx_chan_write(pll, i,
523 REG_HDMI_PHY_QSERDES_TX_LX_PARRATE_REC_DETECT_IDLE_EN,
524 0x40);
525 hdmi_tx_chan_write(pll, i,
526 REG_HDMI_PHY_QSERDES_TX_LX_HP_PD_ENABLES,
527 cfg.tx_lx_hp_pd_enables[i]);
528 }
529
530 hdmi_phy_write(phy, REG_HDMI_8996_PHY_MODE, cfg.phy_mode);
531 hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x1F);
532
533 /*
534 * Ensure that vco configuration gets flushed to hardware before
535 * enabling the PLL
536 */
537 wmb();
538
539 return 0;
540}
541
542static int hdmi_8996_phy_ready_status(struct hdmi_phy *phy)
543{
544 u32 nb_tries = HDMI_PLL_POLL_MAX_READS;
545 unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
546 u32 status;
547 int phy_ready = 0;
548
549 DBG("Waiting for PHY ready");
550
551 while (nb_tries--) {
552 status = hdmi_phy_read(phy, REG_HDMI_8996_PHY_STATUS);
553 phy_ready = status & BIT(0);
554
555 if (phy_ready)
556 break;
557
558 udelay(timeout);
559 }
560
561 DBG("PHY is %sready", phy_ready ? "" : "*not* ");
562
563 return phy_ready;
564}
565
566static int hdmi_8996_pll_lock_status(struct hdmi_pll_8996 *pll)
567{
568 u32 status;
569 int nb_tries = HDMI_PLL_POLL_MAX_READS;
570 unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
571 int pll_locked = 0;
572
573 DBG("Waiting for PLL lock");
574
575 while (nb_tries--) {
576 status = hdmi_pll_read(pll,
577 REG_HDMI_PHY_QSERDES_COM_C_READY_STATUS);
578 pll_locked = status & BIT(0);
579
580 if (pll_locked)
581 break;
582
583 udelay(timeout);
584 }
585
586 DBG("HDMI PLL is %slocked", pll_locked ? "" : "*not* ");
587
588 return pll_locked;
589}
590
591static int hdmi_8996_pll_prepare(struct clk_hw *hw)
592{
593 struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
594 struct hdmi_phy *phy = pll_get_phy(pll);
595 int i, ret = 0;
596
597 hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x1);
598 udelay(100);
599
600 hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x19);
601 udelay(100);
602
603 ret = hdmi_8996_pll_lock_status(pll);
604 if (!ret)
605 return ret;
606
607 for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++)
608 hdmi_tx_chan_write(pll, i,
609 REG_HDMI_PHY_QSERDES_TX_LX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN,
610 0x6F);
611
612 /* Disable SSC */
613 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_PER1, 0x0);
614 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_PER2, 0x0);
615 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_STEP_SIZE1, 0x0);
616 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_STEP_SIZE2, 0x0);
617 hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_EN_CENTER, 0x2);
618
619 ret = hdmi_8996_phy_ready_status(phy);
620 if (!ret)
621 return ret;
622
623 /* Restart the retiming buffer */
624 hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x18);
625 udelay(1);
626 hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x19);
627
628 return 0;
629}
630
631static long hdmi_8996_pll_round_rate(struct clk_hw *hw,
632 unsigned long rate,
633 unsigned long *parent_rate)
634{
635 if (rate < HDMI_PCLK_MIN_FREQ)
636 return HDMI_PCLK_MIN_FREQ;
637 else if (rate > HDMI_PCLK_MAX_FREQ)
638 return HDMI_PCLK_MAX_FREQ;
639 else
640 return rate;
641}
642
643static unsigned long hdmi_8996_pll_recalc_rate(struct clk_hw *hw,
644 unsigned long parent_rate)
645{
646 struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
647 u64 fdata;
648 u32 cmp1, cmp2, cmp3, pll_cmp;
649
650 cmp1 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP1_MODE0);
651 cmp2 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP2_MODE0);
652 cmp3 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP3_MODE0);
653
654 pll_cmp = cmp1 | (cmp2 << 8) | (cmp3 << 16);
655
656 fdata = pll_cmp_to_fdata(pll_cmp + 1, parent_rate);
657
658 do_div(fdata, 10);
659
660 return fdata;
661}
662
663static void hdmi_8996_pll_unprepare(struct clk_hw *hw)
664{
b474cbbb
AT
665 struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
666 struct hdmi_phy *phy = pll_get_phy(pll);
667
668 hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x6);
669 usleep_range(100, 150);
e17afdce
AT
670}
671
672static int hdmi_8996_pll_is_enabled(struct clk_hw *hw)
673{
674 struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
675 u32 status;
676 int pll_locked;
677
678 status = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_C_READY_STATUS);
679 pll_locked = status & BIT(0);
680
681 return pll_locked;
682}
683
684static struct clk_ops hdmi_8996_pll_ops = {
685 .set_rate = hdmi_8996_pll_set_clk_rate,
686 .round_rate = hdmi_8996_pll_round_rate,
687 .recalc_rate = hdmi_8996_pll_recalc_rate,
688 .prepare = hdmi_8996_pll_prepare,
689 .unprepare = hdmi_8996_pll_unprepare,
690 .is_enabled = hdmi_8996_pll_is_enabled,
691};
692
693static const char * const hdmi_pll_parents[] = {
694 "xo",
695};
696
697static struct clk_init_data pll_init = {
698 .name = "hdmipll",
699 .ops = &hdmi_8996_pll_ops,
700 .parent_names = hdmi_pll_parents,
701 .num_parents = ARRAY_SIZE(hdmi_pll_parents),
73b65b19 702 .flags = CLK_IGNORE_UNUSED,
e17afdce
AT
703};
704
fcda50c8 705int msm_hdmi_pll_8996_init(struct platform_device *pdev)
e17afdce
AT
706{
707 struct device *dev = &pdev->dev;
708 struct hdmi_pll_8996 *pll;
709 struct clk *clk;
710 int i;
711
712 pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
713 if (!pll)
714 return -ENOMEM;
715
716 pll->pdev = pdev;
717
718 pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll", "HDMI_PLL");
719 if (IS_ERR(pll->mmio_qserdes_com)) {
6a41da17 720 DRM_DEV_ERROR(dev, "failed to map pll base\n");
e17afdce
AT
721 return -ENOMEM;
722 }
723
724 for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
725 char name[32], label[32];
726
727 snprintf(name, sizeof(name), "hdmi_tx_l%d", i);
728 snprintf(label, sizeof(label), "HDMI_TX_L%d", i);
729
730 pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name, label);
731 if (IS_ERR(pll->mmio_qserdes_tx[i])) {
6a41da17 732 DRM_DEV_ERROR(dev, "failed to map pll base\n");
e17afdce
AT
733 return -ENOMEM;
734 }
735 }
736 pll->clk_hw.init = &pll_init;
737
738 clk = devm_clk_register(dev, &pll->clk_hw);
739 if (IS_ERR(clk)) {
6a41da17 740 DRM_DEV_ERROR(dev, "failed to register pll clock\n");
e17afdce
AT
741 return -EINVAL;
742 }
743
744 return 0;
745}
746
747static const char * const hdmi_phy_8996_reg_names[] = {
748 "vddio",
749 "vcca",
750};
751
752static const char * const hdmi_phy_8996_clk_names[] = {
aede1e9e 753 "iface", "ref",
e17afdce
AT
754};
755
fcda50c8 756const struct hdmi_phy_cfg msm_hdmi_phy_8996_cfg = {
e17afdce
AT
757 .type = MSM_HDMI_PHY_8996,
758 .reg_names = hdmi_phy_8996_reg_names,
759 .num_regs = ARRAY_SIZE(hdmi_phy_8996_reg_names),
760 .clk_names = hdmi_phy_8996_clk_names,
761 .num_clks = ARRAY_SIZE(hdmi_phy_8996_clk_names),
762};