blob: bfb1153e4049c19d4e3d6225f00cc976ce1dbc2a [file] [log] [blame]
Huaibin Yangcbec39b2014-11-07 13:54:38 -08001/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Arpita Banerjee841fa062013-05-24 14:59:51 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in
10 * the documentation and/or other materials provided with the
11 * distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <debug.h>
31#include <err.h>
32#include <smem.h>
Veera Sundaram Sankaran824e6fa2014-12-09 11:32:58 -080033#include <clock.h>
Arpita Banerjee841fa062013-05-24 14:59:51 -070034#include <msm_panel.h>
Dhaval Patel9f61f132013-07-18 14:45:11 -070035#include <string.h>
36#include <stdlib.h>
Arpita Banerjee841fa062013-05-24 14:59:51 -070037#include <board.h>
38#include <mdp5.h>
Veera Sundaram Sankaran824e6fa2014-12-09 11:32:58 -080039#include <qtimer.h>
Arpita Banerjee841fa062013-05-24 14:59:51 -070040#include <platform/gpio.h>
41#include <mipi_dsi.h>
Huaibin Yangb6fa92b2015-01-28 16:21:37 -080042#include <partition_parser.h>
Arpita Banerjee841fa062013-05-24 14:59:51 -070043
44#include "include/display_resource.h"
45#include "include/panel.h"
46#include "panel_display.h"
47#include "gcdb_display.h"
48#include "target/display.h"
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -070049#include "gcdb_autopll.h"
Arpita Banerjee841fa062013-05-24 14:59:51 -070050
51/*---------------------------------------------------------------------------*/
52/* static */
53/*---------------------------------------------------------------------------*/
54static struct msm_fb_panel_data panel;
55struct panel_struct panelstruct;
56static uint8_t display_enable;
57static struct mdss_dsi_phy_ctrl dsi_video_mode_phy_db;
58
Arpita Banerjee841fa062013-05-24 14:59:51 -070059/*---------------------------------------------------------------------------*/
60/* Extern */
61/*---------------------------------------------------------------------------*/
62extern int msm_display_init(struct msm_fb_panel_data *pdata);
63extern int msm_display_off();
64
65static uint32_t panel_backlight_ctrl(uint8_t enable)
66{
Vineet Bajaj22442342015-04-29 16:55:18 +053067 uint32_t ret = NO_ERROR;
68 if (panelstruct.backlightinfo)
69 ret = target_backlight_ctrl(panelstruct.backlightinfo, enable);
70 return ret;
Arpita Banerjee841fa062013-05-24 14:59:51 -070071}
72
73static uint32_t mdss_dsi_panel_reset(uint8_t enable)
74{
75 uint32_t ret = NO_ERROR;
Vineet Bajaj22442342015-04-29 16:55:18 +053076 if (panelstruct.panelresetseq)
77 ret = target_panel_reset(enable, panelstruct.panelresetseq,
78 &panel.panel_info);
Arpita Banerjee841fa062013-05-24 14:59:51 -070079 return ret;
80}
81
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -070082static uint32_t mdss_dsi_panel_clock(uint8_t enable,
83 struct msm_panel_info *pinfo)
Arpita Banerjee841fa062013-05-24 14:59:51 -070084{
85 uint32_t ret = NO_ERROR;
86
Arpita Banerjeeda0c39a2013-05-24 16:12:45 -070087 ret = calculate_clock_config(pinfo);
Huaibin Yangcbec39b2014-11-07 13:54:38 -080088 if (ret)
89 dprintf(CRITICAL, "Clock calculation failed\n");
90 else
91 ret = target_panel_clock(enable, pinfo);
Arpita Banerjee841fa062013-05-24 14:59:51 -070092
93 return ret;
94}
95
Kuogee Hsieh93bcff62014-08-22 14:02:08 -070096static int mdss_dsi_panel_power(uint8_t enable,
97 struct msm_panel_info *pinfo)
Arpita Banerjee841fa062013-05-24 14:59:51 -070098{
99 int ret = NO_ERROR;
100
101 if (enable) {
Kuogee Hsieh93bcff62014-08-22 14:02:08 -0700102 ret = target_ldo_ctrl(enable, pinfo);
Arpita Banerjee841fa062013-05-24 14:59:51 -0700103 if (ret) {
Jayant Shekharc9611a92013-11-20 16:59:27 +0530104 dprintf(CRITICAL, "LDO control enable failed\n");
Arpita Banerjee841fa062013-05-24 14:59:51 -0700105 return ret;
106 }
107
108 /* Panel Reset */
Jayant Shekharc9611a92013-11-20 16:59:27 +0530109 if (!panelstruct.paneldata->panel_lp11_init) {
110 ret = mdss_dsi_panel_reset(enable);
111 if (ret) {
112 dprintf(CRITICAL, "panel reset failed\n");
113 return ret;
114 }
Arpita Banerjee841fa062013-05-24 14:59:51 -0700115 }
116 dprintf(SPEW, "Panel power on done\n");
117 } else {
Casey Piper1bbd1572013-09-11 16:23:18 -0700118 /* Disable panel and ldo */
Arpita Banerjee841fa062013-05-24 14:59:51 -0700119 ret = mdss_dsi_panel_reset(enable);
120 if (ret) {
Jayant Shekharc9611a92013-11-20 16:59:27 +0530121 dprintf(CRITICAL, "panel reset disable failed\n");
Arpita Banerjee841fa062013-05-24 14:59:51 -0700122 return ret;
123 }
124
Kuogee Hsieh93bcff62014-08-22 14:02:08 -0700125 ret = target_ldo_ctrl(enable, pinfo);
Arpita Banerjee841fa062013-05-24 14:59:51 -0700126 if (ret) {
Jayant Shekharc9611a92013-11-20 16:59:27 +0530127 dprintf(CRITICAL, "ldo control disable failed\n");
Arpita Banerjee841fa062013-05-24 14:59:51 -0700128 return ret;
129 }
130 dprintf(SPEW, "Panel power off done\n");
131 }
132
133 return ret;
134}
135
Ray Zhangeb462f62013-12-03 17:16:08 +0800136static int mdss_dsi_panel_pre_init(void)
Jayant Shekharc9611a92013-11-20 16:59:27 +0530137{
138 int ret = NO_ERROR;
139
Ray Zhangeb462f62013-12-03 17:16:08 +0800140 if (panelstruct.paneldata->panel_lp11_init) {
141 ret = mdss_dsi_panel_reset(1);
142 if (ret) {
143 dprintf(CRITICAL, "panel reset failed\n");
144 return ret;
Jayant Shekharc9611a92013-11-20 16:59:27 +0530145 }
Jayant Shekharc9611a92013-11-20 16:59:27 +0530146 }
147
Ray Zhangeb462f62013-12-03 17:16:08 +0800148 if(panelstruct.paneldata->panel_init_delay)
149 udelay(panelstruct.paneldata->panel_init_delay);
150
151 dprintf(SPEW, "Panel pre init done\n");
Jayant Shekharc9611a92013-11-20 16:59:27 +0530152 return ret;
153}
154
Huaibin Yangb6fa92b2015-01-28 16:21:37 -0800155static int mdss_dsi_dfps_get_pll_codes_cal(struct msm_panel_info *pinfo)
Huaibin Yangcbec39b2014-11-07 13:54:38 -0800156{
157 int ret = NO_ERROR;
158 uint32_t fps_bak;
159 uint32_t i;
160
161 fps_bak = pinfo->mipi.frame_rate;
162
163 for (i = 0; i < pinfo->dfps.panel_dfps.frame_rate_cnt; i++) {
164 int err;
165 pinfo->mipi.frame_rate = pinfo->dfps.panel_dfps.frame_rate[i];
166
167 err = mdss_dsi_panel_clock(1, pinfo);
168 if (!err) {
169 pinfo->dfps.codes_dfps[i].is_valid = 1;
170 pinfo->dfps.codes_dfps[i].frame_rate =
171 pinfo->mipi.frame_rate;
172 pinfo->dfps.codes_dfps[i].frame_rate =
173 pinfo->mipi.frame_rate;
174 pinfo->dfps.codes_dfps[i].clk_rate =
175 pinfo->mipi.dsi_pll_config->vco_clock;
176 pinfo->dfps.codes_dfps[i].pll_codes =
177 pinfo->mipi.pll_codes;
178
179 mdss_dsi_panel_clock(0, pinfo);
180 } else {
181 ret = err;
182 pinfo->dfps.codes_dfps[i].is_valid = 0;
183 dprintf(CRITICAL, "frame_rate=%d failed!\n",
184 pinfo->mipi.frame_rate);
185 }
186 }
187
188 pinfo->mipi.frame_rate = fps_bak;
189
190 return ret;
191}
192
Huaibin Yangb6fa92b2015-01-28 16:21:37 -0800193static int mdss_dsi_dfps_get_stored_pll_codes(struct msm_panel_info *pinfo)
194{
195 int ret = NO_ERROR;
196 int index;
197 unsigned long long ptn;
198 uint32_t blocksize;
199 struct dfps_info *dfps;
200
201 index = partition_get_index("splash");
Casey Piper69f95682015-03-30 16:19:45 -0700202 if (index == INVALID_PTN) {
203 dprintf(INFO, "%s: splash partition table not found\n", __func__);
204 ret = NO_ERROR;
Huaibin Yangb6fa92b2015-01-28 16:21:37 -0800205 goto splash_err;
206 }
207
208 ptn = partition_get_offset(index);
209 if (ptn == 0) {
210 dprintf(CRITICAL, "ERROR: splash Partition invalid offset\n");
211 ret = ERROR;
212 goto splash_err;
213 }
214
Channagoud Kadabi7f666372015-02-24 14:37:32 -0800215 mmc_set_lun(partition_get_lun(index));
216
Huaibin Yangb6fa92b2015-01-28 16:21:37 -0800217 blocksize = mmc_get_device_blocksize();
218 if (blocksize == 0) {
219 dprintf(CRITICAL, "ERROR:splash Partition invalid blocksize\n");
220 ret = ERROR;
221 goto splash_err;
222 }
223
224 dfps = (struct dfps_info *)memalign(CACHE_LINE, ROUNDUP(PAGE_SIZE,
225 CACHE_LINE));
226 if (!dfps) {
227 dprintf(CRITICAL, "ERROR:splash Partition invalid memory\n");
228 ret = ERROR;
229 goto splash_err;
230 }
231
232 if (mmc_read(ptn, (uint32_t *) dfps, blocksize)) {
233 dprintf(CRITICAL, "mmc read splash failure%d\n", PAGE_SIZE);
234 ret = ERROR;
235 free(dfps);
236 goto splash_err;
237 }
238
239 dprintf(SPEW, "enable=%d cnt=%d\n", dfps->panel_dfps.enabled,
240 dfps->panel_dfps.frame_rate_cnt);
241
242 if (!dfps->panel_dfps.enabled || dfps->panel_dfps.frame_rate_cnt >
243 DFPS_MAX_FRAME_RATE) {
244 ret = ERROR;
245 free(dfps);
246 goto splash_err;
247 }
248
249 pinfo->dfps = *dfps;
250 free(dfps);
251
252splash_err:
253 return ret;
254}
255
256static int mdss_dsi_dfps_store_pll_codes(struct msm_panel_info *pinfo)
257{
258 int ret = NO_ERROR;
259 int index;
260 unsigned long long ptn;
261
262 index = partition_get_index("splash");
Casey Piper69f95682015-03-30 16:19:45 -0700263 if (index == INVALID_PTN) {
264 dprintf(INFO, "%s: splash partition table not found\n", __func__);
265 ret = NO_ERROR;
Huaibin Yangb6fa92b2015-01-28 16:21:37 -0800266 goto store_err;
267 }
268
269 ptn = partition_get_offset(index);
270 if (ptn == 0) {
271 dprintf(CRITICAL, "ERROR: splash Partition invalid offset\n");
272 ret = ERROR;
273 goto store_err;
274 }
275
Channagoud Kadabi7f666372015-02-24 14:37:32 -0800276 mmc_set_lun(partition_get_lun(index));
277
Huaibin Yangb6fa92b2015-01-28 16:21:37 -0800278 ret = mmc_write(ptn, sizeof(uint32_t), &pinfo->dfps);
279 if (ret)
280 dprintf(CRITICAL, "mmc write failed!\n");
281
282store_err:
283 return ret;
284}
285
Huaibin Yangcbec39b2014-11-07 13:54:38 -0800286static int mdss_dsi_mipi_dfps_config(struct msm_panel_info *pinfo)
287{
288 int ret = NO_ERROR;
289
290 if (!pinfo)
291 return ERROR;
292
293 if (!pinfo->dfps.panel_dfps.enabled)
294 goto dfps_done;
295
Huaibin Yangb6fa92b2015-01-28 16:21:37 -0800296 if (!mdss_dsi_dfps_get_stored_pll_codes(pinfo)) {
297 dprintf(SPEW, "Found stored PLL codes!\n");
298 goto dfps_cal_done;
299 }
Huaibin Yangcbec39b2014-11-07 13:54:38 -0800300
Huaibin Yangb6fa92b2015-01-28 16:21:37 -0800301 ret = mdss_dsi_dfps_get_pll_codes_cal(pinfo);
302 if (ret) {
303 dprintf(CRITICAL, "Cannot cal pll codes!\n");
304 goto dfps_done;
305 } else {
306 dprintf(SPEW, "Calibrate all pll codes!\n");
307 }
308
309 ret = mdss_dsi_dfps_store_pll_codes(pinfo);
310 if (ret)
311 dprintf(CRITICAL, "Cannot store pll codes!\n");
312
313dfps_cal_done:
Huaibin Yangb9f15e52015-01-22 10:34:47 -0800314 if (pinfo->dfps.dfps_fb_base)
315 memcpy(pinfo->dfps.dfps_fb_base, &pinfo->dfps,
316 sizeof(struct dfps_info));
Huaibin Yangcbec39b2014-11-07 13:54:38 -0800317dfps_done:
318 return ret;
319}
320
Casey Piper1bbd1572013-09-11 16:23:18 -0700321static int mdss_dsi_bl_enable(uint8_t enable)
322{
323 int ret = NO_ERROR;
324
325 ret = panel_backlight_ctrl(enable);
326 if (ret)
327 dprintf(CRITICAL, "Backlight %s failed\n", enable ? "enable" :
328 "disable");
329 return ret;
330}
331
Kuogee Hsieh80b8a6c2014-06-09 17:25:38 -0700332static void mdss_edp_panel_init(struct msm_panel_info *pinfo)
333{
334 return target_edp_panel_init(pinfo);
335}
336
337static uint32_t mdss_edp_panel_clock(uint8_t enable,
338 struct msm_panel_info *pinfo)
339{
340 return target_edp_panel_clock(enable, pinfo);
341}
342
343static uint32_t mdss_edp_panel_enable(void)
344{
345 return target_edp_panel_enable();
346}
347
348static uint32_t mdss_edp_panel_disable(void)
349{
350 return target_edp_panel_disable();
351}
352
Kuogee Hsieh93bcff62014-08-22 14:02:08 -0700353static int mdss_edp_panel_power(uint8_t enable,
354 struct msm_panel_info *pinfo)
Arpita Banerjee841fa062013-05-24 14:59:51 -0700355{
Casey Piperc574e082013-09-05 14:54:42 -0700356 int ret = NO_ERROR;
Arpita Banerjee841fa062013-05-24 14:59:51 -0700357
Kuogee Hsieh80b8a6c2014-06-09 17:25:38 -0700358 if (enable) {
Kuogee Hsieh93bcff62014-08-22 14:02:08 -0700359 ret = target_ldo_ctrl(enable, pinfo);
Kuogee Hsieh80b8a6c2014-06-09 17:25:38 -0700360 if (ret) {
361 dprintf(CRITICAL, "LDO control enable failed\n");
362 return ret;
363 }
364
365 ret = mdss_edp_panel_enable();
366 if (ret) {
367 dprintf(CRITICAL, "%s: panel enable failed\n", __func__);
368 return ret;
369 }
370 dprintf(SPEW, "EDP Panel power on done\n");
371 } else {
372 /* Disable panel and ldo */
373 ret = mdss_edp_panel_disable();
374 if (ret) {
375 dprintf(CRITICAL, "%s: panel disable failed\n", __func__);
376 return ret;
377 }
378
Kuogee Hsieh93bcff62014-08-22 14:02:08 -0700379 ret = target_ldo_ctrl(enable, pinfo);
Kuogee Hsieh80b8a6c2014-06-09 17:25:38 -0700380 if (ret) {
381 dprintf(CRITICAL, "%s: ldo control disable failed\n", __func__);
382 return ret;
383 }
384 dprintf(SPEW, "EDP Panel power off done\n");
385 }
386
387 return ret;
388}
389
390static int mdss_edp_bl_enable(uint8_t enable)
391{
392 int ret = NO_ERROR;
393
394 ret = target_edp_bl_ctrl(enable);
395 if (ret)
396 dprintf(CRITICAL, "Backlight %s failed\n", enable ? "enable" :
397 "disable");
398 return ret;
399}
400
Vineet Bajajc2272462015-05-07 17:35:03 +0530401static int mdss_dsi2HDMI_config (struct msm_panel_info *pinfo)
402{
403 return target_display_dsi2hdmi_config(pinfo);
404}
405
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530406struct panel_struct mdss_dsi_get_panel_data(void)
407{
408 return panelstruct;
409}
410
Kuogee Hsieh80b8a6c2014-06-09 17:25:38 -0700411int gcdb_display_init(const char *panel_name, uint32_t rev, void *base)
412{
413 int ret = NO_ERROR;
414 int pan_type;
415
Dhaval Patel8b9a5822015-03-16 13:01:26 -0700416 dsi_video_mode_phy_db.pll_type = DSI_PLL_TYPE_28NM;
Kuogee Hsieh80b8a6c2014-06-09 17:25:38 -0700417 pan_type = oem_panel_select(panel_name, &panelstruct, &(panel.panel_info),
418 &dsi_video_mode_phy_db);
419
420 if (pan_type == PANEL_TYPE_DSI) {
Dhaval Patel7709c412015-05-12 10:09:41 -0700421 target_dsi_phy_config(&dsi_video_mode_phy_db);
Kuogee Hsieh80b8a6c2014-06-09 17:25:38 -0700422 if (dsi_panel_init(&(panel.panel_info), &panelstruct)) {
423 dprintf(CRITICAL, "DSI panel init failed!\n");
424 ret = ERROR;
425 goto error_gcdb_display_init;
426 }
427
428 panel.panel_info.mipi.mdss_dsi_phy_db = &dsi_video_mode_phy_db;
429 panel.pll_clk_func = mdss_dsi_panel_clock;
Huaibin Yangcbec39b2014-11-07 13:54:38 -0800430 panel.dfps_func = mdss_dsi_mipi_dfps_config;
Kuogee Hsieh80b8a6c2014-06-09 17:25:38 -0700431 panel.power_func = mdss_dsi_panel_power;
432 panel.pre_init_func = mdss_dsi_panel_pre_init;
433 panel.bl_func = mdss_dsi_bl_enable;
Vineet Bajajc2272462015-05-07 17:35:03 +0530434 panel.dsi2HDMI_config = mdss_dsi2HDMI_config;
Huaibin Yangb9f15e52015-01-22 10:34:47 -0800435 /*
436 * If dfps enabled, reserve fb memory to store pll
437 * codes and pass pll codes values to kernel.
438 */
439 if (panel.panel_info.dfps.panel_dfps.enabled) {
440 panel.panel_info.dfps.dfps_fb_base = base;
441 base += DFPS_PLL_CODES_SIZE;
442 dprintf(SPEW, "fb_base=0x%p!\n", base);
443 }
444
Kuogee Hsieh80b8a6c2014-06-09 17:25:38 -0700445 panel.fb.base = base;
446 panel.fb.width = panel.panel_info.xres;
447 panel.fb.height = panel.panel_info.yres;
448 panel.fb.stride = panel.panel_info.xres;
449 panel.fb.bpp = panel.panel_info.bpp;
450 panel.fb.format = panel.panel_info.mipi.dst_format;
451 } else if (pan_type == PANEL_TYPE_EDP) {
452 mdss_edp_panel_init(&(panel.panel_info));
453 /* prepare func is set up at edp_panel_init */
454 panel.clk_func = mdss_edp_panel_clock;
455 panel.power_func = mdss_edp_panel_power;
456 panel.bl_func = mdss_edp_bl_enable;
457 panel.fb.format = FB_FORMAT_RGB888;
458 } else {
Arpita Banerjee841fa062013-05-24 14:59:51 -0700459 dprintf(CRITICAL, "Target panel init not found!\n");
Casey Piperc574e082013-09-05 14:54:42 -0700460 ret = ERR_NOT_SUPPORTED;
461 goto error_gcdb_display_init;
Arpita Banerjee841fa062013-05-24 14:59:51 -0700462
Arpita Banerjee841fa062013-05-24 14:59:51 -0700463 }
464
Arpita Banerjee841fa062013-05-24 14:59:51 -0700465 panel.fb.base = base;
Arpita Banerjee841fa062013-05-24 14:59:51 -0700466 panel.mdp_rev = rev;
467
Casey Piperc574e082013-09-05 14:54:42 -0700468 ret = msm_display_init(&panel);
Arpita Banerjee841fa062013-05-24 14:59:51 -0700469
Casey Piperc574e082013-09-05 14:54:42 -0700470error_gcdb_display_init:
471 display_enable = ret ? 0 : 1;
472 return ret;
Arpita Banerjee841fa062013-05-24 14:59:51 -0700473}
474
475void gcdb_display_shutdown(void)
476{
477 if (display_enable)
478 msm_display_off();
479}