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