blob: f0e46f77a0ad8ca5c488af353308c78f52ccf57f [file] [log] [blame]
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13#include <linux/clk.h>
14#include <linux/interrupt.h>
15#include <linux/delay.h>
16#include <linux/err.h>
17#include <linux/io.h>
18#include <linux/clk/msm-clk.h>
19#include <linux/iopoll.h>
20#include <linux/kthread.h>
21
22#include "mdss_dsi.h"
23#include "mdss_edp.h"
24#include "mdss_dsi_phy.h"
25
26#define MDSS_DSI_DSIPHY_REGULATOR_CTRL_0 0x00
27#define MDSS_DSI_DSIPHY_REGULATOR_CTRL_1 0x04
28#define MDSS_DSI_DSIPHY_REGULATOR_CTRL_2 0x08
29#define MDSS_DSI_DSIPHY_REGULATOR_CTRL_3 0x0c
30#define MDSS_DSI_DSIPHY_REGULATOR_CTRL_4 0x10
31#define MDSS_DSI_DSIPHY_REGULATOR_CAL_PWR_CFG 0x18
32#define MDSS_DSI_DSIPHY_LDO_CNTRL 0x1dc
33#define MDSS_DSI_DSIPHY_REGULATOR_TEST 0x294
34#define MDSS_DSI_DSIPHY_STRENGTH_CTRL_0 0x184
35#define MDSS_DSI_DSIPHY_STRENGTH_CTRL_1 0x188
36#define MDSS_DSI_DSIPHY_STRENGTH_CTRL_2 0x18c
37#define MDSS_DSI_DSIPHY_TIMING_CTRL_0 0x140
38#define MDSS_DSI_DSIPHY_GLBL_TEST_CTRL 0x1d4
39#define MDSS_DSI_DSIPHY_CTRL_0 0x170
40#define MDSS_DSI_DSIPHY_CTRL_1 0x174
41
42#define SW_RESET BIT(2)
43#define SW_RESET_PLL BIT(0)
44#define PWRDN_B BIT(7)
45
46/* 8996 */
47#define DATALANE_OFFSET_FROM_BASE_8996 0x100
48#define DSIPHY_CMN_PLL_CNTRL 0x0048
49#define DATALANE_SIZE_8996 0x80
50
51#define DSIPHY_CMN_GLBL_TEST_CTRL 0x0018
52#define DSIPHY_CMN_CTRL_0 0x001c
53#define DSIPHY_CMN_CTRL_1 0x0020
54#define DSIPHY_CMN_LDO_CNTRL 0x004c
55#define DSIPHY_PLL_CLKBUFLR_EN 0x041c
56#define DSIPHY_PLL_PLL_BANDGAP 0x0508
57
58#define DSIPHY_LANE_STRENGTH_CTRL_1 0x003c
59#define DSIPHY_LANE_VREG_CNTRL 0x0064
60
61#define DSI_DYNAMIC_REFRESH_PLL_CTRL0 0x214
62#define DSI_DYNAMIC_REFRESH_PLL_CTRL1 0x218
63#define DSI_DYNAMIC_REFRESH_PLL_CTRL2 0x21C
64#define DSI_DYNAMIC_REFRESH_PLL_CTRL3 0x220
65#define DSI_DYNAMIC_REFRESH_PLL_CTRL4 0x224
66#define DSI_DYNAMIC_REFRESH_PLL_CTRL5 0x228
67#define DSI_DYNAMIC_REFRESH_PLL_CTRL6 0x22C
68#define DSI_DYNAMIC_REFRESH_PLL_CTRL7 0x230
69#define DSI_DYNAMIC_REFRESH_PLL_CTRL8 0x234
70#define DSI_DYNAMIC_REFRESH_PLL_CTRL9 0x238
71#define DSI_DYNAMIC_REFRESH_PLL_CTRL10 0x23C
72#define DSI_DYNAMIC_REFRESH_PLL_CTRL11 0x240
73#define DSI_DYNAMIC_REFRESH_PLL_CTRL12 0x244
74#define DSI_DYNAMIC_REFRESH_PLL_CTRL13 0x248
75#define DSI_DYNAMIC_REFRESH_PLL_CTRL14 0x24C
76#define DSI_DYNAMIC_REFRESH_PLL_CTRL15 0x250
77#define DSI_DYNAMIC_REFRESH_PLL_CTRL16 0x254
78#define DSI_DYNAMIC_REFRESH_PLL_CTRL17 0x258
79#define DSI_DYNAMIC_REFRESH_PLL_CTRL18 0x25C
80#define DSI_DYNAMIC_REFRESH_PLL_CTRL19 0x260
81#define DSI_DYNAMIC_REFRESH_PLL_CTRL19 0x260
82#define DSI_DYNAMIC_REFRESH_PLL_CTRL20 0x264
83#define DSI_DYNAMIC_REFRESH_PLL_CTRL21 0x268
84#define DSI_DYNAMIC_REFRESH_PLL_CTRL22 0x26C
85#define DSI_DYNAMIC_REFRESH_PLL_CTRL23 0x270
86#define DSI_DYNAMIC_REFRESH_PLL_CTRL24 0x274
87#define DSI_DYNAMIC_REFRESH_PLL_CTRL25 0x278
88#define DSI_DYNAMIC_REFRESH_PLL_CTRL26 0x27C
89#define DSI_DYNAMIC_REFRESH_PLL_CTRL27 0x280
90#define DSI_DYNAMIC_REFRESH_PLL_CTRL28 0x284
91#define DSI_DYNAMIC_REFRESH_PLL_CTRL29 0x288
92#define DSI_DYNAMIC_REFRESH_PLL_CTRL30 0x28C
93#define DSI_DYNAMIC_REFRESH_PLL_CTRL31 0x290
94#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR 0x294
95#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR2 0x298
96
97#define DSIPHY_DLN0_CFG1 0x0104
98#define DSIPHY_DLN0_TIMING_CTRL_4 0x0118
99#define DSIPHY_DLN0_TIMING_CTRL_5 0x011C
100#define DSIPHY_DLN0_TIMING_CTRL_6 0x0120
101#define DSIPHY_DLN0_TIMING_CTRL_7 0x0124
102#define DSIPHY_DLN0_TIMING_CTRL_8 0x0128
103
104#define DSIPHY_DLN1_CFG1 0x0184
105#define DSIPHY_DLN1_TIMING_CTRL_4 0x0198
106#define DSIPHY_DLN1_TIMING_CTRL_5 0x019C
107#define DSIPHY_DLN1_TIMING_CTRL_6 0x01A0
108#define DSIPHY_DLN1_TIMING_CTRL_7 0x01A4
109#define DSIPHY_DLN1_TIMING_CTRL_8 0x01A8
110
111#define DSIPHY_DLN2_CFG1 0x0204
112#define DSIPHY_DLN2_TIMING_CTRL_4 0x0218
113#define DSIPHY_DLN2_TIMING_CTRL_5 0x021C
114#define DSIPHY_DLN2_TIMING_CTRL_6 0x0220
115#define DSIPHY_DLN2_TIMING_CTRL_7 0x0224
116#define DSIPHY_DLN2_TIMING_CTRL_8 0x0228
117
118#define DSIPHY_DLN3_CFG1 0x0284
119#define DSIPHY_DLN3_TIMING_CTRL_4 0x0298
120#define DSIPHY_DLN3_TIMING_CTRL_5 0x029C
121#define DSIPHY_DLN3_TIMING_CTRL_6 0x02A0
122#define DSIPHY_DLN3_TIMING_CTRL_7 0x02A4
123#define DSIPHY_DLN3_TIMING_CTRL_8 0x02A8
124
125#define DSIPHY_CKLN_CFG1 0x0304
126#define DSIPHY_CKLN_TIMING_CTRL_4 0x0318
127#define DSIPHY_CKLN_TIMING_CTRL_5 0x031C
128#define DSIPHY_CKLN_TIMING_CTRL_6 0x0320
129#define DSIPHY_CKLN_TIMING_CTRL_7 0x0324
130#define DSIPHY_CKLN_TIMING_CTRL_8 0x0328
131
132#define DSIPHY_PLL_RESETSM_CNTRL5 0x043c
133
134#define PLL_CALC_DATA(addr0, addr1, data0, data1) \
135 (((data1) << 24) | ((((addr1)/4) & 0xFF) << 16) | \
136 ((data0) << 8) | (((addr0)/4) & 0xFF))
137
138#define MDSS_DYN_REF_REG_W(base, offset, addr0, addr1, data0, data1) \
139 writel_relaxed(PLL_CALC_DATA(addr0, addr1, data0, data1), \
140 (base) + (offset))
141
142void mdss_dsi_dfps_config_8996(struct mdss_dsi_ctrl_pdata *ctrl)
143{
144 struct mdss_panel_data *pdata;
145 struct mdss_panel_info *pinfo;
146 struct mdss_dsi_phy_ctrl *pd;
147 int glbl_tst_cntrl =
148 MIPI_INP(ctrl->phy_io.base + DSIPHY_CMN_GLBL_TEST_CTRL);
149
150 pdata = &ctrl->panel_data;
151 if (!pdata) {
152 pr_err("%s: Invalid panel data\n", __func__);
153 return;
154 }
155 pinfo = &pdata->panel_info;
156 pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db);
157
158 if (mdss_dsi_is_ctrl_clk_slave(ctrl)) {
159 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
160 DSI_DYNAMIC_REFRESH_PLL_CTRL0,
161 DSIPHY_DLN0_CFG1, DSIPHY_DLN1_CFG1,
162 0, 0);
163 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
164 DSI_DYNAMIC_REFRESH_PLL_CTRL1,
165 DSIPHY_DLN2_CFG1, DSIPHY_DLN3_CFG1,
166 0x0, 0x0);
167 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
168 DSI_DYNAMIC_REFRESH_PLL_CTRL2,
169 DSIPHY_CKLN_CFG1, DSIPHY_DLN0_TIMING_CTRL_4,
170 0x0, pd->timing_8996[0]);
171 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
172 DSI_DYNAMIC_REFRESH_PLL_CTRL3,
173 DSIPHY_DLN1_TIMING_CTRL_4,
174 DSIPHY_DLN2_TIMING_CTRL_4,
175 pd->timing_8996[8],
176 pd->timing_8996[16]);
177 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
178 DSI_DYNAMIC_REFRESH_PLL_CTRL4,
179 DSIPHY_DLN3_TIMING_CTRL_4,
180 DSIPHY_CKLN_TIMING_CTRL_4,
181 pd->timing_8996[24],
182 pd->timing_8996[32]);
183 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
184 DSI_DYNAMIC_REFRESH_PLL_CTRL5,
185 DSIPHY_DLN0_TIMING_CTRL_5,
186 DSIPHY_DLN1_TIMING_CTRL_5,
187 pd->timing_8996[1],
188 pd->timing_8996[9]);
189 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
190 DSI_DYNAMIC_REFRESH_PLL_CTRL6,
191 DSIPHY_DLN2_TIMING_CTRL_5,
192 DSIPHY_DLN3_TIMING_CTRL_5,
193 pd->timing_8996[17],
194 pd->timing_8996[25]);
195 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
196 DSI_DYNAMIC_REFRESH_PLL_CTRL7,
197 DSIPHY_CKLN_TIMING_CTRL_5,
198 DSIPHY_DLN0_TIMING_CTRL_6,
199 pd->timing_8996[33],
200 pd->timing_8996[2]);
201 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
202 DSI_DYNAMIC_REFRESH_PLL_CTRL8,
203 DSIPHY_DLN1_TIMING_CTRL_6,
204 DSIPHY_DLN2_TIMING_CTRL_6,
205 pd->timing_8996[10],
206 pd->timing_8996[18]);
207 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
208 DSI_DYNAMIC_REFRESH_PLL_CTRL9,
209 DSIPHY_DLN3_TIMING_CTRL_6,
210 DSIPHY_CKLN_TIMING_CTRL_6,
211 pd->timing_8996[26],
212 pd->timing_8996[34]);
213 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
214 DSI_DYNAMIC_REFRESH_PLL_CTRL10,
215 DSIPHY_DLN0_TIMING_CTRL_7,
216 DSIPHY_DLN1_TIMING_CTRL_7,
217 pd->timing_8996[3],
218 pd->timing_8996[11]);
219 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
220 DSI_DYNAMIC_REFRESH_PLL_CTRL11,
221 DSIPHY_DLN2_TIMING_CTRL_7,
222 DSIPHY_DLN3_TIMING_CTRL_7,
223 pd->timing_8996[19],
224 pd->timing_8996[27]);
225 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
226 DSI_DYNAMIC_REFRESH_PLL_CTRL12,
227 DSIPHY_CKLN_TIMING_CTRL_7,
228 DSIPHY_DLN0_TIMING_CTRL_8,
229 pd->timing_8996[35],
230 pd->timing_8996[4]);
231 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
232 DSI_DYNAMIC_REFRESH_PLL_CTRL13,
233 DSIPHY_DLN1_TIMING_CTRL_8,
234 DSIPHY_DLN2_TIMING_CTRL_8,
235 pd->timing_8996[12],
236 pd->timing_8996[20]);
237 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
238 DSI_DYNAMIC_REFRESH_PLL_CTRL14,
239 DSIPHY_DLN3_TIMING_CTRL_8,
240 DSIPHY_CKLN_TIMING_CTRL_8,
241 pd->timing_8996[28],
242 pd->timing_8996[36]);
243 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
244 DSI_DYNAMIC_REFRESH_PLL_CTRL15,
245 0x0110, 0x0110, 0, 0);
246 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
247 DSI_DYNAMIC_REFRESH_PLL_CTRL16,
248 0x0110, 0x0110, 0, 0);
249 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
250 DSI_DYNAMIC_REFRESH_PLL_CTRL17,
251 0x0110, 0x0110, 0, 0);
252 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
253 DSI_DYNAMIC_REFRESH_PLL_CTRL18,
254 0x0110, 0x0110, 0, 0);
255 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
256 DSI_DYNAMIC_REFRESH_PLL_CTRL19,
257 0x0110, 0x0110, 0, 0);
258 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
259 DSI_DYNAMIC_REFRESH_PLL_CTRL20,
260 0x110, 0x110, 0, 0);
261 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
262 DSI_DYNAMIC_REFRESH_PLL_CTRL21,
263 0x110, 0x110, 0, 0);
264 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
265 DSI_DYNAMIC_REFRESH_PLL_CTRL22,
266 0x110, 0x110, 0, 0);
267 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
268 DSI_DYNAMIC_REFRESH_PLL_CTRL23,
269 0x110, 0x110, 0, 0);
270 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
271 DSI_DYNAMIC_REFRESH_PLL_CTRL24,
272 0x110, 0x110, 0, 0);
273 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
274 DSI_DYNAMIC_REFRESH_PLL_CTRL25,
275 0x110, 0x110, 0, 0);
276 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
277 DSI_DYNAMIC_REFRESH_PLL_CTRL26,
278 0x110, 0x110, 0, 0);
279 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
280 DSI_DYNAMIC_REFRESH_PLL_CTRL27,
281 0x110, 0x110, 0, 0);
282 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
283 DSI_DYNAMIC_REFRESH_PLL_CTRL28,
284 0x110, 0x110, 0, 0);
285 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
286 DSI_DYNAMIC_REFRESH_PLL_CTRL29,
287 0x110, 0x110, 0, 0);
288 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
289 DSI_DYNAMIC_REFRESH_PLL_CTRL30,
290 0x110, 0x110, 0, 0);
291 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
292 DSI_DYNAMIC_REFRESH_PLL_CTRL31,
293 0x110, 0x110, 0, 0);
294 MIPI_OUTP(ctrl->ctrl_base +
295 DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR, 0x0);
296 MIPI_OUTP(ctrl->ctrl_base +
297 DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR2, 0x0);
298 } else {
299 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
300 DSI_DYNAMIC_REFRESH_PLL_CTRL0,
301 DSIPHY_CMN_GLBL_TEST_CTRL,
302 DSIPHY_PLL_PLL_BANDGAP,
303 glbl_tst_cntrl | BIT(1), 0x1);
304 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
305 DSI_DYNAMIC_REFRESH_PLL_CTRL1,
306 DSIPHY_PLL_RESETSM_CNTRL5,
307 DSIPHY_PLL_PLL_BANDGAP,
308 0x0D, 0x03);
309 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
310 DSI_DYNAMIC_REFRESH_PLL_CTRL2,
311 DSIPHY_PLL_RESETSM_CNTRL5,
312 DSIPHY_CMN_PLL_CNTRL,
313 0x1D, 0x00);
314 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
315 DSI_DYNAMIC_REFRESH_PLL_CTRL3,
316 DSIPHY_CMN_CTRL_1, DSIPHY_DLN0_CFG1,
317 0x20, 0);
318 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
319 DSI_DYNAMIC_REFRESH_PLL_CTRL4,
320 DSIPHY_DLN1_CFG1, DSIPHY_DLN2_CFG1,
321 0, 0);
322 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
323 DSI_DYNAMIC_REFRESH_PLL_CTRL5,
324 DSIPHY_DLN3_CFG1, DSIPHY_CKLN_CFG1,
325 0, 0);
326 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
327 DSI_DYNAMIC_REFRESH_PLL_CTRL6,
328 DSIPHY_DLN0_TIMING_CTRL_4,
329 DSIPHY_DLN1_TIMING_CTRL_4,
330 pd->timing_8996[0],
331 pd->timing_8996[8]);
332 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
333 DSI_DYNAMIC_REFRESH_PLL_CTRL7,
334 DSIPHY_DLN2_TIMING_CTRL_4,
335 DSIPHY_DLN3_TIMING_CTRL_4,
336 pd->timing_8996[16],
337 pd->timing_8996[24]);
338 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
339 DSI_DYNAMIC_REFRESH_PLL_CTRL8,
340 DSIPHY_CKLN_TIMING_CTRL_4,
341 DSIPHY_DLN0_TIMING_CTRL_5,
342 pd->timing_8996[32],
343 pd->timing_8996[1]);
344 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
345 DSI_DYNAMIC_REFRESH_PLL_CTRL9,
346 DSIPHY_DLN1_TIMING_CTRL_5,
347 DSIPHY_DLN2_TIMING_CTRL_5,
348 pd->timing_8996[9],
349 pd->timing_8996[17]);
350 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
351 DSI_DYNAMIC_REFRESH_PLL_CTRL10,
352 DSIPHY_DLN3_TIMING_CTRL_5,
353 DSIPHY_CKLN_TIMING_CTRL_5,
354 pd->timing_8996[25],
355 pd->timing_8996[33]);
356 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
357 DSI_DYNAMIC_REFRESH_PLL_CTRL11,
358 DSIPHY_DLN0_TIMING_CTRL_6,
359 DSIPHY_DLN1_TIMING_CTRL_6,
360 pd->timing_8996[2],
361 pd->timing_8996[10]);
362 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
363 DSI_DYNAMIC_REFRESH_PLL_CTRL12,
364 DSIPHY_DLN2_TIMING_CTRL_6,
365 DSIPHY_DLN3_TIMING_CTRL_6,
366 pd->timing_8996[18],
367 pd->timing_8996[26]);
368 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
369 DSI_DYNAMIC_REFRESH_PLL_CTRL13,
370 DSIPHY_CKLN_TIMING_CTRL_6,
371 DSIPHY_DLN0_TIMING_CTRL_7,
372 pd->timing_8996[34],
373 pd->timing_8996[3]);
374 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
375 DSI_DYNAMIC_REFRESH_PLL_CTRL14,
376 DSIPHY_DLN1_TIMING_CTRL_7,
377 DSIPHY_DLN2_TIMING_CTRL_7,
378 pd->timing_8996[11],
379 pd->timing_8996[19]);
380 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
381 DSI_DYNAMIC_REFRESH_PLL_CTRL15,
382 DSIPHY_DLN3_TIMING_CTRL_7,
383 DSIPHY_CKLN_TIMING_CTRL_7,
384 pd->timing_8996[27],
385 pd->timing_8996[35]);
386 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
387 DSI_DYNAMIC_REFRESH_PLL_CTRL16,
388 DSIPHY_DLN0_TIMING_CTRL_8,
389 DSIPHY_DLN1_TIMING_CTRL_8,
390 pd->timing_8996[4],
391 pd->timing_8996[12]);
392 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
393 DSI_DYNAMIC_REFRESH_PLL_CTRL17,
394 DSIPHY_DLN2_TIMING_CTRL_8,
395 DSIPHY_DLN3_TIMING_CTRL_8,
396 pd->timing_8996[20],
397 pd->timing_8996[28]);
398 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
399 DSI_DYNAMIC_REFRESH_PLL_CTRL18,
400 DSIPHY_CKLN_TIMING_CTRL_8,
401 DSIPHY_CMN_CTRL_1,
402 pd->timing_8996[36], 0);
403 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
404 DSI_DYNAMIC_REFRESH_PLL_CTRL30,
405 DSIPHY_CMN_GLBL_TEST_CTRL,
406 DSIPHY_CMN_GLBL_TEST_CTRL,
407 ((glbl_tst_cntrl) & (~BIT(2))),
408 ((glbl_tst_cntrl) & (~BIT(2))));
409 MDSS_DYN_REF_REG_W(ctrl->ctrl_base,
410 DSI_DYNAMIC_REFRESH_PLL_CTRL31,
411 DSIPHY_CMN_GLBL_TEST_CTRL,
412 DSIPHY_CMN_GLBL_TEST_CTRL,
413 ((glbl_tst_cntrl) & (~BIT(2))),
414 ((glbl_tst_cntrl) & (~BIT(2))));
415 }
416
417 wmb(); /* make sure phy timings are updated*/
418}
419
420static void mdss_dsi_ctrl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl)
421{
422 /* start phy sw reset */
423 MIPI_OUTP(ctrl->ctrl_base + 0x12c, 0x0001);
424 udelay(1000);
425 wmb(); /* make sure reset */
426 /* end phy sw reset */
427 MIPI_OUTP(ctrl->ctrl_base + 0x12c, 0x0000);
428 udelay(100);
429 wmb(); /* maek sure reset cleared */
430}
431
432int mdss_dsi_phy_pll_reset_status(struct mdss_dsi_ctrl_pdata *ctrl)
433{
434 int rc;
435 u32 val;
436 u32 const sleep_us = 10, timeout_us = 100;
437
438 pr_debug("%s: polling for RESETSM_READY_STATUS.CORE_READY\n",
439 __func__);
440 rc = readl_poll_timeout(ctrl->phy_io.base + 0x4cc, val,
441 (val & 0x1), sleep_us, timeout_us);
442
443 return rc;
444}
445
446static void mdss_dsi_phy_sw_reset_sub(struct mdss_dsi_ctrl_pdata *ctrl)
447{
448 struct mdss_dsi_ctrl_pdata *sctrl = NULL;
449 struct dsi_shared_data *sdata;
450 struct mdss_dsi_ctrl_pdata *octrl;
451 u32 reg_val = 0;
452
453 if (ctrl == NULL) {
454 pr_err("%s: Invalid input data\n", __func__);
455 return;
456 }
457
458 sdata = ctrl->shared_data;
459 octrl = mdss_dsi_get_other_ctrl(ctrl);
460
461 if (ctrl->shared_data->phy_rev == DSI_PHY_REV_20) {
462 if (mdss_dsi_is_ctrl_clk_master(ctrl))
463 sctrl = mdss_dsi_get_ctrl_clk_slave();
464 else
465 return;
466 }
467
468 /*
469 * For dual dsi case if we do DSI PHY sw reset,
470 * this will reset DSI PHY regulators also.
471 * Since DSI PHY regulator is shared among both
472 * the DSI controllers, we should not do DSI PHY
473 * sw reset when the other DSI controller is still
474 * active.
475 */
476 mutex_lock(&sdata->phy_reg_lock);
477 if ((mdss_dsi_is_hw_config_dual(sdata) &&
478 (octrl && octrl->is_phyreg_enabled))) {
479 /* start phy lane and HW reset */
480 reg_val = MIPI_INP(ctrl->ctrl_base + 0x12c);
481 reg_val |= (BIT(16) | BIT(8));
482 MIPI_OUTP(ctrl->ctrl_base + 0x12c, reg_val);
483 /* wait for 1ms as per HW design */
484 usleep_range(1000, 2000);
485 /* ensure phy lane and HW reset starts */
486 wmb();
487 /* end phy lane and HW reset */
488 reg_val = MIPI_INP(ctrl->ctrl_base + 0x12c);
489 reg_val &= ~(BIT(16) | BIT(8));
490 MIPI_OUTP(ctrl->ctrl_base + 0x12c, reg_val);
491 /* wait for 100us as per HW design */
492 usleep_range(100, 200);
493 /* ensure phy lane and HW reset ends */
494 wmb();
495 } else {
496 /* start phy sw reset */
497 mdss_dsi_ctrl_phy_reset(ctrl);
498 if (sctrl)
499 mdss_dsi_ctrl_phy_reset(sctrl);
500
501 }
502 mutex_unlock(&sdata->phy_reg_lock);
503}
504
505void mdss_dsi_phy_sw_reset(struct mdss_dsi_ctrl_pdata *ctrl)
506{
507 struct mdss_dsi_ctrl_pdata *sctrl = NULL;
508 struct dsi_shared_data *sdata;
509
510 if (ctrl == NULL) {
511 pr_err("%s: Invalid input data\n", __func__);
512 return;
513 }
514
515 sdata = ctrl->shared_data;
516
517 /*
518 * When operating in split display mode, make sure that the PHY reset
519 * is only done from the clock master. This will ensure that the PLL is
520 * off when PHY reset is called.
521 */
Padmanabhan Komanduru81d8dc522018-03-22 20:00:58 +0530522 if (mdss_dsi_is_ctrl_clk_slave(ctrl) ||
523 (ctrl->shared_data->phy_rev == DSI_PHY_REV_12NM))
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530524 return;
525
526 mdss_dsi_phy_sw_reset_sub(ctrl);
527
528 if (mdss_dsi_is_ctrl_clk_master(ctrl)) {
529 sctrl = mdss_dsi_get_ctrl_clk_slave();
530 if (sctrl)
531 mdss_dsi_phy_sw_reset_sub(sctrl);
532 else
533 pr_warn("%s: unable to get slave ctrl\n", __func__);
534 }
535
536 /* All other quirks go here */
537 if ((sdata->hw_rev == MDSS_DSI_HW_REV_103) &&
538 !mdss_dsi_is_hw_config_dual(sdata) &&
539 mdss_dsi_is_right_ctrl(ctrl)) {
540
541 /*
542 * phy sw reset will wipe out the pll settings for PLL.
543 * Need to explicitly turn off PLL1 if unused to avoid
544 * current leakage issues.
545 */
546 if ((mdss_dsi_is_hw_config_split(sdata) ||
547 mdss_dsi_is_pll_src_pll0(sdata)) &&
548 ctrl->vco_dummy_clk) {
549 pr_debug("Turn off unused PLL1 registers\n");
550 clk_set_rate(ctrl->vco_dummy_clk, 1);
551 }
552 }
553}
554
555static void mdss_dsi_phy_regulator_disable(struct mdss_dsi_ctrl_pdata *ctrl)
556{
557 if (!ctrl) {
558 pr_err("%s: Invalid input data\n", __func__);
559 return;
560 }
561
562 if (ctrl->shared_data->phy_rev == DSI_PHY_REV_20)
563 return;
564
Padmanabhan Komanduru81d8dc522018-03-22 20:00:58 +0530565 if (ctrl->shared_data->phy_rev == DSI_PHY_REV_12NM)
566 return;
567
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530568 MIPI_OUTP(ctrl->phy_regulator_io.base + 0x018, 0x000);
569}
570
571static void mdss_dsi_phy_shutdown(struct mdss_dsi_ctrl_pdata *ctrl)
572{
573 if (!ctrl) {
574 pr_err("%s: Invalid input data\n", __func__);
575 return;
576 }
577
578 if (ctrl->shared_data->phy_rev == DSI_PHY_REV_20) {
579 MIPI_OUTP(ctrl->phy_io.base + DSIPHY_PLL_CLKBUFLR_EN, 0);
580 MIPI_OUTP(ctrl->phy_io.base + DSIPHY_CMN_GLBL_TEST_CTRL, 0);
581 MIPI_OUTP(ctrl->phy_io.base + DSIPHY_CMN_CTRL_0, 0);
Padmanabhan Komanduru81d8dc522018-03-22 20:00:58 +0530582 } else if (ctrl->shared_data->phy_rev == DSI_PHY_REV_12NM) {
583 mdss_dsi_12nm_phy_shutdown(ctrl);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530584 } else {
585 MIPI_OUTP(ctrl->phy_io.base + MDSS_DSI_DSIPHY_CTRL_0, 0x000);
586 }
587}
588
589/**
590 * mdss_dsi_lp_cd_rx() -- enable LP and CD at receiving
591 * @ctrl: pointer to DSI controller structure
592 *
593 * LP: low power
594 * CD: contention detection
595 */
596void mdss_dsi_lp_cd_rx(struct mdss_dsi_ctrl_pdata *ctrl)
597{
598 struct mdss_dsi_phy_ctrl *pd;
599
600 if (!ctrl) {
601 pr_err("%s: Invalid input data\n", __func__);
602 return;
603 }
604
Padmanabhan Komanduru81d8dc522018-03-22 20:00:58 +0530605 if ((ctrl->shared_data->phy_rev == DSI_PHY_REV_20) ||
606 (ctrl->shared_data->phy_rev == DSI_PHY_REV_12NM))
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530607 return;
608
609 pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db);
610
611 MIPI_OUTP((ctrl->phy_io.base) + 0x0188, pd->strength[1]);
612 /* Strength ctrl 1, LP Rx + CD Rxcontention detection */
613 wmb();
614}
615
616static void mdss_dsi_28nm_phy_regulator_enable(
617 struct mdss_dsi_ctrl_pdata *ctrl_pdata)
618{
619 struct mdss_dsi_phy_ctrl *pd;
620
621 pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db);
622
623 if (pd->reg_ldo_mode) {
624 /* Regulator ctrl 0 */
625 MIPI_OUTP(ctrl_pdata->phy_regulator_io.base, 0x0);
626 /* Regulator ctrl - CAL_PWR_CFG */
627 MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
628 + 0x18, pd->regulator[6]);
629 /* Add H/w recommended delay */
630 udelay(1000);
631 /* Regulator ctrl - TEST */
632 MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
633 + 0x14, pd->regulator[5]);
634 /* Regulator ctrl 3 */
635 MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
636 + 0xc, pd->regulator[3]);
637 /* Regulator ctrl 2 */
638 MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
639 + 0x8, pd->regulator[2]);
640 /* Regulator ctrl 1 */
641 MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
642 + 0x4, pd->regulator[1]);
643 /* Regulator ctrl 4 */
644 MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
645 + 0x10, pd->regulator[4]);
646 /* LDO ctrl */
647 if ((ctrl_pdata->shared_data->hw_rev ==
648 MDSS_DSI_HW_REV_103_1)
649 || (ctrl_pdata->shared_data->hw_rev ==
650 MDSS_DSI_HW_REV_104_2))
651 MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x1dc, 0x05);
652 else
653 MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x1dc, 0x0d);
654 } else {
655 /* Regulator ctrl 0 */
656 MIPI_OUTP(ctrl_pdata->phy_regulator_io.base,
657 0x0);
658 /* Regulator ctrl - CAL_PWR_CFG */
659 MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
660 + 0x18, pd->regulator[6]);
661 /* Add H/w recommended delay */
662 udelay(1000);
663 /* Regulator ctrl 1 */
664 MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
665 + 0x4, pd->regulator[1]);
666 /* Regulator ctrl 2 */
667 MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
668 + 0x8, pd->regulator[2]);
669 /* Regulator ctrl 3 */
670 MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
671 + 0xc, pd->regulator[3]);
672 /* Regulator ctrl 4 */
673 MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
674 + 0x10, pd->regulator[4]);
675 /* LDO ctrl */
676 MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x1dc, 0x00);
677 /* Regulator ctrl 0 */
678 MIPI_OUTP(ctrl_pdata->phy_regulator_io.base,
679 pd->regulator[0]);
680 }
681}
682
683static void mdss_dsi_28nm_phy_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
684{
685 struct mdss_dsi_phy_ctrl *pd;
686 int i, off, ln, offset;
687
688 if (!ctrl_pdata) {
689 pr_err("%s: Invalid input data\n", __func__);
690 return;
691 }
692
693 pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db);
694
695 /* Strength ctrl 0 for 28nm PHY*/
696 if ((ctrl_pdata->shared_data->hw_rev <= MDSS_DSI_HW_REV_104_2) &&
697 (ctrl_pdata->shared_data->hw_rev != MDSS_DSI_HW_REV_103)) {
698 MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0170, 0x5b);
699 MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0184, pd->strength[0]);
700 /* make sure PHY strength ctrl is set */
701 wmb();
702 }
703
704 off = 0x0140; /* phy timing ctrl 0 - 11 */
705 for (i = 0; i < 12; i++) {
706 MIPI_OUTP((ctrl_pdata->phy_io.base) + off, pd->timing[i]);
707 /* make sure phy timing register is programed */
708 wmb();
709 off += 4;
710 }
711
712 /* 4 lanes + clk lane configuration */
713 /* lane config n * (0 - 4) & DataPath setup */
714 for (ln = 0; ln < 5; ln++) {
715 off = (ln * 0x40);
716 for (i = 0; i < 9; i++) {
717 offset = i + (ln * 9);
718 MIPI_OUTP((ctrl_pdata->phy_io.base) + off,
719 pd->lanecfg[offset]);
720 /* make sure lane config register is programed */
721 wmb();
722 off += 4;
723 }
724 }
725
726 MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0180, 0x0a);
727 /* MMSS_DSI_0_PHY_DSIPHY_CTRL_4 */
728 wmb();
729
730 /* DSI_0_PHY_DSIPHY_GLBL_TEST_CTRL */
731 if (!mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) {
732 MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x01d4, 0x01);
733 } else {
734 if (((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1) ||
735 (ctrl_pdata->shared_data->hw_rev == MDSS_DSI_HW_REV_103_1))
736 MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x01d4, 0x01);
737 else
738 MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x01d4, 0x00);
739 }
740 /* ensure DSIPHY_GLBL_TEST_CTRL is set */
741 wmb();
742
743 /* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */
744 MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0170, 0x5f);
745 /* make sure PHY lanes are powered on */
746 wmb();
747
748 off = 0x01b4; /* phy BIST ctrl 0 - 5 */
749 for (i = 0; i < 6; i++) {
750 MIPI_OUTP((ctrl_pdata->phy_io.base) + off, pd->bistctrl[i]);
751 wmb(); /* make sure PHY bit control is configured */
752 off += 4;
753 }
754
755}
756
757static void mdss_dsi_20nm_phy_regulator_enable(struct mdss_dsi_ctrl_pdata
758 *ctrl_pdata)
759{
760 struct mdss_dsi_phy_ctrl *pd;
761 void __iomem *phy_io_base;
762
763 pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db);
764 phy_io_base = ctrl_pdata->phy_regulator_io.base;
765
766 if (pd->regulator_len != 7) {
767 pr_err("%s: wrong regulator settings\n", __func__);
768 return;
769 }
770
771 if (pd->reg_ldo_mode) {
772 MIPI_OUTP(ctrl_pdata->phy_io.base + MDSS_DSI_DSIPHY_LDO_CNTRL,
773 0x1d);
774 } else {
775 MIPI_OUTP(phy_io_base + MDSS_DSI_DSIPHY_REGULATOR_CTRL_1,
776 pd->regulator[1]);
777 MIPI_OUTP(phy_io_base + MDSS_DSI_DSIPHY_REGULATOR_CTRL_2,
778 pd->regulator[2]);
779 MIPI_OUTP(phy_io_base + MDSS_DSI_DSIPHY_REGULATOR_CTRL_3,
780 pd->regulator[3]);
781 MIPI_OUTP(phy_io_base + MDSS_DSI_DSIPHY_REGULATOR_CTRL_4,
782 pd->regulator[4]);
783 MIPI_OUTP(phy_io_base + MDSS_DSI_DSIPHY_REGULATOR_CAL_PWR_CFG,
784 pd->regulator[6]);
785 MIPI_OUTP(ctrl_pdata->phy_io.base + MDSS_DSI_DSIPHY_LDO_CNTRL,
786 0x00);
787 MIPI_OUTP(phy_io_base + MDSS_DSI_DSIPHY_REGULATOR_CTRL_0,
788 pd->regulator[0]);
789 }
790}
791
792static void mdss_dsi_20nm_phy_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
793{
794 struct mdss_dsi_phy_ctrl *pd;
795 int i, off, ln, offset;
796
797 pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db);
798
799 if (pd->strength_len != 2) {
800 pr_err("%s: wrong strength ctrl\n", __func__);
801 return;
802 }
803
804 MIPI_OUTP((ctrl_pdata->phy_io.base) + MDSS_DSI_DSIPHY_STRENGTH_CTRL_0,
805 pd->strength[0]);
806
807
808 if (!mdss_dsi_is_hw_config_dual(ctrl_pdata->shared_data)) {
809 if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) ||
810 mdss_dsi_is_left_ctrl(ctrl_pdata) ||
811 (mdss_dsi_is_right_ctrl(ctrl_pdata) &&
812 mdss_dsi_is_pll_src_pll0(ctrl_pdata->shared_data)))
813 MIPI_OUTP((ctrl_pdata->phy_io.base) +
814 MDSS_DSI_DSIPHY_GLBL_TEST_CTRL, 0x00);
815 else
816 MIPI_OUTP((ctrl_pdata->phy_io.base) +
817 MDSS_DSI_DSIPHY_GLBL_TEST_CTRL, 0x01);
818 } else {
819 if (mdss_dsi_is_left_ctrl(ctrl_pdata))
820 MIPI_OUTP((ctrl_pdata->phy_io.base) +
821 MDSS_DSI_DSIPHY_GLBL_TEST_CTRL, 0x00);
822 else
823 MIPI_OUTP((ctrl_pdata->phy_io.base) +
824 MDSS_DSI_DSIPHY_GLBL_TEST_CTRL, 0x01);
825 }
826
827 if (pd->lanecfg_len != 45) {
828 pr_err("%s: wrong lane cfg\n", __func__);
829 return;
830 }
831
832 /* 4 lanes + clk lane configuration */
833 /* lane config n * (0 - 4) & DataPath setup */
834 for (ln = 0; ln < 5; ln++) {
835 off = (ln * 0x40);
836 for (i = 0; i < 9; i++) {
837 offset = i + (ln * 9);
838 MIPI_OUTP((ctrl_pdata->phy_io.base) + off,
839 pd->lanecfg[offset]);
840 /* make sure lane config register is programed */
841 wmb();
842 off += 4;
843 }
844 }
845
846 off = 0; /* phy timing ctrl 0 - 11 */
847 for (i = 0; i < 12; i++) {
848 MIPI_OUTP((ctrl_pdata->phy_io.base) +
849 MDSS_DSI_DSIPHY_TIMING_CTRL_0 + off, pd->timing[i]);
850 wmb(); /* make sure phy timing register is programed */
851 off += 4;
852 }
853
854 MIPI_OUTP((ctrl_pdata->phy_io.base) + MDSS_DSI_DSIPHY_CTRL_1, 0);
855 /* make sure everything is written before enable */
856 wmb();
857 MIPI_OUTP((ctrl_pdata->phy_io.base) + MDSS_DSI_DSIPHY_CTRL_0, 0x7f);
858}
859
860static void mdss_dsi_8996_pll_source_standalone(
861 struct mdss_dsi_ctrl_pdata *ctrl)
862{
863 u32 data;
864
865 /*
866 * pll right output enabled
867 * bit clk select from left
868 */
869 MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_PLL_CLKBUFLR_EN, 0x01);
870 data = MIPI_INP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL);
871 data &= ~BIT(2);
872 MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL, data);
873}
874
875static void mdss_dsi_8996_pll_source_from_right(
876 struct mdss_dsi_ctrl_pdata *ctrl)
877{
878 u32 data;
879
880 /*
881 * pll left + right output disabled
882 * bit clk select from right
883 */
884 MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_PLL_CLKBUFLR_EN, 0x00);
885 data = MIPI_INP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL);
886 data |= BIT(2);
887 MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL, data);
888
889 /* enable bias current for pll1 during split display case */
890 MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_PLL_PLL_BANDGAP, 0x3);
891}
892
893static void mdss_dsi_8996_pll_source_from_left(
894 struct mdss_dsi_ctrl_pdata *ctrl)
895{
896 u32 data;
897
898 /*
899 * pll left + right output enabled
900 * bit clk select from left
901 */
902 MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_PLL_CLKBUFLR_EN, 0x03);
903 data = MIPI_INP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL);
904 data &= ~BIT(2);
905 MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL, data);
906}
907
908static void mdss_dsi_8996_phy_regulator_enable(
909 struct mdss_dsi_ctrl_pdata *ctrl)
910{
911 struct mdss_dsi_phy_ctrl *pd;
912 int j, off, ln, cnt, ln_off;
913 char *ip;
914 void __iomem *base;
915
916 pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db);
917 /* 4 lanes + clk lane configuration */
918 for (ln = 0; ln < 5; ln++) {
919 /*
920 * data lane offset from base: 0x100
921 * data lane size: 0x80
922 */
923 base = ctrl->phy_io.base +
924 DATALANE_OFFSET_FROM_BASE_8996;
925 base += (ln * DATALANE_SIZE_8996); /* lane base */
926
927 /* vreg ctrl, 1 * 5 */
928 cnt = 1;
929 ln_off = cnt * ln;
930 ip = &pd->regulator[ln_off];
931 off = 0x64;
932 for (j = 0; j < cnt; j++, off += 4)
933 MIPI_OUTP(base + off, *ip++);
934 }
935
936 wmb(); /* make sure registers committed */
937
938}
939
940static void mdss_dsi_8996_phy_power_off(
941 struct mdss_dsi_ctrl_pdata *ctrl)
942{
943 int ln;
944 void __iomem *base;
945 u32 data;
946
947 /* Turn off PLL power */
948 data = MIPI_INP(ctrl->phy_io.base + DSIPHY_CMN_CTRL_0);
949 MIPI_OUTP(ctrl->phy_io.base + DSIPHY_CMN_CTRL_0, data & ~BIT(7));
950
951 /* 4 lanes + clk lane configuration */
952 for (ln = 0; ln < 5; ln++) {
953 base = ctrl->phy_io.base +
954 DATALANE_OFFSET_FROM_BASE_8996;
955 base += (ln * DATALANE_SIZE_8996); /* lane base */
956
957 /* turn off phy ldo */
958 MIPI_OUTP(base + DSIPHY_LANE_VREG_CNTRL, 0x1c);
959 }
960 MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_LDO_CNTRL, 0x1c);
961
962 /* 4 lanes + clk lane configuration */
963 for (ln = 0; ln < 5; ln++) {
964 base = ctrl->phy_io.base +
965 DATALANE_OFFSET_FROM_BASE_8996;
966 base += (ln * DATALANE_SIZE_8996); /* lane base */
967
968 MIPI_OUTP(base + DSIPHY_LANE_STRENGTH_CTRL_1, 0x0);
969 }
970
971 wmb(); /* make sure registers committed */
972}
973
974static void mdss_dsi_phy_power_off(
975 struct mdss_dsi_ctrl_pdata *ctrl)
976{
977 struct mdss_panel_info *pinfo;
978
979 if (ctrl->phy_power_off)
980 return;
981
982 pinfo = &ctrl->panel_data.panel_info;
983
984 if ((ctrl->shared_data->phy_rev != DSI_PHY_REV_20) ||
985 !pinfo->allow_phy_power_off) {
986 pr_debug("%s: ctrl%d phy rev:%d panel support for phy off:%d\n",
987 __func__, ctrl->ndx, ctrl->shared_data->phy_rev,
988 pinfo->allow_phy_power_off);
989 return;
990 }
991
992 /* supported for phy rev 2.0 and if panel allows it*/
993 mdss_dsi_8996_phy_power_off(ctrl);
994
995 ctrl->phy_power_off = true;
996}
997
998static void mdss_dsi_8996_phy_power_on(
999 struct mdss_dsi_ctrl_pdata *ctrl)
1000{
1001 int j, off, ln, cnt, ln_off;
1002 void __iomem *base;
1003 struct mdss_dsi_phy_ctrl *pd;
1004 char *ip;
1005 u32 data;
1006
1007 pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db);
1008
1009 /* 4 lanes + clk lane configuration */
1010 for (ln = 0; ln < 5; ln++) {
1011 base = ctrl->phy_io.base +
1012 DATALANE_OFFSET_FROM_BASE_8996;
1013 base += (ln * DATALANE_SIZE_8996); /* lane base */
1014
1015 /* strength, 2 * 5 */
1016 cnt = 2;
1017 ln_off = cnt * ln;
1018 ip = &pd->strength[ln_off];
1019 off = 0x38;
1020 for (j = 0; j < cnt; j++, off += 4)
1021 MIPI_OUTP(base + off, *ip++);
1022 }
1023
1024 mdss_dsi_8996_phy_regulator_enable(ctrl);
1025
1026 /* Turn on PLL power */
1027 data = MIPI_INP(ctrl->phy_io.base + DSIPHY_CMN_CTRL_0);
1028 MIPI_OUTP(ctrl->phy_io.base + DSIPHY_CMN_CTRL_0, data | BIT(7));
1029}
1030
1031static void mdss_dsi_phy_power_on(
1032 struct mdss_dsi_ctrl_pdata *ctrl, bool mmss_clamp)
1033{
1034 if (mmss_clamp && !ctrl->phy_power_off)
1035 mdss_dsi_phy_init(ctrl);
1036 else if ((ctrl->shared_data->phy_rev == DSI_PHY_REV_20) &&
1037 ctrl->phy_power_off)
1038 mdss_dsi_8996_phy_power_on(ctrl);
1039
1040 ctrl->phy_power_off = false;
1041}
1042
1043static void mdss_dsi_8996_phy_config(struct mdss_dsi_ctrl_pdata *ctrl)
1044{
1045 struct mdss_dsi_phy_ctrl *pd;
1046 int j, off, ln, cnt, ln_off;
1047 char *ip;
1048 void __iomem *base;
1049
1050 pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db);
1051
1052 MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_LDO_CNTRL, 0x1c);
1053
1054 /* clk_en */
1055 MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL, 0x1);
1056
1057 if (pd->lanecfg_len != 20) {
1058 pr_err("%s: wrong lane cfg\n", __func__);
1059 return;
1060 }
1061
1062 if (pd->strength_len != 10) {
1063 pr_err("%s: wrong strength ctrl\n", __func__);
1064 return;
1065 }
1066
1067 if (pd->regulator_len != 5) {
1068 pr_err("%s: wrong regulator setting\n", __func__);
1069 return;
1070 }
1071
1072 /* 4 lanes + clk lane configuration */
1073 for (ln = 0; ln < 5; ln++) {
1074 /*
1075 * data lane offset from base: 0x100
1076 * data lane size: 0x80
1077 */
1078 base = ctrl->phy_io.base +
1079 DATALANE_OFFSET_FROM_BASE_8996;
1080 base += (ln * DATALANE_SIZE_8996); /* lane base */
1081
1082 /* lane cfg, 4 * 5 */
1083 cnt = 4;
1084 ln_off = cnt * ln;
1085 ip = &pd->lanecfg[ln_off];
1086 off = 0x0;
1087 for (j = 0; j < cnt; j++) {
1088 MIPI_OUTP(base + off, *ip++);
1089 off += 4;
1090 }
1091
1092 /* test str */
1093 MIPI_OUTP(base + 0x14, 0x0088); /* fixed */
1094
1095 /* phy timing, 8 * 5 */
1096 cnt = 8;
1097 ln_off = cnt * ln;
1098 ip = &pd->timing_8996[ln_off];
1099 off = 0x18;
1100 for (j = 0; j < cnt; j++, off += 4)
1101 MIPI_OUTP(base + off, *ip++);
1102
1103 /* strength, 2 * 5 */
1104 cnt = 2;
1105 ln_off = cnt * ln;
1106 ip = &pd->strength[ln_off];
1107 off = 0x38;
1108 for (j = 0; j < cnt; j++, off += 4)
1109 MIPI_OUTP(base + off, *ip++);
1110 }
1111
1112 wmb(); /* make sure registers committed */
1113
1114 /* reset digital block */
1115 MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_CTRL_1, 0x80);
1116 udelay(100);
1117 MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_CTRL_1, 0x00);
1118
1119 if (mdss_dsi_is_hw_config_split(ctrl->shared_data)) {
1120 if (mdss_dsi_is_left_ctrl(ctrl))
1121 mdss_dsi_8996_pll_source_from_left(ctrl);
1122 else
1123 mdss_dsi_8996_pll_source_from_right(ctrl);
1124 } else {
1125 if (mdss_dsi_is_right_ctrl(ctrl) &&
1126 mdss_dsi_is_pll_src_pll0(ctrl->shared_data))
1127 mdss_dsi_8996_pll_source_from_left(ctrl);
1128 else
1129 mdss_dsi_8996_pll_source_standalone(ctrl);
1130 }
1131
1132 MIPI_OUTP(ctrl->phy_io.base + DSIPHY_CMN_CTRL_0, 0x7f);
1133 wmb(); /* make sure registers committed */
1134}
1135
1136static void mdss_dsi_phy_regulator_ctrl(struct mdss_dsi_ctrl_pdata *ctrl,
1137 bool enable)
1138{
1139 struct mdss_dsi_ctrl_pdata *other_ctrl;
1140 struct dsi_shared_data *sdata;
1141
1142 if (!ctrl) {
1143 pr_err("%s: Invalid input data\n", __func__);
1144 return;
1145 }
1146
1147 sdata = ctrl->shared_data;
1148 other_ctrl = mdss_dsi_get_other_ctrl(ctrl);
1149
1150 mutex_lock(&sdata->phy_reg_lock);
1151 if (enable) {
1152 if (ctrl->shared_data->phy_rev == DSI_PHY_REV_20) {
1153 mdss_dsi_8996_phy_regulator_enable(ctrl);
Padmanabhan Komanduru81d8dc522018-03-22 20:00:58 +05301154 } else if (ctrl->shared_data->phy_rev == DSI_PHY_REV_12NM) {
1155 mdss_dsi_12nm_phy_regulator_enable(ctrl);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301156 } else {
1157 switch (ctrl->shared_data->hw_rev) {
1158 case MDSS_DSI_HW_REV_103:
1159 mdss_dsi_20nm_phy_regulator_enable(ctrl);
1160 break;
1161 default:
1162 /*
1163 * For dual dsi case, do not reconfigure dsi phy
1164 * regulator if the other dsi controller is still
1165 * active.
1166 */
1167 if (!mdss_dsi_is_hw_config_dual(sdata) ||
1168 (other_ctrl && (!other_ctrl->is_phyreg_enabled
1169 || other_ctrl->mmss_clamp)))
1170 mdss_dsi_28nm_phy_regulator_enable(ctrl);
1171 break;
1172 }
1173 }
1174 ctrl->is_phyreg_enabled = 1;
1175 } else {
1176 /*
1177 * In split-dsi/dual-dsi configuration, the dsi phy regulator
1178 * should be turned off only when both the DSI devices are
1179 * going to be turned off since it is shared.
1180 */
1181 if (mdss_dsi_is_hw_config_split(ctrl->shared_data) ||
1182 mdss_dsi_is_hw_config_dual(ctrl->shared_data)) {
1183 if (other_ctrl && !other_ctrl->is_phyreg_enabled)
1184 mdss_dsi_phy_regulator_disable(ctrl);
1185 } else {
1186 mdss_dsi_phy_regulator_disable(ctrl);
1187 }
1188 ctrl->is_phyreg_enabled = 0;
1189 }
1190 mutex_unlock(&sdata->phy_reg_lock);
1191}
1192
1193static void mdss_dsi_phy_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, bool enable)
1194{
1195 struct mdss_dsi_ctrl_pdata *other_ctrl;
1196
1197 if (!ctrl) {
1198 pr_err("%s: Invalid input data\n", __func__);
1199 return;
1200 }
1201
1202 if (enable) {
1203
1204 if (ctrl->shared_data->phy_rev == DSI_PHY_REV_20) {
1205 mdss_dsi_8996_phy_config(ctrl);
Padmanabhan Komanduru81d8dc522018-03-22 20:00:58 +05301206 } else if (ctrl->shared_data->phy_rev == DSI_PHY_REV_12NM) {
1207 mdss_dsi_12nm_phy_config(ctrl);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301208 } else {
1209 switch (ctrl->shared_data->hw_rev) {
1210 case MDSS_DSI_HW_REV_103:
1211 mdss_dsi_20nm_phy_config(ctrl);
1212 break;
1213 default:
1214 mdss_dsi_28nm_phy_config(ctrl);
1215 break;
1216 }
1217 }
1218 } else {
1219 /*
1220 * In split-dsi configuration, the phy should be disabled for
1221 * the first controller only when the second controller is
1222 * disabled. This is true regardless of whether broadcast
1223 * mode is enabled.
1224 */
1225 if (mdss_dsi_is_hw_config_split(ctrl->shared_data)) {
1226 other_ctrl = mdss_dsi_get_other_ctrl(ctrl);
1227 if (mdss_dsi_is_right_ctrl(ctrl) && other_ctrl) {
1228 mdss_dsi_phy_shutdown(other_ctrl);
1229 mdss_dsi_phy_shutdown(ctrl);
1230 }
1231 } else {
1232 mdss_dsi_phy_shutdown(ctrl);
1233 }
1234 }
1235}
1236
1237void mdss_dsi_phy_disable(struct mdss_dsi_ctrl_pdata *ctrl)
1238{
1239 if (ctrl == NULL) {
1240 pr_err("%s: Invalid input data\n", __func__);
1241 return;
1242 }
1243
1244 mdss_dsi_phy_ctrl(ctrl, false);
1245 mdss_dsi_phy_regulator_ctrl(ctrl, false);
1246 /*
1247 * Wait for the registers writes to complete in order to
1248 * ensure that the phy is completely disabled
1249 */
1250 wmb();
1251}
1252
1253static void mdss_dsi_phy_init_sub(struct mdss_dsi_ctrl_pdata *ctrl)
1254{
1255 mdss_dsi_phy_regulator_ctrl(ctrl, true);
1256 mdss_dsi_phy_ctrl(ctrl, true);
1257}
1258
1259void mdss_dsi_phy_init(struct mdss_dsi_ctrl_pdata *ctrl)
1260{
1261 struct mdss_dsi_ctrl_pdata *sctrl = NULL;
1262
1263 /*
1264 * When operating in split display mode, make sure that both the PHY
1265 * blocks are initialized together prior to the PLL being enabled. This
1266 * is achieved by calling the phy_init function for the clk_slave from
1267 * the clock_master.
1268 */
1269 if (mdss_dsi_is_ctrl_clk_slave(ctrl))
1270 return;
1271
1272 mdss_dsi_phy_init_sub(ctrl);
1273
1274 if (mdss_dsi_is_ctrl_clk_master(ctrl)) {
1275 sctrl = mdss_dsi_get_ctrl_clk_slave();
1276 if (sctrl)
1277 mdss_dsi_phy_init_sub(sctrl);
1278 else
1279 pr_warn("%s: unable to get slave ctrl\n", __func__);
1280 }
1281}
1282
Padmanabhan Komandurufa3aa592018-04-13 23:10:08 +05301283static void mdss_dsi_phy_hstx_drv_ctrl(
1284 struct mdss_dsi_ctrl_pdata *ctrl, bool enable)
1285{
1286 if (ctrl->shared_data->phy_rev == DSI_PHY_REV_12NM)
1287 mdss_dsi_12nm_phy_hstx_drv_ctrl(ctrl, enable);
1288}
1289
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301290void mdss_dsi_core_clk_deinit(struct device *dev, struct dsi_shared_data *sdata)
1291{
1292 if (sdata->mmss_misc_ahb_clk)
1293 devm_clk_put(dev, sdata->mmss_misc_ahb_clk);
1294 if (sdata->ext_pixel1_clk)
1295 devm_clk_put(dev, sdata->ext_pixel1_clk);
1296 if (sdata->ext_byte1_clk)
1297 devm_clk_put(dev, sdata->ext_byte1_clk);
1298 if (sdata->ext_pixel0_clk)
1299 devm_clk_put(dev, sdata->ext_pixel0_clk);
1300 if (sdata->ext_byte0_clk)
1301 devm_clk_put(dev, sdata->ext_byte0_clk);
1302 if (sdata->axi_clk)
1303 devm_clk_put(dev, sdata->axi_clk);
1304 if (sdata->ahb_clk)
1305 devm_clk_put(dev, sdata->ahb_clk);
1306 if (sdata->mdp_core_clk)
1307 devm_clk_put(dev, sdata->mdp_core_clk);
1308}
1309
1310int mdss_dsi_clk_refresh(struct mdss_panel_data *pdata, bool update_phy)
1311{
1312 struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
1313 struct mdss_panel_info *pinfo = NULL;
1314 int rc = 0;
1315
1316 if (!pdata) {
1317 pr_err("%s: invalid panel data\n", __func__);
1318 return -EINVAL;
1319 }
1320
1321 ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
1322 panel_data);
1323 pinfo = &pdata->panel_info;
1324
1325 if (!ctrl_pdata || !pinfo) {
1326 pr_err("%s: invalid ctrl data\n", __func__);
1327 return -EINVAL;
1328 }
1329
1330 if (update_phy) {
1331 pinfo->mipi.frame_rate = mdss_panel_calc_frame_rate(pinfo);
1332 pr_debug("%s: new frame rate %d\n",
1333 __func__, pinfo->mipi.frame_rate);
1334 }
1335
1336 rc = mdss_dsi_clk_div_config(&pdata->panel_info,
1337 pdata->panel_info.mipi.frame_rate);
1338 if (rc) {
1339 pr_err("%s: unable to initialize the clk dividers\n",
1340 __func__);
1341 return rc;
1342 }
1343 ctrl_pdata->refresh_clk_rate = false;
1344 ctrl_pdata->pclk_rate = pdata->panel_info.mipi.dsi_pclk_rate;
1345 ctrl_pdata->byte_clk_rate = pdata->panel_info.clk_rate / 8;
1346 pr_debug("%s ctrl_pdata->byte_clk_rate=%d ctrl_pdata->pclk_rate=%d\n",
1347 __func__, ctrl_pdata->byte_clk_rate, ctrl_pdata->pclk_rate);
1348
1349 rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle,
1350 MDSS_DSI_LINK_BYTE_CLK, ctrl_pdata->byte_clk_rate,
1351 MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON);
1352 if (rc) {
1353 pr_err("%s: dsi_byte_clk - clk_set_rate failed\n",
1354 __func__);
1355 return rc;
1356 }
1357
1358 rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle,
1359 MDSS_DSI_LINK_PIX_CLK, ctrl_pdata->pclk_rate,
1360 MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON);
1361 if (rc) {
1362 pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n",
1363 __func__);
1364 return rc;
1365 }
1366
1367 if (update_phy) {
1368 /* phy panel timing calaculation */
1369 rc = mdss_dsi_phy_calc_timing_param(pinfo,
1370 ctrl_pdata->shared_data->phy_rev,
1371 pinfo->mipi.frame_rate);
1372 if (rc) {
1373 pr_err("Error in calculating phy timings\n");
1374 return rc;
1375 }
1376 ctrl_pdata->update_phy_timing = false;
1377 }
1378
1379 return rc;
1380}
1381
1382int mdss_dsi_core_clk_init(struct platform_device *pdev,
1383 struct dsi_shared_data *sdata)
1384{
1385 struct device *dev = NULL;
1386 int rc = 0;
1387
1388 if (!pdev) {
1389 pr_err("%s: Invalid pdev\n", __func__);
1390 goto error;
1391 }
1392
1393 dev = &pdev->dev;
1394
1395 /* Mandatory Clocks */
1396 sdata->mdp_core_clk = devm_clk_get(dev, "mdp_core_clk");
1397 if (IS_ERR(sdata->mdp_core_clk)) {
1398 rc = PTR_ERR(sdata->mdp_core_clk);
1399 pr_err("%s: Unable to get mdp core clk. rc=%d\n",
1400 __func__, rc);
1401 goto error;
1402 }
1403
1404 sdata->ahb_clk = devm_clk_get(dev, "iface_clk");
1405 if (IS_ERR(sdata->ahb_clk)) {
1406 rc = PTR_ERR(sdata->ahb_clk);
1407 pr_err("%s: Unable to get mdss ahb clk. rc=%d\n",
1408 __func__, rc);
1409 goto error;
1410 }
1411
1412 sdata->axi_clk = devm_clk_get(dev, "bus_clk");
1413 if (IS_ERR(sdata->axi_clk)) {
1414 rc = PTR_ERR(sdata->axi_clk);
1415 pr_err("%s: Unable to get axi bus clk. rc=%d\n",
1416 __func__, rc);
1417 goto error;
1418 }
1419
1420 /* Optional Clocks */
1421 sdata->ext_byte0_clk = devm_clk_get(dev, "ext_byte0_clk");
1422 if (IS_ERR(sdata->ext_byte0_clk)) {
1423 pr_debug("%s: unable to get byte0 clk rcg. rc=%d\n",
1424 __func__, rc);
1425 sdata->ext_byte0_clk = NULL;
1426 }
1427
1428 sdata->ext_pixel0_clk = devm_clk_get(dev, "ext_pixel0_clk");
1429 if (IS_ERR(sdata->ext_pixel0_clk)) {
1430 pr_debug("%s: unable to get pixel0 clk rcg. rc=%d\n",
1431 __func__, rc);
1432 sdata->ext_pixel0_clk = NULL;
1433 }
1434
1435 sdata->ext_byte1_clk = devm_clk_get(dev, "ext_byte1_clk");
1436 if (IS_ERR(sdata->ext_byte1_clk)) {
1437 pr_debug("%s: unable to get byte1 clk rcg. rc=%d\n",
1438 __func__, rc);
1439 sdata->ext_byte1_clk = NULL;
1440 }
1441
1442 sdata->ext_pixel1_clk = devm_clk_get(dev, "ext_pixel1_clk");
1443 if (IS_ERR(sdata->ext_pixel1_clk)) {
1444 pr_debug("%s: unable to get pixel1 clk rcg. rc=%d\n",
1445 __func__, rc);
1446 sdata->ext_pixel1_clk = NULL;
1447 }
1448
1449 sdata->mmss_misc_ahb_clk = devm_clk_get(dev, "core_mmss_clk");
1450 if (IS_ERR(sdata->mmss_misc_ahb_clk)) {
1451 sdata->mmss_misc_ahb_clk = NULL;
1452 pr_debug("%s: Unable to get mmss misc ahb clk\n",
1453 __func__);
1454 }
1455
1456error:
1457 if (rc)
1458 mdss_dsi_core_clk_deinit(dev, sdata);
1459 return rc;
1460}
1461
1462void mdss_dsi_link_clk_deinit(struct device *dev,
1463 struct mdss_dsi_ctrl_pdata *ctrl)
1464{
1465 if (ctrl->vco_dummy_clk)
1466 devm_clk_put(dev, ctrl->vco_dummy_clk);
1467 if (ctrl->pixel_clk_rcg)
1468 devm_clk_put(dev, ctrl->pixel_clk_rcg);
1469 if (ctrl->byte_clk_rcg)
1470 devm_clk_put(dev, ctrl->byte_clk_rcg);
1471 if (ctrl->byte_clk)
1472 devm_clk_put(dev, ctrl->byte_clk);
1473 if (ctrl->esc_clk)
1474 devm_clk_put(dev, ctrl->esc_clk);
1475 if (ctrl->pixel_clk)
1476 devm_clk_put(dev, ctrl->pixel_clk);
1477}
1478
1479int mdss_dsi_link_clk_init(struct platform_device *pdev,
1480 struct mdss_dsi_ctrl_pdata *ctrl)
1481{
1482 struct device *dev = NULL;
1483 int rc = 0;
1484
1485 if (!pdev) {
1486 pr_err("%s: Invalid pdev\n", __func__);
1487 goto error;
1488 }
1489
1490 dev = &pdev->dev;
1491
1492 /* Mandatory Clocks */
1493 ctrl->byte_clk = devm_clk_get(dev, "byte_clk");
1494 if (IS_ERR(ctrl->byte_clk)) {
1495 rc = PTR_ERR(ctrl->byte_clk);
1496 pr_err("%s: can't find dsi_byte_clk. rc=%d\n",
1497 __func__, rc);
1498 ctrl->byte_clk = NULL;
1499 goto error;
1500 }
1501
1502 ctrl->pixel_clk = devm_clk_get(dev, "pixel_clk");
1503 if (IS_ERR(ctrl->pixel_clk)) {
1504 rc = PTR_ERR(ctrl->pixel_clk);
1505 pr_err("%s: can't find dsi_pixel_clk. rc=%d\n",
1506 __func__, rc);
1507 ctrl->pixel_clk = NULL;
1508 goto error;
1509 }
1510
1511 ctrl->esc_clk = devm_clk_get(dev, "core_clk");
1512 if (IS_ERR(ctrl->esc_clk)) {
1513 rc = PTR_ERR(ctrl->esc_clk);
1514 pr_err("%s: can't find dsi_esc_clk. rc=%d\n",
1515 __func__, rc);
1516 ctrl->esc_clk = NULL;
1517 goto error;
1518 }
1519
1520 /* Optional Clocks */
1521 ctrl->byte_clk_rcg = devm_clk_get(dev, "byte_clk_rcg");
1522 if (IS_ERR(ctrl->byte_clk_rcg)) {
1523 pr_debug("%s: can't find byte clk rcg. rc=%d\n", __func__, rc);
1524 ctrl->byte_clk_rcg = NULL;
1525 }
1526
1527 ctrl->pixel_clk_rcg = devm_clk_get(dev, "pixel_clk_rcg");
1528 if (IS_ERR(ctrl->pixel_clk_rcg)) {
1529 pr_debug("%s: can't find pixel clk rcg. rc=%d\n", __func__, rc);
1530 ctrl->pixel_clk_rcg = NULL;
1531 }
1532
1533 ctrl->vco_dummy_clk = devm_clk_get(dev, "pll_vco_dummy_clk");
1534 if (IS_ERR(ctrl->vco_dummy_clk)) {
1535 pr_debug("%s: can't find vco dummy clk. rc=%d\n", __func__, rc);
1536 ctrl->vco_dummy_clk = NULL;
1537 }
1538
1539error:
1540 if (rc)
1541 mdss_dsi_link_clk_deinit(dev, ctrl);
1542 return rc;
1543}
1544
1545void mdss_dsi_shadow_clk_deinit(struct device *dev,
1546 struct mdss_dsi_ctrl_pdata *ctrl)
1547{
1548 if (ctrl->mux_byte_clk)
1549 devm_clk_put(dev, ctrl->mux_byte_clk);
1550 if (ctrl->mux_pixel_clk)
1551 devm_clk_put(dev, ctrl->mux_pixel_clk);
1552 if (ctrl->pll_byte_clk)
1553 devm_clk_put(dev, ctrl->pll_byte_clk);
1554 if (ctrl->pll_pixel_clk)
1555 devm_clk_put(dev, ctrl->pll_pixel_clk);
1556 if (ctrl->shadow_byte_clk)
1557 devm_clk_put(dev, ctrl->shadow_byte_clk);
1558 if (ctrl->shadow_pixel_clk)
1559 devm_clk_put(dev, ctrl->shadow_pixel_clk);
1560}
1561
1562int mdss_dsi_shadow_clk_init(struct platform_device *pdev,
1563 struct mdss_dsi_ctrl_pdata *ctrl)
1564{
1565 struct device *dev = NULL;
1566 int rc = 0;
1567
1568 if (!pdev) {
1569 pr_err("%s: Invalid pdev\n", __func__);
1570 return -EINVAL;
1571 }
1572
1573 dev = &pdev->dev;
1574 ctrl->mux_byte_clk = devm_clk_get(dev, "pll_byte_clk_mux");
1575 if (IS_ERR(ctrl->mux_byte_clk)) {
1576 rc = PTR_ERR(ctrl->mux_byte_clk);
1577 pr_err("%s: can't find mux_byte_clk. rc=%d\n",
1578 __func__, rc);
1579 ctrl->mux_byte_clk = NULL;
1580 goto error;
1581 }
1582
1583 ctrl->mux_pixel_clk = devm_clk_get(dev, "pll_pixel_clk_mux");
1584 if (IS_ERR(ctrl->mux_pixel_clk)) {
1585 rc = PTR_ERR(ctrl->mux_pixel_clk);
1586 pr_err("%s: can't find mdss_mux_pixel_clk. rc=%d\n",
1587 __func__, rc);
1588 ctrl->mux_pixel_clk = NULL;
1589 goto error;
1590 }
1591
1592 ctrl->pll_byte_clk = devm_clk_get(dev, "pll_byte_clk_src");
1593 if (IS_ERR(ctrl->pll_byte_clk)) {
1594 rc = PTR_ERR(ctrl->pll_byte_clk);
1595 pr_err("%s: can't find pll_byte_clk. rc=%d\n",
1596 __func__, rc);
1597 ctrl->pll_byte_clk = NULL;
1598 goto error;
1599 }
1600
1601 ctrl->pll_pixel_clk = devm_clk_get(dev, "pll_pixel_clk_src");
1602 if (IS_ERR(ctrl->pll_pixel_clk)) {
1603 rc = PTR_ERR(ctrl->pll_pixel_clk);
1604 pr_err("%s: can't find pll_pixel_clk. rc=%d\n",
1605 __func__, rc);
1606 ctrl->pll_pixel_clk = NULL;
1607 goto error;
1608 }
1609
1610 ctrl->shadow_byte_clk = devm_clk_get(dev, "pll_shadow_byte_clk_src");
1611 if (IS_ERR(ctrl->shadow_byte_clk)) {
1612 rc = PTR_ERR(ctrl->shadow_byte_clk);
1613 pr_err("%s: can't find shadow_byte_clk. rc=%d\n",
1614 __func__, rc);
1615 ctrl->shadow_byte_clk = NULL;
1616 goto error;
1617 }
1618
1619 ctrl->shadow_pixel_clk = devm_clk_get(dev, "pll_shadow_pixel_clk_src");
1620 if (IS_ERR(ctrl->shadow_pixel_clk)) {
1621 rc = PTR_ERR(ctrl->shadow_pixel_clk);
1622 pr_err("%s: can't find shadow_pixel_clk. rc=%d\n",
1623 __func__, rc);
1624 ctrl->shadow_pixel_clk = NULL;
1625 goto error;
1626 }
1627
1628error:
1629 if (rc)
1630 mdss_dsi_shadow_clk_deinit(dev, ctrl);
1631 return rc;
1632}
1633
1634bool is_diff_frame_rate(struct mdss_panel_info *panel_info,
1635 u32 frame_rate)
1636{
1637 if (panel_info->dynamic_fps && panel_info->current_fps)
1638 return (frame_rate != panel_info->current_fps);
1639 else
1640 return (frame_rate != panel_info->mipi.frame_rate);
1641}
1642
1643int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info,
1644 int frame_rate)
1645{
1646 struct mdss_panel_data *pdata = container_of(panel_info,
1647 struct mdss_panel_data, panel_info);
1648 struct mdss_dsi_ctrl_pdata *ctrl_pdata = container_of(pdata,
1649 struct mdss_dsi_ctrl_pdata, panel_data);
1650 u64 h_period, v_period, clk_rate;
1651 u32 dsi_pclk_rate;
1652 u8 lanes = 0, bpp;
1653
1654 if (panel_info->mipi.data_lane3)
1655 lanes += 1;
1656 if (panel_info->mipi.data_lane2)
1657 lanes += 1;
1658 if (panel_info->mipi.data_lane1)
1659 lanes += 1;
1660 if (panel_info->mipi.data_lane0)
1661 lanes += 1;
1662
1663 switch (panel_info->mipi.dst_format) {
1664 case DSI_CMD_DST_FORMAT_RGB888:
1665 case DSI_VIDEO_DST_FORMAT_RGB888:
1666 case DSI_VIDEO_DST_FORMAT_RGB666_LOOSE:
1667 bpp = 3;
1668 break;
1669 case DSI_CMD_DST_FORMAT_RGB565:
1670 case DSI_VIDEO_DST_FORMAT_RGB565:
1671 bpp = 2;
1672 break;
1673 default:
1674 bpp = 3; /* Default format set to RGB888 */
1675 break;
1676 }
1677
1678 h_period = mdss_panel_get_htotal(panel_info, true);
1679 v_period = mdss_panel_get_vtotal(panel_info);
1680
1681 if (ctrl_pdata->refresh_clk_rate || is_diff_frame_rate(panel_info,
1682 frame_rate) || (!panel_info->clk_rate)) {
1683 if (lanes > 0) {
1684 panel_info->clk_rate = h_period * v_period * frame_rate
1685 * bpp * 8;
1686 do_div(panel_info->clk_rate, lanes);
1687 } else {
1688 pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__);
1689 panel_info->clk_rate =
1690 h_period * v_period * frame_rate * bpp * 8;
1691 }
1692 }
1693
1694 if (panel_info->clk_rate == 0)
1695 panel_info->clk_rate = 454000000;
1696
1697 clk_rate = panel_info->clk_rate;
1698 do_div(clk_rate, 8 * bpp);
1699 dsi_pclk_rate = (u32) clk_rate * lanes;
1700
1701 if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 250000000))
1702 dsi_pclk_rate = 35000000;
1703 panel_info->mipi.dsi_pclk_rate = dsi_pclk_rate;
1704
1705 return 0;
1706}
1707
1708static bool mdss_dsi_is_ulps_req_valid(struct mdss_dsi_ctrl_pdata *ctrl,
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05301709 int enable, bool reconfig)
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301710{
1711 struct mdss_dsi_ctrl_pdata *octrl = NULL;
1712 struct mdss_panel_data *pdata = &ctrl->panel_data;
1713 struct mdss_panel_info *pinfo = &pdata->panel_info;
1714
1715 pr_debug("%s: checking ulps req validity for ctrl%d\n",
1716 __func__, ctrl->ndx);
1717
1718 if (!mdss_dsi_ulps_feature_enabled(pdata) &&
1719 !pinfo->ulps_suspend_enabled) {
1720 pr_debug("%s: ULPS feature is not enabled\n", __func__);
1721 return false;
1722 }
1723
1724 /*
1725 * No need to enter ULPS when transitioning from splash screen to
1726 * boot animation since it is expected that the clocks would be turned
1727 * right back on.
1728 */
1729 if (enable && pinfo->cont_splash_enabled) {
1730 pr_debug("%s: skip ULPS config with splash screen enabled\n",
1731 __func__);
1732 return false;
1733 }
1734
1735 /*
1736 * No need to enable ULPS if panel is not yet initialized.
1737 * However, this should be allowed in following usecases:
1738 * 1. If ULPS during suspend feature is enabled, where we
1739 * configure the lanes in ULPS after turning off the panel.
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05301740 * 2. When coming out of idle PC with ULPS enabled, where we need to
1741 * reconfigure the controller HW state again to ULPS prior to
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301742 * disabling ULPS.
1743 */
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05301744 if (enable && !reconfig &&
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301745 !(ctrl->ctrl_state & CTRL_STATE_PANEL_INIT) &&
1746 !pdata->panel_info.ulps_suspend_enabled) {
1747 pr_debug("%s: panel not yet initialized\n", __func__);
1748 return false;
1749 }
1750
1751 /*
1752 * For split-DSI usecase, wait till both controllers are initialized.
1753 * The same exceptions as above are applicable here too.
1754 */
1755 if (mdss_dsi_is_hw_config_split(ctrl->shared_data)) {
1756 octrl = mdss_dsi_get_other_ctrl(ctrl);
1757 if (enable && !ctrl->mmss_clamp && octrl &&
1758 !(octrl->ctrl_state & CTRL_STATE_PANEL_INIT) &&
1759 !pdata->panel_info.ulps_suspend_enabled) {
1760 pr_debug("%s: split-DSI, other ctrl not ready yet\n",
1761 __func__);
1762 return false;
1763 }
1764 }
1765
1766 return true;
1767}
1768
1769/**
1770 * mdss_dsi_ulps_config() - Program DSI lanes to enter/exit ULPS mode
1771 * @ctrl: pointer to DSI controller structure
1772 * @enable: 1 to enter ULPS, 0 to exit ULPS
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05301773 * @reconfig: boolean to specify if DSI controller is reconfigured to enter ULPS
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301774 *
1775 * This function executes the necessary programming sequence to enter/exit
1776 * DSI Ultra-Low Power State (ULPS). This function assumes that the link and
1777 * core clocks are already on.
1778 */
1779static int mdss_dsi_ulps_config(struct mdss_dsi_ctrl_pdata *ctrl,
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05301780 int enable, bool reconfig)
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301781{
1782 int ret = 0;
1783 struct mdss_panel_data *pdata = NULL;
1784 struct mdss_panel_info *pinfo;
1785 struct mipi_panel_info *mipi;
1786 u32 lane_status = 0;
1787 u32 active_lanes = 0;
1788
1789 if (!ctrl) {
1790 pr_err("%s: invalid input\n", __func__);
1791 return -EINVAL;
1792 }
1793
1794 pdata = &ctrl->panel_data;
1795 if (!pdata) {
1796 pr_err("%s: Invalid panel data\n", __func__);
1797 return -EINVAL;
1798 }
1799 pinfo = &pdata->panel_info;
1800 mipi = &pinfo->mipi;
1801
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05301802 if (!mdss_dsi_is_ulps_req_valid(ctrl, enable, reconfig)) {
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301803 pr_debug("%s: skiping ULPS config for ctrl%d, enable=%d\n",
1804 __func__, ctrl->ndx, enable);
1805 return 0;
1806 }
1807
1808 /* clock lane will always be programmed for ulps */
1809 active_lanes = BIT(4);
1810 /*
1811 * make a note of all active data lanes for which ulps entry/exit
1812 * is needed
1813 */
1814 if (mipi->data_lane0)
1815 active_lanes |= BIT(0);
1816 if (mipi->data_lane1)
1817 active_lanes |= BIT(1);
1818 if (mipi->data_lane2)
1819 active_lanes |= BIT(2);
1820 if (mipi->data_lane3)
1821 active_lanes |= BIT(3);
1822
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05301823 pr_debug("%s: configuring ulps (%s) for ctrl%d, active lanes=0x%08x,reconfig=%s\n",
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301824 __func__, (enable ? "on" : "off"), ctrl->ndx,
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05301825 active_lanes, reconfig ? "true" : "false");
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301826
1827 if (enable && !ctrl->ulps) {
1828 /*
1829 * Ensure that the lanes are idle prior to placing a ULPS entry
1830 * request. This is needed to ensure that there is no overlap
1831 * between any HS or LP commands being sent out on the lane and
1832 * a potential ULPS entry request.
1833 *
1834 * This check needs to be avoided when we are resuming from idle
1835 * power collapse and just restoring the controller state to
1836 * ULPS with the clamps still in place.
1837 */
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05301838 if (!reconfig) {
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301839 ret = mdss_dsi_wait_for_lane_idle(ctrl);
1840 if (ret) {
1841 pr_warn("%s: lanes not idle, skip ulps\n",
1842 __func__);
1843 ret = 0;
1844 goto error;
1845 }
1846 }
1847
1848 /*
1849 * ULPS Entry Request.
1850 * Wait for a short duration to ensure that the lanes
1851 * enter ULP state.
1852 */
1853 MIPI_OUTP(ctrl->ctrl_base + 0x0AC, active_lanes);
1854 usleep_range(100, 110);
1855
1856 /* Check to make sure that all active data lanes are in ULPS */
1857 lane_status = MIPI_INP(ctrl->ctrl_base + 0xA8);
1858 if (lane_status & (active_lanes << 8)) {
1859 pr_err("%s: ULPS entry req failed for ctrl%d. Lane status=0x%08x\n",
1860 __func__, ctrl->ndx, lane_status);
1861 ret = -EINVAL;
1862 goto error;
1863 }
1864
1865 ctrl->ulps = true;
1866 } else if (!enable && ctrl->ulps) {
1867 /*
1868 * Clear out any phy errors prior to exiting ULPS
1869 * This fixes certain instances where phy does not exit
1870 * ULPS cleanly. Also, do not print error during such cases.
1871 */
1872 mdss_dsi_dln0_phy_err(ctrl, false);
1873
1874 /*
1875 * ULPS Exit Request
1876 * Hardware requirement is to wait for at least 1ms
1877 */
1878 MIPI_OUTP(ctrl->ctrl_base + 0x0AC, active_lanes << 8);
1879 usleep_range(1000, 1100);
1880
1881 /*
1882 * Sometimes when exiting ULPS, it is possible that some DSI
1883 * lanes are not in the stop state which could lead to DSI
1884 * commands not going through. To avoid this, force the lanes
1885 * to be in stop state.
1886 */
1887 MIPI_OUTP(ctrl->ctrl_base + 0x0AC, active_lanes << 16);
1888 wmb(); /* ensure lanes are put to stop state */
1889
1890 MIPI_OUTP(ctrl->ctrl_base + 0x0AC, 0x0);
1891 wmb(); /* ensure lanes are in proper state */
1892
1893 /*
1894 * Wait for a short duration before enabling
1895 * data transmission
1896 */
1897 usleep_range(100, 110);
1898
1899 lane_status = MIPI_INP(ctrl->ctrl_base + 0xA8);
1900 ctrl->ulps = false;
1901 } else {
1902 pr_debug("%s: No change requested: %s -> %s\n", __func__,
1903 ctrl->ulps ? "enabled" : "disabled",
1904 enable ? "enabled" : "disabled");
1905 }
1906
1907 pr_debug("%s: DSI lane status = 0x%08x. Ulps %s\n", __func__,
1908 lane_status, enable ? "enabled" : "disabled");
1909
1910error:
1911 return ret;
1912}
1913
1914/**
1915 * mdss_dsi_clamp_ctrl() - Program DSI clamps for supporting power collapse
1916 * @ctrl: pointer to DSI controller structure
1917 * @enable: 1 to enable clamps, 0 to disable clamps
1918 *
1919 * For idle-screen usecases with command mode panels, MDSS can be power
1920 * collapsed. However, DSI phy needs to remain on. To avoid any mismatch
1921 * between the DSI controller state, DSI phy needs to be clamped before
1922 * power collapsing. This function executes the required programming
1923 * sequence to configure these DSI clamps. This function should only be called
1924 * when the DSI link clocks are disabled.
1925 */
1926static int mdss_dsi_clamp_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
1927{
1928 struct mipi_panel_info *mipi = NULL;
1929 u32 clamp_reg, regval = 0;
1930 u32 clamp_reg_off, phyrst_reg_off;
1931
1932 if (!ctrl) {
1933 pr_err("%s: invalid input\n", __func__);
1934 return -EINVAL;
1935 }
1936
1937 if (!ctrl->mmss_misc_io.base) {
1938 pr_err("%s: mmss_misc_io not mapped\n", __func__);
1939 return -EINVAL;
1940 }
1941
1942 clamp_reg_off = ctrl->shared_data->ulps_clamp_ctrl_off;
1943 phyrst_reg_off = ctrl->shared_data->ulps_phyrst_ctrl_off;
1944 mipi = &ctrl->panel_data.panel_info.mipi;
1945
1946 /* clock lane will always be clamped */
1947 clamp_reg = BIT(9);
1948 if (ctrl->ulps)
1949 clamp_reg |= BIT(8);
1950 /* make a note of all active data lanes which need to be clamped */
1951 if (mipi->data_lane0) {
1952 clamp_reg |= BIT(7);
1953 if (ctrl->ulps)
1954 clamp_reg |= BIT(6);
1955 }
1956 if (mipi->data_lane1) {
1957 clamp_reg |= BIT(5);
1958 if (ctrl->ulps)
1959 clamp_reg |= BIT(4);
1960 }
1961 if (mipi->data_lane2) {
1962 clamp_reg |= BIT(3);
1963 if (ctrl->ulps)
1964 clamp_reg |= BIT(2);
1965 }
1966 if (mipi->data_lane3) {
1967 clamp_reg |= BIT(1);
1968 if (ctrl->ulps)
1969 clamp_reg |= BIT(0);
1970 }
1971 pr_debug("%s: called for ctrl%d, enable=%d, clamp_reg=0x%08x\n",
1972 __func__, ctrl->ndx, enable, clamp_reg);
1973 if (enable && !ctrl->mmss_clamp) {
1974 regval = MIPI_INP(ctrl->mmss_misc_io.base + clamp_reg_off);
1975 /* Enable MMSS DSI Clamps */
1976 if (ctrl->ndx == DSI_CTRL_0) {
1977 MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
1978 regval | clamp_reg);
1979 MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
1980 regval | (clamp_reg | BIT(15)));
1981 } else if (ctrl->ndx == DSI_CTRL_1) {
1982 MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
1983 regval | (clamp_reg << 16));
1984 MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
1985 regval | ((clamp_reg << 16) | BIT(31)));
1986 }
1987 /* update clamp ctrl before setting phy reset disable */
1988 wmb();
1989
1990 /*
1991 * This register write ensures that DSI PHY will not be
1992 * reset when mdss ahb clock reset is asserted while coming
1993 * out of power collapse
1994 */
1995 if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->shared_data->hw_rev,
1996 MDSS_DSI_HW_REV_104) &&
1997 (MDSS_GET_STEP(ctrl->shared_data->hw_rev) !=
1998 MDSS_DSI_HW_REV_STEP_2)) {
1999
2000 regval = MIPI_INP(ctrl->mmss_misc_io.base +
2001 clamp_reg_off);
2002 MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
2003 regval | BIT(30));
2004 } else {
2005 MIPI_OUTP(ctrl->mmss_misc_io.base + phyrst_reg_off,
2006 0x1);
2007 }
2008 /* make sure that clamp ctrl is updated before disable call */
2009 wmb();
2010 ctrl->mmss_clamp = true;
2011 } else if (!enable && ctrl->mmss_clamp) {
2012 if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->shared_data->hw_rev,
2013 MDSS_DSI_HW_REV_104) &&
2014 (MDSS_GET_STEP(ctrl->shared_data->hw_rev) !=
2015 MDSS_DSI_HW_REV_STEP_2)) {
2016
2017 regval = MIPI_INP(ctrl->mmss_misc_io.base +
2018 clamp_reg_off);
2019 MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
2020 regval & ~BIT(30));
2021 } else {
2022 MIPI_OUTP(ctrl->mmss_misc_io.base + phyrst_reg_off,
2023 0x0);
2024 }
2025 /* update clamp ctrl before unsetting phy reset disable */
2026 wmb();
2027
2028 regval = MIPI_INP(ctrl->mmss_misc_io.base + clamp_reg_off);
2029 /* Disable MMSS DSI Clamps */
2030 if (ctrl->ndx == DSI_CTRL_0)
2031 MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
2032 regval & ~(clamp_reg | BIT(15)));
2033 else if (ctrl->ndx == DSI_CTRL_1)
2034 MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
2035 regval & ~((clamp_reg << 16) | BIT(31)));
2036 /* make sure that clamp ctrl is updated before enable call */
2037 wmb();
2038 ctrl->mmss_clamp = false;
2039 } else {
2040 pr_debug("%s: No change requested: %s -> %s\n", __func__,
2041 ctrl->mmss_clamp ? "enabled" : "disabled",
2042 enable ? "enabled" : "disabled");
2043 }
2044
2045 return 0;
2046}
2047
2048DEFINE_MUTEX(dsi_clk_mutex);
2049
2050int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle,
2051 enum mdss_dsi_clk_type clk_type, enum mdss_dsi_clk_state clk_state)
2052{
2053 int rc = 0;
2054 struct mdss_dsi_ctrl_pdata *mctrl = NULL;
Sachin Bhayareb6b5a0f2018-03-02 19:50:39 +05302055 int i, *vote_cnt = NULL;
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302056
2057 void *m_clk_handle;
2058 bool is_ecg = false;
2059 int state = MDSS_DSI_CLK_OFF;
2060
2061 if (!ctrl) {
2062 pr_err("%s: Invalid arg\n", __func__);
2063 return -EINVAL;
2064 }
2065
2066 mutex_lock(&dsi_clk_mutex);
2067 /*
2068 * In sync_wait_broadcast mode, we need to enable clocks
2069 * for the other controller as well when enabling clocks
2070 * for the trigger controller.
2071 *
2072 * If sync wait_broadcase mode is not enabled, but if split display
2073 * mode is enabled where both DSI controller's branch clocks are
2074 * sourced out of a single PLL, then we need to ensure that the
2075 * controller associated with that PLL also has it's clocks turned
2076 * on. This is required to make sure that if that controller's PLL/PHY
2077 * are clamped then they can be removed.
2078 */
2079 if (mdss_dsi_sync_wait_trigger(ctrl)) {
2080 mctrl = mdss_dsi_get_other_ctrl(ctrl);
2081 if (!mctrl)
2082 pr_warn("%s: Unable to get other control\n", __func__);
2083 } else if (mdss_dsi_is_ctrl_clk_slave(ctrl)) {
2084 mctrl = mdss_dsi_get_ctrl_clk_master();
2085 if (!mctrl)
2086 pr_warn("%s: Unable to get clk master control\n",
2087 __func__);
2088 }
2089
2090 /*
2091 * it should add and remove extra votes based on voting clients to avoid
2092 * removal of legitimate vote from DSI client.
2093 */
2094 if (mctrl && (clk_handle == ctrl->dsi_clk_handle)) {
2095 m_clk_handle = mctrl->dsi_clk_handle;
2096 vote_cnt = &mctrl->m_dsi_vote_cnt;
2097 } else if (mctrl) {
2098 m_clk_handle = mctrl->mdp_clk_handle;
2099 vote_cnt = &mctrl->m_mdp_vote_cnt;
2100 }
2101
2102 /*
2103 * When DSI is used in split mode, the link clock for master controller
2104 * has to be turned on first before the link clock for slave can be
2105 * turned on. In case the current controller is a slave, an ON vote is
2106 * cast for master before changing the state of the slave clock. After
2107 * the state change for slave, the ON votes will be removed depending on
2108 * the new state.
2109 */
2110 pr_debug("%s: DSI_%d: clk = %d, state = %d, caller = %pS, mctrl=%d\n",
2111 __func__, ctrl->ndx, clk_type, clk_state,
2112 __builtin_return_address(0), mctrl ? 1 : 0);
2113 if (mctrl && (clk_type & MDSS_DSI_LINK_CLK)) {
2114 if (clk_state != MDSS_DSI_CLK_ON) {
2115 /* preserve clk state; do not turn off forcefully */
2116 is_ecg = is_dsi_clk_in_ecg_state(m_clk_handle);
2117 if (is_ecg)
2118 state = MDSS_DSI_CLK_EARLY_GATE;
2119 }
2120
2121 rc = mdss_dsi_clk_req_state(m_clk_handle,
2122 MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON, mctrl->ndx);
2123 if (rc) {
2124 pr_err("%s: failed to turn on mctrl clocks, rc=%d\n",
2125 __func__, rc);
2126 goto error;
2127 }
2128 (*vote_cnt)++;
2129 }
2130
2131 rc = mdss_dsi_clk_req_state(clk_handle, clk_type, clk_state, ctrl->ndx);
2132 if (rc) {
2133 pr_err("%s: failed set clk state, rc = %d\n", __func__, rc);
2134 goto error;
2135 }
2136
2137 if (mctrl && (clk_type & MDSS_DSI_LINK_CLK) &&
2138 clk_state != MDSS_DSI_CLK_ON) {
2139
2140 /*
2141 * In case of split dsi, an ON vote is cast for all state change
2142 * requests. If the current state is ON, then the vote would not
2143 * be released.
2144 *
2145 * If the current state is ECG, there is one possible way to
2146 * transition in to this state, which is ON -> ECG. In this case
2147 * two votes will be removed because one was cast at ON and
2148 * other when entering ECG.
2149 *
2150 * If the current state is OFF, it could have been due to two
2151 * possible transitions in to OFF state.
2152 * 1. ON -> OFF: In this case two votes were cast by the
2153 * slave controller, one during ON (which is not
2154 * removed) and one during OFF. So we need to remove two
2155 * votes.
2156 * 2. ECG -> OFF: In this case there is only one vote
2157 * for ON, since the previous ECG state must have
2158 * removed two votes to let clocks turn off.
2159 *
2160 * To satisfy the above requirement, vote_cnt keeps track of
2161 * the number of ON votes for master requested by slave. For
2162 * every OFF/ECG state request, Either 2 or vote_cnt number of
2163 * votes are removed depending on which is lower.
2164 */
2165 for (i = 0; (i < *vote_cnt && i < 2); i++) {
2166 rc = mdss_dsi_clk_req_state(m_clk_handle,
2167 MDSS_DSI_ALL_CLKS, state, mctrl->ndx);
2168 if (rc) {
2169 pr_err("%s: failed to set mctrl clk state, rc = %d\n",
2170 __func__, rc);
2171 goto error;
2172 }
2173 }
2174 (*vote_cnt) -= i;
2175 pr_debug("%s: ctrl=%d, vote_cnt=%d dsi_vote_cnt=%d mdp_vote_cnt:%d\n",
2176 __func__, ctrl->ndx, *vote_cnt, mctrl->m_dsi_vote_cnt,
2177 mctrl->m_mdp_vote_cnt);
2178 }
2179
2180error:
2181 mutex_unlock(&dsi_clk_mutex);
2182 return rc;
2183}
2184
2185int mdss_dsi_pre_clkoff_cb(void *priv,
2186 enum mdss_dsi_clk_type clk,
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05302187 enum mdss_dsi_lclk_type l_type,
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302188 enum mdss_dsi_clk_state new_state)
2189{
2190 int rc = 0;
2191 struct mdss_dsi_ctrl_pdata *ctrl = priv;
2192 struct mdss_panel_data *pdata = NULL;
2193
2194 pdata = &ctrl->panel_data;
2195
Padmanabhan Komandurufa3aa592018-04-13 23:10:08 +05302196 if ((clk & MDSS_DSI_LINK_CLK) && (l_type == MDSS_DSI_LINK_HS_CLK) &&
2197 (new_state == MDSS_DSI_CLK_OFF)) {
2198 /* Disable HS TX driver in DSI PHY if applicable */
2199 mdss_dsi_phy_hstx_drv_ctrl(ctrl, false);
2200 }
2201
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05302202 if ((clk & MDSS_DSI_LINK_CLK) && (l_type == MDSS_DSI_LINK_LP_CLK) &&
2203 (new_state == MDSS_DSI_CLK_OFF)) {
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302204 /*
2205 * If ULPS feature is enabled, enter ULPS first.
2206 * However, when blanking the panel, we should enter ULPS
2207 * only if ULPS during suspend feature is enabled.
2208 */
2209 if (!(ctrl->ctrl_state & CTRL_STATE_PANEL_INIT)) {
2210 if (pdata->panel_info.ulps_suspend_enabled)
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05302211 mdss_dsi_ulps_config(ctrl, 1, false);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302212 } else if (mdss_dsi_ulps_feature_enabled(pdata)) {
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05302213 rc = mdss_dsi_ulps_config(ctrl, 1, false);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302214 }
2215 if (rc) {
2216 pr_err("%s: failed enable ulps, rc = %d\n",
2217 __func__, rc);
2218 }
2219 }
2220
2221 if ((clk & MDSS_DSI_CORE_CLK) && (new_state == MDSS_DSI_CLK_OFF)) {
2222 /*
2223 * Enable DSI clamps only if entering idle power collapse or
2224 * when ULPS during suspend is enabled.
2225 */
2226 if ((ctrl->ctrl_state & CTRL_STATE_DSI_ACTIVE) ||
2227 pdata->panel_info.ulps_suspend_enabled) {
2228 mdss_dsi_phy_power_off(ctrl);
2229 rc = mdss_dsi_clamp_ctrl(ctrl, 1);
2230 if (rc)
2231 pr_err("%s: Failed to enable dsi clamps. rc=%d\n",
2232 __func__, rc);
2233 } else {
2234 /*
2235 * Make sure that controller is not in ULPS state when
2236 * the DSI link is not active.
2237 */
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05302238 rc = mdss_dsi_ulps_config(ctrl, 0, false);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302239 if (rc)
2240 pr_err("%s: failed to disable ulps. rc=%d\n",
2241 __func__, rc);
2242 }
2243 }
2244
2245 return rc;
2246}
2247
2248int mdss_dsi_post_clkon_cb(void *priv,
2249 enum mdss_dsi_clk_type clk,
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05302250 enum mdss_dsi_lclk_type l_type,
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302251 enum mdss_dsi_clk_state curr_state)
2252{
2253 int rc = 0;
2254 struct mdss_panel_data *pdata = NULL;
2255 struct mdss_dsi_ctrl_pdata *ctrl = priv;
2256 bool mmss_clamp;
2257
2258 pdata = &ctrl->panel_data;
2259
2260 if (clk & MDSS_DSI_CORE_CLK) {
2261 mmss_clamp = ctrl->mmss_clamp;
2262 /*
2263 * controller setup is needed if coming out of idle
2264 * power collapse with clamps enabled.
2265 */
2266 if (mmss_clamp)
2267 mdss_dsi_ctrl_setup(ctrl);
2268
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05302269 rc = mdss_dsi_clamp_ctrl(ctrl, 0);
2270 if (rc) {
2271 pr_err("%s: Failed to disable dsi clamps. rc=%d\n",
2272 __func__, rc);
2273 goto error;
2274 }
2275
2276 /*
2277 * Phy setup is needed if coming out of idle
2278 * power collapse with clamps enabled.
2279 */
2280 if (ctrl->phy_power_off || mmss_clamp)
2281 mdss_dsi_phy_power_on(ctrl, mmss_clamp);
2282 }
2283 if ((clk & MDSS_DSI_LINK_CLK) && (l_type == MDSS_DSI_LINK_HS_CLK)) {
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302284 if (ctrl->ulps) {
2285 /*
2286 * ULPS Entry Request. This is needed if the lanes were
2287 * in ULPS prior to power collapse, since after
2288 * power collapse and reset, the DSI controller resets
2289 * back to idle state and not ULPS. This ulps entry
2290 * request will transition the state of the DSI
2291 * controller to ULPS which will match the state of the
2292 * DSI phy. This needs to be done prior to disabling
2293 * the DSI clamps.
2294 *
2295 * Also, reset the ulps flag so that ulps_config
2296 * function would reconfigure the controller state to
2297 * ULPS.
2298 */
2299 ctrl->ulps = false;
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05302300 rc = mdss_dsi_ulps_config(ctrl, 1, true);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302301 if (rc) {
2302 pr_err("%s: Failed to enter ULPS. rc=%d\n",
2303 __func__, rc);
2304 goto error;
2305 }
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302306
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05302307 rc = mdss_dsi_ulps_config(ctrl, 0, false);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302308 if (rc) {
2309 pr_err("%s: failed to disable ulps, rc= %d\n",
2310 __func__, rc);
2311 goto error;
2312 }
2313 }
Padmanabhan Komandurufa3aa592018-04-13 23:10:08 +05302314 /* Enable HS TX driver in DSI PHY if applicable */
2315 mdss_dsi_phy_hstx_drv_ctrl(ctrl, true);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302316 }
2317error:
2318 return rc;
2319}
2320
2321int mdss_dsi_post_clkoff_cb(void *priv,
2322 enum mdss_dsi_clk_type clk_type,
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05302323 enum mdss_dsi_lclk_type l_type,
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302324 enum mdss_dsi_clk_state curr_state)
2325{
2326 int rc = 0;
2327 struct mdss_dsi_ctrl_pdata *ctrl = priv;
2328 struct mdss_panel_data *pdata = NULL;
2329 struct dsi_shared_data *sdata;
2330 int i;
2331
2332 if (!ctrl) {
2333 pr_err("%s: Invalid arg\n", __func__);
2334 return -EINVAL;
2335 }
2336
2337 pdata = &ctrl->panel_data;
2338 if ((clk_type & MDSS_DSI_CORE_CLK) &&
2339 (curr_state == MDSS_DSI_CLK_OFF)) {
2340 sdata = ctrl->shared_data;
2341
2342 for (i = DSI_MAX_PM - 1; i >= DSI_CORE_PM; i--) {
2343 if ((ctrl->ctrl_state & CTRL_STATE_DSI_ACTIVE) &&
2344 (i != DSI_CORE_PM))
2345 continue;
Sachin Bhayare5076e252018-01-18 14:56:45 +05302346 rc = msm_mdss_enable_vreg(
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302347 sdata->power_data[i].vreg_config,
2348 sdata->power_data[i].num_vreg, 0);
2349 if (rc) {
2350 pr_warn("%s: failed to disable vregs for %s\n",
2351 __func__,
2352 __mdss_dsi_pm_name(i));
2353 rc = 0;
2354 } else {
2355 ctrl->core_power = false;
2356 }
2357 }
2358
2359 /*
2360 * temp workaround until framework issues pertaining to LP2
2361 * power state transitions are fixed. For now, we internally
2362 * transition to LP2 state whenever core power is turned off
2363 * in LP1 state
2364 */
2365 if (mdss_dsi_is_panel_on_lp(pdata))
2366 mdss_dsi_panel_power_ctrl(pdata,
2367 MDSS_PANEL_POWER_LP2);
2368 }
2369 return rc;
2370}
2371
2372int mdss_dsi_pre_clkon_cb(void *priv,
2373 enum mdss_dsi_clk_type clk_type,
Padmanabhan Komandurub0008fd2018-04-12 16:25:43 +05302374 enum mdss_dsi_lclk_type l_type,
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302375 enum mdss_dsi_clk_state new_state)
2376{
2377 int rc = 0;
2378 struct mdss_dsi_ctrl_pdata *ctrl = priv;
2379 struct mdss_panel_data *pdata = NULL;
2380 struct dsi_shared_data *sdata;
2381 int i;
2382
2383 if (!ctrl) {
2384 pr_err("%s: invalid input\n", __func__);
2385 return -EINVAL;
2386 }
2387
2388 pdata = &ctrl->panel_data;
2389 if ((clk_type & MDSS_DSI_CORE_CLK) && (new_state == MDSS_DSI_CLK_ON) &&
2390 (ctrl->core_power == false)) {
2391 sdata = ctrl->shared_data;
2392 /*
2393 * Enable DSI core power
2394 * 1.> PANEL_PM are controlled as part of
2395 * panel_power_ctrl. Needed not be handled here.
2396 * 2.> CORE_PM are controlled by dsi clk manager.
2397 * 3.> CTRL_PM need to be enabled/disabled
2398 * only during unblank/blank. Their state should
2399 * not be changed during static screen.
2400 */
2401 pr_debug("%s: Enable DSI core power\n", __func__);
2402 for (i = DSI_CORE_PM; i < DSI_MAX_PM; i++) {
2403 if ((ctrl->ctrl_state & CTRL_STATE_DSI_ACTIVE) &&
2404 (!pdata->panel_info.cont_splash_enabled) &&
2405 (i != DSI_CORE_PM))
2406 continue;
Sachin Bhayare5076e252018-01-18 14:56:45 +05302407 rc = msm_mdss_enable_vreg(
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302408 sdata->power_data[i].vreg_config,
2409 sdata->power_data[i].num_vreg, 1);
2410 if (rc) {
2411 pr_err("%s: failed to enable vregs for %s\n",
2412 __func__,
2413 __mdss_dsi_pm_name(i));
2414 } else {
2415 ctrl->core_power = true;
2416 }
2417
2418 }
2419 /*
2420 * temp workaround until framework issues pertaining to LP2
2421 * power state transitions are fixed. For now, if we intend to
2422 * send a frame update when in LP1, we have to explicitly exit
2423 * LP2 state here
2424 */
2425 if (mdss_dsi_is_panel_on_ulp(pdata))
2426 mdss_dsi_panel_power_ctrl(pdata, MDSS_PANEL_POWER_LP1);
2427 }
2428 /* Disable dynamic clock gating*/
2429 if (ctrl->mdss_util->dyn_clk_gating_ctrl)
2430 ctrl->mdss_util->dyn_clk_gating_ctrl(0);
2431
2432 return rc;
2433}
2434
2435void mdss_edp_clk_deinit(struct mdss_edp_drv_pdata *edp_drv)
2436{
2437 if (edp_drv->aux_clk)
2438 clk_put(edp_drv->aux_clk);
2439 if (edp_drv->pixel_clk)
2440 clk_put(edp_drv->pixel_clk);
2441 if (edp_drv->ahb_clk)
2442 clk_put(edp_drv->ahb_clk);
2443 if (edp_drv->link_clk)
2444 clk_put(edp_drv->link_clk);
2445 if (edp_drv->mdp_core_clk)
2446 clk_put(edp_drv->mdp_core_clk);
2447}
2448
2449int mdss_edp_clk_init(struct mdss_edp_drv_pdata *edp_drv)
2450{
2451 struct device *dev = &(edp_drv->pdev->dev);
2452
2453 edp_drv->aux_clk = clk_get(dev, "core_clk");
2454 if (IS_ERR(edp_drv->aux_clk)) {
2455 pr_err("%s: Can't find aux_clk", __func__);
2456 edp_drv->aux_clk = NULL;
2457 goto mdss_edp_clk_err;
2458 }
2459
2460 edp_drv->pixel_clk = clk_get(dev, "pixel_clk");
2461 if (IS_ERR(edp_drv->pixel_clk)) {
2462 pr_err("%s: Can't find pixel_clk", __func__);
2463 edp_drv->pixel_clk = NULL;
2464 goto mdss_edp_clk_err;
2465 }
2466
2467 edp_drv->ahb_clk = clk_get(dev, "iface_clk");
2468 if (IS_ERR(edp_drv->ahb_clk)) {
2469 pr_err("%s: Can't find ahb_clk", __func__);
2470 edp_drv->ahb_clk = NULL;
2471 goto mdss_edp_clk_err;
2472 }
2473
2474 edp_drv->link_clk = clk_get(dev, "link_clk");
2475 if (IS_ERR(edp_drv->link_clk)) {
2476 pr_err("%s: Can't find link_clk", __func__);
2477 edp_drv->link_clk = NULL;
2478 goto mdss_edp_clk_err;
2479 }
2480
2481 /* need mdss clock to receive irq */
2482 edp_drv->mdp_core_clk = clk_get(dev, "mdp_core_clk");
2483 if (IS_ERR(edp_drv->mdp_core_clk)) {
2484 pr_err("%s: Can't find mdp_core_clk", __func__);
2485 edp_drv->mdp_core_clk = NULL;
2486 goto mdss_edp_clk_err;
2487 }
2488
2489 return 0;
2490
2491mdss_edp_clk_err:
2492 mdss_edp_clk_deinit(edp_drv);
2493 return -EPERM;
2494}
2495
2496int mdss_edp_aux_clk_enable(struct mdss_edp_drv_pdata *edp_drv)
2497{
2498 int ret;
2499
2500 if (clk_set_rate(edp_drv->aux_clk, 19200000) < 0)
2501 pr_err("%s: aux_clk - clk_set_rate failed\n",
2502 __func__);
2503
2504 ret = clk_enable(edp_drv->aux_clk);
2505 if (ret) {
2506 pr_err("%s: Failed to enable aux clk\n", __func__);
2507 goto c2;
2508 }
2509
2510 ret = clk_enable(edp_drv->ahb_clk);
2511 if (ret) {
2512 pr_err("%s: Failed to enable ahb clk\n", __func__);
2513 goto c1;
2514 }
2515
2516 /* need mdss clock to receive irq */
2517 ret = clk_enable(edp_drv->mdp_core_clk);
2518 if (ret) {
2519 pr_err("%s: Failed to enable mdp_core_clk\n", __func__);
2520 goto c0;
2521 }
2522
2523 return 0;
2524c0:
2525 clk_disable(edp_drv->ahb_clk);
2526c1:
2527 clk_disable(edp_drv->aux_clk);
2528c2:
2529 return ret;
2530
2531}
2532
2533void mdss_edp_aux_clk_disable(struct mdss_edp_drv_pdata *edp_drv)
2534{
2535 clk_disable(edp_drv->aux_clk);
2536 clk_disable(edp_drv->ahb_clk);
2537 clk_disable(edp_drv->mdp_core_clk);
2538}
2539
2540static void mdss_edp_clk_set_rate(struct mdss_edp_drv_pdata *edp_drv)
2541{
2542 if (clk_set_rate(edp_drv->link_clk, edp_drv->link_rate * 27000000) < 0)
2543 pr_err("%s: link_clk - clk_set_rate failed\n",
2544 __func__);
2545
2546 if (clk_set_rate(edp_drv->pixel_clk, edp_drv->pixel_rate) < 0)
2547 pr_err("%s: pixel_clk - clk_set_rate failed\n",
2548 __func__);
2549}
2550
2551int mdss_edp_clk_enable(struct mdss_edp_drv_pdata *edp_drv)
2552{
2553 int ret;
2554
2555 if (edp_drv->clk_on) {
2556 pr_info("%s: edp clks are already ON\n", __func__);
2557 return 0;
2558 }
2559
2560 if (clk_set_rate(edp_drv->link_clk, edp_drv->link_rate * 27000000) < 0)
2561 pr_err("%s: link_clk - clk_set_rate failed\n",
2562 __func__);
2563
2564 if (clk_set_rate(edp_drv->aux_clk, edp_drv->aux_rate) < 0)
2565 pr_err("%s: aux_clk - clk_set_rate failed\n",
2566 __func__);
2567
2568 if (clk_set_rate(edp_drv->pixel_clk, edp_drv->pixel_rate) < 0)
2569 pr_err("%s: pixel_clk - clk_set_rate failed\n",
2570 __func__);
2571
2572 ret = clk_enable(edp_drv->aux_clk);
2573 if (ret) {
2574 pr_err("%s: Failed to enable aux clk\n", __func__);
2575 goto c4;
2576 }
2577 ret = clk_enable(edp_drv->pixel_clk);
2578 if (ret) {
2579 pr_err("%s: Failed to enable pixel clk\n", __func__);
2580 goto c3;
2581 }
2582 ret = clk_enable(edp_drv->ahb_clk);
2583 if (ret) {
2584 pr_err("%s: Failed to enable ahb clk\n", __func__);
2585 goto c2;
2586 }
2587 ret = clk_enable(edp_drv->link_clk);
2588 if (ret) {
2589 pr_err("%s: Failed to enable link clk\n", __func__);
2590 goto c1;
2591 }
2592 ret = clk_enable(edp_drv->mdp_core_clk);
2593 if (ret) {
2594 pr_err("%s: Failed to enable mdp_core_clk\n", __func__);
2595 goto c0;
2596 }
2597
2598 edp_drv->clk_on = 1;
2599
2600 return 0;
2601
2602c0:
2603 clk_disable(edp_drv->link_clk);
2604c1:
2605 clk_disable(edp_drv->ahb_clk);
2606c2:
2607 clk_disable(edp_drv->pixel_clk);
2608c3:
2609 clk_disable(edp_drv->aux_clk);
2610c4:
2611 return ret;
2612}
2613
2614void mdss_edp_clk_disable(struct mdss_edp_drv_pdata *edp_drv)
2615{
2616 if (edp_drv->clk_on == 0) {
2617 pr_info("%s: edp clks are already OFF\n", __func__);
2618 return;
2619 }
2620
2621 clk_disable(edp_drv->aux_clk);
2622 clk_disable(edp_drv->pixel_clk);
2623 clk_disable(edp_drv->ahb_clk);
2624 clk_disable(edp_drv->link_clk);
2625 clk_disable(edp_drv->mdp_core_clk);
2626
2627 edp_drv->clk_on = 0;
2628}
2629
2630int mdss_edp_prepare_aux_clocks(struct mdss_edp_drv_pdata *edp_drv)
2631{
2632 int ret;
2633
2634 /* ahb clock should be prepared first */
2635 ret = clk_prepare(edp_drv->ahb_clk);
2636 if (ret) {
2637 pr_err("%s: Failed to prepare ahb clk\n", __func__);
2638 goto c3;
2639 }
2640 ret = clk_prepare(edp_drv->aux_clk);
2641 if (ret) {
2642 pr_err("%s: Failed to prepare aux clk\n", __func__);
2643 goto c2;
2644 }
2645
2646 /* need mdss clock to receive irq */
2647 ret = clk_prepare(edp_drv->mdp_core_clk);
2648 if (ret) {
2649 pr_err("%s: Failed to prepare mdp_core clk\n", __func__);
2650 goto c1;
2651 }
2652
2653 return 0;
2654c1:
2655 clk_unprepare(edp_drv->aux_clk);
2656c2:
2657 clk_unprepare(edp_drv->ahb_clk);
2658c3:
2659 return ret;
2660
2661}
2662
2663void mdss_edp_unprepare_aux_clocks(struct mdss_edp_drv_pdata *edp_drv)
2664{
2665 clk_unprepare(edp_drv->mdp_core_clk);
2666 clk_unprepare(edp_drv->aux_clk);
2667 clk_unprepare(edp_drv->ahb_clk);
2668}
2669
2670int mdss_edp_prepare_clocks(struct mdss_edp_drv_pdata *edp_drv)
2671{
2672 int ret;
2673
2674 mdss_edp_clk_set_rate(edp_drv);
2675
2676 /* ahb clock should be prepared first */
2677 ret = clk_prepare(edp_drv->ahb_clk);
2678 if (ret) {
2679 pr_err("%s: Failed to prepare ahb clk\n", __func__);
2680 goto c4;
2681 }
2682 ret = clk_prepare(edp_drv->aux_clk);
2683 if (ret) {
2684 pr_err("%s: Failed to prepare aux clk\n", __func__);
2685 goto c3;
2686 }
2687 ret = clk_prepare(edp_drv->pixel_clk);
2688 if (ret) {
2689 pr_err("%s: Failed to prepare pixel clk\n", __func__);
2690 goto c2;
2691 }
2692 ret = clk_prepare(edp_drv->link_clk);
2693 if (ret) {
2694 pr_err("%s: Failed to prepare link clk\n", __func__);
2695 goto c1;
2696 }
2697 ret = clk_prepare(edp_drv->mdp_core_clk);
2698 if (ret) {
2699 pr_err("%s: Failed to prepare mdp_core clk\n", __func__);
2700 goto c0;
2701 }
2702
2703 return 0;
2704c0:
2705 clk_unprepare(edp_drv->link_clk);
2706c1:
2707 clk_unprepare(edp_drv->pixel_clk);
2708c2:
2709 clk_unprepare(edp_drv->aux_clk);
2710c3:
2711 clk_unprepare(edp_drv->ahb_clk);
2712c4:
2713 return ret;
2714}
2715
2716void mdss_edp_unprepare_clocks(struct mdss_edp_drv_pdata *edp_drv)
2717{
2718 clk_unprepare(edp_drv->mdp_core_clk);
2719 clk_unprepare(edp_drv->aux_clk);
2720 clk_unprepare(edp_drv->pixel_clk);
2721 clk_unprepare(edp_drv->link_clk);
2722 /* ahb clock should be last one to disable */
2723 clk_unprepare(edp_drv->ahb_clk);
2724}
2725
2726void mdss_edp_clk_debug(unsigned char *edp_base, unsigned char *mmss_cc_base)
2727{
2728 u32 da4, da0, d32c;
2729 u32 dc4, dc0, d330;
2730
2731 /* pixel clk */
2732 da0 = edp_read(mmss_cc_base + 0x0a0);
2733 da4 = edp_read(mmss_cc_base + 0x0a4);
2734 d32c = edp_read(mmss_cc_base + 0x32c);
2735
2736 /* main link clk */
2737 dc0 = edp_read(mmss_cc_base + 0x0c0);
2738 dc4 = edp_read(mmss_cc_base + 0x0c4);
2739 d330 = edp_read(mmss_cc_base + 0x330);
2740
2741 pr_err("%s: da0=%x da4=%x d32c=%x dc0=%x dc4=%x d330=%x\n", __func__,
2742 (int)da0, (int)da4, (int)d32c, (int)dc0, (int)dc4, (int)d330);
2743
2744}