blob: 34ae63fb8f3037df2a0e3e0c759d5398c20be4aa [file] [log] [blame]
Dhaval Pateldacdac92016-02-08 17:04:33 -08001/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
Dhaval Patelb95039c2015-03-16 11:14:06 -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 <string.h>
32#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 <endian.h>
42#include <regulator.h>
43#include <qtimer.h>
44#include <arch/defines.h>
45#include <platform/gpio.h>
46#include <platform/clock.h>
47#include <platform/iomap.h>
48#include <target/display.h>
49#include <mipi_dsi_autopll_thulium.h>
Siddharth Zaveriacaacc32015-12-12 15:10:33 -050050#include <mipi_dsi_i2c.h>
Dhaval Patelb95039c2015-03-16 11:14:06 -070051
52#include "include/panel.h"
53#include "include/display_resource.h"
54#include "gcdb_display.h"
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
65#define MAX_POLL_READS 15
66#define POLL_TIMEOUT_US 1000
67
68#define STRENGTH_SIZE_IN_BYTES_8996 10
69#define REGULATOR_SIZE_IN_BYTES_8996 5
70#define LANE_SIZE_IN_BYTES_8996 20
71
72/*---------------------------------------------------------------------------*/
73/* GPIO configuration */
74/*---------------------------------------------------------------------------*/
75static struct gpio_pin reset_gpio = {
76 "msmgpio", 8, 3, 1, 0, 1
77};
78
79static struct gpio_pin lcd_reg_en = { /* boost regulator */
80 "pmi8994_gpios", 8, 3, 1, 0, 1
81};
82
83static struct gpio_pin bklt_gpio = { /* lcd_bklt_reg_en */
84 "pm8994_gpios", 14, 3, 1, 0, 1
85};
86
Siddharth Zaveriacaacc32015-12-12 15:10:33 -050087static struct gpio_pin enable_gpio = {
88 "msmgpio", 10, 3, 1, 0, 1
89};
90
91static struct gpio_pin dsi2hdmi_switch_gpio = {
92 "msmgpio", 105, 3, 1, 0, 1
93};
94
Ajay Singh Parmar865f7d22015-02-13 23:47:40 -080095/* gpio name, id, strength, direction, pull, state. */
96static struct gpio_pin hdmi_cec_gpio = { /* CEC */
97 "msmgpio", 31, 0, 2, 3, 1
98};
99
100static struct gpio_pin hdmi_ddc_clk_gpio = { /* DDC CLK */
101 "msmgpio", 32, 0, 2, 3, 1
102};
103
104static struct gpio_pin hdmi_ddc_data_gpio = { /* DDC DATA */
105 "msmgpio", 33, 0, 2, 3, 1
106};
107
108static struct gpio_pin hdmi_hpd_gpio = { /* HPD, input */
109 "msmgpio", 34, 7, 0, 1, 1
110};
111
112int target_hdmi_gpio_ctrl(uint8_t enable)
113{
114 gpio_tlmm_config(hdmi_cec_gpio.pin_id, 1, /* gpio 31, CEC */
115 hdmi_cec_gpio.pin_direction, hdmi_cec_gpio.pin_pull,
116 hdmi_cec_gpio.pin_strength, hdmi_cec_gpio.pin_state);
117
118 gpio_tlmm_config(hdmi_ddc_clk_gpio.pin_id, 1, /* gpio 32, DDC CLK */
119 hdmi_ddc_clk_gpio.pin_direction, hdmi_ddc_clk_gpio.pin_pull,
120 hdmi_ddc_clk_gpio.pin_strength, hdmi_ddc_clk_gpio.pin_state);
121
122
123 gpio_tlmm_config(hdmi_ddc_data_gpio.pin_id, 1, /* gpio 33, DDC DATA */
124 hdmi_ddc_data_gpio.pin_direction, hdmi_ddc_data_gpio.pin_pull,
125 hdmi_ddc_data_gpio.pin_strength, hdmi_ddc_data_gpio.pin_state);
126
127 gpio_tlmm_config(hdmi_hpd_gpio.pin_id, 1, /* gpio 34, HPD */
128 hdmi_hpd_gpio.pin_direction, hdmi_hpd_gpio.pin_pull,
129 hdmi_hpd_gpio.pin_strength, hdmi_hpd_gpio.pin_state);
130
131 gpio_set(hdmi_cec_gpio.pin_id, hdmi_cec_gpio.pin_direction);
132 gpio_set(hdmi_ddc_clk_gpio.pin_id, hdmi_ddc_clk_gpio.pin_direction);
133 gpio_set(hdmi_ddc_data_gpio.pin_id, hdmi_ddc_data_gpio.pin_direction);
134 gpio_set(hdmi_hpd_gpio.pin_id, hdmi_hpd_gpio.pin_direction);
135
136 return NO_ERROR;
137}
138
Dhaval Patelb95039c2015-03-16 11:14:06 -0700139static uint32_t thulium_dsi_pll_lock_status(uint32_t pll_base, uint32_t off,
140 uint32_t bit)
141{
142 uint32_t cnt, status;
143
144 /* check pll lock first */
145 for (cnt = 0; cnt < MAX_POLL_READS; cnt++) {
146 status = readl(pll_base + off);
147 dprintf(SPEW, "%s: pll_base=%x cnt=%d status=%x\n",
148 __func__, pll_base, cnt, status);
149 status &= BIT(bit); /* bit 5 */
150 if (status)
151 break;
152 udelay(POLL_TIMEOUT_US);
153 }
154
155 return status;
156}
157
158static uint32_t thulium_dsi_pll_enable_seq(uint32_t phy_base, uint32_t pll_base)
159{
160 uint32_t pll_locked;
161
Dhaval Patela9959bf2015-10-13 11:43:54 -0700162 writel(0x10, phy_base + 0x45c);
Dhaval Patelb95039c2015-03-16 11:14:06 -0700163 writel(0x01, phy_base + 0x48);
164 dmb();
165
166 pll_locked = thulium_dsi_pll_lock_status(pll_base, 0xcc, 5);
167 if (pll_locked)
168 pll_locked = thulium_dsi_pll_lock_status(pll_base, 0xcc, 0);
169
170 if (!pll_locked)
171 dprintf(ERROR, "%s: DSI PLL lock failed\n", __func__);
172 else
173 dprintf(SPEW, "%s: DSI PLL lock Success\n", __func__);
174
175 return pll_locked;
176}
177
178static int thulium_wled_backlight_ctrl(uint8_t enable)
179{
180 qpnp_wled_enable_backlight(enable);
Dhaval Patelb95039c2015-03-16 11:14:06 -0700181 return NO_ERROR;
182}
183
184static int thulium_pwm_backlight_ctrl(uint8_t enable)
185{
186 uint8_t slave_id = 3; /* lpg at pmi */
187
188 if (enable) {
189 /* lpg channel 4 */
190
191 /* LPG_ENABLE_CONTROL */
192 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x0);
193 mdelay(100);
194
195 /* LPG_VALUE_LSB, duty cycle = 0x80/0x200 = 1/4 */
196 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x44, 0x80);
197 /* LPG_VALUE_MSB */
198 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x45, 0x00);
199 /* LPG_PWM_SYNC */
200 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x47, 0x01);
201
202 /* LPG_PWM_SIZE_CLK, */
203 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x41, 0x13);
204 /* LPG_PWM_FREQ_PREDIV */
205 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x42, 0x02);
206 /* LPG_PWM_TYPE_CONFIG */
207 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x43, 0x20);
208 /* LPG_ENABLE_CONTROL */
209 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x04);
210
211 /* SEC_ACCESS */
212 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0xD0, 0xA5);
213 /* DTEST4, OUT_HI */
214 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0xE5, 0x01);
215 /* LPG_ENABLE_CONTROL */
216 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0xA4);
217 } else {
218 /* LPG_ENABLE_CONTROL */
219 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x0);
220 }
221
222 return NO_ERROR;
223}
224
225static void lcd_reg_enable(void)
226{
227 uint8_t slave_id = 2; /* gpio at pmi */
228
229 struct pm8x41_gpio gpio = {
230 .direction = PM_GPIO_DIR_OUT,
231 .function = PM_GPIO_FUNC_HIGH,
232 .vin_sel = 2, /* VIN_2 */
233 .output_buffer = PM_GPIO_OUT_CMOS,
234 .out_strength = PM_GPIO_OUT_DRIVE_MED,
235 };
236
237 pm8x41_gpio_config_sid(slave_id, lcd_reg_en.pin_id, &gpio);
238 pm8x41_gpio_set_sid(slave_id, lcd_reg_en.pin_id, 1);
239}
240
241static void lcd_reg_disable(void)
242{
243 uint8_t slave_id = 2; /* gpio at pmi */
244
245 pm8x41_gpio_set_sid(slave_id, lcd_reg_en.pin_id, 0);
246}
247
248static void lcd_bklt_reg_enable(void)
249{
250 struct pm8x41_gpio gpio = {
251 .direction = PM_GPIO_DIR_OUT,
252 .function = PM_GPIO_FUNC_HIGH,
253 .vin_sel = 2, /* VIN_2 */
254 .output_buffer = PM_GPIO_OUT_CMOS,
255 .out_strength = PM_GPIO_OUT_DRIVE_LOW,
256 };
257
258 pm8x41_gpio_config(bklt_gpio.pin_id, &gpio);
259 pm8x41_gpio_set(bklt_gpio.pin_id, 1);
260}
261
262static void lcd_bklt_reg_disable(void)
263{
264 pm8x41_gpio_set(bklt_gpio.pin_id, 0);
265}
266
Siddharth Zaveriacaacc32015-12-12 15:10:33 -0500267static int dsi2HDMI_i2c_write_regs(struct msm_panel_info *pinfo,
268 struct mipi_dsi_i2c_cmd *cfg, int size)
269{
270 int ret = NO_ERROR;
271 int i;
272 uint8_t addr;
273
274 if (!cfg || size < 0) {
275 dprintf(CRITICAL, "Invalid input: register array is null\n");
276 return ERR_INVALID_ARGS;
277 }
278
279 for (i = 0; i < size; i++) {
280 switch (cfg[i].i2c_addr) {
281 case ADV7533_MAIN:
282 addr = pinfo->adv7533.i2c_main_addr;
283 break;
284 case ADV7533_CEC_DSI:
285 addr = pinfo->adv7533.i2c_cec_addr;
286 break;
287 default:
288 dprintf(CRITICAL, "Invalid I2C addr in array\n");
289 ret = ERR_INVALID_ARGS;
290 goto w_regs_fail;
291 }
292
293 ret = mipi_dsi_i2c_write_byte(addr, cfg[i].reg,
294 cfg[i].val);
295 if (ret) {
296 dprintf(CRITICAL, "mipi_dsi reg writes failed\n");
297 goto w_regs_fail;
298 }
299 if (cfg[i].sleep_in_ms) {
300 udelay(cfg[i].sleep_in_ms*1000);
301 }
302 }
303w_regs_fail:
304 return ret;
305}
306
307int target_display_dsi2hdmi_program_addr(struct msm_panel_info *pinfo)
308{
309 int ret = NO_ERROR;
310 uint8_t i2c_8bits = pinfo->adv7533.i2c_cec_addr << 1;
311 ret = mipi_dsi_i2c_write_byte(pinfo->adv7533.i2c_main_addr,
312 0xE1, i2c_8bits);
313 if (ret) {
314 dprintf(CRITICAL, "Error in programming CEC DSI addr\n");
315 } else {
316 dprintf(SPEW, "CEC address programming successful\n");
317 }
318 return ret;
319}
320
321int target_display_dsi2hdmi_config(struct msm_panel_info *pinfo)
322{
323 int ret = NO_ERROR;
324
325 if (!pinfo) {
326 dprintf(CRITICAL, "Invalid input: pinfo is null\n");
327 return ERR_INVALID_ARGS;
328 }
329
330 if (!pinfo->adv7533.program_i2c_addr) {
331 ret = target_display_dsi2hdmi_program_addr(pinfo);
332 if (ret) {
333 dprintf(CRITICAL, "Error in programming cec dsi addr\n");
334 return ret;
335 } else {
336 dprintf(SPEW, "successfully programmed cec dsi addr\n");
337 pinfo->adv7533.program_i2c_addr = 1;
338 }
339 }
340
341 /*
342 * If dsi to HDMI bridge chip connected then
343 * send I2c commands to the chip
344 */
345 if (pinfo->adv7533.dsi_setup_cfg_i2c_cmd)
346 ret = dsi2HDMI_i2c_write_regs(pinfo, pinfo->adv7533.dsi_setup_cfg_i2c_cmd,
347 pinfo->adv7533.num_of_cfg_i2c_cmds);
348 if (ret) {
349 dprintf(CRITICAL, "Error in writing adv7533 setup registers\n");
350 return ret;
351 }
352
353 if (pinfo->adv7533.dsi_tg_i2c_cmd)
354 ret = dsi2HDMI_i2c_write_regs(pinfo, pinfo->adv7533.dsi_tg_i2c_cmd,
355 pinfo->adv7533.num_of_tg_i2c_cmds);
356 if (ret) {
357 dprintf(CRITICAL, "Error in writing adv7533 timing registers\n");
358 }
359
360 return ret;
361}
362
Dhaval Patelb95039c2015-03-16 11:14:06 -0700363int target_backlight_ctrl(struct backlight *bl, uint8_t enable)
364{
365 uint32_t ret = NO_ERROR;
366 struct pm8x41_mpp mpp;
367 int rc;
368
369 if (!bl) {
370 dprintf(CRITICAL, "backlight structure is not available\n");
371 return ERR_INVALID_ARGS;
372 }
373
374 switch (bl->bl_interface_type) {
375 case BL_WLED:
376 /* Enable MPP4 */
377 pmi8994_config_mpp_slave_id(PMIC_MPP_SLAVE_ID);
378 mpp.base = PM8x41_MMP4_BASE;
379 mpp.vin = MPP_VIN2;
380 if (enable) {
381 pm_pwm_enable(false);
382 rc = pm_pwm_config(PWM_DUTY_US, PWM_PERIOD_US);
383 if (rc < 0) {
384 mpp.mode = MPP_HIGH;
385 } else {
386 mpp.mode = MPP_DTEST1;
387 pm_pwm_enable(true);
388 }
389 pm8x41_config_output_mpp(&mpp);
390 pm8x41_enable_mpp(&mpp, MPP_ENABLE);
391 } else {
392 pm_pwm_enable(false);
393 pm8x41_enable_mpp(&mpp, MPP_DISABLE);
394 }
Dhaval Patelb95039c2015-03-16 11:14:06 -0700395 /* Enable WLED backlight control */
396 ret = thulium_wled_backlight_ctrl(enable);
397 break;
398 case BL_PWM:
399 /* Enable MPP1 */
400 pmi8994_config_mpp_slave_id(PMIC_MPP_SLAVE_ID);
401 mpp.base = PM8x41_MMP1_BASE;
402 mpp.vin = MPP_VIN2;
403 mpp.mode = MPP_DTEST4;
404 if (enable) {
405 pm8x41_config_output_mpp(&mpp);
406 pm8x41_enable_mpp(&mpp, MPP_ENABLE);
407 } else {
408 pm8x41_enable_mpp(&mpp, MPP_DISABLE);
409 }
Dhaval Patelb95039c2015-03-16 11:14:06 -0700410 ret = thulium_pwm_backlight_ctrl(enable);
411 break;
412 default:
413 dprintf(CRITICAL, "backlight type:%d not supported\n",
414 bl->bl_interface_type);
415 return ERR_NOT_SUPPORTED;
416 }
417
418 return ret;
419}
420
421int target_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
422{
Aravind Venkateswaran9586be62015-05-20 00:51:06 -0700423 uint32_t flags, dsi_phy_pll_out;
Dhaval Patelb95039c2015-03-16 11:14:06 -0700424 uint32_t ret = NO_ERROR;
425 uint32_t board_version = board_soc_version();
Dhaval Pateldacdac92016-02-08 17:04:33 -0800426 uint32_t board_hw_id = board_hardware_id();
427 bool video_core_enable = false;
Jeevan Shrirama3860092015-08-03 15:16:57 -0700428 struct dfps_pll_codes *pll_codes = &pinfo->mipi.pll_codes;
Dhaval Patelb95039c2015-03-16 11:14:06 -0700429
430 if (pinfo->dest == DISPLAY_2) {
431 flags = MMSS_DSI_CLKS_FLAG_DSI1;
432 if (pinfo->mipi.dual_dsi)
433 flags |= MMSS_DSI_CLKS_FLAG_DSI0;
434 } else {
435 flags = MMSS_DSI_CLKS_FLAG_DSI0;
436 if (pinfo->mipi.dual_dsi)
437 flags |= MMSS_DSI_CLKS_FLAG_DSI1;
438 }
439
Dhaval Pateldacdac92016-02-08 17:04:33 -0800440 /* only required for msm8996 v2 and v2.1 revision */
441 video_core_enable = (board_version == 0x20000 || board_version == 0x20001) &&
442 !(board_hw_id == MSM8996SG || board_hw_id == APQ8096SG);
443
Dhaval Patelb95039c2015-03-16 11:14:06 -0700444 if (!enable) {
445 /* stop pll */
446 writel(0x0, pinfo->mipi.phy_base + 0x48);
447 dmb();
448
449 mmss_dsi_clock_disable(flags);
450 goto clks_disable;
451 }
452
Dhaval Pateldacdac92016-02-08 17:04:33 -0800453 if (video_core_enable)
Dhaval Patelb95039c2015-03-16 11:14:06 -0700454 video_gdsc_enable();
455 mmss_gdsc_enable();
456 mmss_bus_clock_enable();
457 mdp_clock_enable();
458 mdss_dsi_auto_pll_thulium_config(pinfo);
459
460 if (!thulium_dsi_pll_enable_seq(pinfo->mipi.phy_base,
461 pinfo->mipi.pll_base)) {
462 ret = ERROR;
463 dprintf(CRITICAL, "PLL failed to lock!\n");
464 goto clks_disable;
465 }
Aravind Venkateswaran9586be62015-05-20 00:51:06 -0700466
Jeevan Shrirama3860092015-08-03 15:16:57 -0700467 pll_codes->codes[0] = readl_relaxed(pinfo->mipi.pll_base +
468 MMSS_DSI_PHY_PLL_CORE_KVCO_CODE);
469 pll_codes->codes[1] = readl_relaxed(pinfo->mipi.pll_base +
470 MMSS_DSI_PHY_PLL_CORE_VCO_TUNE);
471 dprintf(SPEW, "codes %d %d\n", pll_codes->codes[0],
472 pll_codes->codes[1]);
473
Aravind Venkateswaran9586be62015-05-20 00:51:06 -0700474 if (pinfo->mipi.use_dsi1_pll)
475 dsi_phy_pll_out = DSI1_PHY_PLL_OUT;
476 else
477 dsi_phy_pll_out = DSI0_PHY_PLL_OUT;
478 mmss_dsi_clock_enable(dsi_phy_pll_out, flags);
479
Dhaval Patelb95039c2015-03-16 11:14:06 -0700480 return NO_ERROR;
481
482clks_disable:
483 mdp_clock_disable();
484 mmss_bus_clock_disable();
485 mmss_gdsc_disable();
Dhaval Pateldacdac92016-02-08 17:04:33 -0800486 if (video_core_enable)
Dhaval Patelb95039c2015-03-16 11:14:06 -0700487 video_gdsc_disable();
488
489 return ret;
490}
491
492int target_panel_reset(uint8_t enable, struct panel_reset_sequence *resetseq,
493 struct msm_panel_info *pinfo)
494{
495 uint32_t i = 0;
496
497 if (enable) {
498 gpio_tlmm_config(reset_gpio.pin_id, 0,
499 reset_gpio.pin_direction, reset_gpio.pin_pull,
500 reset_gpio.pin_strength, reset_gpio.pin_state);
501 /* reset */
502 for (i = 0; i < RESET_GPIO_SEQ_LEN; i++) {
503 if (resetseq->pin_state[i] == GPIO_STATE_LOW)
504 gpio_set(reset_gpio.pin_id, GPIO_STATE_LOW);
505 else
506 gpio_set(reset_gpio.pin_id, GPIO_STATE_HIGH);
507 mdelay(resetseq->sleep[i]);
508 }
509 lcd_bklt_reg_enable();
510 } else {
511 lcd_bklt_reg_disable();
512 gpio_set(reset_gpio.pin_id, 0);
513 }
514
515 return NO_ERROR;
516}
517
518static void wled_init(struct msm_panel_info *pinfo)
519{
520 struct qpnp_wled_config_data config = {0};
521 struct labibb_desc *labibb;
522 int display_type = 0;
523
524 labibb = pinfo->labibb;
525
526 if (labibb)
527 display_type = labibb->amoled_panel;
528
529 config.display_type = display_type;
530 config.lab_init_volt = 4600000; /* fixed, see pmi register */
531 config.ibb_init_volt = 1400000; /* fixed, see pmi register */
532
533 if (labibb && labibb->force_config) {
534 config.lab_min_volt = labibb->lab_min_volt;
535 config.lab_max_volt = labibb->lab_max_volt;
536 config.ibb_min_volt = labibb->ibb_min_volt;
537 config.ibb_max_volt = labibb->ibb_max_volt;
538 config.pwr_up_delay = labibb->pwr_up_delay;
539 config.pwr_down_delay = labibb->pwr_down_delay;
540 config.ibb_discharge_en = labibb->ibb_discharge_en;
541 } else {
542 /* default */
543 config.pwr_up_delay = 3;
544 config.pwr_down_delay = 3;
545 config.ibb_discharge_en = 1;
546 if (display_type) { /* amoled */
547 config.lab_min_volt = 4600000;
548 config.lab_max_volt = 4600000;
549 config.ibb_min_volt = 4000000;
550 config.ibb_max_volt = 4000000;
551 } else { /* lcd */
552 config.lab_min_volt = 5500000;
553 config.lab_max_volt = 5500000;
554 config.ibb_min_volt = 5500000;
555 config.ibb_max_volt = 5500000;
556 }
557 }
558
559 dprintf(SPEW, "%s: %d %d %d %d %d %d %d %d %d %d\n", __func__,
560 config.display_type,
561 config.lab_min_volt, config.lab_max_volt,
562 config.ibb_min_volt, config.ibb_max_volt,
563 config.lab_init_volt, config.ibb_init_volt,
564 config.pwr_up_delay, config.pwr_down_delay,
565 config.ibb_discharge_en);
566
567
568 /* QPNP WLED init for display backlight */
569 pm8x41_wled_config_slave_id(PMIC_WLED_SLAVE_ID);
570
571 qpnp_wled_init(&config);
572}
573
574int target_ldo_ctrl(uint8_t enable, struct msm_panel_info *pinfo)
575{
576 uint32_t val = BIT(1) | BIT(13) | BIT(27);
577
578 if (enable) {
579 regulator_enable(val);
580 mdelay(10);
581 wled_init(pinfo);
582 qpnp_ibb_enable(true); /* +5V and -5V */
Dhaval Patel77d06852015-08-04 11:00:01 -0700583 mdelay(20);
Dhaval Patelb95039c2015-03-16 11:14:06 -0700584
585 if (pinfo->lcd_reg_en)
586 lcd_reg_enable();
587 } else {
588 if (pinfo->lcd_reg_en)
589 lcd_reg_disable();
590
591 regulator_disable(val);
592 }
593
594 return NO_ERROR;
595}
596
597int target_display_pre_on()
598{
599 writel(0xC0000CCC, MDP_CLK_CTRL0);
600 writel(0xC0000CCC, MDP_CLK_CTRL1);
601 writel(0x00CCCCCC, MDP_CLK_CTRL2);
602 writel(0x000000CC, MDP_CLK_CTRL6);
603 writel(0x0CCCC0C0, MDP_CLK_CTRL3);
604 writel(0xCCCCC0C0, MDP_CLK_CTRL4);
605 writel(0xCCCCC0C0, MDP_CLK_CTRL5);
606 writel(0x00CCC000, MDP_CLK_CTRL7);
607
608 return NO_ERROR;
609}
610
611int target_dsi_phy_config(struct mdss_dsi_phy_ctrl *phy_db)
612{
613 memcpy(phy_db->strength, panel_strength_ctrl, STRENGTH_SIZE_IN_BYTES_8996 *
614 sizeof(uint32_t));
615 memcpy(phy_db->regulator, panel_regulator_settings,
616 REGULATOR_SIZE_IN_BYTES_8996 * sizeof(uint32_t));
617 memcpy(phy_db->laneCfg, panel_lane_config, LANE_SIZE_IN_BYTES_8996);
618 return NO_ERROR;
619}
620
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530621bool target_display_panel_node(char *pbuf, uint16_t buf_size)
Dhaval Patelb95039c2015-03-16 11:14:06 -0700622{
623 int prefix_string_len = strlen(DISPLAY_CMDLINE_PREFIX);
624 bool ret = true;
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530625 struct oem_panel_data oem = mdss_dsi_get_oem_data();
Tatenda Chipeperekwa6143b272015-10-28 18:21:28 -0700626 char vic_buf[HDMI_VIC_LEN] = "0";
Dhaval Patelb95039c2015-03-16 11:14:06 -0700627
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530628 if (!strcmp(oem.panel, HDMI_PANEL_NAME)) {
Dhaval Patelb95039c2015-03-16 11:14:06 -0700629 if (buf_size < (prefix_string_len + LK_OVERRIDE_PANEL_LEN +
630 strlen(HDMI_CONTROLLER_STRING))) {
631 dprintf(CRITICAL, "command line argument is greater than buffer size\n");
632 return false;
633 }
634
635 strlcpy(pbuf, DISPLAY_CMDLINE_PREFIX, buf_size);
636 buf_size -= prefix_string_len;
637 strlcat(pbuf, LK_OVERRIDE_PANEL, buf_size);
638 buf_size -= LK_OVERRIDE_PANEL_LEN;
639 strlcat(pbuf, HDMI_CONTROLLER_STRING, buf_size);
Tatenda Chipeperekwa6143b272015-10-28 18:21:28 -0700640 buf_size -= strlen(HDMI_CONTROLLER_STRING);
641 mdss_hdmi_get_vic(vic_buf);
642 strlcat(pbuf, vic_buf, buf_size);
Dhaval Patelb95039c2015-03-16 11:14:06 -0700643 } else {
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530644 ret = gcdb_display_cmdline_arg(pbuf, buf_size);
Dhaval Patelb95039c2015-03-16 11:14:06 -0700645 }
646
647 return ret;
648}
649
Siddharth Zaveriacaacc32015-12-12 15:10:33 -0500650void target_set_switch_gpio(int enable_dsi2hdmibridge)
651{
652 gpio_tlmm_config(dsi2hdmi_switch_gpio.pin_id, 0,
653 dsi2hdmi_switch_gpio.pin_direction,
654 dsi2hdmi_switch_gpio.pin_pull,
655 dsi2hdmi_switch_gpio.pin_strength,
656 dsi2hdmi_switch_gpio.pin_state);
657 gpio_set(enable_gpio.pin_id, GPIO_STATE_HIGH);
658 if (enable_dsi2hdmibridge)
659 gpio_set(enable_gpio.pin_id, GPIO_STATE_LOW); /* DSI2HDMI Bridge */
660 else
661 gpio_set(enable_gpio.pin_id, GPIO_STATE_HIGH); /* Normal DSI operation */
662}
663
Dhaval Patelb95039c2015-03-16 11:14:06 -0700664void target_display_init(const char *panel_name)
665{
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530666 struct oem_panel_data oem;
Dhaval Patelb95039c2015-03-16 11:14:06 -0700667
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530668 set_panel_cmd_string(panel_name);
669 oem = mdss_dsi_get_oem_data();
670 if (!strcmp(oem.panel, NO_PANEL_CONFIG)
671 || !strcmp(oem.panel, SIM_VIDEO_PANEL)
672 || !strcmp(oem.panel, SIM_DUALDSI_VIDEO_PANEL)
673 || !strcmp(oem.panel, SIM_CMD_PANEL)
674 || !strcmp(oem.panel, SIM_DUALDSI_CMD_PANEL)
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530675 || oem.skip) {
Dhaval Patelb95039c2015-03-16 11:14:06 -0700676 dprintf(INFO, "Selected panel: %s\nSkip panel configuration\n",
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530677 oem.panel);
Dhaval Patelb95039c2015-03-16 11:14:06 -0700678 return;
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530679 } else if (!strcmp(oem.panel, HDMI_PANEL_NAME)) {
Ajay Singh Parmar68b8ce92015-02-12 19:16:47 -0800680 dprintf(INFO, "%s: HDMI is primary\n", __func__);
681 mdss_hdmi_display_init(MDP_REV_50, (void *) HDMI_FB_ADDR);
Dhaval Patelb95039c2015-03-16 11:14:06 -0700682 return;
683 }
684
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530685 if (gcdb_display_init(oem.panel, MDP_REV_50, (void *)MIPI_FB_ADDR)) {
Dhaval Patelb95039c2015-03-16 11:14:06 -0700686 target_force_cont_splash_disable(true);
687 msm_display_off();
688 }
689
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530690 if (!oem.cont_splash) {
Dhaval Patelb95039c2015-03-16 11:14:06 -0700691 dprintf(INFO, "Forcing continuous splash disable\n");
692 target_force_cont_splash_disable(true);
693 }
694}
695
696void target_display_shutdown(void)
697{
698 gcdb_display_shutdown();
699}