blob: bdc9b1b010ae1900e91df491dcd3eff20bd06a03 [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>
Ajay Singh Parmar6d395a52015-02-16 21:05:24 -080036#include <mdss_hdmi.h>
Dhaval Patelb95039c2015-03-16 11:14:06 -070037#include <pm8x41.h>
38#include <pm8x41_wled.h>
39#include <qpnp_wled.h>
40#include <board.h>
41#include <mdp5.h>
42#include <endian.h>
43#include <regulator.h>
44#include <qtimer.h>
45#include <arch/defines.h>
46#include <platform/gpio.h>
47#include <platform/clock.h>
48#include <platform/iomap.h>
49#include <target/display.h>
50#include <mipi_dsi_autopll_thulium.h>
Siddharth Zaveriacaacc32015-12-12 15:10:33 -050051#include <mipi_dsi_i2c.h>
Dhaval Patelb95039c2015-03-16 11:14:06 -070052
53#include "include/panel.h"
54#include "include/display_resource.h"
55#include "gcdb_display.h"
56
57#define GPIO_STATE_LOW 0
58#define GPIO_STATE_HIGH 2
59#define RESET_GPIO_SEQ_LEN 3
60
61#define PWM_DUTY_US 13
62#define PWM_PERIOD_US 27
63#define PMIC_WLED_SLAVE_ID 3
64#define PMIC_MPP_SLAVE_ID 2
65
66#define MAX_POLL_READS 15
67#define POLL_TIMEOUT_US 1000
68
69#define STRENGTH_SIZE_IN_BYTES_8996 10
70#define REGULATOR_SIZE_IN_BYTES_8996 5
71#define LANE_SIZE_IN_BYTES_8996 20
72
73/*---------------------------------------------------------------------------*/
74/* GPIO configuration */
75/*---------------------------------------------------------------------------*/
76static struct gpio_pin reset_gpio = {
77 "msmgpio", 8, 3, 1, 0, 1
78};
79
80static struct gpio_pin lcd_reg_en = { /* boost regulator */
81 "pmi8994_gpios", 8, 3, 1, 0, 1
82};
83
84static struct gpio_pin bklt_gpio = { /* lcd_bklt_reg_en */
85 "pm8994_gpios", 14, 3, 1, 0, 1
86};
87
Siddharth Zaveriacaacc32015-12-12 15:10:33 -050088static struct gpio_pin enable_gpio = {
89 "msmgpio", 10, 3, 1, 0, 1
90};
91
92static struct gpio_pin dsi2hdmi_switch_gpio = {
93 "msmgpio", 105, 3, 1, 0, 1
94};
95
Ajay Singh Parmar865f7d22015-02-13 23:47:40 -080096/* gpio name, id, strength, direction, pull, state. */
97static struct gpio_pin hdmi_cec_gpio = { /* CEC */
98 "msmgpio", 31, 0, 2, 3, 1
99};
100
101static struct gpio_pin hdmi_ddc_clk_gpio = { /* DDC CLK */
102 "msmgpio", 32, 0, 2, 3, 1
103};
104
105static struct gpio_pin hdmi_ddc_data_gpio = { /* DDC DATA */
106 "msmgpio", 33, 0, 2, 3, 1
107};
108
109static struct gpio_pin hdmi_hpd_gpio = { /* HPD, input */
110 "msmgpio", 34, 7, 0, 1, 1
111};
112
Ajay Singh Parmar47252ac2015-02-14 13:16:15 -0800113static void target_hdmi_ldo_enable(uint8_t enable)
114{
115 if (enable)
116 regulator_enable(REG_LDO12);
117 else
118 regulator_disable(REG_LDO12);
119}
120
121static void target_hdmi_mpp4_enable(uint8_t enable)
122{
123 struct pm8x41_mpp mpp;
124
125 /* Enable MPP4 */
126 pmi8994_config_mpp_slave_id(0);
127
128 mpp.base = PM8x41_MMP4_BASE;
129 mpp.vin = MPP_VIN2;
130 mpp.mode = MPP_HIGH;;
131 if (enable) {
132 pm8x41_config_output_mpp(&mpp);
133 pm8x41_enable_mpp(&mpp, MPP_ENABLE);
134 } else {
135 pm8x41_enable_mpp(&mpp, MPP_DISABLE);
136 }
137
138 /* Need delay before power on regulators */
139 mdelay(20);
140}
141
142int target_hdmi_regulator_ctrl(uint8_t enable)
143{
144 target_hdmi_ldo_enable(enable);
145
146 target_hdmi_mpp4_enable(enable);
147
148 return 0;
149}
150
Ajay Singh Parmar865f7d22015-02-13 23:47:40 -0800151int target_hdmi_gpio_ctrl(uint8_t enable)
152{
153 gpio_tlmm_config(hdmi_cec_gpio.pin_id, 1, /* gpio 31, CEC */
154 hdmi_cec_gpio.pin_direction, hdmi_cec_gpio.pin_pull,
155 hdmi_cec_gpio.pin_strength, hdmi_cec_gpio.pin_state);
156
157 gpio_tlmm_config(hdmi_ddc_clk_gpio.pin_id, 1, /* gpio 32, DDC CLK */
158 hdmi_ddc_clk_gpio.pin_direction, hdmi_ddc_clk_gpio.pin_pull,
159 hdmi_ddc_clk_gpio.pin_strength, hdmi_ddc_clk_gpio.pin_state);
160
161
162 gpio_tlmm_config(hdmi_ddc_data_gpio.pin_id, 1, /* gpio 33, DDC DATA */
163 hdmi_ddc_data_gpio.pin_direction, hdmi_ddc_data_gpio.pin_pull,
164 hdmi_ddc_data_gpio.pin_strength, hdmi_ddc_data_gpio.pin_state);
165
166 gpio_tlmm_config(hdmi_hpd_gpio.pin_id, 1, /* gpio 34, HPD */
167 hdmi_hpd_gpio.pin_direction, hdmi_hpd_gpio.pin_pull,
168 hdmi_hpd_gpio.pin_strength, hdmi_hpd_gpio.pin_state);
169
170 gpio_set(hdmi_cec_gpio.pin_id, hdmi_cec_gpio.pin_direction);
171 gpio_set(hdmi_ddc_clk_gpio.pin_id, hdmi_ddc_clk_gpio.pin_direction);
172 gpio_set(hdmi_ddc_data_gpio.pin_id, hdmi_ddc_data_gpio.pin_direction);
173 gpio_set(hdmi_hpd_gpio.pin_id, hdmi_hpd_gpio.pin_direction);
174
175 return NO_ERROR;
176}
177
Tatenda Chipeperekwa65c482f2015-11-04 16:46:22 -0800178int target_hdmi_pll_clock(uint8_t enable, struct msm_panel_info *pinfo)
179{
180 if (enable) {
181 hdmi_phy_reset();
182 hdmi_pll_config(pinfo->clk_rate);
183 hdmi_vco_enable();
184 hdmi_pixel_clk_enable(pinfo->clk_rate);
185 } else if(!target_cont_splash_screen()) {
186 /* Disable clocks if continuous splash off */
187 hdmi_pixel_clk_disable();
188 hdmi_vco_disable();
189 }
190
191 return NO_ERROR;
192}
193
Ajay Singh Parmar6d395a52015-02-16 21:05:24 -0800194int target_hdmi_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
195{
196 dprintf(SPEW, "%s: target_panel_clock\n", __func__);
197
Tatenda Chipeperekwa65c482f2015-11-04 16:46:22 -0800198 uint32_t board_version = board_soc_version();
199
200 if (board_version == 0x20000 || board_version == 0x20001)
201 video_gdsc_enable();
202
Ajay Singh Parmar6d395a52015-02-16 21:05:24 -0800203 if (enable) {
204 mmss_gdsc_enable();
205 mmss_bus_clock_enable();
206 mdp_clock_enable();
Tatenda Chipeperekwa65c482f2015-11-04 16:46:22 -0800207 hdmi_ahb_core_clk_enable();
Ajay Singh Parmar6d395a52015-02-16 21:05:24 -0800208 } else if(!target_cont_splash_screen()) {
Tatenda Chipeperekwa65c482f2015-11-04 16:46:22 -0800209 hdmi_core_ahb_clk_disable();
Ajay Singh Parmar6d395a52015-02-16 21:05:24 -0800210 mdp_clock_disable();
211 mmss_bus_clock_disable();
212 mmss_gdsc_disable();
Tatenda Chipeperekwa65c482f2015-11-04 16:46:22 -0800213 if (board_version == 0x20000 || board_version == 0x20001)
214 video_gdsc_disable();
Ajay Singh Parmar6d395a52015-02-16 21:05:24 -0800215 }
216
217 return NO_ERROR;
218}
219
Dhaval Patelb95039c2015-03-16 11:14:06 -0700220static uint32_t thulium_dsi_pll_lock_status(uint32_t pll_base, uint32_t off,
221 uint32_t bit)
222{
223 uint32_t cnt, status;
224
225 /* check pll lock first */
226 for (cnt = 0; cnt < MAX_POLL_READS; cnt++) {
227 status = readl(pll_base + off);
228 dprintf(SPEW, "%s: pll_base=%x cnt=%d status=%x\n",
229 __func__, pll_base, cnt, status);
230 status &= BIT(bit); /* bit 5 */
231 if (status)
232 break;
233 udelay(POLL_TIMEOUT_US);
234 }
235
236 return status;
237}
238
239static uint32_t thulium_dsi_pll_enable_seq(uint32_t phy_base, uint32_t pll_base)
240{
241 uint32_t pll_locked;
242
Dhaval Patela9959bf2015-10-13 11:43:54 -0700243 writel(0x10, phy_base + 0x45c);
Dhaval Patelb95039c2015-03-16 11:14:06 -0700244 writel(0x01, phy_base + 0x48);
245 dmb();
246
247 pll_locked = thulium_dsi_pll_lock_status(pll_base, 0xcc, 5);
248 if (pll_locked)
249 pll_locked = thulium_dsi_pll_lock_status(pll_base, 0xcc, 0);
250
251 if (!pll_locked)
252 dprintf(ERROR, "%s: DSI PLL lock failed\n", __func__);
253 else
254 dprintf(SPEW, "%s: DSI PLL lock Success\n", __func__);
255
256 return pll_locked;
257}
258
259static int thulium_wled_backlight_ctrl(uint8_t enable)
260{
261 qpnp_wled_enable_backlight(enable);
Dhaval Patelb95039c2015-03-16 11:14:06 -0700262 return NO_ERROR;
263}
264
265static int thulium_pwm_backlight_ctrl(uint8_t enable)
266{
267 uint8_t slave_id = 3; /* lpg at pmi */
268
269 if (enable) {
270 /* lpg channel 4 */
271
272 /* LPG_ENABLE_CONTROL */
273 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x0);
274 mdelay(100);
275
276 /* LPG_VALUE_LSB, duty cycle = 0x80/0x200 = 1/4 */
277 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x44, 0x80);
278 /* LPG_VALUE_MSB */
279 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x45, 0x00);
280 /* LPG_PWM_SYNC */
281 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x47, 0x01);
282
283 /* LPG_PWM_SIZE_CLK, */
284 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x41, 0x13);
285 /* LPG_PWM_FREQ_PREDIV */
286 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x42, 0x02);
287 /* LPG_PWM_TYPE_CONFIG */
288 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x43, 0x20);
289 /* LPG_ENABLE_CONTROL */
290 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x04);
291
292 /* SEC_ACCESS */
293 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0xD0, 0xA5);
294 /* DTEST4, OUT_HI */
295 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0xE5, 0x01);
296 /* LPG_ENABLE_CONTROL */
297 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0xA4);
298 } else {
299 /* LPG_ENABLE_CONTROL */
300 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x0);
301 }
302
303 return NO_ERROR;
304}
305
306static void lcd_reg_enable(void)
307{
308 uint8_t slave_id = 2; /* gpio at pmi */
309
310 struct pm8x41_gpio gpio = {
311 .direction = PM_GPIO_DIR_OUT,
312 .function = PM_GPIO_FUNC_HIGH,
313 .vin_sel = 2, /* VIN_2 */
314 .output_buffer = PM_GPIO_OUT_CMOS,
315 .out_strength = PM_GPIO_OUT_DRIVE_MED,
316 };
317
318 pm8x41_gpio_config_sid(slave_id, lcd_reg_en.pin_id, &gpio);
319 pm8x41_gpio_set_sid(slave_id, lcd_reg_en.pin_id, 1);
320}
321
322static void lcd_reg_disable(void)
323{
324 uint8_t slave_id = 2; /* gpio at pmi */
325
326 pm8x41_gpio_set_sid(slave_id, lcd_reg_en.pin_id, 0);
327}
328
329static void lcd_bklt_reg_enable(void)
330{
331 struct pm8x41_gpio gpio = {
332 .direction = PM_GPIO_DIR_OUT,
333 .function = PM_GPIO_FUNC_HIGH,
334 .vin_sel = 2, /* VIN_2 */
335 .output_buffer = PM_GPIO_OUT_CMOS,
336 .out_strength = PM_GPIO_OUT_DRIVE_LOW,
337 };
338
339 pm8x41_gpio_config(bklt_gpio.pin_id, &gpio);
340 pm8x41_gpio_set(bklt_gpio.pin_id, 1);
341}
342
343static void lcd_bklt_reg_disable(void)
344{
345 pm8x41_gpio_set(bklt_gpio.pin_id, 0);
346}
347
Siddharth Zaveriacaacc32015-12-12 15:10:33 -0500348static int dsi2HDMI_i2c_write_regs(struct msm_panel_info *pinfo,
349 struct mipi_dsi_i2c_cmd *cfg, int size)
350{
351 int ret = NO_ERROR;
352 int i;
353 uint8_t addr;
354
355 if (!cfg || size < 0) {
356 dprintf(CRITICAL, "Invalid input: register array is null\n");
357 return ERR_INVALID_ARGS;
358 }
359
360 for (i = 0; i < size; i++) {
361 switch (cfg[i].i2c_addr) {
362 case ADV7533_MAIN:
363 addr = pinfo->adv7533.i2c_main_addr;
364 break;
365 case ADV7533_CEC_DSI:
366 addr = pinfo->adv7533.i2c_cec_addr;
367 break;
368 default:
369 dprintf(CRITICAL, "Invalid I2C addr in array\n");
370 ret = ERR_INVALID_ARGS;
371 goto w_regs_fail;
372 }
373
374 ret = mipi_dsi_i2c_write_byte(addr, cfg[i].reg,
375 cfg[i].val);
376 if (ret) {
377 dprintf(CRITICAL, "mipi_dsi reg writes failed\n");
378 goto w_regs_fail;
379 }
380 if (cfg[i].sleep_in_ms) {
381 udelay(cfg[i].sleep_in_ms*1000);
382 }
383 }
384w_regs_fail:
385 return ret;
386}
387
388int target_display_dsi2hdmi_program_addr(struct msm_panel_info *pinfo)
389{
390 int ret = NO_ERROR;
391 uint8_t i2c_8bits = pinfo->adv7533.i2c_cec_addr << 1;
392 ret = mipi_dsi_i2c_write_byte(pinfo->adv7533.i2c_main_addr,
393 0xE1, i2c_8bits);
394 if (ret) {
395 dprintf(CRITICAL, "Error in programming CEC DSI addr\n");
396 } else {
397 dprintf(SPEW, "CEC address programming successful\n");
398 }
399 return ret;
400}
401
402int target_display_dsi2hdmi_config(struct msm_panel_info *pinfo)
403{
404 int ret = NO_ERROR;
405
406 if (!pinfo) {
407 dprintf(CRITICAL, "Invalid input: pinfo is null\n");
408 return ERR_INVALID_ARGS;
409 }
410
411 if (!pinfo->adv7533.program_i2c_addr) {
412 ret = target_display_dsi2hdmi_program_addr(pinfo);
413 if (ret) {
414 dprintf(CRITICAL, "Error in programming cec dsi addr\n");
415 return ret;
416 } else {
417 dprintf(SPEW, "successfully programmed cec dsi addr\n");
418 pinfo->adv7533.program_i2c_addr = 1;
419 }
420 }
421
422 /*
423 * If dsi to HDMI bridge chip connected then
424 * send I2c commands to the chip
425 */
426 if (pinfo->adv7533.dsi_setup_cfg_i2c_cmd)
427 ret = dsi2HDMI_i2c_write_regs(pinfo, pinfo->adv7533.dsi_setup_cfg_i2c_cmd,
428 pinfo->adv7533.num_of_cfg_i2c_cmds);
429 if (ret) {
430 dprintf(CRITICAL, "Error in writing adv7533 setup registers\n");
431 return ret;
432 }
433
434 if (pinfo->adv7533.dsi_tg_i2c_cmd)
435 ret = dsi2HDMI_i2c_write_regs(pinfo, pinfo->adv7533.dsi_tg_i2c_cmd,
436 pinfo->adv7533.num_of_tg_i2c_cmds);
437 if (ret) {
438 dprintf(CRITICAL, "Error in writing adv7533 timing registers\n");
439 }
440
441 return ret;
442}
443
Dhaval Patelb95039c2015-03-16 11:14:06 -0700444int target_backlight_ctrl(struct backlight *bl, uint8_t enable)
445{
446 uint32_t ret = NO_ERROR;
447 struct pm8x41_mpp mpp;
448 int rc;
449
450 if (!bl) {
451 dprintf(CRITICAL, "backlight structure is not available\n");
452 return ERR_INVALID_ARGS;
453 }
454
455 switch (bl->bl_interface_type) {
456 case BL_WLED:
457 /* Enable MPP4 */
458 pmi8994_config_mpp_slave_id(PMIC_MPP_SLAVE_ID);
459 mpp.base = PM8x41_MMP4_BASE;
460 mpp.vin = MPP_VIN2;
461 if (enable) {
462 pm_pwm_enable(false);
463 rc = pm_pwm_config(PWM_DUTY_US, PWM_PERIOD_US);
464 if (rc < 0) {
465 mpp.mode = MPP_HIGH;
466 } else {
467 mpp.mode = MPP_DTEST1;
468 pm_pwm_enable(true);
469 }
470 pm8x41_config_output_mpp(&mpp);
471 pm8x41_enable_mpp(&mpp, MPP_ENABLE);
472 } else {
473 pm_pwm_enable(false);
474 pm8x41_enable_mpp(&mpp, MPP_DISABLE);
475 }
Dhaval Patelb95039c2015-03-16 11:14:06 -0700476 /* Enable WLED backlight control */
477 ret = thulium_wled_backlight_ctrl(enable);
478 break;
479 case BL_PWM:
480 /* Enable MPP1 */
481 pmi8994_config_mpp_slave_id(PMIC_MPP_SLAVE_ID);
482 mpp.base = PM8x41_MMP1_BASE;
483 mpp.vin = MPP_VIN2;
484 mpp.mode = MPP_DTEST4;
485 if (enable) {
486 pm8x41_config_output_mpp(&mpp);
487 pm8x41_enable_mpp(&mpp, MPP_ENABLE);
488 } else {
489 pm8x41_enable_mpp(&mpp, MPP_DISABLE);
490 }
Dhaval Patelb95039c2015-03-16 11:14:06 -0700491 ret = thulium_pwm_backlight_ctrl(enable);
492 break;
493 default:
494 dprintf(CRITICAL, "backlight type:%d not supported\n",
495 bl->bl_interface_type);
496 return ERR_NOT_SUPPORTED;
497 }
498
499 return ret;
500}
501
502int target_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
503{
Aravind Venkateswaran9586be62015-05-20 00:51:06 -0700504 uint32_t flags, dsi_phy_pll_out;
Dhaval Patelb95039c2015-03-16 11:14:06 -0700505 uint32_t ret = NO_ERROR;
506 uint32_t board_version = board_soc_version();
Dhaval Pateldacdac92016-02-08 17:04:33 -0800507 uint32_t board_hw_id = board_hardware_id();
508 bool video_core_enable = false;
Jeevan Shrirama3860092015-08-03 15:16:57 -0700509 struct dfps_pll_codes *pll_codes = &pinfo->mipi.pll_codes;
Dhaval Patelb95039c2015-03-16 11:14:06 -0700510
511 if (pinfo->dest == DISPLAY_2) {
512 flags = MMSS_DSI_CLKS_FLAG_DSI1;
513 if (pinfo->mipi.dual_dsi)
514 flags |= MMSS_DSI_CLKS_FLAG_DSI0;
515 } else {
516 flags = MMSS_DSI_CLKS_FLAG_DSI0;
517 if (pinfo->mipi.dual_dsi)
518 flags |= MMSS_DSI_CLKS_FLAG_DSI1;
519 }
520
Dhaval Pateldacdac92016-02-08 17:04:33 -0800521 /* only required for msm8996 v2 and v2.1 revision */
522 video_core_enable = (board_version == 0x20000 || board_version == 0x20001) &&
523 !(board_hw_id == MSM8996SG || board_hw_id == APQ8096SG);
524
Dhaval Patelb95039c2015-03-16 11:14:06 -0700525 if (!enable) {
Ashish Garg113885e2016-08-25 16:42:21 +0530526 mmss_dsi_clock_disable(flags);
527
Dhaval Patelb95039c2015-03-16 11:14:06 -0700528 /* stop pll */
529 writel(0x0, pinfo->mipi.phy_base + 0x48);
530 dmb();
531
Dhaval Patelb95039c2015-03-16 11:14:06 -0700532 goto clks_disable;
533 }
534
Dhaval Pateldacdac92016-02-08 17:04:33 -0800535 if (video_core_enable)
Dhaval Patelb95039c2015-03-16 11:14:06 -0700536 video_gdsc_enable();
537 mmss_gdsc_enable();
538 mmss_bus_clock_enable();
539 mdp_clock_enable();
540 mdss_dsi_auto_pll_thulium_config(pinfo);
541
542 if (!thulium_dsi_pll_enable_seq(pinfo->mipi.phy_base,
543 pinfo->mipi.pll_base)) {
544 ret = ERROR;
545 dprintf(CRITICAL, "PLL failed to lock!\n");
546 goto clks_disable;
547 }
Aravind Venkateswaran9586be62015-05-20 00:51:06 -0700548
Jeevan Shrirama3860092015-08-03 15:16:57 -0700549 pll_codes->codes[0] = readl_relaxed(pinfo->mipi.pll_base +
550 MMSS_DSI_PHY_PLL_CORE_KVCO_CODE);
551 pll_codes->codes[1] = readl_relaxed(pinfo->mipi.pll_base +
552 MMSS_DSI_PHY_PLL_CORE_VCO_TUNE);
553 dprintf(SPEW, "codes %d %d\n", pll_codes->codes[0],
554 pll_codes->codes[1]);
555
Aravind Venkateswaran9586be62015-05-20 00:51:06 -0700556 if (pinfo->mipi.use_dsi1_pll)
557 dsi_phy_pll_out = DSI1_PHY_PLL_OUT;
558 else
559 dsi_phy_pll_out = DSI0_PHY_PLL_OUT;
560 mmss_dsi_clock_enable(dsi_phy_pll_out, flags);
561
Dhaval Patelb95039c2015-03-16 11:14:06 -0700562 return NO_ERROR;
563
564clks_disable:
565 mdp_clock_disable();
566 mmss_bus_clock_disable();
567 mmss_gdsc_disable();
Dhaval Pateldacdac92016-02-08 17:04:33 -0800568 if (video_core_enable)
Dhaval Patelb95039c2015-03-16 11:14:06 -0700569 video_gdsc_disable();
570
571 return ret;
572}
573
574int target_panel_reset(uint8_t enable, struct panel_reset_sequence *resetseq,
575 struct msm_panel_info *pinfo)
576{
577 uint32_t i = 0;
578
579 if (enable) {
580 gpio_tlmm_config(reset_gpio.pin_id, 0,
581 reset_gpio.pin_direction, reset_gpio.pin_pull,
582 reset_gpio.pin_strength, reset_gpio.pin_state);
583 /* reset */
584 for (i = 0; i < RESET_GPIO_SEQ_LEN; i++) {
585 if (resetseq->pin_state[i] == GPIO_STATE_LOW)
586 gpio_set(reset_gpio.pin_id, GPIO_STATE_LOW);
587 else
588 gpio_set(reset_gpio.pin_id, GPIO_STATE_HIGH);
589 mdelay(resetseq->sleep[i]);
590 }
591 lcd_bklt_reg_enable();
592 } else {
593 lcd_bklt_reg_disable();
594 gpio_set(reset_gpio.pin_id, 0);
595 }
596
597 return NO_ERROR;
598}
599
600static void wled_init(struct msm_panel_info *pinfo)
601{
602 struct qpnp_wled_config_data config = {0};
603 struct labibb_desc *labibb;
604 int display_type = 0;
605
606 labibb = pinfo->labibb;
607
608 if (labibb)
609 display_type = labibb->amoled_panel;
610
611 config.display_type = display_type;
612 config.lab_init_volt = 4600000; /* fixed, see pmi register */
613 config.ibb_init_volt = 1400000; /* fixed, see pmi register */
614
615 if (labibb && labibb->force_config) {
616 config.lab_min_volt = labibb->lab_min_volt;
617 config.lab_max_volt = labibb->lab_max_volt;
618 config.ibb_min_volt = labibb->ibb_min_volt;
619 config.ibb_max_volt = labibb->ibb_max_volt;
620 config.pwr_up_delay = labibb->pwr_up_delay;
621 config.pwr_down_delay = labibb->pwr_down_delay;
622 config.ibb_discharge_en = labibb->ibb_discharge_en;
623 } else {
624 /* default */
625 config.pwr_up_delay = 3;
626 config.pwr_down_delay = 3;
627 config.ibb_discharge_en = 1;
628 if (display_type) { /* amoled */
629 config.lab_min_volt = 4600000;
630 config.lab_max_volt = 4600000;
631 config.ibb_min_volt = 4000000;
632 config.ibb_max_volt = 4000000;
633 } else { /* lcd */
634 config.lab_min_volt = 5500000;
635 config.lab_max_volt = 5500000;
636 config.ibb_min_volt = 5500000;
637 config.ibb_max_volt = 5500000;
638 }
639 }
640
641 dprintf(SPEW, "%s: %d %d %d %d %d %d %d %d %d %d\n", __func__,
642 config.display_type,
643 config.lab_min_volt, config.lab_max_volt,
644 config.ibb_min_volt, config.ibb_max_volt,
645 config.lab_init_volt, config.ibb_init_volt,
646 config.pwr_up_delay, config.pwr_down_delay,
647 config.ibb_discharge_en);
648
649
650 /* QPNP WLED init for display backlight */
651 pm8x41_wled_config_slave_id(PMIC_WLED_SLAVE_ID);
652
653 qpnp_wled_init(&config);
654}
655
656int target_ldo_ctrl(uint8_t enable, struct msm_panel_info *pinfo)
657{
658 uint32_t val = BIT(1) | BIT(13) | BIT(27);
659
660 if (enable) {
661 regulator_enable(val);
662 mdelay(10);
663 wled_init(pinfo);
664 qpnp_ibb_enable(true); /* +5V and -5V */
Dhaval Patel77d06852015-08-04 11:00:01 -0700665 mdelay(20);
Dhaval Patelb95039c2015-03-16 11:14:06 -0700666
667 if (pinfo->lcd_reg_en)
668 lcd_reg_enable();
669 } else {
670 if (pinfo->lcd_reg_en)
671 lcd_reg_disable();
672
673 regulator_disable(val);
674 }
675
676 return NO_ERROR;
677}
678
679int target_display_pre_on()
680{
681 writel(0xC0000CCC, MDP_CLK_CTRL0);
682 writel(0xC0000CCC, MDP_CLK_CTRL1);
683 writel(0x00CCCCCC, MDP_CLK_CTRL2);
684 writel(0x000000CC, MDP_CLK_CTRL6);
685 writel(0x0CCCC0C0, MDP_CLK_CTRL3);
686 writel(0xCCCCC0C0, MDP_CLK_CTRL4);
687 writel(0xCCCCC0C0, MDP_CLK_CTRL5);
688 writel(0x00CCC000, MDP_CLK_CTRL7);
689
690 return NO_ERROR;
691}
692
693int target_dsi_phy_config(struct mdss_dsi_phy_ctrl *phy_db)
694{
695 memcpy(phy_db->strength, panel_strength_ctrl, STRENGTH_SIZE_IN_BYTES_8996 *
696 sizeof(uint32_t));
697 memcpy(phy_db->regulator, panel_regulator_settings,
698 REGULATOR_SIZE_IN_BYTES_8996 * sizeof(uint32_t));
699 memcpy(phy_db->laneCfg, panel_lane_config, LANE_SIZE_IN_BYTES_8996);
700 return NO_ERROR;
701}
702
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530703bool target_display_panel_node(char *pbuf, uint16_t buf_size)
Dhaval Patelb95039c2015-03-16 11:14:06 -0700704{
705 int prefix_string_len = strlen(DISPLAY_CMDLINE_PREFIX);
706 bool ret = true;
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530707 struct oem_panel_data oem = mdss_dsi_get_oem_data();
Tatenda Chipeperekwa6143b272015-10-28 18:21:28 -0700708 char vic_buf[HDMI_VIC_LEN] = "0";
Dhaval Patelb95039c2015-03-16 11:14:06 -0700709
Shalini Krishnamoorthi3d4bb2a2016-06-24 15:17:29 -0700710 if ((!strcmp(oem.panel, HDMI_PANEL_NAME)) || \
711 ((!strlen(oem.panel)) && (platform_is_apq8096_mediabox()))) {
Dhaval Patelb95039c2015-03-16 11:14:06 -0700712 if (buf_size < (prefix_string_len + LK_OVERRIDE_PANEL_LEN +
713 strlen(HDMI_CONTROLLER_STRING))) {
714 dprintf(CRITICAL, "command line argument is greater than buffer size\n");
715 return false;
716 }
717
718 strlcpy(pbuf, DISPLAY_CMDLINE_PREFIX, buf_size);
719 buf_size -= prefix_string_len;
720 strlcat(pbuf, LK_OVERRIDE_PANEL, buf_size);
721 buf_size -= LK_OVERRIDE_PANEL_LEN;
722 strlcat(pbuf, HDMI_CONTROLLER_STRING, buf_size);
Tatenda Chipeperekwa6143b272015-10-28 18:21:28 -0700723 buf_size -= strlen(HDMI_CONTROLLER_STRING);
724 mdss_hdmi_get_vic(vic_buf);
725 strlcat(pbuf, vic_buf, buf_size);
Dhaval Patelb95039c2015-03-16 11:14:06 -0700726 } else {
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530727 ret = gcdb_display_cmdline_arg(pbuf, buf_size);
Dhaval Patelb95039c2015-03-16 11:14:06 -0700728 }
729
730 return ret;
731}
732
Siddharth Zaveriacaacc32015-12-12 15:10:33 -0500733void target_set_switch_gpio(int enable_dsi2hdmibridge)
734{
735 gpio_tlmm_config(dsi2hdmi_switch_gpio.pin_id, 0,
736 dsi2hdmi_switch_gpio.pin_direction,
737 dsi2hdmi_switch_gpio.pin_pull,
738 dsi2hdmi_switch_gpio.pin_strength,
739 dsi2hdmi_switch_gpio.pin_state);
740 gpio_set(enable_gpio.pin_id, GPIO_STATE_HIGH);
741 if (enable_dsi2hdmibridge)
742 gpio_set(enable_gpio.pin_id, GPIO_STATE_LOW); /* DSI2HDMI Bridge */
743 else
744 gpio_set(enable_gpio.pin_id, GPIO_STATE_HIGH); /* Normal DSI operation */
745}
746
Dhaval Patelb95039c2015-03-16 11:14:06 -0700747void target_display_init(const char *panel_name)
748{
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530749 struct oem_panel_data oem;
Dhaval Patelb95039c2015-03-16 11:14:06 -0700750
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530751 set_panel_cmd_string(panel_name);
752 oem = mdss_dsi_get_oem_data();
753 if (!strcmp(oem.panel, NO_PANEL_CONFIG)
754 || !strcmp(oem.panel, SIM_VIDEO_PANEL)
755 || !strcmp(oem.panel, SIM_DUALDSI_VIDEO_PANEL)
756 || !strcmp(oem.panel, SIM_CMD_PANEL)
757 || !strcmp(oem.panel, SIM_DUALDSI_CMD_PANEL)
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530758 || oem.skip) {
Dhaval Patelb95039c2015-03-16 11:14:06 -0700759 dprintf(INFO, "Selected panel: %s\nSkip panel configuration\n",
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530760 oem.panel);
Dhaval Patelb95039c2015-03-16 11:14:06 -0700761 return;
Shalini Krishnamoorthi3d4bb2a2016-06-24 15:17:29 -0700762 } else if ((!strcmp(oem.panel, HDMI_PANEL_NAME)) || \
763 ((!strlen(oem.panel)) && (platform_is_apq8096_mediabox()))) {
Ajay Singh Parmar68b8ce92015-02-12 19:16:47 -0800764 dprintf(INFO, "%s: HDMI is primary\n", __func__);
765 mdss_hdmi_display_init(MDP_REV_50, (void *) HDMI_FB_ADDR);
Dhaval Patelb95039c2015-03-16 11:14:06 -0700766 return;
767 }
768
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530769 if (gcdb_display_init(oem.panel, MDP_REV_50, (void *)MIPI_FB_ADDR)) {
Dhaval Patelb95039c2015-03-16 11:14:06 -0700770 target_force_cont_splash_disable(true);
771 msm_display_off();
772 }
773
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530774 if (!oem.cont_splash) {
Dhaval Patelb95039c2015-03-16 11:14:06 -0700775 dprintf(INFO, "Forcing continuous splash disable\n");
776 target_force_cont_splash_disable(true);
777 }
778}
779
780void target_display_shutdown(void)
781{
Tatenda Chipeperekwad3f2cae2015-12-15 11:52:48 -0800782 struct oem_panel_data oem = mdss_dsi_get_oem_data();
Shalini Krishnamoorthi3d4bb2a2016-06-24 15:17:29 -0700783 if ((!strcmp(oem.panel, HDMI_PANEL_NAME)) || \
784 ((!strlen(oem.panel)) && (platform_is_apq8096_mediabox()))) {
Tatenda Chipeperekwad3f2cae2015-12-15 11:52:48 -0800785 msm_display_off();
786 } else {
787 gcdb_display_shutdown();
788 }
Dhaval Patelb95039c2015-03-16 11:14:06 -0700789}