blob: 8d7863fa560438bb94934b1f99b8b7e2b28821d5 [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
Jeevan Shriram7aacc322014-12-29 16:02:25 -080065#define DSI0_BASE_ADJUST -0x4000
66#define DSI1_BASE_ADJUST -0xA000
67
Veera Sundaram Sankaran089f70d2014-12-09 14:17:05 -080068/*---------------------------------------------------------------------------*/
69/* GPIO configuration */
70/*---------------------------------------------------------------------------*/
71static struct gpio_pin reset_gpio = {
72 "msmgpio", 78, 3, 1, 0, 1
73};
74
75static struct gpio_pin lcd_reg_en = { /* boost regulator */
76 "pm8994_gpios", 14, 3, 1, 0, 1
77};
78
79static struct gpio_pin bklt_gpio = { /* lcd_bklt_reg_en */
80 "pmi8994_gpios", 2, 3, 1, 0, 1
81};
82
Dhaval Patel019057a2014-08-12 13:52:25 -070083static uint32_t dsi_pll_20nm_enable_seq(uint32_t pll_base)
84{
85 uint32_t pll_locked;
Jeevan Shriram5a9f8f42014-12-14 14:56:14 -080086 /* MDSS_DSI_0_PHY_DSIPHY_CTRL_1 */
87 writel(0x00, pll_base + 0x374);
Dhaval Patel019057a2014-08-12 13:52:25 -070088 dmb();
Jeevan Shriram5a9f8f42014-12-14 14:56:14 -080089 /* MDSS_DSI_0_PHY_DSIPHY_CTRL_0 */
90 writel(0x7f, pll_base + 0x370);
91 dmb();
92 pll_locked = mdss_dsi_pll_20nm_lock_status(pll_base);
93 if (!pll_locked)
94 dprintf(INFO, "%s: DSI PLL lock failed\n", __func__);
95 else
96 dprintf(INFO, "%s: DSI PLL lock Success\n", __func__);
Dhaval Patel019057a2014-08-12 13:52:25 -070097
98 return pll_locked;
99}
100
101static int msm8994_wled_backlight_ctrl(uint8_t enable)
102{
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700103 uint8_t slave_id = 3; /* pmi */
Dhaval Patel019057a2014-08-12 13:52:25 -0700104
Veera Sundaram Sankaranf9ddd6c2014-12-02 11:04:52 -0800105 pm8x41_wled_config_slave_id(slave_id);
106 qpnp_wled_enable_backlight(enable);
Dhaval Patel019057a2014-08-12 13:52:25 -0700107 qpnp_ibb_enable(enable);
108 return NO_ERROR;
109}
110
111static int msm8994_pwm_backlight_ctrl(uint8_t enable)
112{
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700113 uint8_t slave_id = 3; /* lpg at pmi */
114
115 if (enable) {
116 /* mpp-1 had been configured already */
117 /* lpg channel 4 */
118
119 /* LPG_ENABLE_CONTROL */
120 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x0);
121 mdelay(100);
122
123 /* LPG_VALUE_LSB, duty cycle = 0x80/0x200 = 1/4 */
124 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x44, 0x80);
125 /* LPG_VALUE_MSB */
126 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x45, 0x00);
127 /* LPG_PWM_SYNC */
128 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x47, 0x01);
129
130 /* LPG_PWM_SIZE_CLK, */
131 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x41, 0x13);
132 /* LPG_PWM_FREQ_PREDIV */
133 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x42, 0x02);
134 /* LPG_PWM_TYPE_CONFIG */
135 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x43, 0x20);
136 /* LPG_ENABLE_CONTROL */
137 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x04);
138
139 /* SEC_ACCESS */
140 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0xD0, 0xA5);
141 /* DTEST4, OUT_HI */
142 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0xE5, 0x01);
143 /* LPG_ENABLE_CONTROL */
144 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0xA4);
145 } else {
146 /* LPG_ENABLE_CONTROL */
147 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x0);
148 }
149
150 return NO_ERROR;
151}
152
153void lcd_bklt_reg_enable(void)
154{
155 uint8_t slave_id = 2; /* gpio at pmi */
156
157 struct pm8x41_gpio gpio = {
158 .direction = PM_GPIO_DIR_OUT,
159 .function = PM_GPIO_FUNC_HIGH,
160 .vin_sel = 2, /* VIN_2 */
161 .output_buffer = PM_GPIO_OUT_CMOS,
162 .out_strength = PM_GPIO_OUT_DRIVE_LOW,
163 };
164
165 pm8x41_gpio_config_sid(slave_id, bklt_gpio.pin_id, &gpio);
166 pm8x41_gpio_set_sid(slave_id, bklt_gpio.pin_id, 1);
167}
168
169void lcd_bklt_reg_disable(void)
170{
171 uint8_t slave_id = 2; /* gpio at pmi */
172
173 pm8x41_gpio_set_sid(slave_id, bklt_gpio.pin_id, 0);
Dhaval Patel019057a2014-08-12 13:52:25 -0700174}
175
Kuogee Hsieh208736d2014-08-22 14:16:55 -0700176void lcd_reg_enable(void)
Dhaval Patel019057a2014-08-12 13:52:25 -0700177{
178 struct pm8x41_gpio gpio = {
179 .direction = PM_GPIO_DIR_OUT,
180 .function = PM_GPIO_FUNC_HIGH,
181 .vin_sel = 2, /* VIN_2 */
182 .output_buffer = PM_GPIO_OUT_CMOS,
183 .out_strength = PM_GPIO_OUT_DRIVE_MED,
184 };
185
Kuogee Hsieh208736d2014-08-22 14:16:55 -0700186 pm8x41_gpio_config(lcd_reg_en.pin_id, &gpio);
187 pm8x41_gpio_set(lcd_reg_en.pin_id, 1);
188}
189
190void lcd_reg_disable(void)
191{
192 pm8x41_gpio_set(lcd_reg_en.pin_id, 0);
Dhaval Patel019057a2014-08-12 13:52:25 -0700193}
194
195int target_backlight_ctrl(struct backlight *bl, uint8_t enable)
196{
197 uint32_t ret = NO_ERROR;
198 struct pm8x41_mpp mpp;
199 int rc;
200
201 if (!bl) {
202 dprintf(CRITICAL, "backlight structure is not available\n");
203 return ERR_INVALID_ARGS;
204 }
205
206 switch (bl->bl_interface_type) {
207 case BL_WLED:
208 /* Enable MPP4 */
209 pmi8994_config_mpp_slave_id(PMIC_MPP_SLAVE_ID);
210 mpp.base = PM8x41_MMP4_BASE;
211 mpp.vin = MPP_VIN2;
212 if (enable) {
213 pm_pwm_enable(false);
214 rc = pm_pwm_config(PWM_DUTY_US, PWM_PERIOD_US);
215 if (rc < 0) {
216 mpp.mode = MPP_HIGH;
217 } else {
218 mpp.mode = MPP_DTEST1;
219 pm_pwm_enable(true);
220 }
221 pm8x41_config_output_mpp(&mpp);
222 pm8x41_enable_mpp(&mpp, MPP_ENABLE);
223 } else {
224 pm_pwm_enable(false);
225 pm8x41_enable_mpp(&mpp, MPP_DISABLE);
226 }
227 /* Need delay before power on regulators */
228 mdelay(20);
229 /* Enable WLED backlight control */
230 ret = msm8994_wled_backlight_ctrl(enable);
231 break;
232 case BL_PWM:
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700233 /* Enable MPP1 */
234 pmi8994_config_mpp_slave_id(PMIC_MPP_SLAVE_ID);
235 mpp.base = PM8x41_MMP1_BASE;
236 mpp.vin = MPP_VIN2;
237 mpp.mode = MPP_DTEST4;
238 if (enable) {
239 pm8x41_config_output_mpp(&mpp);
240 pm8x41_enable_mpp(&mpp, MPP_ENABLE);
241 } else {
242 pm8x41_enable_mpp(&mpp, MPP_DISABLE);
243 }
244 /* Need delay before power on regulators */
245 mdelay(20);
Dhaval Patel019057a2014-08-12 13:52:25 -0700246 ret = msm8994_pwm_backlight_ctrl(enable);
247 break;
248 default:
249 dprintf(CRITICAL, "backlight type:%d not supported\n",
250 bl->bl_interface_type);
251 return ERR_NOT_SUPPORTED;
252 }
253
254 return ret;
255}
256
257int target_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
258{
259 uint32_t ret;
260 struct mdss_dsi_pll_config *pll_data;
Aravind Venkateswaranf3554322014-12-08 12:03:48 -0800261 uint32_t flags;
262
263 if (pinfo->dest == DISPLAY_2) {
264 flags = MMSS_DSI_CLKS_FLAG_DSI1;
265 if (pinfo->mipi.dual_dsi)
266 flags |= MMSS_DSI_CLKS_FLAG_DSI0;
267 } else {
268 flags = MMSS_DSI_CLKS_FLAG_DSI0;
269 if (pinfo->mipi.dual_dsi)
270 flags |= MMSS_DSI_CLKS_FLAG_DSI1;
271 }
Dhaval Patel019057a2014-08-12 13:52:25 -0700272
273 pll_data = pinfo->mipi.dsi_pll_config;
274 if (enable) {
275 mdp_gdsc_ctrl(enable);
276 mmss_bus_clock_enable();
277 mdp_clock_enable();
278 ret = restore_secure_cfg(SECURE_DEVICE_MDSS);
279 if (ret) {
280 dprintf(CRITICAL,
281 "%s: Failed to restore MDP security configs",
282 __func__);
283 mdp_clock_disable();
284 mmss_bus_clock_disable();
285 mdp_gdsc_ctrl(0);
286 return ret;
287 }
Jeevan Shriram2d3500b2014-12-29 16:25:06 -0800288 mdss_dsi_auto_pll_20nm_config(pinfo->mipi.pll_0_base,
289 pinfo->mipi.ctl_base,
290 pll_data);
291 dsi_pll_20nm_enable_seq(pinfo->mipi.pll_0_base);
Aravind Venkateswaranf3554322014-12-08 12:03:48 -0800292 mmss_dsi_clock_enable(DSI0_PHY_PLL_OUT, flags,
Dhaval Patel019057a2014-08-12 13:52:25 -0700293 pll_data->pclk_m,
294 pll_data->pclk_n,
295 pll_data->pclk_d);
296 } else if(!target_cont_splash_screen()) {
297 /* Disable clocks if continuous splash off */
Aravind Venkateswaranf3554322014-12-08 12:03:48 -0800298 mmss_dsi_clock_disable(flags);
Dhaval Patel019057a2014-08-12 13:52:25 -0700299 mdp_clock_disable();
300 mmss_bus_clock_disable();
301 mdp_gdsc_ctrl(enable);
302 }
303
304 return NO_ERROR;
305}
306
307int target_panel_reset(uint8_t enable, struct panel_reset_sequence *resetseq,
308 struct msm_panel_info *pinfo)
309{
310 uint32_t i = 0;
311
312 if (enable) {
313 gpio_tlmm_config(reset_gpio.pin_id, 0,
314 reset_gpio.pin_direction, reset_gpio.pin_pull,
315 reset_gpio.pin_strength, reset_gpio.pin_state);
316 /* reset */
317 for (i = 0; i < RESET_GPIO_SEQ_LEN; i++) {
318 if (resetseq->pin_state[i] == GPIO_STATE_LOW)
319 gpio_set(reset_gpio.pin_id, GPIO_STATE_LOW);
320 else
321 gpio_set(reset_gpio.pin_id, GPIO_STATE_HIGH);
322 mdelay(resetseq->sleep[i]);
323 }
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700324 lcd_bklt_reg_enable();
Dhaval Patel019057a2014-08-12 13:52:25 -0700325 } else {
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700326 lcd_bklt_reg_disable();
Dhaval Patel019057a2014-08-12 13:52:25 -0700327 gpio_set(reset_gpio.pin_id, 0);
328 }
329
330 return NO_ERROR;
331}
332
Kuogee Hsieh099022f2014-12-05 15:43:40 -0800333static void wled_init(struct msm_panel_info *pinfo)
334{
335 struct qpnp_wled_config_data config = {0};
336 struct labibb_desc *labibb;
337 int display_type = 0;
338
339 labibb = pinfo->labibb;
340
341 if (labibb)
342 display_type = labibb->amoled_panel;
343
344 config.display_type = display_type;
345 config.lab_init_volt = 4600000; /* fixed, see pmi register */
346 config.ibb_init_volt = 1400000; /* fixed, see pmi register */
347
348 if (labibb && labibb->force_config) {
349 config.lab_min_volt = labibb->lab_min_volt;
350 config.lab_max_volt = labibb->lab_max_volt;
351 config.ibb_min_volt = labibb->ibb_min_volt;
352 config.ibb_max_volt = labibb->ibb_max_volt;
353 config.pwr_up_delay = labibb->pwr_up_delay;
354 config.pwr_down_delay = labibb->pwr_down_delay;
355 config.ibb_discharge_en = labibb->ibb_discharge_en;
356 } else {
357 /* default */
358 config.pwr_up_delay = 3;
359 config.pwr_down_delay = 3;
360 config.ibb_discharge_en = 1;
361 if (display_type) { /* amoled */
362 config.lab_min_volt = 4600000;
363 config.lab_max_volt = 4600000;
364 config.ibb_min_volt = 4000000;
365 config.ibb_max_volt = 4000000;
366 } else { /* lcd */
367 config.lab_min_volt = 5500000;
368 config.lab_max_volt = 5500000;
369 config.ibb_min_volt = 5500000;
370 config.ibb_max_volt = 5500000;
371 }
372 }
373
374 dprintf(SPEW, "%s: %d %d %d %d %d %d %d %d %d %d\n", __func__,
375 config.display_type,
376 config.lab_min_volt, config.lab_max_volt,
377 config.ibb_min_volt, config.ibb_max_volt,
378 config.lab_init_volt, config.ibb_init_volt,
379 config.pwr_up_delay, config.pwr_down_delay,
380 config.ibb_discharge_en);
381
382
383 /* QPNP WLED init for display backlight */
384 pm8x41_wled_config_slave_id(PMIC_WLED_SLAVE_ID);
385
386 qpnp_wled_init(&config);
387}
388
Kuogee Hsieh93bcff62014-08-22 14:02:08 -0700389int target_ldo_ctrl(uint8_t enable, struct msm_panel_info *pinfo)
Dhaval Patel019057a2014-08-12 13:52:25 -0700390{
391 if (enable) {
392 regulator_enable(); /* L2, L12, L14, and L28 */
393 mdelay(10);
Kuogee Hsieh099022f2014-12-05 15:43:40 -0800394 wled_init(pinfo);
Dhaval Patel019057a2014-08-12 13:52:25 -0700395 qpnp_ibb_enable(true); /* +5V and -5V */
396 mdelay(50);
Kuogee Hsieh208736d2014-08-22 14:16:55 -0700397
398 if (pinfo->lcd_reg_en)
399 lcd_reg_enable();
Dhaval Patel019057a2014-08-12 13:52:25 -0700400 } else {
Kuogee Hsieh208736d2014-08-22 14:16:55 -0700401 if (pinfo->lcd_reg_en)
402 lcd_reg_disable();
403
Dhaval Patel019057a2014-08-12 13:52:25 -0700404 regulator_disable();
405 }
406
407 return NO_ERROR;
408}
409
410int target_display_pre_on()
411{
Ingrid Gallardoc9776bd2014-09-04 14:13:28 -0700412 writel(0xC0000CCC, MDP_CLK_CTRL0);
413 writel(0xC0000CCC, MDP_CLK_CTRL1);
Dhaval Patel019057a2014-08-12 13:52:25 -0700414 writel(0x00CCCCCC, MDP_CLK_CTRL2);
415 writel(0x000000CC, MDP_CLK_CTRL6);
416 writel(0x0CCCC0C0, MDP_CLK_CTRL3);
417 writel(0xCCCCC0C0, MDP_CLK_CTRL4);
418 writel(0xCCCCC0C0, MDP_CLK_CTRL5);
419 writel(0x00CCC000, MDP_CLK_CTRL7);
420
Dhaval Patel019057a2014-08-12 13:52:25 -0700421 return NO_ERROR;
422}
423
Jeevan Shriram7aacc322014-12-29 16:02:25 -0800424int target_display_get_base_offset(uint32_t base)
425{
426 if(platform_is_msm8992()) {
427 if (base == MIPI_DSI0_BASE)
428 return DSI0_BASE_ADJUST;
429 else if (base == MIPI_DSI1_BASE)
430 return DSI1_BASE_ADJUST;
431 }
432
433 return 0;
434}
435
Dhaval Patel019057a2014-08-12 13:52:25 -0700436bool target_display_panel_node(char *panel_name, char *pbuf, uint16_t buf_size)
437{
Veera Sundaram Sankaran089f70d2014-12-09 14:17:05 -0800438 return gcdb_display_cmdline_arg(panel_name, pbuf, buf_size);
Dhaval Patel019057a2014-08-12 13:52:25 -0700439
Dhaval Patel019057a2014-08-12 13:52:25 -0700440}
441
442void target_display_init(const char *panel_name)
443{
Veera Sundaram Sankaran3b758822014-10-17 12:15:39 -0700444 panel_name += strspn(panel_name, " ");
445
446 if (!strcmp(panel_name, NO_PANEL_CONFIG)
447 || !strcmp(panel_name, SIM_VIDEO_PANEL)
448 || !strcmp(panel_name, SIM_DUALDSI_VIDEO_PANEL)
449 || !strcmp(panel_name, SIM_CMD_PANEL)
450 || !strcmp(panel_name, SIM_DUALDSI_CMD_PANEL)) {
Veera Sundaram Sankaranb620f232014-09-03 22:43:53 -0700451 dprintf(INFO, "Selected panel: %s\nSkip panel configuration\n",
Veera Sundaram Sankaran3b758822014-10-17 12:15:39 -0700452 panel_name);
Veera Sundaram Sankaranb620f232014-09-03 22:43:53 -0700453 return;
454 }
Veera Sundaram Sankaran089f70d2014-12-09 14:17:05 -0800455 if (gcdb_display_init(panel_name, MDP_REV_50, (void *)MIPI_FB_ADDR)) {
Justin Philipbe9de5c2014-09-17 12:26:49 +0530456 target_force_cont_splash_disable(true);
Dhaval Patel019057a2014-08-12 13:52:25 -0700457 msm_display_off();
Justin Philipbe9de5c2014-09-17 12:26:49 +0530458 }
Dhaval Patel019057a2014-08-12 13:52:25 -0700459}
460
461void target_display_shutdown(void)
462{
463 gcdb_display_shutdown();
464}