blob: e7d7a0e3e18e4f1663d11721d08751485c370194 [file] [log] [blame]
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -07001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
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
40static uint32_t calculate_bitclock(struct msm_panel_info *pinfo)
41{
42 uint32_t ret = NO_ERROR;
43 uint32_t h_period = 0, v_period = 0;
Dhaval Patelad152092013-10-25 10:07:57 -070044 uint32_t width = pinfo->xres;
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -070045
Dhaval Patelad152092013-10-25 10:07:57 -070046 if (pinfo->mipi.dual_dsi)
47 width = pinfo->xres / 2;
48
49 h_period = width + pinfo->lcdc.h_back_porch +
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -070050 pinfo->lcdc.h_front_porch + pinfo->lcdc.h_pulse_width +
51 pinfo->lcdc.xres_pad;
52
53 v_period = pinfo->yres + pinfo->lcdc.v_back_porch +
54 pinfo->lcdc.v_front_porch + pinfo->lcdc.v_pulse_width +
55 pinfo->lcdc.yres_pad;
56
57 /* Pixel clock rate */
58 pll_data.pixel_clock = h_period * v_period * pinfo->mipi.frame_rate;
59
60 /* Store all bit clock form data */
61 if (pinfo->mipi.bitclock == 0)
62 pll_data.bit_clock = (pll_data.pixel_clock * pinfo->bpp) /
63 pinfo->mipi.num_of_lanes;
64 else
65 pll_data.bit_clock = pinfo->mipi.bitclock;
66
67 pll_data.byte_clock = pll_data.bit_clock >> 3;
68
69 pll_data.halfbit_clock = pll_data.bit_clock >> 1;
70
71 return ret;
72}
73
74static uint32_t calculate_div1()
75{
76 uint32_t ret = NO_ERROR;
77
78 /* div1 - there is divide by 2 logic present */
79 if (pll_data.halfbit_clock > HALFBIT_CLOCK1) {
80 pll_data.posdiv1 = 0x0; /*div 1 */
81 pll_data.vco_clock = pll_data.halfbit_clock << 1;
82 } else if (pll_data.halfbit_clock > HALFBIT_CLOCK2) {
83 pll_data.posdiv1 = 0x1; /*div 2 */
84 pll_data.vco_clock = pll_data.halfbit_clock << 2;
85 } else if (pll_data.halfbit_clock > HALFBIT_CLOCK3) {
86 pll_data.posdiv1 = 0x3; /*div 4 */
87 pll_data.vco_clock = pll_data.halfbit_clock << 3;
88 } else if (pll_data.halfbit_clock > HALFBIT_CLOCK4) {
89 pll_data.posdiv1 = 0x4; /*div 5 */
90 pll_data.vco_clock = pll_data.halfbit_clock * 10;
91 } else {
92 dprintf(CRITICAL, "Not able to calculate posdiv1\n");
93 }
94
95 return ret;
96}
97
98static uint32_t calculate_div3(uint8_t bpp, uint8_t num_of_lanes)
99{
100 uint32_t ret = NO_ERROR;
101 pll_data.pclk_m = 0x1; /* M = 1, N= 1 */
102 pll_data.pclk_n = 0xFF; /* ~ (N-M) = 0xff */
103 pll_data.pclk_d = 0xFF; /* ~N = 0xFF */
104
105 /* formula is ( vco_clock / pdiv_digital) / mnd = pixel_clock */
106
107 /* div3 */
108 switch (bpp) {
109 case BITS_18:
110 if (num_of_lanes == 3) {
111 pll_data.posdiv3 = pll_data.vco_clock /
112 pll_data.pixel_clock;
113 } else {
114 pll_data.posdiv3 = (pll_data.pixel_clock * 2 / 9) /
115 pll_data.vco_clock;
116 pll_data.pclk_m = 0x2; /* M = 2,N = 9 */
117 pll_data.pclk_n = 0xF8;
118 pll_data.pclk_d = 0xF6;
119 }
120 break;
121 case BITS_16:
122 if (num_of_lanes == 3) {
123 pll_data.posdiv3 = (pll_data.pixel_clock * 3 / 8) /
124 pll_data.vco_clock;
125 pll_data.pclk_m = 0x3; /* M = 3, N = 9 */
126 pll_data.pclk_n = 0xFA;
127 pll_data.pclk_d = 0xF7;
128 } else {
129 pll_data.posdiv3 = pll_data.vco_clock /
130 pll_data.pixel_clock;
131 }
132 break;
133 case BITS_24:
134 default:
135 pll_data.posdiv3 = pll_data.vco_clock /
136 pll_data.pixel_clock;
137 break;
138 }
139
140 pll_data.posdiv3--; /* Register needs one value less */
141}
142
143static uint32_t calculate_vco(uint8_t bpp, uint8_t num_of_lanes)
144{
145 uint32_t ret = NO_ERROR;
146 uint8_t counter = 0;
147 uint32_t temprate = 0;
148
149 /* If half bitclock is more than VCO min value */
150 if (pll_data.halfbit_clock > VCO_MIN_CLOCK) {
151
152 /* Direct Mode */
153
154 /* support vco clock to max value only */
155 if (pll_data.halfbit_clock > VCO_MAX_CLOCK)
156 pll_data.vco_clock = VCO_MAX_CLOCK;
157 else
158 pll_data.vco_clock = pll_data.halfbit_clock;
159 pll_data.directpath = 0x0;
160 pll_data.posdiv1 = 0x0; /*DSI spec says 0 - div 1 */
161 /*1 - div 2 */
162 /*F - div 16 */
163 } else {
164 /* Indirect Mode */
165
166 pll_data.directpath = 0x02; /* set bit 1 to enable for
167 indirect path */
168
169 calculate_div1();
170 }
171
172 /* calculate mnd and div3 for direct and indirect path */
173 calculate_div3(bpp, num_of_lanes);
174
175 return ret;
176}
177
178uint32_t calculate_clock_config(struct msm_panel_info *pinfo)
179{
180 uint32_t ret = NO_ERROR;
181
182 calculate_bitclock(pinfo);
183
184 calculate_vco(pinfo->bpp, pinfo->mipi.num_of_lanes);
185
186 pinfo->mipi.dsi_pll_config = &pll_data;
187
188 return ret;
189}