blob: ffb13103d38bdebfa495abd797c3067ffb6d98ce [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 */
80 pdb->in.pll_lpf_cap2 = 14; /* 14, reg: 0x0500, bit 4 - 7 */
81 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
136static void mdss_mdp_pll_calc_vco_count(struct dsi_pll_db *pdb,
137 uint32_t vco_clk_rate, uint32_t fref)
138{
139 uint64_t data;
140 uint32_t cnt;
141
142 data = fref * pdb->in.vco_measure_time;
143 data /= 1000000;
144 data &= 0x03ff; /* 10 bits */
145 data -= 2;
146 pdb->out.pll_vco_div_ref = data;
147
148 data = vco_clk_rate / 1000000; /* unit is Mhz */
149 data *= pdb->in.vco_measure_time;
150 data /= 10;
151 pdb->out.pll_vco_count = data; /* reg: 0x0474, 0x0478 */
152
153 data = fref * pdb->in.kvco_measure_time;
154 data /= 1000000;
155 data &= 0x03ff; /* 10 bits */
156 data -= 1;
157 pdb->out.pll_kvco_div_ref = data;
158
159 cnt = mdss_mdp_pll_kvco_slop(vco_clk_rate);
160 cnt *= 2;
161 cnt /= 100;
162 cnt *= pdb->in.kvco_measure_time;
163 pdb->out.pll_kvco_count = cnt;
164
165 pdb->out.pll_misc1 = 16;
166 pdb->out.pll_resetsm_cntrl = 0;
167 pdb->out.pll_resetsm_cntrl2 = pdb->in.bandgap_timer << 3;
168 pdb->out.pll_resetsm_cntrl5 = pdb->in.pll_wakeup_timer;
169 pdb->out.pll_kvco_code = 0;
170}
171
172static void mdss_mdp_pll_assert_and_div_cfg(uint32_t phy_base,
173 struct dsi_pll_db *pdb)
174{
175 uint32_t n2div = 0;
176
177 n2div = readl(phy_base + DSIPHY_CMN_CLK_CFG0);
178 n2div &= ~(0xf0);
179 n2div |= (pdb->out.pll_n2div << 4);
180 writel(n2div, phy_base + DSIPHY_CMN_CLK_CFG0);
181
182 dmb();
183}
184
185static void mdss_mdp_pll_nonfreq_config(uint32_t phy_base, struct dsi_pll_db *pdb)
186{
187 uint32_t data;
188
189 writel(pdb->out.cmn_ldo_cntrl, phy_base + DSIPHY_CMN_LDO_CNTRL);
190 writel(0x0, phy_base + DSIPHY_PLL_SYSCLK_EN_RESET);
191
192 data = pdb->out.pll_txclk_en;
193 writel(pdb->out.pll_txclk_en, phy_base + DSIPHY_PLL_TXCLK_EN);
194
195 writel(pdb->out.pll_resetsm_cntrl, phy_base + DSIPHY_PLL_RESETSM_CNTRL);
196 writel(pdb->out.pll_resetsm_cntrl2, phy_base + DSIPHY_PLL_RESETSM_CNTRL2);
197 writel(pdb->out.pll_resetsm_cntrl5, phy_base + DSIPHY_PLL_RESETSM_CNTRL5);
198
199 data = pdb->out.pll_vco_div_ref;
200 data &= 0x0ff;
201 writel(data, phy_base + DSIPHY_PLL_VCO_DIV_REF1);
202 data = (pdb->out.pll_vco_div_ref >> 8);
203 data &= 0x03;
204 writel(data, phy_base + DSIPHY_PLL_VCO_DIV_REF2);
205
206 data = pdb->out.pll_kvco_div_ref;
207 data &= 0x0ff;
208 writel(data, phy_base + DSIPHY_PLL_KVCO_DIV_REF1);
209 data = (pdb->out.pll_kvco_div_ref >> 8);
210 data &= 0x03;
211 writel(data, phy_base + DSIPHY_PLL_KVCO_DIV_REF2);
212
213 writel(pdb->out.pll_misc1, phy_base + DSIPHY_PLL_PLL_MISC1);
214
215 writel(pdb->in.pll_ie_trim, phy_base + DSIPHY_PLL_IE_TRIM);
216
217 writel(pdb->in.pll_ip_trim, phy_base + DSIPHY_PLL_IP_TRIM);
218
219 data = ((pdb->in.pll_cpmset_cur << 3) | pdb->in.pll_cpcset_cur);
220 writel(data, phy_base + DSIPHY_PLL_CP_SET_CUR);
221
222 data = ((pdb->in.pll_icpcset_p << 3) | pdb->in.pll_icpcset_m);
223 writel(data, phy_base + DSIPHY_PLL_PLL_ICPCSET);
224
225 data = ((pdb->in.pll_icpmset_p << 3) | pdb->in.pll_icpcset_m);
226 writel(data, phy_base + DSIPHY_PLL_PLL_ICPMSET);
227
228 data = ((pdb->in.pll_icpmset << 3) | pdb->in.pll_icpcset);
229 writel(data, phy_base + DSIPHY_PLL_PLL_ICP_SET);
230
231 data = ((pdb->in.pll_lpf_cap2 << 4) | pdb->in.pll_lpf_cap1);
232 writel(data, phy_base + DSIPHY_PLL_PLL_LPF1);
233
234 writel(pdb->in.pll_iptat_trim, phy_base + DSIPHY_PLL_IPTAT_TRIM);
235
236 data = (pdb->in.pll_c3ctrl | (pdb->in.pll_r3ctrl << 4));
237 writel(data, phy_base + DSIPHY_PLL_PLL_CRCTRL);
238 dmb();
239}
240
241static void mdss_mdp_pll_freq_config(uint32_t phy_base, struct dsi_pll_db *pdb)
242{
243 uint32_t data;
244
245 writel(0x0, phy_base + DSIPHY_CMN_PLL_CNTRL);
246 /* reset digital block */
247 writel(0x20, phy_base + DSIPHY_CMN_CTRL_1);
248 dmb();
249 udelay(10);
250 writel(0x00, phy_base + DSIPHY_CMN_CTRL_1);
251 dmb();
252
253 writel(pdb->in.dsiclk_sel, phy_base + DSIPHY_CMN_CLK_CFG1);
254 writel(0xff, phy_base + DSIPHY_CMN_CTRL_0);
255 writel(pdb->out.dec_start, phy_base + DSIPHY_PLL_DEC_START);
256
257 data = pdb->out.div_frac_start;
258 data &= 0x0ff;
259 writel(data, phy_base + DSIPHY_PLL_DIV_FRAC_START1);
260 data = (pdb->out.div_frac_start >> 8);
261 data &= 0x0ff;
262 writel(data, phy_base + DSIPHY_PLL_DIV_FRAC_START2);
263 data = (pdb->out.div_frac_start >> 16);
264 data &= 0x0f;
265 writel(data, phy_base + DSIPHY_PLL_DIV_FRAC_START3);
266
267 data = pdb->out.plllock_cmp;
268 data &= 0x0ff;
269 writel(data, phy_base + DSIPHY_PLL_PLLLOCK_CMP1);
270 data = (pdb->out.plllock_cmp >> 8);
271 data &= 0x0ff;
272 writel(data, phy_base + DSIPHY_PLL_PLLLOCK_CMP2);
273 data = (pdb->out.plllock_cmp >> 16);
274 data &= 0x03;
275 writel(data, phy_base + DSIPHY_PLL_PLLLOCK_CMP3);
276
277 data = ((pdb->in.plllock_cnt << 1) | (pdb->in.plllock_rng << 3));
278 writel(data, phy_base + DSIPHY_PLL_PLLLOCK_CMP_EN);
279
280 data = pdb->out.pll_vco_count;
281 data &= 0x0ff;
282 writel(data, phy_base + DSIPHY_PLL_VCO_COUNT1);
283 data = (pdb->out.pll_vco_count >> 8);
284 data &= 0x0ff;
285 writel(data, phy_base + DSIPHY_PLL_VCO_COUNT2);
286
287 data = pdb->out.pll_kvco_count;
288 data &= 0x0ff;
289 writel(data, phy_base + DSIPHY_PLL_KVCO_COUNT1);
290 data = (pdb->out.pll_kvco_count >> 8);
291 data &= 0x03;
292 writel(data, phy_base + DSIPHY_PLL_KVCO_COUNT2);
293
294 /*
295 * tx_band = pll_postdiv
296 * 0: divided by 1 <== for now
297 * 1: divided by 2
298 * 2: divided by 4
299 * 3: divided by 8
300 */
301 if (pdb->out.pll_postdiv)
302 data = (((pdb->out.pll_postdiv - 1) << 4) |
303 pdb->in.pll_lpf_res1);
304 else
305 data = pdb->in.pll_lpf_res1;
306 writel(data, phy_base + DSIPHY_PLL_PLL_LPF2_POSTDIV);
307
308 data = (pdb->out.pll_n1div | (pdb->out.pll_n2div << 4));
309 writel(data, phy_base + DSIPHY_CMN_CLK_CFG0);
310
311 dmb(); /* make sure register committed */
312}
313
314static int mdss_dsi_phy_14nm_init(struct msm_panel_info *pinfo,
315 uint32_t phy_base)
316{
317 struct mdss_dsi_phy_ctrl *pd;
318 struct mipi_panel_info *mipi;
319 int j, off, ln, cnt, ln_off;
320 uint32_t base;
321 uint32_t data;
322
323 mipi = &pinfo->mipi;
324 pd = (mipi->mdss_dsi_phy_db);
325
326 /* Strength ctrl 0 */
327 writel(0x1c, phy_base + MMSS_DSI_DSIPHY_CMN_LDO_CTRL);
328 writel(0x1, phy_base + DSIPHY_CMN_GLBL_TEST_CTRL);
329
330 /* 4 lanes + clk lane configuration */
331 for (ln = 0; ln < 5; ln++) {
332 /*
333 * data lane offset frome base: 0x100
334 * data lane size: 0x80
335 */
336 base = phy_base + DATALANE_OFFSET_FROM_BASE_THULIUM;
337 base += (ln * DATALANE_SIZE_THULIUM); /* lane base */
338
339 /* lane cfg, 4 * 5 */
340 cnt = 4;
341 ln_off = cnt * ln;
342 off = 0x0;
343 for (j = 0; j < cnt; j++, off += 4)
344 writel(pd->laneCfg[ln_off + j], base + off);
345
346 /* test str */
347 writel(0x88, base + 0x14);
348
349 /* phy timing, 8 * 5 */
350 cnt = 8;
351 ln_off = cnt * ln;
352 off = 0x18;
353 for (j = 0; j < cnt; j++, off += 4)
354 writel(pd->timing[ln_off + j], base + off);
355
356 /* strength, 2 * 5 */
357 cnt = 2;
358 ln_off = cnt * ln;
359 off = 0x38;
360 for (j = 0; j < cnt; j++, off += 4)
361 writel(pd->strength[ln_off + j], base + off);
362
363 /* vreg ctrl, 1 * 5 */
364 off = 0x64;
365 writel(pd->regulator[cnt], base + off);
366 }
367 dmb();
368
369 /* reset digital block */
370 writel(0x80, phy_base + DSIPHY_CMN_CTRL_1);
371 dmb();
372 udelay(100);
373 writel(0x00, phy_base + DSIPHY_CMN_CTRL_1);
374
375 if (pinfo->lcdc.split_display) {
376 if (mipi->phy_base == phy_base) {
377 writel(0x3, phy_base + DSIPHY_PLL_CLKBUFLR_EN);
378 data = readl(phy_base + DSIPHY_CMN_GLBL_TEST_CTRL);
379 data &= ~BIT(2);
380 writel(data, phy_base + DSIPHY_CMN_GLBL_TEST_CTRL);
381 } else {
382 writel(0x0, phy_base + DSIPHY_PLL_CLKBUFLR_EN);
383 data = readl(phy_base + DSIPHY_CMN_GLBL_TEST_CTRL);
384 data |= BIT(2);
385 writel(data, phy_base + DSIPHY_CMN_GLBL_TEST_CTRL);
386 writel(0x3, phy_base + DSIPHY_PLL_PLL_BANDGAP);
387 }
388 } else {
389 writel(0x1, phy_base + DSIPHY_PLL_CLKBUFLR_EN);
390 data = readl(phy_base + DSIPHY_CMN_GLBL_TEST_CTRL);
391 data &= ~BIT(2);
392 writel(data, phy_base + DSIPHY_CMN_GLBL_TEST_CTRL);
393 }
394
395 dmb();
396 return 0;
397}
398
399void mdss_dsi_auto_pll_thulium_config(struct msm_panel_info *pinfo)
400{
401 struct dsi_pll_db pdb;
402 struct mdss_dsi_pll_config *pll_data = pinfo->mipi.dsi_pll_config;
403 uint32_t phy_base = pinfo->mipi.phy_base;
404 uint32_t phy_1_base = pinfo->mipi.sphy_base;
405
406 mdss_dsi_phy_sw_reset(pinfo->mipi.ctl_base);
407 if (pinfo->mipi.dual_dsi)
408 mdss_dsi_phy_sw_reset(pinfo->mipi.sctl_base);
409
410 mdss_dsi_phy_14nm_init(pinfo, phy_base);
411 if (pinfo->mipi.dual_dsi)
412 mdss_dsi_phy_14nm_init(pinfo, phy_1_base);
413
414 mdss_mdp_pll_input_init(&pdb);
415 pdb.out.pll_postdiv = pll_data->ndiv;
416 pdb.out.pll_n1div = pll_data->n1div;
417 pdb.out.pll_n2div = pll_data->n2div;
418
419 mdss_mdp_pll_dec_frac_calc(&pdb, pll_data->vco_clock, VCO_REF_CLK_RATE);
420 mdss_mdp_pll_calc_vco_count(&pdb, pll_data->vco_clock, VCO_REF_CLK_RATE);
421
422 /* de-assert pll and start */
423 mdss_mdp_pll_assert_and_div_cfg(phy_base, &pdb);
424 writel(pdb.in.dsiclk_sel, phy_base + DSIPHY_CMN_CLK_CFG1);
425 if (pinfo->lcdc.split_display)
426 mdss_mdp_pll_assert_and_div_cfg(phy_1_base, &pdb);
427
428 /* configure frequence */
429 mdss_mdp_pll_nonfreq_config(phy_base, &pdb);
430 mdss_mdp_pll_freq_config(phy_base, &pdb);
431
432 if (pinfo->lcdc.split_display) {
433 mdss_mdp_pll_nonfreq_config(phy_1_base, &pdb);
434 mdss_mdp_pll_freq_config(phy_1_base, &pdb);
435 }
436}