blob: e558b6901aa2c6c298221e6f90b7c01a9c276eaf [file] [log] [blame]
Jeevan Shriram2d3500b2014-12-29 16:25:06 -08001/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
Dhaval Patel019057a2014-08-12 13:52:25 -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>
Veera Sundaram Sankaran089f70d2014-12-09 14:17:05 -080031#include <string.h>
Dhaval Patel019057a2014-08-12 13:52:25 -070032#include <smem.h>
33#include <err.h>
34#include <msm_panel.h>
35#include <mipi_dsi.h>
36#include <pm8x41.h>
37#include <pm8x41_wled.h>
38#include <qpnp_wled.h>
39#include <board.h>
40#include <mdp5.h>
41#include <scm.h>
42#include <endian.h>
Veera Sundaram Sankaran089f70d2014-12-09 14:17:05 -080043#include <regulator.h>
44#include <qtimer.h>
45#include <arch/defines.h>
Dhaval Patel019057a2014-08-12 13:52:25 -070046#include <platform/gpio.h>
47#include <platform/clock.h>
48#include <platform/iomap.h>
49#include <target/display.h>
50#include "include/panel.h"
51#include "include/display_resource.h"
Veera Sundaram Sankaran089f70d2014-12-09 14:17:05 -080052#include "gcdb_display.h"
Dhaval Patel019057a2014-08-12 13:52:25 -070053
54#define HFPLL_LDO_ID 12
55
56#define GPIO_STATE_LOW 0
57#define GPIO_STATE_HIGH 2
58#define RESET_GPIO_SEQ_LEN 3
59
60#define PWM_DUTY_US 13
61#define PWM_PERIOD_US 27
62#define PMIC_WLED_SLAVE_ID 3
63#define PMIC_MPP_SLAVE_ID 2
64
Veera Sundaram Sankaran089f70d2014-12-09 14:17:05 -080065/*---------------------------------------------------------------------------*/
66/* GPIO configuration */
67/*---------------------------------------------------------------------------*/
68static struct gpio_pin reset_gpio = {
69 "msmgpio", 78, 3, 1, 0, 1
70};
71
72static struct gpio_pin lcd_reg_en = { /* boost regulator */
73 "pm8994_gpios", 14, 3, 1, 0, 1
74};
75
76static struct gpio_pin bklt_gpio = { /* lcd_bklt_reg_en */
77 "pmi8994_gpios", 2, 3, 1, 0, 1
78};
79
Dhaval Patel019057a2014-08-12 13:52:25 -070080static uint32_t dsi_pll_20nm_enable_seq(uint32_t pll_base)
81{
82 uint32_t pll_locked;
Jeevan Shriram5a9f8f42014-12-14 14:56:14 -080083 /* MDSS_DSI_0_PHY_DSIPHY_CTRL_1 */
84 writel(0x00, pll_base + 0x374);
Dhaval Patel019057a2014-08-12 13:52:25 -070085 dmb();
Jeevan Shriram5a9f8f42014-12-14 14:56:14 -080086 /* MDSS_DSI_0_PHY_DSIPHY_CTRL_0 */
87 writel(0x7f, pll_base + 0x370);
88 dmb();
89 pll_locked = mdss_dsi_pll_20nm_lock_status(pll_base);
90 if (!pll_locked)
91 dprintf(INFO, "%s: DSI PLL lock failed\n", __func__);
92 else
93 dprintf(INFO, "%s: DSI PLL lock Success\n", __func__);
Dhaval Patel019057a2014-08-12 13:52:25 -070094
95 return pll_locked;
96}
97
98static int msm8994_wled_backlight_ctrl(uint8_t enable)
99{
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700100 uint8_t slave_id = 3; /* pmi */
Dhaval Patel019057a2014-08-12 13:52:25 -0700101
Veera Sundaram Sankaranf9ddd6c2014-12-02 11:04:52 -0800102 pm8x41_wled_config_slave_id(slave_id);
103 qpnp_wled_enable_backlight(enable);
Dhaval Patel019057a2014-08-12 13:52:25 -0700104 qpnp_ibb_enable(enable);
105 return NO_ERROR;
106}
107
108static int msm8994_pwm_backlight_ctrl(uint8_t enable)
109{
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700110 uint8_t slave_id = 3; /* lpg at pmi */
111
112 if (enable) {
113 /* mpp-1 had been configured already */
114 /* lpg channel 4 */
115
116 /* LPG_ENABLE_CONTROL */
117 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x0);
118 mdelay(100);
119
120 /* LPG_VALUE_LSB, duty cycle = 0x80/0x200 = 1/4 */
121 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x44, 0x80);
122 /* LPG_VALUE_MSB */
123 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x45, 0x00);
124 /* LPG_PWM_SYNC */
125 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x47, 0x01);
126
127 /* LPG_PWM_SIZE_CLK, */
128 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x41, 0x13);
129 /* LPG_PWM_FREQ_PREDIV */
130 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x42, 0x02);
131 /* LPG_PWM_TYPE_CONFIG */
132 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x43, 0x20);
133 /* LPG_ENABLE_CONTROL */
134 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x04);
135
136 /* SEC_ACCESS */
137 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0xD0, 0xA5);
138 /* DTEST4, OUT_HI */
139 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0xE5, 0x01);
140 /* LPG_ENABLE_CONTROL */
141 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0xA4);
142 } else {
143 /* LPG_ENABLE_CONTROL */
144 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x0);
145 }
146
147 return NO_ERROR;
148}
149
150void lcd_bklt_reg_enable(void)
151{
152 uint8_t slave_id = 2; /* gpio at pmi */
153
154 struct pm8x41_gpio gpio = {
155 .direction = PM_GPIO_DIR_OUT,
156 .function = PM_GPIO_FUNC_HIGH,
157 .vin_sel = 2, /* VIN_2 */
158 .output_buffer = PM_GPIO_OUT_CMOS,
159 .out_strength = PM_GPIO_OUT_DRIVE_LOW,
160 };
161
162 pm8x41_gpio_config_sid(slave_id, bklt_gpio.pin_id, &gpio);
163 pm8x41_gpio_set_sid(slave_id, bklt_gpio.pin_id, 1);
164}
165
166void lcd_bklt_reg_disable(void)
167{
168 uint8_t slave_id = 2; /* gpio at pmi */
169
170 pm8x41_gpio_set_sid(slave_id, bklt_gpio.pin_id, 0);
Dhaval Patel019057a2014-08-12 13:52:25 -0700171}
172
Kuogee Hsieh208736d2014-08-22 14:16:55 -0700173void lcd_reg_enable(void)
Dhaval Patel019057a2014-08-12 13:52:25 -0700174{
175 struct pm8x41_gpio gpio = {
176 .direction = PM_GPIO_DIR_OUT,
177 .function = PM_GPIO_FUNC_HIGH,
178 .vin_sel = 2, /* VIN_2 */
179 .output_buffer = PM_GPIO_OUT_CMOS,
180 .out_strength = PM_GPIO_OUT_DRIVE_MED,
181 };
182
Kuogee Hsieh208736d2014-08-22 14:16:55 -0700183 pm8x41_gpio_config(lcd_reg_en.pin_id, &gpio);
184 pm8x41_gpio_set(lcd_reg_en.pin_id, 1);
185}
186
187void lcd_reg_disable(void)
188{
189 pm8x41_gpio_set(lcd_reg_en.pin_id, 0);
Dhaval Patel019057a2014-08-12 13:52:25 -0700190}
191
192int target_backlight_ctrl(struct backlight *bl, uint8_t enable)
193{
194 uint32_t ret = NO_ERROR;
195 struct pm8x41_mpp mpp;
196 int rc;
197
198 if (!bl) {
199 dprintf(CRITICAL, "backlight structure is not available\n");
200 return ERR_INVALID_ARGS;
201 }
202
203 switch (bl->bl_interface_type) {
204 case BL_WLED:
205 /* Enable MPP4 */
206 pmi8994_config_mpp_slave_id(PMIC_MPP_SLAVE_ID);
207 mpp.base = PM8x41_MMP4_BASE;
208 mpp.vin = MPP_VIN2;
209 if (enable) {
210 pm_pwm_enable(false);
211 rc = pm_pwm_config(PWM_DUTY_US, PWM_PERIOD_US);
212 if (rc < 0) {
213 mpp.mode = MPP_HIGH;
214 } else {
215 mpp.mode = MPP_DTEST1;
216 pm_pwm_enable(true);
217 }
218 pm8x41_config_output_mpp(&mpp);
219 pm8x41_enable_mpp(&mpp, MPP_ENABLE);
220 } else {
221 pm_pwm_enable(false);
222 pm8x41_enable_mpp(&mpp, MPP_DISABLE);
223 }
224 /* Need delay before power on regulators */
225 mdelay(20);
226 /* Enable WLED backlight control */
227 ret = msm8994_wled_backlight_ctrl(enable);
228 break;
229 case BL_PWM:
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700230 /* Enable MPP1 */
231 pmi8994_config_mpp_slave_id(PMIC_MPP_SLAVE_ID);
232 mpp.base = PM8x41_MMP1_BASE;
233 mpp.vin = MPP_VIN2;
234 mpp.mode = MPP_DTEST4;
235 if (enable) {
236 pm8x41_config_output_mpp(&mpp);
237 pm8x41_enable_mpp(&mpp, MPP_ENABLE);
238 } else {
239 pm8x41_enable_mpp(&mpp, MPP_DISABLE);
240 }
241 /* Need delay before power on regulators */
242 mdelay(20);
Dhaval Patel019057a2014-08-12 13:52:25 -0700243 ret = msm8994_pwm_backlight_ctrl(enable);
244 break;
245 default:
246 dprintf(CRITICAL, "backlight type:%d not supported\n",
247 bl->bl_interface_type);
248 return ERR_NOT_SUPPORTED;
249 }
250
251 return ret;
252}
253
254int target_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
255{
256 uint32_t ret;
257 struct mdss_dsi_pll_config *pll_data;
Aravind Venkateswaranf3554322014-12-08 12:03:48 -0800258 uint32_t flags;
259
260 if (pinfo->dest == DISPLAY_2) {
261 flags = MMSS_DSI_CLKS_FLAG_DSI1;
262 if (pinfo->mipi.dual_dsi)
263 flags |= MMSS_DSI_CLKS_FLAG_DSI0;
264 } else {
265 flags = MMSS_DSI_CLKS_FLAG_DSI0;
266 if (pinfo->mipi.dual_dsi)
267 flags |= MMSS_DSI_CLKS_FLAG_DSI1;
268 }
Dhaval Patel019057a2014-08-12 13:52:25 -0700269
270 pll_data = pinfo->mipi.dsi_pll_config;
271 if (enable) {
272 mdp_gdsc_ctrl(enable);
273 mmss_bus_clock_enable();
274 mdp_clock_enable();
275 ret = restore_secure_cfg(SECURE_DEVICE_MDSS);
276 if (ret) {
277 dprintf(CRITICAL,
278 "%s: Failed to restore MDP security configs",
279 __func__);
280 mdp_clock_disable();
281 mmss_bus_clock_disable();
282 mdp_gdsc_ctrl(0);
283 return ret;
284 }
Jeevan Shriram2d3500b2014-12-29 16:25:06 -0800285 mdss_dsi_auto_pll_20nm_config(pinfo->mipi.pll_0_base,
286 pinfo->mipi.ctl_base,
287 pll_data);
288 dsi_pll_20nm_enable_seq(pinfo->mipi.pll_0_base);
Aravind Venkateswaranf3554322014-12-08 12:03:48 -0800289 mmss_dsi_clock_enable(DSI0_PHY_PLL_OUT, flags,
Dhaval Patel019057a2014-08-12 13:52:25 -0700290 pll_data->pclk_m,
291 pll_data->pclk_n,
292 pll_data->pclk_d);
293 } else if(!target_cont_splash_screen()) {
294 /* Disable clocks if continuous splash off */
Aravind Venkateswaranf3554322014-12-08 12:03:48 -0800295 mmss_dsi_clock_disable(flags);
Dhaval Patel019057a2014-08-12 13:52:25 -0700296 mdp_clock_disable();
297 mmss_bus_clock_disable();
298 mdp_gdsc_ctrl(enable);
299 }
300
301 return NO_ERROR;
302}
303
304int target_panel_reset(uint8_t enable, struct panel_reset_sequence *resetseq,
305 struct msm_panel_info *pinfo)
306{
307 uint32_t i = 0;
308
309 if (enable) {
310 gpio_tlmm_config(reset_gpio.pin_id, 0,
311 reset_gpio.pin_direction, reset_gpio.pin_pull,
312 reset_gpio.pin_strength, reset_gpio.pin_state);
313 /* reset */
314 for (i = 0; i < RESET_GPIO_SEQ_LEN; i++) {
315 if (resetseq->pin_state[i] == GPIO_STATE_LOW)
316 gpio_set(reset_gpio.pin_id, GPIO_STATE_LOW);
317 else
318 gpio_set(reset_gpio.pin_id, GPIO_STATE_HIGH);
319 mdelay(resetseq->sleep[i]);
320 }
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700321 lcd_bklt_reg_enable();
Dhaval Patel019057a2014-08-12 13:52:25 -0700322 } else {
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700323 lcd_bklt_reg_disable();
Dhaval Patel019057a2014-08-12 13:52:25 -0700324 gpio_set(reset_gpio.pin_id, 0);
325 }
326
327 return NO_ERROR;
328}
329
Kuogee Hsieh099022f2014-12-05 15:43:40 -0800330static void wled_init(struct msm_panel_info *pinfo)
331{
332 struct qpnp_wled_config_data config = {0};
333 struct labibb_desc *labibb;
334 int display_type = 0;
335
336 labibb = pinfo->labibb;
337
338 if (labibb)
339 display_type = labibb->amoled_panel;
340
341 config.display_type = display_type;
342 config.lab_init_volt = 4600000; /* fixed, see pmi register */
343 config.ibb_init_volt = 1400000; /* fixed, see pmi register */
344
345 if (labibb && labibb->force_config) {
346 config.lab_min_volt = labibb->lab_min_volt;
347 config.lab_max_volt = labibb->lab_max_volt;
348 config.ibb_min_volt = labibb->ibb_min_volt;
349 config.ibb_max_volt = labibb->ibb_max_volt;
350 config.pwr_up_delay = labibb->pwr_up_delay;
351 config.pwr_down_delay = labibb->pwr_down_delay;
352 config.ibb_discharge_en = labibb->ibb_discharge_en;
353 } else {
354 /* default */
355 config.pwr_up_delay = 3;
356 config.pwr_down_delay = 3;
357 config.ibb_discharge_en = 1;
358 if (display_type) { /* amoled */
359 config.lab_min_volt = 4600000;
360 config.lab_max_volt = 4600000;
361 config.ibb_min_volt = 4000000;
362 config.ibb_max_volt = 4000000;
363 } else { /* lcd */
364 config.lab_min_volt = 5500000;
365 config.lab_max_volt = 5500000;
366 config.ibb_min_volt = 5500000;
367 config.ibb_max_volt = 5500000;
368 }
369 }
370
371 dprintf(SPEW, "%s: %d %d %d %d %d %d %d %d %d %d\n", __func__,
372 config.display_type,
373 config.lab_min_volt, config.lab_max_volt,
374 config.ibb_min_volt, config.ibb_max_volt,
375 config.lab_init_volt, config.ibb_init_volt,
376 config.pwr_up_delay, config.pwr_down_delay,
377 config.ibb_discharge_en);
378
379
380 /* QPNP WLED init for display backlight */
381 pm8x41_wled_config_slave_id(PMIC_WLED_SLAVE_ID);
382
383 qpnp_wled_init(&config);
384}
385
Kuogee Hsieh93bcff62014-08-22 14:02:08 -0700386int target_ldo_ctrl(uint8_t enable, struct msm_panel_info *pinfo)
Dhaval Patel019057a2014-08-12 13:52:25 -0700387{
388 if (enable) {
389 regulator_enable(); /* L2, L12, L14, and L28 */
390 mdelay(10);
Kuogee Hsieh099022f2014-12-05 15:43:40 -0800391 wled_init(pinfo);
Dhaval Patel019057a2014-08-12 13:52:25 -0700392 qpnp_ibb_enable(true); /* +5V and -5V */
393 mdelay(50);
Kuogee Hsieh208736d2014-08-22 14:16:55 -0700394
395 if (pinfo->lcd_reg_en)
396 lcd_reg_enable();
Dhaval Patel019057a2014-08-12 13:52:25 -0700397 } else {
Kuogee Hsieh208736d2014-08-22 14:16:55 -0700398 if (pinfo->lcd_reg_en)
399 lcd_reg_disable();
400
Dhaval Patel019057a2014-08-12 13:52:25 -0700401 regulator_disable();
402 }
403
404 return NO_ERROR;
405}
406
407int target_display_pre_on()
408{
Ingrid Gallardoc9776bd2014-09-04 14:13:28 -0700409 writel(0xC0000CCC, MDP_CLK_CTRL0);
410 writel(0xC0000CCC, MDP_CLK_CTRL1);
Dhaval Patel019057a2014-08-12 13:52:25 -0700411 writel(0x00CCCCCC, MDP_CLK_CTRL2);
412 writel(0x000000CC, MDP_CLK_CTRL6);
413 writel(0x0CCCC0C0, MDP_CLK_CTRL3);
414 writel(0xCCCCC0C0, MDP_CLK_CTRL4);
415 writel(0xCCCCC0C0, MDP_CLK_CTRL5);
416 writel(0x00CCC000, MDP_CLK_CTRL7);
417
Dhaval Patel019057a2014-08-12 13:52:25 -0700418 return NO_ERROR;
419}
420
421bool target_display_panel_node(char *panel_name, char *pbuf, uint16_t buf_size)
422{
Veera Sundaram Sankaran089f70d2014-12-09 14:17:05 -0800423 return gcdb_display_cmdline_arg(panel_name, pbuf, buf_size);
Dhaval Patel019057a2014-08-12 13:52:25 -0700424
Dhaval Patel019057a2014-08-12 13:52:25 -0700425}
426
427void target_display_init(const char *panel_name)
428{
Veera Sundaram Sankaran3b758822014-10-17 12:15:39 -0700429 panel_name += strspn(panel_name, " ");
430
431 if (!strcmp(panel_name, NO_PANEL_CONFIG)
432 || !strcmp(panel_name, SIM_VIDEO_PANEL)
433 || !strcmp(panel_name, SIM_DUALDSI_VIDEO_PANEL)
434 || !strcmp(panel_name, SIM_CMD_PANEL)
435 || !strcmp(panel_name, SIM_DUALDSI_CMD_PANEL)) {
Veera Sundaram Sankaranb620f232014-09-03 22:43:53 -0700436 dprintf(INFO, "Selected panel: %s\nSkip panel configuration\n",
Veera Sundaram Sankaran3b758822014-10-17 12:15:39 -0700437 panel_name);
Veera Sundaram Sankaranb620f232014-09-03 22:43:53 -0700438 return;
439 }
Veera Sundaram Sankaran089f70d2014-12-09 14:17:05 -0800440 if (gcdb_display_init(panel_name, MDP_REV_50, (void *)MIPI_FB_ADDR)) {
Justin Philipbe9de5c2014-09-17 12:26:49 +0530441 target_force_cont_splash_disable(true);
Dhaval Patel019057a2014-08-12 13:52:25 -0700442 msm_display_off();
Justin Philipbe9de5c2014-09-17 12:26:49 +0530443 }
Dhaval Patel019057a2014-08-12 13:52:25 -0700444}
445
446void target_display_shutdown(void)
447{
448 gcdb_display_shutdown();
449}