blob: 771fb4ff545646bddb14ea1027ab64778b393ccb [file] [log] [blame]
Umang Agrawal4b4e51a2017-12-19 12:10:56 +05301/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +05302 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * 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
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the 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 "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30
31#include <debug.h>
32#include <string.h>
33#include <smem.h>
34#include <err.h>
35#include <msm_panel.h>
36#include <mipi_dsi.h>
37#include <pm8x41.h>
38#include <pm8x41_wled.h>
39#include <qpnp_wled.h>
Umang Agrawal4b4e51a2017-12-19 12:10:56 +053040#include <qpnp_lcdb.h>
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +053041#include <board.h>
42#include <mdp5.h>
43#include <scm.h>
44#include <regulator.h>
45#include <platform/clock.h>
46#include <platform/gpio.h>
47#include <platform/iomap.h>
48#include <target/display.h>
49#include <mipi_dsi_autopll_thulium.h>
50#include <qtimer.h>
51#include <platform.h>
Umang Agrawal4b4e51a2017-12-19 12:10:56 +053052#include <target.h>
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +053053
54#include "include/panel.h"
55#include "include/display_resource.h"
56#include "gcdb_display.h"
57
58#define MAX_POLL_READS 15
59#define POLL_TIMEOUT_US 1000
60#define STRENGTH_SIZE_IN_BYTES 10
61#define REGULATOR_SIZE_IN_BYTES 5
62#define LANE_SIZE_IN_BYTES 20
Rashi Bindra214a7352018-02-02 11:23:18 +053063#define PWM_DUTY_US 13
64#define PWM_PERIOD_US 27
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +053065/*---------------------------------------------------------------------------*/
66/* GPIO configuration */
67/*---------------------------------------------------------------------------*/
68static struct gpio_pin reset_gpio = {
69 "msmgpio", 61, 3, 1, 0, 1
70};
71
72static struct gpio_pin bkl_gpio = {
73 "msmgpio", 59, 3, 1, 0, 1
74};
75
Padmanabhan Komanduruc2a81e92016-02-03 16:00:42 +053076static struct gpio_pin enable_gpio = {
77 "msmgpio", 12, 3, 1, 0, 1
78};
79
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +053080
81#define VCO_DELAY_USEC 1000
82#define GPIO_STATE_LOW 0
83#define GPIO_STATE_HIGH 2
84#define RESET_GPIO_SEQ_LEN 3
85#define PMIC_WLED_SLAVE_ID 3
86
87static uint32_t dsi_pll_lock_status(uint32_t pll_base, uint32_t off,
88 uint32_t bit)
89{
90 uint32_t cnt, status;
91
92 /* check pll lock first */
93 for (cnt = 0; cnt < MAX_POLL_READS; cnt++) {
94 status = readl(pll_base + off);
95 dprintf(SPEW, "%s: pll_base=%x cnt=%d status=%x\n",
96 __func__, pll_base, cnt, status);
97 status &= BIT(bit); /* bit 5 */
98 if (status)
99 break;
100 udelay(POLL_TIMEOUT_US);
101 }
102
103 return status;
104}
105
106static uint32_t dsi_pll_enable_seq(uint32_t phy_base, uint32_t pll_base)
107{
108 uint32_t pll_locked;
109
110 writel(0x10, phy_base + 0x45c);
111 writel(0x01, phy_base + 0x48);
112
113 pll_locked = dsi_pll_lock_status(pll_base, 0xcc, 5);
114 if (pll_locked)
115 pll_locked = dsi_pll_lock_status(pll_base, 0xcc, 0);
116
117 if (!pll_locked)
118 dprintf(ERROR, "%s: DSI PLL lock failed\n", __func__);
119 else
120 dprintf(SPEW, "%s: DSI PLL lock Success\n", __func__);
121
122 return pll_locked;
123}
124
125static int wled_backlight_ctrl(uint8_t enable)
126{
127 uint8_t slave_id = PMIC_WLED_SLAVE_ID; /* pmi */
128
129 pm8x41_wled_config_slave_id(slave_id);
Umang Agrawal4b4e51a2017-12-19 12:10:56 +0530130 if (target_get_pmic() == PMIC_IS_PMI632) {
131 qpnp_lcdb_enable(enable);
Rashi Bindra214a7352018-02-02 11:23:18 +0530132 } else {
Umang Agrawal4b4e51a2017-12-19 12:10:56 +0530133 qpnp_wled_enable_backlight(enable);
134 qpnp_ibb_enable(enable);
135 }
Rashi Bindra214a7352018-02-02 11:23:18 +0530136
137 return NO_ERROR;
138}
139
140static int pwm_backlight_ctrl(uint8_t enable)
141{
142 if(enable) {
143 pm_pwm_enable(false);
144 pm_pwm_config(PWM_DUTY_US, PWM_PERIOD_US);
145 pm_pwm_enable(true);
146 } else {
147 pm_pwm_enable(false);
148 }
149
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530150 return NO_ERROR;
151}
152
153int target_backlight_ctrl(struct backlight *bl, uint8_t enable)
154{
155 uint32_t ret = NO_ERROR;
156
157 if (bl->bl_interface_type == BL_DCS)
158 return ret;
159
Rashi Bindra214a7352018-02-02 11:23:18 +0530160 if(target_get_pmic() == PMIC_IS_PMI632) {
161 ret = pwm_backlight_ctrl(enable);
162 } else {
163 ret = wled_backlight_ctrl(enable);
164 }
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530165 return ret;
166}
167
168
169int target_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
170{
171 int32_t ret = 0, flags, dsi_phy_pll_out;
172 struct dfps_pll_codes *pll_codes = &pinfo->mipi.pll_codes;
173 struct mdss_dsi_pll_config *pll_data;
174 dprintf(SPEW, "target_panel_clock\n");
175
176 pll_data = pinfo->mipi.dsi_pll_config;
177
178 if (pinfo->dest == DISPLAY_2) {
179 flags = MMSS_DSI_CLKS_FLAG_DSI1;
180 if (pinfo->mipi.dual_dsi)
181 flags |= MMSS_DSI_CLKS_FLAG_DSI0;
182 } else {
183 flags = MMSS_DSI_CLKS_FLAG_DSI0;
184 if (pinfo->mipi.dual_dsi)
185 flags |= MMSS_DSI_CLKS_FLAG_DSI1;
186 }
187
188 if (enable) {
189 mdp_gdsc_ctrl(enable);
190 mdss_bus_clocks_enable();
191 mdp_clock_enable();
192 ret = restore_secure_cfg(SECURE_DEVICE_MDSS);
193 if (ret) {
194 dprintf(CRITICAL,
195 "%s: Failed to restore MDP security configs",
196 __func__);
197 mdp_clock_disable();
198 mdss_bus_clocks_disable();
199 mdp_gdsc_ctrl(0);
200 return ret;
201 }
202
203 mdss_dsi_auto_pll_thulium_config(pinfo);
204
205 if (!dsi_pll_enable_seq(pinfo->mipi.phy_base,
206 pinfo->mipi.pll_base)) {
207 ret = ERROR;
208 dprintf(CRITICAL, "PLL failed to lock!\n");
209 mmss_dsi_clock_disable(flags);
210 mdp_clock_disable();
211 mdss_bus_clocks_disable();
212 return ret;
213 }
214
215 pll_codes->codes[0] = readl_relaxed(pinfo->mipi.pll_base +
216 MMSS_DSI_PHY_PLL_CORE_KVCO_CODE);
217 pll_codes->codes[1] = readl_relaxed(pinfo->mipi.pll_base +
218 MMSS_DSI_PHY_PLL_CORE_VCO_TUNE);
219 dprintf(SPEW, "codes %d %d\n", pll_codes->codes[0],
220 pll_codes->codes[1]);
221
222 if (pinfo->mipi.use_dsi1_pll)
223 dsi_phy_pll_out = DSI1_PHY_PLL_OUT;
224 else
225 dsi_phy_pll_out = DSI0_PHY_PLL_OUT;
226 mmss_dsi_clock_enable(dsi_phy_pll_out, flags,
227 pll_data->pclk_m, pll_data->pclk_n, pll_data->pclk_d);
228
229 } else if(!target_cont_splash_screen()) {
230 /* stop pll */
231 writel(0x0, pinfo->mipi.phy_base + 0x48);
232
233 mmss_dsi_clock_disable(flags);
234 mdp_clock_disable();
235 mdss_bus_clocks_disable();
236 mdp_gdsc_ctrl(enable);
237 }
238
239 return 0;
240
241}
242
243int target_panel_reset(uint8_t enable, struct panel_reset_sequence *resetseq,
244 struct msm_panel_info *pinfo)
245{
246 int ret = NO_ERROR;
Mao Flynna80980c2016-03-03 09:46:31 +0800247 uint32_t hw_id = board_hardware_id();
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530248
249 if (enable) {
250
Padmanabhan Komanduruc2a81e92016-02-03 16:00:42 +0530251 if (pinfo->mipi.use_enable_gpio) {
252 gpio_tlmm_config(enable_gpio.pin_id, 0,
253 enable_gpio.pin_direction, enable_gpio.pin_pull,
254 enable_gpio.pin_strength,
255 enable_gpio.pin_state);
256
257 gpio_set_dir(enable_gpio.pin_id, 2);
258 }
259
Mao Flynna80980c2016-03-03 09:46:31 +0800260 if (hw_id != HW_PLATFORM_QRD) {
261 gpio_tlmm_config(bkl_gpio.pin_id, 0,
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530262 bkl_gpio.pin_direction, bkl_gpio.pin_pull,
263 bkl_gpio.pin_strength, bkl_gpio.pin_state);
264
Mao Flynna80980c2016-03-03 09:46:31 +0800265 gpio_set_dir(bkl_gpio.pin_id, 2);
266 }
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530267
268 gpio_tlmm_config(reset_gpio.pin_id, 0,
269 reset_gpio.pin_direction, reset_gpio.pin_pull,
270 reset_gpio.pin_strength, reset_gpio.pin_state);
271
272 gpio_set_dir(reset_gpio.pin_id, 2);
273
274 /* reset */
275 for (int i = 0; i < RESET_GPIO_SEQ_LEN; i++) {
276 if (resetseq->pin_state[i] == GPIO_STATE_LOW)
277 gpio_set_dir(reset_gpio.pin_id, GPIO_STATE_LOW);
278 else
279 gpio_set_dir(reset_gpio.pin_id, GPIO_STATE_HIGH);
280 mdelay(resetseq->sleep[i]);
281 }
282
283 } else if(!target_cont_splash_screen()) {
284 gpio_set_dir(reset_gpio.pin_id, 0);
Padmanabhan Komanduruc2a81e92016-02-03 16:00:42 +0530285 gpio_set_dir(enable_gpio.pin_id, 0);
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530286 }
287
288 return ret;
289}
290
291static void wled_init(struct msm_panel_info *pinfo)
292{
293 struct qpnp_wled_config_data config = {0};
294 struct labibb_desc *labibb;
295 int display_type = 0;
P.V. Phani Kumar3dd859b2016-02-12 15:46:51 +0530296 bool swire_control = 0;
297 bool wled_avdd_control = 0;
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530298
299 labibb = pinfo->labibb;
300
301 if (labibb)
302 display_type = labibb->amoled_panel;
303
P.V. Phani Kumar3dd859b2016-02-12 15:46:51 +0530304 if (display_type) {
305 swire_control = labibb->swire_control;
306 wled_avdd_control = true;
307 } else {
308 swire_control = false;
309 wled_avdd_control = false;
310 }
311
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530312 config.display_type = display_type;
313 config.lab_init_volt = 4600000; /* fixed, see pmi register */
314 config.ibb_init_volt = 1400000; /* fixed, see pmi register */
P.V. Phani Kumar3dd859b2016-02-12 15:46:51 +0530315 config.lab_ibb_swire_control = swire_control;
316 config.wled_avdd_control = wled_avdd_control;
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530317
P.V. Phani Kumar3dd859b2016-02-12 15:46:51 +0530318 if (!swire_control) {
319 if (labibb && labibb->force_config) {
320 config.lab_min_volt = labibb->lab_min_volt;
321 config.lab_max_volt = labibb->lab_max_volt;
322 config.ibb_min_volt = labibb->ibb_min_volt;
323 config.ibb_max_volt = labibb->ibb_max_volt;
324 config.pwr_up_delay = labibb->pwr_up_delay;
325 config.pwr_down_delay = labibb->pwr_down_delay;
326 config.ibb_discharge_en = labibb->ibb_discharge_en;
327 } else {
328 /* default */
329 config.pwr_up_delay = 3;
330 config.pwr_down_delay = 3;
331 config.ibb_discharge_en = 1;
332 if (display_type) { /* amoled */
333 config.lab_min_volt = 4600000;
334 config.lab_max_volt = 4600000;
335 config.ibb_min_volt = 4000000;
336 config.ibb_max_volt = 4000000;
337 } else { /* lcd */
338 config.lab_min_volt = 5500000;
339 config.lab_max_volt = 5500000;
340 config.ibb_min_volt = 5500000;
341 config.ibb_max_volt = 5500000;
342 }
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530343 }
344 }
345
Narender Ankam59423d52018-05-30 17:44:46 +0530346 if (target_get_pmic() == PMIC_IS_PMI632) {
347 config.pwr_up_delay = 1;
348 config.pwr_down_delay = 0;
349 }
350
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530351 dprintf(SPEW, "%s: %d %d %d %d %d %d %d %d %d %d\n", __func__,
352 config.display_type,
353 config.lab_min_volt, config.lab_max_volt,
354 config.ibb_min_volt, config.ibb_max_volt,
355 config.lab_init_volt, config.ibb_init_volt,
356 config.pwr_up_delay, config.pwr_down_delay,
357 config.ibb_discharge_en);
358
359 /* QPNP WLED init for display backlight */
360 pm8x41_wled_config_slave_id(PMIC_WLED_SLAVE_ID);
361
Umang Agrawal4b4e51a2017-12-19 12:10:56 +0530362 if (target_get_pmic() == PMIC_IS_PMI632)
363 qpnp_lcdb_init(&config);
364 else
365 qpnp_wled_init(&config);
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530366}
367
368int target_dsi_phy_config(struct mdss_dsi_phy_ctrl *phy_db)
369{
370 memcpy(phy_db->strength, panel_strength_ctrl, STRENGTH_SIZE_IN_BYTES *
371 sizeof(uint32_t));
372 memcpy(phy_db->regulator, panel_regulator_settings,
373 REGULATOR_SIZE_IN_BYTES * sizeof(uint32_t));
374 memcpy(phy_db->laneCfg, panel_lane_config, LANE_SIZE_IN_BYTES);
375 return NO_ERROR;
376}
377
378
379int target_display_get_base_offset(uint32_t base)
380{
381 return 0;
382}
383
384int target_ldo_ctrl(uint8_t enable, struct msm_panel_info *pinfo)
385{
Mao Flynna80980c2016-03-03 09:46:31 +0800386 uint32_t ldo_num = REG_LDO6 | REG_LDO3 | REG_SMPS3;
387 uint32_t hw_id = board_hardware_id();
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530388
389 if (enable) {
Mao Flynna80980c2016-03-03 09:46:31 +0800390 if (hw_id != HW_PLATFORM_QRD)
391 ldo_num |= REG_LDO17;
392
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530393 regulator_enable(ldo_num);
394 mdelay(10);
395 wled_init(pinfo);
Umang Agrawal4b4e51a2017-12-19 12:10:56 +0530396 if (target_get_pmic() == PMIC_IS_PMI632)
397 qpnp_lcdb_enable(true);
398 else
399 qpnp_ibb_enable(true); /*5V boost*/
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530400 mdelay(50);
401 } else {
402 /*
403 * LDO6, LDO3 and SMPS3 are shared with other subsystems.
404 * Do not disable them.
405 */
Mao Flynna80980c2016-03-03 09:46:31 +0800406 if (hw_id != HW_PLATFORM_QRD)
407 regulator_disable(REG_LDO17);
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530408 }
409
410 return NO_ERROR;
411}
412
413bool target_display_panel_node(char *pbuf, uint16_t buf_size)
414{
Ashish Garg59607c52016-09-30 16:10:57 +0530415 int prefix_string_len = strlen(DISPLAY_CMDLINE_PREFIX);
416 bool ret = true;
417 struct oem_panel_data oem = mdss_dsi_get_oem_data();
Ashish Garg59607c52016-09-30 16:10:57 +0530418
Ashish Garg4094dcc2017-05-24 12:55:53 +0530419 /*
420 * if disable config is passed irrespective of
421 * platform type, disable DSI controllers
422 */
423 if (!strcmp(oem.panel, DISABLE_PANEL_CONFIG)) {
424 if (buf_size < (prefix_string_len +
425 strlen(DISABLE_PANEL_STRING))) {
426 dprintf(CRITICAL, "Disable command line argument \
427 is greater than buffer size\n");
428 return false;
429 }
430 strlcpy(pbuf, DISPLAY_CMDLINE_PREFIX, buf_size);
431 buf_size -= prefix_string_len;
432 pbuf += prefix_string_len;
433 strlcpy(pbuf, DISABLE_PANEL_STRING, buf_size);
Ashish Garg59607c52016-09-30 16:10:57 +0530434 } else {
435 ret = gcdb_display_cmdline_arg(pbuf, buf_size);
436 }
437
438 return ret;
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530439}
440
441void target_display_init(const char *panel_name)
442{
443 struct oem_panel_data oem;
444 int32_t ret = 0;
445 uint32_t panel_loop = 0;
446
447 set_panel_cmd_string(panel_name);
448 oem = mdss_dsi_get_oem_data();
449
450 if (!strcmp(oem.panel, NO_PANEL_CONFIG)
451 || !strcmp(oem.panel, SIM_VIDEO_PANEL)
Sandeep Panda45d8d0a2016-03-16 12:39:57 +0530452 || !strcmp(oem.panel, SIM_DUALDSI_VIDEO_PANEL)
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530453 || !strcmp(oem.panel, SIM_CMD_PANEL)
Sandeep Panda45d8d0a2016-03-16 12:39:57 +0530454 || !strcmp(oem.panel, SIM_DUALDSI_CMD_PANEL)
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530455 || oem.skip) {
456 dprintf(INFO, "Selected panel: %s\nSkip panel configuration\n",
457 oem.panel);
Sandeep Panda45d8d0a2016-03-16 12:39:57 +0530458 oem.cont_splash = false;
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530459 }
460
Ashish Garg4094dcc2017-05-24 12:55:53 +0530461 /* skip splash screen completely not just cont splash */
Rashi Bindra60d54d52018-02-02 17:17:42 +0530462 if (!strcmp(oem.panel, DISABLE_PANEL_CONFIG)) {
463 dprintf(INFO, "%s: disable splash screen \n",
464 __func__);
Ashish Garg59607c52016-09-30 16:10:57 +0530465 return;
466 }
467
Padmanabhan Komanduru0104a892016-01-22 16:58:10 +0530468 do {
469 target_force_cont_splash_disable(false);
470 ret = gcdb_display_init(oem.panel, MDP_REV_50, (void *)MIPI_FB_ADDR);
471 if (!ret || ret == ERR_NOT_SUPPORTED) {
472 break;
473 } else {
474 target_force_cont_splash_disable(true);
475 msm_display_off();
476 }
477 } while (++panel_loop <= oem_panel_max_auto_detect_panels());
478
479 if (!oem.cont_splash) {
480 dprintf(INFO, "Forcing continuous splash disable\n");
481 target_force_cont_splash_disable(true);
482 }
483}
484
485void target_display_shutdown(void)
486{
487 gcdb_display_shutdown();
488}