blob: 970270cf5570498f95a55ebb6286030642109d6f [file] [log] [blame]
Padmanabhan Komanduru40f0d3c2018-04-26 17:41:17 +05301/* Copyright (c) 2013-2015, 2018, The Linux Foundation. All rights reserved.
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are 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 copyright
9 * notice, this list of conditions and the following disclaimer in
10 * the documentation and/or other materials provided with the
11 * 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <debug.h>
31#include <err.h>
32#include <smem.h>
33#include <msm_panel.h>
34#include <mipi_dsi.h>
35
36#include "gcdb_autopll.h"
37
38static struct mdss_dsi_pll_config pll_data;
39
Dhaval Pateld19fcf12014-08-12 13:16:05 -070040static void calculate_bitclock(struct msm_panel_info *pinfo)
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -070041{
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -070042 uint32_t h_period = 0, v_period = 0;
Dhaval Patelee8675a2013-10-25 10:07:57 -070043 uint32_t width = pinfo->xres;
Kuogee Hsiehe0fbc022015-07-07 10:26:58 -070044 struct dsc_desc *dsc = NULL;
Kuogee Hsiehc9ff3a72015-08-31 12:44:38 -070045 int bpp_lane;
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -070046
Dhaval Patelee8675a2013-10-25 10:07:57 -070047 if (pinfo->mipi.dual_dsi)
Siddhartha Agrawalfe64dcb2014-10-07 12:41:01 -070048 width /= 2;
49
Kuogee Hsiehe0fbc022015-07-07 10:26:58 -070050 if (pinfo->compression_mode == COMPRESSION_DSC) {
51 dsc = &pinfo->dsc;
52 width = dsc->pclk_per_line;
53 } else if (pinfo->compression_mode == COMPRESSION_FBC) {
54 if (pinfo->fbc.comp_ratio)
55 width /= pinfo->fbc.comp_ratio;
56 }
Dhaval Patelee8675a2013-10-25 10:07:57 -070057
58 h_period = width + pinfo->lcdc.h_back_porch +
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -070059 pinfo->lcdc.h_front_porch + pinfo->lcdc.h_pulse_width +
60 pinfo->lcdc.xres_pad;
61
62 v_period = pinfo->yres + pinfo->lcdc.v_back_porch +
63 pinfo->lcdc.v_front_porch + pinfo->lcdc.v_pulse_width +
64 pinfo->lcdc.yres_pad;
65
Kuogee Hsiehc9ff3a72015-08-31 12:44:38 -070066 bpp_lane = pinfo->bpp / pinfo->mipi.num_of_lanes;
67
Aravind Venkateswaran31119842015-01-13 14:46:04 -080068 /*
69 * If a bit clock rate is not specified, calculate it based
70 * on panel parameters
71 */
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -070072 if (pinfo->mipi.bitclock == 0)
Aravind Venkateswaran31119842015-01-13 14:46:04 -080073 pll_data.bit_clock = (h_period * v_period *
Kuogee Hsiehc9ff3a72015-08-31 12:44:38 -070074 pinfo->mipi.frame_rate * bpp_lane);
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -070075 else
76 pll_data.bit_clock = pinfo->mipi.bitclock;
77
Kuogee Hsiehc9ff3a72015-08-31 12:44:38 -070078 pll_data.pixel_clock = (pll_data.bit_clock / bpp_lane);
79
80 dprintf(SPEW, "%s: bit_clk=%d pix_clk=%d\n", __func__,
81 pll_data.bit_clock, pll_data.pixel_clock);
Aravind Venkateswaran31119842015-01-13 14:46:04 -080082
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -070083 pll_data.byte_clock = pll_data.bit_clock >> 3;
84
85 pll_data.halfbit_clock = pll_data.bit_clock >> 1;
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -070086}
87
88static uint32_t calculate_div1()
89{
90 uint32_t ret = NO_ERROR;
91
92 /* div1 - there is divide by 2 logic present */
93 if (pll_data.halfbit_clock > HALFBIT_CLOCK1) {
94 pll_data.posdiv1 = 0x0; /*div 1 */
95 pll_data.vco_clock = pll_data.halfbit_clock << 1;
96 } else if (pll_data.halfbit_clock > HALFBIT_CLOCK2) {
97 pll_data.posdiv1 = 0x1; /*div 2 */
98 pll_data.vco_clock = pll_data.halfbit_clock << 2;
99 } else if (pll_data.halfbit_clock > HALFBIT_CLOCK3) {
100 pll_data.posdiv1 = 0x3; /*div 4 */
101 pll_data.vco_clock = pll_data.halfbit_clock << 3;
102 } else if (pll_data.halfbit_clock > HALFBIT_CLOCK4) {
103 pll_data.posdiv1 = 0x4; /*div 5 */
104 pll_data.vco_clock = pll_data.halfbit_clock * 10;
105 } else {
106 dprintf(CRITICAL, "Not able to calculate posdiv1\n");
107 }
108
109 return ret;
110}
111
112static uint32_t calculate_div3(uint8_t bpp, uint8_t num_of_lanes)
113{
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -0700114 pll_data.pclk_m = 0x1; /* M = 1, N= 1 */
115 pll_data.pclk_n = 0xFF; /* ~ (N-M) = 0xff */
116 pll_data.pclk_d = 0xFF; /* ~N = 0xFF */
117
118 /* formula is ( vco_clock / pdiv_digital) / mnd = pixel_clock */
119
120 /* div3 */
121 switch (bpp) {
122 case BITS_18:
123 if (num_of_lanes == 3) {
124 pll_data.posdiv3 = pll_data.vco_clock /
125 pll_data.pixel_clock;
126 } else {
127 pll_data.posdiv3 = (pll_data.pixel_clock * 2 / 9) /
128 pll_data.vco_clock;
129 pll_data.pclk_m = 0x2; /* M = 2,N = 9 */
130 pll_data.pclk_n = 0xF8;
131 pll_data.pclk_d = 0xF6;
132 }
133 break;
134 case BITS_16:
135 if (num_of_lanes == 3) {
136 pll_data.posdiv3 = (pll_data.pixel_clock * 3 / 8) /
137 pll_data.vco_clock;
138 pll_data.pclk_m = 0x3; /* M = 3, N = 9 */
139 pll_data.pclk_n = 0xFA;
140 pll_data.pclk_d = 0xF7;
141 } else {
142 pll_data.posdiv3 = pll_data.vco_clock /
143 pll_data.pixel_clock;
144 }
145 break;
146 case BITS_24:
147 default:
148 pll_data.posdiv3 = pll_data.vco_clock /
149 pll_data.pixel_clock;
150 break;
151 }
152
153 pll_data.posdiv3--; /* Register needs one value less */
Veera Sundaram Sankaran824e6fa2014-12-09 11:32:58 -0800154 return NO_ERROR;
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -0700155}
156
Dhaval Pateld19fcf12014-08-12 13:16:05 -0700157static uint32_t calculate_dec_frac_start()
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -0700158{
Dhaval Pateld19fcf12014-08-12 13:16:05 -0700159 uint32_t refclk = 19200000;
160 uint32_t vco_rate = pll_data.vco_clock;
Chandan Uddaraju058298e2015-02-04 14:25:30 -0800161 uint32_t tmp, mod;
Dhaval Pateld19fcf12014-08-12 13:16:05 -0700162
163 vco_rate /= 2;
164 pll_data.dec_start = vco_rate / refclk;
165 tmp = vco_rate % refclk; /* module, fraction */
166 tmp /= 192;
167 tmp *= 1024;
168 tmp /= 100;
169 tmp *= 1024;
170 tmp /= 1000;
171 pll_data.frac_start = tmp;
172
173 vco_rate *= 2; /* restore */
Chandan Uddaraju058298e2015-02-04 14:25:30 -0800174 if (pll_data.en_vco_zero_phase) {
175 tmp = vco_rate / (refclk / 1000);/* div 1000 first */
176 tmp *= 1024;
177 tmp /= 1000;
178 tmp /= 10;
179 pll_data.lock_comp = tmp - 1;
180 } else {
181 tmp = vco_rate / refclk;
182 mod = vco_rate % refclk;
183 tmp *= 127;
184 mod *= 127;
185 mod /= refclk;
186 tmp += mod;
187 tmp /= 10;
188 pll_data.lock_comp = tmp;
189 }
Dhaval Pateld19fcf12014-08-12 13:16:05 -0700190
Chandan Uddaraju67519562014-11-01 17:00:45 -0700191 dprintf(SPEW, "%s: dec_start=0x%x dec_frac=0x%x lock_comp=0x%x\n", __func__,
Dhaval Pateld19fcf12014-08-12 13:16:05 -0700192 pll_data.dec_start, pll_data.frac_start, pll_data.lock_comp);
Veera Sundaram Sankaran824e6fa2014-12-09 11:32:58 -0800193 return NO_ERROR;
Dhaval Pateld19fcf12014-08-12 13:16:05 -0700194}
195
196static uint32_t calculate_vco_28nm(uint8_t bpp, uint8_t num_of_lanes)
197{
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -0700198 /* If half bitclock is more than VCO min value */
199 if (pll_data.halfbit_clock > VCO_MIN_CLOCK) {
200
201 /* Direct Mode */
202
203 /* support vco clock to max value only */
204 if (pll_data.halfbit_clock > VCO_MAX_CLOCK)
205 pll_data.vco_clock = VCO_MAX_CLOCK;
206 else
207 pll_data.vco_clock = pll_data.halfbit_clock;
208 pll_data.directpath = 0x0;
209 pll_data.posdiv1 = 0x0; /*DSI spec says 0 - div 1 */
210 /*1 - div 2 */
211 /*F - div 16 */
212 } else {
213 /* Indirect Mode */
214
215 pll_data.directpath = 0x02; /* set bit 1 to enable for
216 indirect path */
217
218 calculate_div1();
219 }
220
221 /* calculate mnd and div3 for direct and indirect path */
222 calculate_div3(bpp, num_of_lanes);
223
Dhaval Pateld19fcf12014-08-12 13:16:05 -0700224 return NO_ERROR;
225}
226
Chandan Uddaraju058298e2015-02-04 14:25:30 -0800227#ifndef DISPLAY_EN_20NM_PLL_90_PHASE
228static void config_20nm_pll_vco_range(void)
229{
230 pll_data.vco_min = 300000000;
231 pll_data.vco_max = 1500000000;
232 pll_data.en_vco_zero_phase = 1;
233 dprintf(SPEW, "%s: Configured VCO for zero phase\n", __func__);
234}
235#else
236static void config_20nm_pll_vco_range(void)
237{
238 pll_data.vco_min = 1000000000;
239 pll_data.vco_max = 2000000000;
240 pll_data.en_vco_zero_phase = 0;
241 dprintf(SPEW, "%s: Configured VCO for 90 phase\n", __func__);
242}
243#endif
244
Dhaval Patel236b32b2015-10-16 14:44:35 -0700245static uint32_t calculate_vco_thulium(uint8_t bpp, uint8_t lanes)
Dhaval Patel8b9a5822015-03-16 13:01:26 -0700246{
247 uint32_t rate;
248 uint32_t mod;
Dhaval Patel236b32b2015-10-16 14:44:35 -0700249 int bpp_lane;
250
251 /* round up the pixel clock to get the correct n2 div */
252 bpp_lane = bpp / lanes;
253 mod = pll_data.bit_clock % bpp_lane;
254 if (mod)
255 pll_data.pixel_clock++;
Dhaval Patel8b9a5822015-03-16 13:01:26 -0700256
257 pll_data.vco_min = MIN_THULIUM_VCO_RATE;
258 pll_data.vco_max = MAX_THULIUM_VCO_RATE;
259
260 if (pll_data.bit_clock < pll_data.vco_min)
261 rate = pll_data.vco_min;
262 else if (pll_data.bit_clock > pll_data.vco_max)
263 rate = pll_data.vco_max;
264 else
265 rate = pll_data.bit_clock;
266
267 pll_data.ndiv = FIX_N_DIV;
268 if (pll_data.bit_clock) {
269 pll_data.n1div = rate / pll_data.bit_clock;
270 } else {
271 dprintf(ERROR, "%s: bit clock is 0, divider calculation failed\n",
272 __func__);
273 return ERROR;
274 }
275
276 mod = rate % pll_data.bit_clock;
277 if (mod)
278 pll_data.n1div++;
279
280 if (pll_data.n1div < MIN_THULIUM_DIV_VAL ||
281 pll_data.n1div > MAX_THULIUM_DIV_VAL) {
282 dprintf(ERROR, "%s: n1div is out of ranget:%d\n",
283 __func__, pll_data.n1div);
284 return ERROR;
285 }
286
Kuogee Hsiehc9ff3a72015-08-31 12:44:38 -0700287 pll_data.vco_clock = pll_data.bit_clock * pll_data.ndiv *
288 pll_data.n1div;
289
290 rate = pll_data.vco_clock;
291
Dhaval Patel8b9a5822015-03-16 13:01:26 -0700292 rate /= pll_data.n1div;
293 rate /= FIX_PIXEL_CLOCK_DIV;
294
295 pll_data.n2div = rate / pll_data.pixel_clock;
296 mod = rate % pll_data.pixel_clock;
297 if (mod)
298 pll_data.n2div++;
299
300 if (pll_data.n2div < MIN_THULIUM_DIV_VAL ||
301 pll_data.n2div > MAX_THULIUM_DIV_VAL) {
302 dprintf(ERROR, "%s: n2div is out of ranget:%d\n",
303 __func__, pll_data.n2div);
304 return ERROR;
305 }
Dhaval Patel8b9a5822015-03-16 13:01:26 -0700306
307 dprintf(SPEW, "%s: vco:%u n1div:%d n2div:%d bit_clk:%u pixel_clk:%u\n",
308 __func__, pll_data.vco_clock, pll_data.n1div, pll_data.n2div,
309 pll_data.bit_clock, pll_data.pixel_clock);
310
311 return NO_ERROR;
312}
313
Dhaval Pateld19fcf12014-08-12 13:16:05 -0700314static uint32_t calculate_vco_20nm(uint8_t bpp, uint8_t lanes)
315{
316 uint32_t vco, dsi_clk;
317 int mod, ndiv, hr_oclk2, hr_oclk3;
318 int m = 1;
319 int n = 1;
320 int bpp_m = 3; /* bpp = 3 */
321 int bpp_n = 1;
322
323 if (bpp == BITS_18) {
324 bpp_m = 9; /* bpp = 2.25 */
325 bpp_n = 4;
326
327 if (lanes == 2) {
328 m = 2;
329 n = 9;
330 } else if (lanes == 4) {
331 m = 4;
332 n = 9;
333 }
334 } else if (bpp == BITS_16) {
335 bpp_m = 2; /* bpp = 2 */
336 bpp_n = 1;
337 if (lanes == 3) {
338 m = 3;
339 n = 8;
340 }
341 }
342
343 hr_oclk2 = 4;
344
345 /* If bitclock is more than VCO min value */
Chandan Uddaraju058298e2015-02-04 14:25:30 -0800346 if (pll_data.halfbit_clock >= ((pll_data.vco_min) >> 1)) {
Dhaval Pateld19fcf12014-08-12 13:16:05 -0700347 /* Direct Mode */
348 vco = pll_data.halfbit_clock << 1;
349 /* support vco clock to max value only */
Chandan Uddaraju058298e2015-02-04 14:25:30 -0800350 if (vco > (pll_data.vco_max))
351 vco = (pll_data.vco_max);
Dhaval Pateld19fcf12014-08-12 13:16:05 -0700352
353 pll_data.directpath = 0x0;
354 pll_data.byte_clock = vco / 2 / hr_oclk2;
355 pll_data.lp_div_mux = 0x0;
356 ndiv = 1;
357 hr_oclk3 = hr_oclk2 * m / n * bpp_m / bpp_n / lanes;
358 } else {
359 /* Indirect Mode */
Chandan Uddaraju058298e2015-02-04 14:25:30 -0800360 mod = (pll_data.vco_min) % (4 * pll_data.halfbit_clock );
361 ndiv = (pll_data.vco_min) / (4 * pll_data.halfbit_clock );
Dhaval Pateld19fcf12014-08-12 13:16:05 -0700362 if (mod)
363 ndiv += 1;
364
365 vco = pll_data.halfbit_clock * 4 * ndiv;
366 pll_data.lp_div_mux = 0x1;
367 pll_data.directpath = 0x02; /* set bit 1 to enable for
368 indirect path */
369
370 pll_data.byte_clock = vco / 4 / hr_oclk2 / ndiv;
371 hr_oclk3 = hr_oclk2 * m / n * ndiv * 2 * bpp_m / bpp_n / lanes;
372 }
373
374 pll_data.vco_clock = vco;
375 dsi_clk = vco / 2 / hr_oclk3;
376 pll_data.ndiv = ndiv;
377 pll_data.hr_oclk2 = hr_oclk2 - 1; /* strat from 0 */
378 pll_data.hr_oclk3 = hr_oclk3 - 1; /* strat from 0 */
379
380 pll_data.pclk_m = m; /* M */
381 pll_data.pclk_n = ~(n - m); /* ~(N-M) */
382 pll_data.pclk_d = ~n; /* ~N */
383
384 dprintf(SPEW, "%s: oclk2=%d oclk3=%d ndiv=%d vco=%u dsi_clk=%u byte_clk=%u\n",
385 __func__, hr_oclk2, hr_oclk3, ndiv, vco, dsi_clk, pll_data.byte_clock);
386
387 calculate_dec_frac_start();
388
389 return NO_ERROR;
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -0700390}
391
Padmanabhan Komanduru40f0d3c2018-04-26 17:41:17 +0530392static uint32_t calculate_p_div_mux(uint32_t hr_bitclk)
393{
394 uint32_t hr_bitclk_mhz = (hr_bitclk / 1000000);
395
396 if (hr_bitclk_mhz >= 1000 && hr_bitclk_mhz <= 1250)
397 return 0x0;
398 else if (hr_bitclk_mhz >= 500 && hr_bitclk_mhz < 1000)
399 return 0x1;
400 else if (hr_bitclk_mhz >= 250 && hr_bitclk_mhz < 500)
401 return 0x2;
402 else if (hr_bitclk_mhz >= 125 && hr_bitclk_mhz < 250)
403 return 0x3;
404 else if (hr_bitclk_mhz >= 63 && hr_bitclk_mhz < 125)
405 return 0x4;
406 else
407 return 0x5;
408}
409
410static void calculate_divhf(uint32_t hr_bitclk, uint8_t bpp,
411 uint8_t lanes)
412{
413 int m = 1;
414 int n = 1;
415 uint32_t dsi_clk = 0;
416
417 if (bpp == BITS_18) {
418 if (lanes == 2) {
419 m = 2;
420 n = 9;
421 } else if (lanes == 4) {
422 m = 4;
423 n = 9;
424 }
425 } else if (bpp == BITS_16) {
426 if (lanes == 3) {
427 m = 3;
428 n = 8;
429 }
430 }
431
432 dsi_clk = (pll_data.pixel_clock * n) / m;
433 pll_data.divhf = ((pll_data.halfbit_clock / dsi_clk) - 1);
434
435 pll_data.pclk_m = m; /* M */
436 pll_data.pclk_n = ~(n - m); /* ~(N-M) */
437 pll_data.pclk_d = ~n; /* ~N */
438}
439
440static uint32_t calculate_vco_12nm(uint8_t bpp, uint8_t lanes)
441{
442 pll_data.vco_min = MIN_12NM_VCO_RATE;
443 pll_data.vco_max = MAX_12NM_VCO_RATE;
444 pll_data.p_div_mux = calculate_p_div_mux(pll_data.halfbit_clock);
445 pll_data.gp_div_mux = pll_data.p_div_mux;
446 pll_data.vco_clock = pll_data.halfbit_clock * (1 << pll_data.p_div_mux);
447 calculate_divhf(pll_data.halfbit_clock, bpp, lanes);
448 return NO_ERROR;
449}
450
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -0700451uint32_t calculate_clock_config(struct msm_panel_info *pinfo)
452{
453 uint32_t ret = NO_ERROR;
454
455 calculate_bitclock(pinfo);
456
Dhaval Patel8b9a5822015-03-16 13:01:26 -0700457 switch (pinfo->mipi.mdss_dsi_phy_db->pll_type) {
458 case DSI_PLL_TYPE_20NM:
Chandan Uddaraju058298e2015-02-04 14:25:30 -0800459 config_20nm_pll_vco_range();
Dhaval Pateld19fcf12014-08-12 13:16:05 -0700460 ret = calculate_vco_20nm(pinfo->bpp, pinfo->mipi.num_of_lanes);
Dhaval Patel8b9a5822015-03-16 13:01:26 -0700461 break;
462 case DSI_PLL_TYPE_THULIUM:
463 ret = calculate_vco_thulium(pinfo->bpp, pinfo->mipi.num_of_lanes);
464 break;
Padmanabhan Komanduru40f0d3c2018-04-26 17:41:17 +0530465 case DSI_PLL_TYPE_12NM:
466 ret = calculate_vco_12nm(pinfo->bpp, pinfo->mipi.num_of_lanes);
467 break;
Dhaval Patel8b9a5822015-03-16 13:01:26 -0700468 case DSI_PLL_TYPE_28NM:
469 default:
Dhaval Pateld19fcf12014-08-12 13:16:05 -0700470 ret = calculate_vco_28nm(pinfo->bpp, pinfo->mipi.num_of_lanes);
Dhaval Patel8b9a5822015-03-16 13:01:26 -0700471 break;
472 }
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -0700473
474 pinfo->mipi.dsi_pll_config = &pll_data;
475
476 return ret;
477}