]> Git Repo - linux.git/blob - drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c
Linux 6.14-rc3
[linux.git] / drivers / gpu / drm / msm / hdmi / hdmi_phy_8998.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
4  * Copyright (c) 2024 Freebox SAS
5  */
6
7 #include <linux/clk-provider.h>
8 #include <linux/delay.h>
9
10 #include "hdmi.h"
11
12 #define HDMI_VCO_MAX_FREQ                       12000000000UL
13 #define HDMI_VCO_MIN_FREQ                       8000000000UL
14
15 #define HDMI_PCLK_MAX_FREQ                      600000000
16 #define HDMI_PCLK_MIN_FREQ                      25000000
17
18 #define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD        3400000000UL
19 #define HDMI_DIG_FREQ_BIT_CLK_THRESHOLD         1500000000UL
20 #define HDMI_MID_FREQ_BIT_CLK_THRESHOLD         750000000UL
21 #define HDMI_CORECLK_DIV                        5
22 #define HDMI_DEFAULT_REF_CLOCK                  19200000
23 #define HDMI_PLL_CMP_CNT                        1024
24
25 #define HDMI_PLL_POLL_MAX_READS                 100
26 #define HDMI_PLL_POLL_TIMEOUT_US                150
27
28 #define HDMI_NUM_TX_CHANNEL                     4
29
30 struct hdmi_pll_8998 {
31         struct platform_device *pdev;
32         struct clk_hw clk_hw;
33         unsigned long rate;
34
35         /* pll mmio base */
36         void __iomem *mmio_qserdes_com;
37         /* tx channel base */
38         void __iomem *mmio_qserdes_tx[HDMI_NUM_TX_CHANNEL];
39 };
40
41 #define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8998, clk_hw)
42
43 struct hdmi_8998_phy_pll_reg_cfg {
44         u32 com_svs_mode_clk_sel;
45         u32 com_hsclk_sel;
46         u32 com_pll_cctrl_mode0;
47         u32 com_pll_rctrl_mode0;
48         u32 com_cp_ctrl_mode0;
49         u32 com_dec_start_mode0;
50         u32 com_div_frac_start1_mode0;
51         u32 com_div_frac_start2_mode0;
52         u32 com_div_frac_start3_mode0;
53         u32 com_integloop_gain0_mode0;
54         u32 com_integloop_gain1_mode0;
55         u32 com_lock_cmp_en;
56         u32 com_lock_cmp1_mode0;
57         u32 com_lock_cmp2_mode0;
58         u32 com_lock_cmp3_mode0;
59         u32 com_core_clk_en;
60         u32 com_coreclk_div_mode0;
61
62         u32 tx_lx_tx_band[HDMI_NUM_TX_CHANNEL];
63         u32 tx_lx_tx_drv_lvl[HDMI_NUM_TX_CHANNEL];
64         u32 tx_lx_tx_emp_post1_lvl[HDMI_NUM_TX_CHANNEL];
65         u32 tx_lx_pre_driver_1[HDMI_NUM_TX_CHANNEL];
66         u32 tx_lx_pre_driver_2[HDMI_NUM_TX_CHANNEL];
67         u32 tx_lx_res_code_offset[HDMI_NUM_TX_CHANNEL];
68
69         u32 phy_mode;
70 };
71
72 struct hdmi_8998_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
80 static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8998 *pll)
81 {
82         return platform_get_drvdata(pll->pdev);
83 }
84
85 static inline void hdmi_pll_write(struct hdmi_pll_8998 *pll, int offset,
86                                   u32 data)
87 {
88         writel(data, pll->mmio_qserdes_com + offset);
89 }
90
91 static inline u32 hdmi_pll_read(struct hdmi_pll_8998 *pll, int offset)
92 {
93         return readl(pll->mmio_qserdes_com + offset);
94 }
95
96 static inline void hdmi_tx_chan_write(struct hdmi_pll_8998 *pll, int channel,
97                                       int offset, int data)
98 {
99          writel(data, pll->mmio_qserdes_tx[channel] + offset);
100 }
101
102 static 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 0x8;
107
108         return 0x30;
109 }
110
111 static 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 0x18;
117 }
118
119 static inline u32 pll_get_cctrl(u64 frac_start, bool gen_ssc)
120 {
121         if ((frac_start != 0) || gen_ssc)
122                 return 0x34;
123
124         return 0x2;
125 }
126
127 static 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 = 0x3F;
135         else
136                 base = 0xC4;
137
138         base <<= (digclk_divsel == 2 ? 1 : 0);
139
140         return base;
141 }
142
143 static 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
156 #define HDMI_REF_CLOCK_HZ ((u64)19200000)
157 #define HDMI_MHZ_TO_HZ ((u64)1000000)
158 static int pll_get_post_div(struct hdmi_8998_post_divider *pd, u64 bclk)
159 {
160         static const u32 ratio_list[] = {1, 2, 3, 4, 5, 6, 9, 10, 12, 15, 25};
161         static const u32 band_list[] = {0, 1, 2, 3};
162         u32 const sz_ratio = ARRAY_SIZE(ratio_list);
163         u32 const sz_band = ARRAY_SIZE(band_list);
164         u32 const cmp_cnt = 1024;
165         u32 const th_min = 500, th_max = 1000;
166         u32 half_rate_mode = 0;
167         u32 list_elements;
168         int optimal_index;
169         u32 i, j, k;
170         u32 found_hsclk_divsel = 0, found_vco_ratio;
171         u32 found_tx_band_sel;
172         u64 const min_freq = HDMI_VCO_MIN_FREQ, max_freq = HDMI_VCO_MAX_FREQ;
173         u64 freq_list[ARRAY_SIZE(ratio_list) * ARRAY_SIZE(band_list)];
174         u64 found_vco_freq;
175         u64 freq_optimal;
176
177 find_optimal_index:
178         freq_optimal = max_freq;
179         optimal_index = -1;
180         list_elements = 0;
181
182         for (i = 0; i < sz_ratio; i++) {
183                 for (j = 0; j < sz_band; j++) {
184                         u64 freq = div_u64(bclk, (1 << half_rate_mode));
185
186                         freq *= (ratio_list[i] * (1 << band_list[j]));
187                         freq_list[list_elements++] = freq;
188                 }
189         }
190
191         for (k = 0; k < ARRAY_SIZE(freq_list); k++) {
192                 u32 const clks_pll_div = 2, core_clk_div = 5;
193                 u32 const rng1 = 16, rng2 = 8;
194                 u32 th1, th2;
195                 u64 core_clk, rvar1, rem;
196
197                 core_clk = div_u64(freq_list[k],
198                                    ratio_list[k / sz_band] * clks_pll_div *
199                                    core_clk_div);
200
201                 rvar1 = HDMI_REF_CLOCK_HZ * rng1 * HDMI_MHZ_TO_HZ;
202                 rvar1 = div64_u64_rem(rvar1, (cmp_cnt * core_clk), &rem);
203                 if (rem > ((cmp_cnt * core_clk) >> 1))
204                         rvar1++;
205                 th1 = rvar1;
206
207                 rvar1 = HDMI_REF_CLOCK_HZ * rng2 * HDMI_MHZ_TO_HZ;
208                 rvar1 = div64_u64_rem(rvar1, (cmp_cnt * core_clk), &rem);
209                 if (rem > ((cmp_cnt * core_clk) >> 1))
210                         rvar1++;
211                 th2 = rvar1;
212
213                 if (freq_list[k] >= min_freq &&
214                                 freq_list[k] <= max_freq) {
215                         if ((th1 >= th_min && th1 <= th_max) ||
216                                         (th2 >= th_min && th2 <= th_max)) {
217                                 if (freq_list[k] <= freq_optimal) {
218                                         freq_optimal = freq_list[k];
219                                         optimal_index = k;
220                                 }
221                         }
222                 }
223         }
224
225         if (optimal_index == -1) {
226                 if (!half_rate_mode) {
227                         half_rate_mode = 1;
228                         goto find_optimal_index;
229                 } else {
230                         return -EINVAL;
231                 }
232         } else {
233                 found_vco_ratio = ratio_list[optimal_index / sz_band];
234                 found_tx_band_sel = band_list[optimal_index % sz_band];
235                 found_vco_freq = freq_optimal;
236         }
237
238         switch (found_vco_ratio) {
239         case 1:
240                 found_hsclk_divsel = 15;
241                 break;
242         case 2:
243                 found_hsclk_divsel = 0;
244                 break;
245         case 3:
246                 found_hsclk_divsel = 4;
247                 break;
248         case 4:
249                 found_hsclk_divsel = 8;
250                 break;
251         case 5:
252                 found_hsclk_divsel = 12;
253                 break;
254         case 6:
255                 found_hsclk_divsel = 1;
256                 break;
257         case 9:
258                 found_hsclk_divsel = 5;
259                 break;
260         case 10:
261                 found_hsclk_divsel = 2;
262                 break;
263         case 12:
264                 found_hsclk_divsel = 9;
265                 break;
266         case 15:
267                 found_hsclk_divsel = 13;
268                 break;
269         case 25:
270                 found_hsclk_divsel = 14;
271                 break;
272         }
273
274         pd->vco_freq = found_vco_freq;
275         pd->tx_band_sel = found_tx_band_sel;
276         pd->vco_ratio = found_vco_ratio;
277         pd->hsclk_divsel = found_hsclk_divsel;
278
279         return 0;
280 }
281
282 static int pll_calculate(unsigned long pix_clk, unsigned long ref_clk,
283                          struct hdmi_8998_phy_pll_reg_cfg *cfg)
284 {
285         struct hdmi_8998_post_divider pd;
286         u64 bclk;
287         u64 dec_start;
288         u64 frac_start;
289         u64 fdata;
290         u32 pll_divisor;
291         u32 rem;
292         u32 cpctrl;
293         u32 rctrl;
294         u32 cctrl;
295         u32 integloop_gain;
296         u32 pll_cmp;
297         int i, ret;
298
299         /* bit clk = 10 * pix_clk */
300         bclk = ((u64)pix_clk) * 10;
301
302         ret = pll_get_post_div(&pd, bclk);
303         if (ret)
304                 return ret;
305
306         dec_start = pd.vco_freq;
307         pll_divisor = 4 * ref_clk;
308         do_div(dec_start, pll_divisor);
309
310         frac_start = pd.vco_freq * (1 << 20);
311
312         rem = do_div(frac_start, pll_divisor);
313         frac_start -= dec_start * (1 << 20);
314         if (rem > (pll_divisor >> 1))
315                 frac_start++;
316
317         cpctrl = pll_get_cpctrl(frac_start, ref_clk, false);
318         rctrl = pll_get_rctrl(frac_start, false);
319         cctrl = pll_get_cctrl(frac_start, false);
320         integloop_gain = pll_get_integloop_gain(frac_start, bclk,
321                                                 ref_clk, false);
322
323         fdata = pd.vco_freq;
324         do_div(fdata, pd.vco_ratio);
325
326         pll_cmp = pll_get_pll_cmp(fdata, ref_clk);
327
328         /* Convert these values to register specific values */
329         if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD)
330                 cfg->com_svs_mode_clk_sel = 1;
331         else
332                 cfg->com_svs_mode_clk_sel = 2;
333
334         cfg->com_hsclk_sel = (0x20 | pd.hsclk_divsel);
335         cfg->com_pll_cctrl_mode0 = cctrl;
336         cfg->com_pll_rctrl_mode0 = rctrl;
337         cfg->com_cp_ctrl_mode0 = cpctrl;
338         cfg->com_dec_start_mode0 = dec_start;
339         cfg->com_div_frac_start1_mode0 = (frac_start & 0xff);
340         cfg->com_div_frac_start2_mode0 = ((frac_start & 0xff00) >> 8);
341         cfg->com_div_frac_start3_mode0 = ((frac_start & 0xf0000) >> 16);
342         cfg->com_integloop_gain0_mode0 = (integloop_gain & 0xff);
343         cfg->com_integloop_gain1_mode0 = ((integloop_gain & 0xf00) >> 8);
344         cfg->com_lock_cmp1_mode0 = (pll_cmp & 0xff);
345         cfg->com_lock_cmp2_mode0 = ((pll_cmp & 0xff00) >> 8);
346         cfg->com_lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16);
347         cfg->com_lock_cmp_en = 0x0;
348         cfg->com_core_clk_en = 0x2c;
349         cfg->com_coreclk_div_mode0 = HDMI_CORECLK_DIV;
350         cfg->phy_mode = (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x5 : 0x4;
351
352         for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++)
353                 cfg->tx_lx_tx_band[i] = pd.tx_band_sel;
354
355         if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) {
356                 cfg->tx_lx_tx_drv_lvl[0] = 0x0f;
357                 cfg->tx_lx_tx_drv_lvl[1] = 0x0f;
358                 cfg->tx_lx_tx_drv_lvl[2] = 0x0f;
359                 cfg->tx_lx_tx_drv_lvl[3] = 0x0f;
360                 cfg->tx_lx_tx_emp_post1_lvl[0] = 0x03;
361                 cfg->tx_lx_tx_emp_post1_lvl[1] = 0x02;
362                 cfg->tx_lx_tx_emp_post1_lvl[2] = 0x03;
363                 cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00;
364                 cfg->tx_lx_pre_driver_1[0] = 0x00;
365                 cfg->tx_lx_pre_driver_1[1] = 0x00;
366                 cfg->tx_lx_pre_driver_1[2] = 0x00;
367                 cfg->tx_lx_pre_driver_1[3] = 0x00;
368                 cfg->tx_lx_pre_driver_2[0] = 0x1C;
369                 cfg->tx_lx_pre_driver_2[1] = 0x1C;
370                 cfg->tx_lx_pre_driver_2[2] = 0x1C;
371                 cfg->tx_lx_pre_driver_2[3] = 0x00;
372                 cfg->tx_lx_res_code_offset[0] = 0x03;
373                 cfg->tx_lx_res_code_offset[1] = 0x00;
374                 cfg->tx_lx_res_code_offset[2] = 0x00;
375                 cfg->tx_lx_res_code_offset[3] = 0x03;
376         } else if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD) {
377                 cfg->tx_lx_tx_drv_lvl[0] = 0x0f;
378                 cfg->tx_lx_tx_drv_lvl[1] = 0x0f;
379                 cfg->tx_lx_tx_drv_lvl[2] = 0x0f;
380                 cfg->tx_lx_tx_drv_lvl[3] = 0x0f;
381                 cfg->tx_lx_tx_emp_post1_lvl[0] = 0x03;
382                 cfg->tx_lx_tx_emp_post1_lvl[1] = 0x03;
383                 cfg->tx_lx_tx_emp_post1_lvl[2] = 0x03;
384                 cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00;
385                 cfg->tx_lx_pre_driver_1[0] = 0x00;
386                 cfg->tx_lx_pre_driver_1[1] = 0x00;
387                 cfg->tx_lx_pre_driver_1[2] = 0x00;
388                 cfg->tx_lx_pre_driver_1[3] = 0x00;
389                 cfg->tx_lx_pre_driver_2[0] = 0x16;
390                 cfg->tx_lx_pre_driver_2[1] = 0x16;
391                 cfg->tx_lx_pre_driver_2[2] = 0x16;
392                 cfg->tx_lx_pre_driver_2[3] = 0x18;
393                 cfg->tx_lx_res_code_offset[0] = 0x03;
394                 cfg->tx_lx_res_code_offset[1] = 0x00;
395                 cfg->tx_lx_res_code_offset[2] = 0x00;
396                 cfg->tx_lx_res_code_offset[3] = 0x00;
397         } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) {
398                 cfg->tx_lx_tx_drv_lvl[0] = 0x0f;
399                 cfg->tx_lx_tx_drv_lvl[1] = 0x0f;
400                 cfg->tx_lx_tx_drv_lvl[2] = 0x0f;
401                 cfg->tx_lx_tx_drv_lvl[3] = 0x0f;
402                 cfg->tx_lx_tx_emp_post1_lvl[0] = 0x05;
403                 cfg->tx_lx_tx_emp_post1_lvl[1] = 0x05;
404                 cfg->tx_lx_tx_emp_post1_lvl[2] = 0x05;
405                 cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00;
406                 cfg->tx_lx_pre_driver_1[0] = 0x00;
407                 cfg->tx_lx_pre_driver_1[1] = 0x00;
408                 cfg->tx_lx_pre_driver_1[2] = 0x00;
409                 cfg->tx_lx_pre_driver_1[3] = 0x00;
410                 cfg->tx_lx_pre_driver_2[0] = 0x0E;
411                 cfg->tx_lx_pre_driver_2[1] = 0x0E;
412                 cfg->tx_lx_pre_driver_2[2] = 0x0E;
413                 cfg->tx_lx_pre_driver_2[3] = 0x0E;
414                 cfg->tx_lx_res_code_offset[0] = 0x00;
415                 cfg->tx_lx_res_code_offset[1] = 0x00;
416                 cfg->tx_lx_res_code_offset[2] = 0x00;
417                 cfg->tx_lx_res_code_offset[3] = 0x00;
418         } else {
419                 cfg->tx_lx_tx_drv_lvl[0] = 0x01;
420                 cfg->tx_lx_tx_drv_lvl[1] = 0x01;
421                 cfg->tx_lx_tx_drv_lvl[2] = 0x01;
422                 cfg->tx_lx_tx_drv_lvl[3] = 0x00;
423                 cfg->tx_lx_tx_emp_post1_lvl[0] = 0x00;
424                 cfg->tx_lx_tx_emp_post1_lvl[1] = 0x00;
425                 cfg->tx_lx_tx_emp_post1_lvl[2] = 0x00;
426                 cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00;
427                 cfg->tx_lx_pre_driver_1[0] = 0x00;
428                 cfg->tx_lx_pre_driver_1[1] = 0x00;
429                 cfg->tx_lx_pre_driver_1[2] = 0x00;
430                 cfg->tx_lx_pre_driver_1[3] = 0x00;
431                 cfg->tx_lx_pre_driver_2[0] = 0x16;
432                 cfg->tx_lx_pre_driver_2[1] = 0x16;
433                 cfg->tx_lx_pre_driver_2[2] = 0x16;
434                 cfg->tx_lx_pre_driver_2[3] = 0x18;
435                 cfg->tx_lx_res_code_offset[0] = 0x00;
436                 cfg->tx_lx_res_code_offset[1] = 0x00;
437                 cfg->tx_lx_res_code_offset[2] = 0x00;
438                 cfg->tx_lx_res_code_offset[3] = 0x00;
439         }
440
441         return 0;
442 }
443
444 static int hdmi_8998_pll_set_clk_rate(struct clk_hw *hw, unsigned long rate,
445                                       unsigned long parent_rate)
446 {
447         struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
448         struct hdmi_phy *phy = pll_get_phy(pll);
449         struct hdmi_8998_phy_pll_reg_cfg cfg = {};
450         int i, ret;
451
452         ret = pll_calculate(rate, parent_rate, &cfg);
453         if (ret) {
454                 DRM_ERROR("PLL calculation failed\n");
455                 return ret;
456         }
457
458         /* Initially shut down PHY */
459         hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0x0);
460         udelay(500);
461
462         /* Power up sequence */
463         hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0x1);
464         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_RESETSM_CNTRL, 0x20);
465         hdmi_phy_write(phy, REG_HDMI_8998_PHY_CMN_CTRL, 0x6);
466
467         for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
468                 hdmi_tx_chan_write(pll, i,
469                                    REG_HDMI_8998_PHY_TXn_INTERFACE_SELECT_TX_BAND,
470                                    cfg.tx_lx_tx_band[i]);
471                 hdmi_tx_chan_write(pll, i,
472                                    REG_HDMI_8998_PHY_TXn_CLKBUF_TERM_ENABLE,
473                                    0x1);
474                 hdmi_tx_chan_write(pll, i,
475                                    REG_HDMI_8998_PHY_TXn_LANE_MODE,
476                                    0x20);
477         }
478
479         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYSCLK_BUF_ENABLE, 0x02);
480         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x0B);
481         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYSCLK_EN_SEL, 0x37);
482         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYS_CLK_CTRL, 0x02);
483         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CLK_ENABLE1, 0x0E);
484
485         /* Bypass VCO calibration */
486         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SVS_MODE_CLK_SEL,
487                        cfg.com_svs_mode_clk_sel);
488
489         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_IVCO, 0x07);
490         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_VCO_TUNE_CTRL, 0x00);
491
492         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CLK_SEL, 0x30);
493         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_HSCLK_SEL,
494                        cfg.com_hsclk_sel);
495         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP_EN,
496                        cfg.com_lock_cmp_en);
497
498         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_CCTRL_MODE0,
499                        cfg.com_pll_cctrl_mode0);
500         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_RCTRL_MODE0,
501                        cfg.com_pll_rctrl_mode0);
502         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CP_CTRL_MODE0,
503                        cfg.com_cp_ctrl_mode0);
504         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DEC_START_MODE0,
505                        cfg.com_dec_start_mode0);
506         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START1_MODE0,
507                        cfg.com_div_frac_start1_mode0);
508         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START2_MODE0,
509                        cfg.com_div_frac_start2_mode0);
510         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START3_MODE0,
511                        cfg.com_div_frac_start3_mode0);
512
513         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_INTEGLOOP_GAIN0_MODE0,
514                        cfg.com_integloop_gain0_mode0);
515         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_INTEGLOOP_GAIN1_MODE0,
516                        cfg.com_integloop_gain1_mode0);
517
518         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP1_MODE0,
519                        cfg.com_lock_cmp1_mode0);
520         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP2_MODE0,
521                        cfg.com_lock_cmp2_mode0);
522         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP3_MODE0,
523                        cfg.com_lock_cmp3_mode0);
524
525         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_VCO_TUNE_MAP, 0x00);
526         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CORE_CLK_EN,
527                        cfg.com_core_clk_en);
528         hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CORECLK_DIV_MODE0,
529                        cfg.com_coreclk_div_mode0);
530
531         /* TX lanes setup (TX 0/1/2/3) */
532         for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
533                 hdmi_tx_chan_write(pll, i,
534                                    REG_HDMI_8998_PHY_TXn_DRV_LVL,
535                                    cfg.tx_lx_tx_drv_lvl[i]);
536                 hdmi_tx_chan_write(pll, i,
537                                    REG_HDMI_8998_PHY_TXn_EMP_POST1_LVL,
538                                    cfg.tx_lx_tx_emp_post1_lvl[i]);
539                 hdmi_tx_chan_write(pll, i,
540                                    REG_HDMI_8998_PHY_TXn_PRE_DRIVER_1,
541                                    cfg.tx_lx_pre_driver_1[i]);
542                 hdmi_tx_chan_write(pll, i,
543                                    REG_HDMI_8998_PHY_TXn_PRE_DRIVER_2,
544                                    cfg.tx_lx_pre_driver_2[i]);
545                 hdmi_tx_chan_write(pll, i,
546                                    REG_HDMI_8998_PHY_TXn_DRV_LVL_RES_CODE_OFFSET,
547                                    cfg.tx_lx_res_code_offset[i]);
548         }
549
550         hdmi_phy_write(phy, REG_HDMI_8998_PHY_MODE, cfg.phy_mode);
551
552         for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
553                 hdmi_tx_chan_write(pll, i,
554                                    REG_HDMI_8998_PHY_TXn_LANE_CONFIG,
555                                    0x10);
556         }
557
558         /*
559          * Ensure that vco configuration gets flushed to hardware before
560          * enabling the PLL
561          */
562         wmb();
563
564         pll->rate = rate;
565
566         return 0;
567 }
568
569 static int hdmi_8998_phy_ready_status(struct hdmi_phy *phy)
570 {
571         u32 nb_tries = HDMI_PLL_POLL_MAX_READS;
572         unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
573         u32 status;
574         int phy_ready = 0;
575
576         while (nb_tries--) {
577                 status = hdmi_phy_read(phy, REG_HDMI_8998_PHY_STATUS);
578                 phy_ready = status & BIT(0);
579
580                 if (phy_ready)
581                         break;
582
583                 udelay(timeout);
584         }
585
586         return phy_ready;
587 }
588
589 static int hdmi_8998_pll_lock_status(struct hdmi_pll_8998 *pll)
590 {
591         u32 status;
592         int nb_tries = HDMI_PLL_POLL_MAX_READS;
593         unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
594         int pll_locked = 0;
595
596         while (nb_tries--) {
597                 status = hdmi_pll_read(pll,
598                                        REG_HDMI_8998_PHY_QSERDES_COM_C_READY_STATUS);
599                 pll_locked = status & BIT(0);
600
601                 if (pll_locked)
602                         break;
603
604                 udelay(timeout);
605         }
606
607         return pll_locked;
608 }
609
610 static int hdmi_8998_pll_prepare(struct clk_hw *hw)
611 {
612         struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
613         struct hdmi_phy *phy = pll_get_phy(pll);
614         int i, ret = 0;
615
616         hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x1);
617         udelay(100);
618
619         hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x59);
620         udelay(100);
621
622         ret = hdmi_8998_pll_lock_status(pll);
623         if (!ret)
624                 return ret;
625
626         for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
627                 hdmi_tx_chan_write(pll, i,
628                                    REG_HDMI_8998_PHY_TXn_LANE_CONFIG, 0x1F);
629         }
630
631         /* Ensure all registers are flushed to hardware */
632         wmb();
633
634         ret = hdmi_8998_phy_ready_status(phy);
635         if (!ret)
636                 return ret;
637
638         /* Restart the retiming buffer */
639         hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x58);
640         udelay(1);
641         hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x59);
642
643         /* Ensure all registers are flushed to hardware */
644         wmb();
645
646         return 0;
647 }
648
649 static long hdmi_8998_pll_round_rate(struct clk_hw *hw,
650                                      unsigned long rate,
651                                      unsigned long *parent_rate)
652 {
653         if (rate < HDMI_PCLK_MIN_FREQ)
654                 return HDMI_PCLK_MIN_FREQ;
655         else if (rate > HDMI_PCLK_MAX_FREQ)
656                 return HDMI_PCLK_MAX_FREQ;
657         else
658                 return rate;
659 }
660
661 static unsigned long hdmi_8998_pll_recalc_rate(struct clk_hw *hw,
662                                                unsigned long parent_rate)
663 {
664         struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
665         return pll->rate;
666 }
667
668 static void hdmi_8998_pll_unprepare(struct clk_hw *hw)
669 {
670         struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
671         struct hdmi_phy *phy = pll_get_phy(pll);
672
673         hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0);
674         usleep_range(100, 150);
675 }
676
677 static int hdmi_8998_pll_is_enabled(struct clk_hw *hw)
678 {
679         struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
680         u32 status;
681         int pll_locked;
682
683         status = hdmi_pll_read(pll, REG_HDMI_8998_PHY_QSERDES_COM_C_READY_STATUS);
684         pll_locked = status & BIT(0);
685
686         return pll_locked;
687 }
688
689 static const struct clk_ops hdmi_8998_pll_ops = {
690         .set_rate = hdmi_8998_pll_set_clk_rate,
691         .round_rate = hdmi_8998_pll_round_rate,
692         .recalc_rate = hdmi_8998_pll_recalc_rate,
693         .prepare = hdmi_8998_pll_prepare,
694         .unprepare = hdmi_8998_pll_unprepare,
695         .is_enabled = hdmi_8998_pll_is_enabled,
696 };
697
698 static const struct clk_init_data pll_init = {
699         .name = "hdmipll",
700         .ops = &hdmi_8998_pll_ops,
701         .parent_data = (const struct clk_parent_data[]){
702                 { .fw_name = "xo", .name = "xo_board" },
703         },
704         .num_parents = 1,
705         .flags = CLK_IGNORE_UNUSED,
706 };
707
708 int msm_hdmi_pll_8998_init(struct platform_device *pdev)
709 {
710         struct device *dev = &pdev->dev;
711         struct hdmi_pll_8998 *pll;
712         int ret, i;
713
714         pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
715         if (!pll)
716                 return -ENOMEM;
717
718         pll->pdev = pdev;
719
720         pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll");
721         if (IS_ERR(pll->mmio_qserdes_com)) {
722                 DRM_DEV_ERROR(dev, "failed to map pll base\n");
723                 return -ENOMEM;
724         }
725
726         for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
727                 char name[32];
728
729                 snprintf(name, sizeof(name), "hdmi_tx_l%d", i);
730
731                 pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name);
732                 if (IS_ERR(pll->mmio_qserdes_tx[i])) {
733                         DRM_DEV_ERROR(dev, "failed to map pll base\n");
734                         return -ENOMEM;
735                 }
736         }
737         pll->clk_hw.init = &pll_init;
738
739         ret = devm_clk_hw_register(dev, &pll->clk_hw);
740         if (ret) {
741                 DRM_DEV_ERROR(dev, "failed to register pll clock\n");
742                 return ret;
743         }
744
745         ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &pll->clk_hw);
746         if (ret) {
747                 DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);
748                 return ret;
749         }
750
751         return 0;
752 }
753
754 static const char * const hdmi_phy_8998_reg_names[] = {
755         "vddio",
756         "vcca",
757 };
758
759 static const char * const hdmi_phy_8998_clk_names[] = {
760         "iface", "ref", "xo",
761 };
762
763 const struct hdmi_phy_cfg msm_hdmi_phy_8998_cfg = {
764         .type = MSM_HDMI_PHY_8998,
765         .reg_names = hdmi_phy_8998_reg_names,
766         .num_regs = ARRAY_SIZE(hdmi_phy_8998_reg_names),
767         .clk_names = hdmi_phy_8998_clk_names,
768         .num_clks = ARRAY_SIZE(hdmi_phy_8998_clk_names),
769 };
This page took 0.075878 seconds and 4 git commands to generate.