blob: 85317305af24e45cf17cde3eb4aa704bca4a82cb [file] [log] [blame]
Dhaval Patele890ef22016-02-08 16:56:05 -08001/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
Dhaval Patelffb7b592015-03-23 23:34:07 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29#include <debug.h>
30#include <bits.h>
31#include <reg.h>
32#include <err.h>
33#include <smem.h>
34#include <board.h>
35#include <mipi_dsi.h>
36#include <mipi_dsi_autopll_thulium.h>
37#include <platform/iomap.h>
38#include <qtimer.h>
39#include <arch/defines.h>
40
41#define DATALANE_OFFSET_FROM_BASE_THULIUM 0x100
42#define DATALANE_SIZE_THULIUM 0x80
43#define MMSS_DSI_DSIPHY_CMN_LDO_CTRL 0x4c
44
45#define VCO_REF_CLK_RATE 19200000
46
47static void mdss_mdp_pll_input_init(struct dsi_pll_db *pdb)
48{
49 pdb->in.fref = 19200000; /* 19.2 Mhz*/
50 pdb->in.fdata = 0; /* bit clock rate */
51 pdb->in.dsiclk_sel = 1; /* 1, reg: 0x0014 */
52 pdb->in.ssc_en = 0; /* 1, reg: 0x0494, bit 0 */
53 pdb->in.ldo_en = 0; /* 0, reg: 0x004c, bit 0 */
54
55 /* fixed input */
56 pdb->in.refclk_dbler_en = 0; /* 0, reg: 0x04c0, bit 1 */
57 pdb->in.vco_measure_time = 5; /* 5, unknown */
58 pdb->in.kvco_measure_time = 5; /* 5, unknown */
59 pdb->in.bandgap_timer = 4; /* 4, reg: 0x0430, bit 3 - 5 */
60 pdb->in.pll_wakeup_timer = 5; /* 5, reg: 0x043c, bit 0 - 2 */
61 pdb->in.plllock_cnt = 1; /* 1, reg: 0x0488, bit 1 - 2 */
62 pdb->in.plllock_rng = 0; /* 0, reg: 0x0488, bit 3 - 4 */
63 pdb->in.ssc_center_spread = 0; /* 0, reg: 0x0494, bit 1 */
64 pdb->in.ssc_adj_per = 37; /* 37, reg: 0x498, bit 0 - 9 */
65 pdb->in.ssc_spread = 5; /* 0.005, 5kppm */
66 pdb->in.ssc_freq = 31500; /* 31.5 khz */
67
68 pdb->in.pll_ie_trim = 4; /* 4, reg: 0x0400 */
69 pdb->in.pll_ip_trim = 4; /* 4, reg: 0x0404 */
70 pdb->in.pll_cpcset_cur = 1; /* 1, reg: 0x04f0, bit 0 - 2 */
71 pdb->in.pll_cpmset_cur = 1; /* 1, reg: 0x04f0, bit 3 - 5 */
72 pdb->in.pll_icpmset = 4; /* 4, reg: 0x04fc, bit 3 - 5 */
73 pdb->in.pll_icpcset = 4; /* 4, reg: 0x04fc, bit 0 - 2 */
74 pdb->in.pll_icpmset_p = 0; /* 0, reg: 0x04f4, bit 0 - 2 */
75 pdb->in.pll_icpmset_m = 0; /* 0, reg: 0x04f4, bit 3 - 5 */
76 pdb->in.pll_icpcset_p = 0; /* 0, reg: 0x04f8, bit 0 - 2 */
77 pdb->in.pll_icpcset_m = 0; /* 0, reg: 0x04f8, bit 3 - 5 */
78 pdb->in.pll_lpf_res1 = 3; /* 3, reg: 0x0504, bit 0 - 3 */
79 pdb->in.pll_lpf_cap1 = 11; /* 11, reg: 0x0500, bit 0 - 3 */
Chandan Uddaraju5fb979f2016-01-29 10:02:20 -080080 pdb->in.pll_lpf_cap2 = 1; /* 1, reg: 0x0500, bit 4 - 7 */
Dhaval Patelffb7b592015-03-23 23:34:07 -070081 pdb->in.pll_iptat_trim = 7;
82 pdb->in.pll_c3ctrl = 2; /* 2 */
83 pdb->in.pll_r3ctrl = 1; /* 1 */
84}
85
86static void mdss_mdp_pll_dec_frac_calc(struct dsi_pll_db *pdb,
87 uint32_t vco_clk_rate, uint32_t fref)
88{
89 uint64_t vco_clk;
90 uint64_t multiplier = BIT(20);
91 uint64_t dec_start_multiple, dec_start, pll_comp_val;
92 uint32_t duration, div_frac_start;
93
94 vco_clk = vco_clk_rate * multiplier;
95
96 dec_start_multiple = (uint64_t) vco_clk / fref;
97 div_frac_start = (uint32_t) dec_start_multiple % multiplier;
98
99 dec_start = dec_start_multiple / multiplier;
100
101 pdb->out.dec_start = (uint32_t)dec_start;
102 pdb->out.div_frac_start = div_frac_start;
103
104 if (pdb->in.plllock_cnt == 0)
105 duration = 1024;
106 else if (pdb->in.plllock_cnt == 1)
107 duration = 256;
108 else if (pdb->in.plllock_cnt == 2)
109 duration = 128;
110 else
111 duration = 32;
112
113 pll_comp_val = (uint64_t)duration * dec_start_multiple;
114 pll_comp_val /= (multiplier * 10);
115
116 pdb->out.plllock_cmp = (uint32_t)pll_comp_val;
117
118 pdb->out.pll_txclk_en = 1;
Dhaval Patele890ef22016-02-08 16:56:05 -0800119 pdb->out.cmn_ldo_cntrl = 0x3c;
Dhaval Patelffb7b592015-03-23 23:34:07 -0700120}
121
122static uint32_t mdss_mdp_pll_kvco_slop(uint32_t vrate)
123{
124 uint32_t slop = 0;
125
126 if (vrate > 1300000000 && vrate <= 1800000000)
127 slop = 600;
128 else if (vrate > 1800000000 && vrate < 2300000000)
129 slop = 400;
130 else if (vrate > 2300000000 && vrate < 2600000000)
131 slop = 280;
132
133 return slop;
134}
135
Ingrid Gallardo2b831f32016-06-15 15:08:08 -0700136static inline uint32_t mdss_mdp_pll_calc_kvco_code(uint32_t vco_clk_rate)
137{
138 uint32_t kvco_code;
139
140 if ((vco_clk_rate >= 2300000000ULL) &&
141 (vco_clk_rate <= 2600000000ULL))
142 kvco_code = 0x2f;
143 else if ((vco_clk_rate >= 1800000000ULL) &&
144 (vco_clk_rate < 2300000000ULL))
145 kvco_code = 0x2c;
146 else
147 kvco_code = 0x28;
148
149 return kvco_code;
150}
151
Dhaval Patelffb7b592015-03-23 23:34:07 -0700152static void mdss_mdp_pll_calc_vco_count(struct dsi_pll_db *pdb,
153 uint32_t vco_clk_rate, uint32_t fref)
154{
155 uint64_t data;
156 uint32_t cnt;
157
158 data = fref * pdb->in.vco_measure_time;
159 data /= 1000000;
160 data &= 0x03ff; /* 10 bits */
161 data -= 2;
162 pdb->out.pll_vco_div_ref = data;
163
164 data = vco_clk_rate / 1000000; /* unit is Mhz */
165 data *= pdb->in.vco_measure_time;
166 data /= 10;
167 pdb->out.pll_vco_count = data; /* reg: 0x0474, 0x0478 */
168
169 data = fref * pdb->in.kvco_measure_time;
170 data /= 1000000;
171 data &= 0x03ff; /* 10 bits */
172 data -= 1;
173 pdb->out.pll_kvco_div_ref = data;
174
175 cnt = mdss_mdp_pll_kvco_slop(vco_clk_rate);
176 cnt *= 2;
177 cnt /= 100;
178 cnt *= pdb->in.kvco_measure_time;
179 pdb->out.pll_kvco_count = cnt;
180
181 pdb->out.pll_misc1 = 16;
Chandan Uddaraju5fb979f2016-01-29 10:02:20 -0800182 pdb->out.pll_resetsm_cntrl = 48;
Dhaval Patelffb7b592015-03-23 23:34:07 -0700183 pdb->out.pll_resetsm_cntrl2 = pdb->in.bandgap_timer << 3;
184 pdb->out.pll_resetsm_cntrl5 = pdb->in.pll_wakeup_timer;
Ingrid Gallardo2b831f32016-06-15 15:08:08 -0700185 pdb->out.pll_kvco_code = mdss_mdp_pll_calc_kvco_code(vco_clk_rate);
Dhaval Patelffb7b592015-03-23 23:34:07 -0700186}
187
188static void mdss_mdp_pll_assert_and_div_cfg(uint32_t phy_base,
189 struct dsi_pll_db *pdb)
190{
191 uint32_t n2div = 0;
192
193 n2div = readl(phy_base + DSIPHY_CMN_CLK_CFG0);
194 n2div &= ~(0xf0);
195 n2div |= (pdb->out.pll_n2div << 4);
196 writel(n2div, phy_base + DSIPHY_CMN_CLK_CFG0);
197
198 dmb();
199}
200
201static void mdss_mdp_pll_nonfreq_config(uint32_t phy_base, struct dsi_pll_db *pdb)
202{
203 uint32_t data;
204
205 writel(pdb->out.cmn_ldo_cntrl, phy_base + DSIPHY_CMN_LDO_CNTRL);
206 writel(0x0, phy_base + DSIPHY_PLL_SYSCLK_EN_RESET);
207
208 data = pdb->out.pll_txclk_en;
209 writel(pdb->out.pll_txclk_en, phy_base + DSIPHY_PLL_TXCLK_EN);
210
211 writel(pdb->out.pll_resetsm_cntrl, phy_base + DSIPHY_PLL_RESETSM_CNTRL);
212 writel(pdb->out.pll_resetsm_cntrl2, phy_base + DSIPHY_PLL_RESETSM_CNTRL2);
213 writel(pdb->out.pll_resetsm_cntrl5, phy_base + DSIPHY_PLL_RESETSM_CNTRL5);
214
215 data = pdb->out.pll_vco_div_ref;
216 data &= 0x0ff;
217 writel(data, phy_base + DSIPHY_PLL_VCO_DIV_REF1);
218 data = (pdb->out.pll_vco_div_ref >> 8);
219 data &= 0x03;
220 writel(data, phy_base + DSIPHY_PLL_VCO_DIV_REF2);
221
222 data = pdb->out.pll_kvco_div_ref;
223 data &= 0x0ff;
224 writel(data, phy_base + DSIPHY_PLL_KVCO_DIV_REF1);
225 data = (pdb->out.pll_kvco_div_ref >> 8);
226 data &= 0x03;
227 writel(data, phy_base + DSIPHY_PLL_KVCO_DIV_REF2);
228
229 writel(pdb->out.pll_misc1, phy_base + DSIPHY_PLL_PLL_MISC1);
230
231 writel(pdb->in.pll_ie_trim, phy_base + DSIPHY_PLL_IE_TRIM);
232
233 writel(pdb->in.pll_ip_trim, phy_base + DSIPHY_PLL_IP_TRIM);
234
235 data = ((pdb->in.pll_cpmset_cur << 3) | pdb->in.pll_cpcset_cur);
236 writel(data, phy_base + DSIPHY_PLL_CP_SET_CUR);
237
238 data = ((pdb->in.pll_icpcset_p << 3) | pdb->in.pll_icpcset_m);
239 writel(data, phy_base + DSIPHY_PLL_PLL_ICPCSET);
240
241 data = ((pdb->in.pll_icpmset_p << 3) | pdb->in.pll_icpcset_m);
242 writel(data, phy_base + DSIPHY_PLL_PLL_ICPMSET);
243
244 data = ((pdb->in.pll_icpmset << 3) | pdb->in.pll_icpcset);
245 writel(data, phy_base + DSIPHY_PLL_PLL_ICP_SET);
246
247 data = ((pdb->in.pll_lpf_cap2 << 4) | pdb->in.pll_lpf_cap1);
248 writel(data, phy_base + DSIPHY_PLL_PLL_LPF1);
249
250 writel(pdb->in.pll_iptat_trim, phy_base + DSIPHY_PLL_IPTAT_TRIM);
251
252 data = (pdb->in.pll_c3ctrl | (pdb->in.pll_r3ctrl << 4));
253 writel(data, phy_base + DSIPHY_PLL_PLL_CRCTRL);
254 dmb();
255}
256
257static void mdss_mdp_pll_freq_config(uint32_t phy_base, struct dsi_pll_db *pdb)
258{
259 uint32_t data;
260
261 writel(0x0, phy_base + DSIPHY_CMN_PLL_CNTRL);
262 /* reset digital block */
263 writel(0x20, phy_base + DSIPHY_CMN_CTRL_1);
264 dmb();
265 udelay(10);
266 writel(0x00, phy_base + DSIPHY_CMN_CTRL_1);
267 dmb();
268
269 writel(pdb->in.dsiclk_sel, phy_base + DSIPHY_CMN_CLK_CFG1);
270 writel(0xff, phy_base + DSIPHY_CMN_CTRL_0);
271 writel(pdb->out.dec_start, phy_base + DSIPHY_PLL_DEC_START);
272
273 data = pdb->out.div_frac_start;
274 data &= 0x0ff;
275 writel(data, phy_base + DSIPHY_PLL_DIV_FRAC_START1);
276 data = (pdb->out.div_frac_start >> 8);
277 data &= 0x0ff;
278 writel(data, phy_base + DSIPHY_PLL_DIV_FRAC_START2);
279 data = (pdb->out.div_frac_start >> 16);
280 data &= 0x0f;
281 writel(data, phy_base + DSIPHY_PLL_DIV_FRAC_START3);
282
283 data = pdb->out.plllock_cmp;
284 data &= 0x0ff;
285 writel(data, phy_base + DSIPHY_PLL_PLLLOCK_CMP1);
286 data = (pdb->out.plllock_cmp >> 8);
287 data &= 0x0ff;
288 writel(data, phy_base + DSIPHY_PLL_PLLLOCK_CMP2);
289 data = (pdb->out.plllock_cmp >> 16);
290 data &= 0x03;
291 writel(data, phy_base + DSIPHY_PLL_PLLLOCK_CMP3);
292
293 data = ((pdb->in.plllock_cnt << 1) | (pdb->in.plllock_rng << 3));
294 writel(data, phy_base + DSIPHY_PLL_PLLLOCK_CMP_EN);
295
296 data = pdb->out.pll_vco_count;
297 data &= 0x0ff;
298 writel(data, phy_base + DSIPHY_PLL_VCO_COUNT1);
299 data = (pdb->out.pll_vco_count >> 8);
300 data &= 0x0ff;
301 writel(data, phy_base + DSIPHY_PLL_VCO_COUNT2);
302
303 data = pdb->out.pll_kvco_count;
304 data &= 0x0ff;
305 writel(data, phy_base + DSIPHY_PLL_KVCO_COUNT1);
306 data = (pdb->out.pll_kvco_count >> 8);
307 data &= 0x03;
308 writel(data, phy_base + DSIPHY_PLL_KVCO_COUNT2);
309
Ingrid Gallardo2b831f32016-06-15 15:08:08 -0700310 data = pdb->out.pll_kvco_code;
311 writel(data, phy_base + DSIPHY_PLL_KVCO_CODE);
312
Dhaval Patelffb7b592015-03-23 23:34:07 -0700313 /*
314 * tx_band = pll_postdiv
315 * 0: divided by 1 <== for now
316 * 1: divided by 2
317 * 2: divided by 4
318 * 3: divided by 8
319 */
320 if (pdb->out.pll_postdiv)
321 data = (((pdb->out.pll_postdiv - 1) << 4) |
322 pdb->in.pll_lpf_res1);
323 else
324 data = pdb->in.pll_lpf_res1;
325 writel(data, phy_base + DSIPHY_PLL_PLL_LPF2_POSTDIV);
326
327 data = (pdb->out.pll_n1div | (pdb->out.pll_n2div << 4));
328 writel(data, phy_base + DSIPHY_CMN_CLK_CFG0);
329
330 dmb(); /* make sure register committed */
331}
332
333static int mdss_dsi_phy_14nm_init(struct msm_panel_info *pinfo,
334 uint32_t phy_base)
335{
336 struct mdss_dsi_phy_ctrl *pd;
337 struct mipi_panel_info *mipi;
338 int j, off, ln, cnt, ln_off;
339 uint32_t base;
340 uint32_t data;
341
342 mipi = &pinfo->mipi;
343 pd = (mipi->mdss_dsi_phy_db);
344
345 /* Strength ctrl 0 */
346 writel(0x1c, phy_base + MMSS_DSI_DSIPHY_CMN_LDO_CTRL);
347 writel(0x1, phy_base + DSIPHY_CMN_GLBL_TEST_CTRL);
348
349 /* 4 lanes + clk lane configuration */
350 for (ln = 0; ln < 5; ln++) {
351 /*
352 * data lane offset frome base: 0x100
353 * data lane size: 0x80
354 */
355 base = phy_base + DATALANE_OFFSET_FROM_BASE_THULIUM;
356 base += (ln * DATALANE_SIZE_THULIUM); /* lane base */
357
358 /* lane cfg, 4 * 5 */
359 cnt = 4;
360 ln_off = cnt * ln;
361 off = 0x0;
362 for (j = 0; j < cnt; j++, off += 4)
363 writel(pd->laneCfg[ln_off + j], base + off);
364
365 /* test str */
366 writel(0x88, base + 0x14);
367
368 /* phy timing, 8 * 5 */
369 cnt = 8;
370 ln_off = cnt * ln;
371 off = 0x18;
372 for (j = 0; j < cnt; j++, off += 4)
373 writel(pd->timing[ln_off + j], base + off);
374
375 /* strength, 2 * 5 */
376 cnt = 2;
377 ln_off = cnt * ln;
378 off = 0x38;
379 for (j = 0; j < cnt; j++, off += 4)
380 writel(pd->strength[ln_off + j], base + off);
381
382 /* vreg ctrl, 1 * 5 */
383 off = 0x64;
384 writel(pd->regulator[cnt], base + off);
385 }
386 dmb();
387
388 /* reset digital block */
389 writel(0x80, phy_base + DSIPHY_CMN_CTRL_1);
390 dmb();
391 udelay(100);
392 writel(0x00, phy_base + DSIPHY_CMN_CTRL_1);
393
394 if (pinfo->lcdc.split_display) {
395 if (mipi->phy_base == phy_base) {
396 writel(0x3, phy_base + DSIPHY_PLL_CLKBUFLR_EN);
397 data = readl(phy_base + DSIPHY_CMN_GLBL_TEST_CTRL);
398 data &= ~BIT(2);
399 writel(data, phy_base + DSIPHY_CMN_GLBL_TEST_CTRL);
400 } else {
401 writel(0x0, phy_base + DSIPHY_PLL_CLKBUFLR_EN);
402 data = readl(phy_base + DSIPHY_CMN_GLBL_TEST_CTRL);
403 data |= BIT(2);
404 writel(data, phy_base + DSIPHY_CMN_GLBL_TEST_CTRL);
405 writel(0x3, phy_base + DSIPHY_PLL_PLL_BANDGAP);
406 }
407 } else {
408 writel(0x1, phy_base + DSIPHY_PLL_CLKBUFLR_EN);
409 data = readl(phy_base + DSIPHY_CMN_GLBL_TEST_CTRL);
410 data &= ~BIT(2);
411 writel(data, phy_base + DSIPHY_CMN_GLBL_TEST_CTRL);
412 }
413
414 dmb();
415 return 0;
416}
417
418void mdss_dsi_auto_pll_thulium_config(struct msm_panel_info *pinfo)
419{
420 struct dsi_pll_db pdb;
421 struct mdss_dsi_pll_config *pll_data = pinfo->mipi.dsi_pll_config;
422 uint32_t phy_base = pinfo->mipi.phy_base;
423 uint32_t phy_1_base = pinfo->mipi.sphy_base;
424
425 mdss_dsi_phy_sw_reset(pinfo->mipi.ctl_base);
426 if (pinfo->mipi.dual_dsi)
427 mdss_dsi_phy_sw_reset(pinfo->mipi.sctl_base);
428
429 mdss_dsi_phy_14nm_init(pinfo, phy_base);
430 if (pinfo->mipi.dual_dsi)
431 mdss_dsi_phy_14nm_init(pinfo, phy_1_base);
432
433 mdss_mdp_pll_input_init(&pdb);
434 pdb.out.pll_postdiv = pll_data->ndiv;
435 pdb.out.pll_n1div = pll_data->n1div;
436 pdb.out.pll_n2div = pll_data->n2div;
437
438 mdss_mdp_pll_dec_frac_calc(&pdb, pll_data->vco_clock, VCO_REF_CLK_RATE);
439 mdss_mdp_pll_calc_vco_count(&pdb, pll_data->vco_clock, VCO_REF_CLK_RATE);
440
441 /* de-assert pll and start */
442 mdss_mdp_pll_assert_and_div_cfg(phy_base, &pdb);
443 writel(pdb.in.dsiclk_sel, phy_base + DSIPHY_CMN_CLK_CFG1);
444 if (pinfo->lcdc.split_display)
445 mdss_mdp_pll_assert_and_div_cfg(phy_1_base, &pdb);
446
447 /* configure frequence */
448 mdss_mdp_pll_nonfreq_config(phy_base, &pdb);
449 mdss_mdp_pll_freq_config(phy_base, &pdb);
450
451 if (pinfo->lcdc.split_display) {
452 mdss_mdp_pll_nonfreq_config(phy_1_base, &pdb);
453 mdss_mdp_pll_freq_config(phy_1_base, &pdb);
454 }
455}