blob: 0dfcdc1ca8cfabb51c61fb17fd0a574cac8e3311 [file] [log] [blame]
Sandeep Panda0ce96e92015-05-13 12:24:10 +05301/* Copyright (c) 2013, 2015, The Linux Foundation. All rights reserved.
Arpita Banerjee2522bc62013-05-24 16:03:53 -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 <reg.h>
31#include <err.h>
32#include <smem.h>
33#include <mipi_dsi.h>
34#include <platform/iomap.h>
35
36#define LPFR_LUT_SIZE 10
37
38#define VCO_REF_CLOCK_RATE 19200000
39
40#define FRAC_DIVIDER 10000
41
42typedef struct lpfr_cfg {
43 uint32_t vco_rate;
44 uint8_t resistance;
45};
46
47static struct lpfr_cfg lpfr_lut[LPFR_LUT_SIZE] = {
48 {479500000, 8},
49 {480000000, 11},
50 {575500000, 8},
51 {576000000, 12},
52 {610500000, 8},
53 {659500000, 9},
54 {671500000, 10},
55 {672000000, 14},
56 {708500000, 10},
57 {750000000, 11},
58 };
59
60uint64_t div_s64(uint64_t dividend, uint32_t divisor, uint32_t *remainder)
61{
62 *remainder = dividend % divisor;
63
64 return dividend / divisor;
65}
66
Casey Piper83559892013-08-26 11:22:25 -070067int32_t mdss_dsi_auto_pll_config(uint32_t ctl_base,
68 struct mdss_dsi_pll_config *pd)
Arpita Banerjee2522bc62013-05-24 16:03:53 -070069{
70 uint32_t rem, divider;
71 uint32_t refclk_cfg = 0, frac_n_mode = 0, ref_doubler_en_b = 0;
72 uint64_t vco_clock, div_fbx;
73 uint32_t ref_clk_to_pll = 0, frac_n_value = 0;
74 uint32_t sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3;
75 uint32_t gen_vco_clk, cal_cfg10, cal_cfg11;
76 uint32_t res;
77 uint8_t i, rc = NO_ERROR;
78
79 /* Configure the Loop filter resistance */
80 for (i = 0; i < LPFR_LUT_SIZE; i++)
81 if (pd->vco_clock <= lpfr_lut[i].vco_rate)
82 break;
83 if (i == LPFR_LUT_SIZE) {
84 dprintf(INFO, "unable to get loop filter resistance. vco=%d\n"
85 , lpfr_lut[i].vco_rate);
86 rc = ERROR;
87 return rc;
88 }
89
Casey Piper83559892013-08-26 11:22:25 -070090 mdss_dsi_phy_sw_reset(ctl_base);
Arpita Banerjee2522bc62013-05-24 16:03:53 -070091
92 /* Loop filter resistance value */
Casey Piper83559892013-08-26 11:22:25 -070093 writel(lpfr_lut[i].resistance, ctl_base + 0x022c);
Arpita Banerjee2522bc62013-05-24 16:03:53 -070094 /* Loop filter capacitance values : c1 and c2 */
Casey Piper83559892013-08-26 11:22:25 -070095 writel(0x70, ctl_base + 0x0230);
96 writel(0x15, ctl_base + 0x0234);
Arpita Banerjee2522bc62013-05-24 16:03:53 -070097
Casey Piper83559892013-08-26 11:22:25 -070098 writel(0x02, ctl_base + 0x0208); /* ChgPump */
Arpita Banerjee2522bc62013-05-24 16:03:53 -070099 /* postDiv1 - calculated in pll config*/
Casey Piper83559892013-08-26 11:22:25 -0700100 writel(pd->posdiv1, ctl_base + 0x0204);
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700101 /* postDiv2 - fixed devision 4 */
Casey Piper83559892013-08-26 11:22:25 -0700102 writel(0x03, ctl_base + 0x0224);
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700103 /* postDiv3 - calculated in pll config */
Casey Piper83559892013-08-26 11:22:25 -0700104 writel(pd->posdiv3, ctl_base + 0x0228); /* postDiv3 */
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700105
Casey Piper83559892013-08-26 11:22:25 -0700106 writel(0x2b, ctl_base + 0x0278); /* Cal CFG3 */
107 writel(0x66, ctl_base + 0x027c); /* Cal CFG4 */
Sandeep Pandaabe9ad42015-08-21 12:20:40 +0530108 writel(0x0d, ctl_base + 0x0264); /* LKDetect CFG2 */
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700109
110 rem = pd->vco_clock % VCO_REF_CLOCK_RATE;
111 if (rem) {
112 refclk_cfg = 0x1;
113 frac_n_mode = 1;
114 ref_doubler_en_b = 0;
115 } else {
116 refclk_cfg = 0x0;
117 frac_n_mode = 0;
118 ref_doubler_en_b = 1;
119 }
120
121 ref_clk_to_pll = (VCO_REF_CLOCK_RATE * 2 * refclk_cfg)
122 + (ref_doubler_en_b * VCO_REF_CLOCK_RATE);
123
124 vco_clock = ((uint64_t) pd->vco_clock) * FRAC_DIVIDER;
125
126 div_fbx = vco_clock / ref_clk_to_pll;
127
128 rem = (uint32_t) (div_fbx % FRAC_DIVIDER);
129 rem = rem * (1 << 16);
130 frac_n_value = rem / FRAC_DIVIDER;
131
132 divider = pd->vco_clock / ref_clk_to_pll;
133 div_fbx *= ref_clk_to_pll;
134 gen_vco_clk = div_fbx / FRAC_DIVIDER;
135
136 if (frac_n_mode) {
137 sdm_cfg0 = 0x0;
138 sdm_cfg1 = (divider & 0x3f) - 1;
139 sdm_cfg3 = frac_n_value / 256;
140 sdm_cfg2 = frac_n_value % 256;
141 } else {
142 sdm_cfg0 = (0x1 << 5);
143 sdm_cfg0 |= (divider & 0x3f) - 1;
144 sdm_cfg1 = 0x0;
145 sdm_cfg2 = 0;
146 sdm_cfg3 = 0;
147 }
148
149 cal_cfg11 = gen_vco_clk / 256000000;
150 cal_cfg10 = (gen_vco_clk % 256000000) / 1000000;
151
Sandeep Panda0ce96e92015-05-13 12:24:10 +0530152 writel(sdm_cfg1 & 0xff , ctl_base + 0x023c); /* SDM CFG1 */
153 writel(sdm_cfg2 & 0xff , ctl_base + 0x0240); /* SDM CFG2 */
154 writel(sdm_cfg3 & 0xff, ctl_base + 0x0244); /* SDM CFG3 */
Casey Piper83559892013-08-26 11:22:25 -0700155 writel(0x00, ctl_base + 0x0248); /* SDM CFG4 */
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700156
157 udelay(10);
158
Casey Piper83559892013-08-26 11:22:25 -0700159 writel(refclk_cfg, ctl_base + 0x0200); /* REFCLK CFG */
160 writel(0x00, ctl_base + 0x0214); /* PWRGEN CFG */
161 writel(0x71, ctl_base + 0x020c); /* VCOLPF CFG */
162 writel(pd->directpath, ctl_base + 0x0210); /* VREG CFG */
163 writel(sdm_cfg0, ctl_base + 0x0238); /* SDM CFG0 */
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700164
Sandeep Panda0ce96e92015-05-13 12:24:10 +0530165 writel(0x12, ctl_base + 0x026c); /* CAL CFG0 */
Casey Piper83559892013-08-26 11:22:25 -0700166 writel(0x30, ctl_base + 0x0284); /* CAL CFG6 */
167 writel(0x00, ctl_base + 0x0288); /* CAL CFG7 */
168 writel(0x60, ctl_base + 0x028c); /* CAL CFG8 */
169 writel(0x00, ctl_base + 0x0290); /* CAL CFG9 */
170 writel(cal_cfg10, ctl_base + 0x0294); /* CAL CFG10 */
171 writel(cal_cfg11, ctl_base + 0x0298); /* CAL CFG11 */
172 writel(0x20, ctl_base + 0x029c); /* EFUSE CFG */
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700173}