blob: 45baa2bf37cc29a18136654aa7601a306b57c3fa [file] [log] [blame]
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +05301/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
2 *
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 <smem.h>
32#include <err.h>
33#include <msm_panel.h>
34#include <mipi_dsi.h>
35#include <pm8x41.h>
36#include <pm8x41_wled.h>
37#include <board.h>
38#include <mdp5.h>
39#include <scm.h>
40#include <platform/gpio.h>
41#include <platform/iomap.h>
42#include <target/display.h>
Aparna Mallavarapu430797d2014-05-15 11:52:56 +053043#include <i2c_qup.h>
44#include <blsp_qup.h>
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +053045
46#include "include/panel.h"
47#include "include/display_resource.h"
48
Padmanabhan Komanduru18aa5072014-04-17 16:52:53 +053049#define VCO_DELAY_USEC 1000
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +053050#define GPIO_STATE_LOW 0
51#define GPIO_STATE_HIGH 2
52#define RESET_GPIO_SEQ_LEN 3
53#define PWM_DUTY_US 13
54#define PWM_PERIOD_US 27
55
Padmanabhan Komanduru0a5db942014-04-17 16:56:04 +053056static void mdss_dsi_uniphy_pll_sw_reset_8916(uint32_t pll_base)
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +053057{
Padmanabhan Komanduru0a5db942014-04-17 16:56:04 +053058 writel(0x01, pll_base + 0x0068); /* PLL TEST CFG */
59 mdelay(1);
60 writel(0x00, pll_base + 0x0068); /* PLL TEST CFG */
61 mdelay(1);
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +053062}
63
Padmanabhan Komanduru0a5db942014-04-17 16:56:04 +053064static uint32_t dsi_pll_enable_seq_8916(uint32_t pll_base)
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +053065{
66 uint32_t pll_locked = 0;
67
Padmanabhan Komanduru0a5db942014-04-17 16:56:04 +053068 writel(0x01, pll_base + 0x0068); /* PLL TEST CFG */
69 udelay(1);
70 writel(0x00, pll_base + 0x0068); /* PLL TEST CFG */
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +053071
72 /*
73 * Add hardware recommended delays between register writes for
74 * the updates to take effect. These delays are necessary for the
75 * PLL to successfully lock
76 */
Padmanabhan Komanduru0a5db942014-04-17 16:56:04 +053077 writel(0x34, pll_base + 0x0070); /* CAL CFG1*/
78 udelay(1);
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +053079 writel(0x01, pll_base + 0x0020); /* GLB CFG */
Padmanabhan Komanduru0a5db942014-04-17 16:56:04 +053080 udelay(1);
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +053081 writel(0x05, pll_base + 0x0020); /* GLB CFG */
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +053082 udelay(1);
83 writel(0x0f, pll_base + 0x0020); /* GLB CFG */
Padmanabhan Komanduru0a5db942014-04-17 16:56:04 +053084 udelay(1);
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +053085
Padmanabhan Komanduru0a5db942014-04-17 16:56:04 +053086 writel(0x04, pll_base + 0x0064); /* LKDetect CFG2 */
87 udelay(1);
88 writel(0x05, pll_base + 0x0064); /* LKDetect CFG2 */
89 udelay(512);
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +053090 pll_locked = readl(pll_base + 0x00c0) & 0x01;
91
92 return pll_locked;
93}
94
95int target_backlight_ctrl(struct backlight *bl, uint8_t enable)
96{
97 struct pm8x41_mpp mpp;
98 int rc;
99
Shuo Yan123546b2014-05-19 19:35:41 +0800100 if (bl->bl_interface_type == BL_DCS)
101 return 0;
102
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530103 mpp.base = PM8x41_MMP4_BASE;
104 mpp.vin = MPP_VIN0;
105 if (enable) {
106 pm_pwm_enable(false);
107 rc = pm_pwm_config(PWM_DUTY_US, PWM_PERIOD_US);
108 if (rc < 0)
109 mpp.mode = MPP_HIGH;
110 else {
111 mpp.mode = MPP_DTEST1;
112 pm_pwm_enable(true);
113 }
114 pm8x41_config_output_mpp(&mpp);
115 pm8x41_enable_mpp(&mpp, MPP_ENABLE);
116 } else {
117 pm_pwm_enable(false);
118 pm8x41_enable_mpp(&mpp, MPP_DISABLE);
119 }
120 mdelay(20);
121 return 0;
122}
123
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530124int target_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
125{
126 int32_t ret = 0;
127 struct mdss_dsi_pll_config *pll_data;
128 dprintf(SPEW, "target_panel_clock\n");
129
130 pll_data = pinfo->mipi.dsi_pll_config;
Padmanabhan Komanduru18aa5072014-04-17 16:52:53 +0530131 pll_data->vco_delay = VCO_DELAY_USEC;
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530132
133 if (enable) {
134 mdp_gdsc_ctrl(enable);
135 mdss_bus_clocks_enable();
136 mdp_clock_enable();
137 ret = restore_secure_cfg(SECURE_DEVICE_MDSS);
138 if (ret) {
139 dprintf(CRITICAL,
140 "%s: Failed to restore MDP security configs",
141 __func__);
142 mdp_clock_disable();
143 mdss_bus_clocks_disable();
144 mdp_gdsc_ctrl(0);
145 return ret;
146 }
Padmanabhan Komanduru0a5db942014-04-17 16:56:04 +0530147 mdss_dsi_uniphy_pll_sw_reset_8916(DSI0_PLL_BASE);
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530148 mdss_dsi_auto_pll_config(DSI0_PLL_BASE,
149 MIPI_DSI0_BASE, pll_data);
Padmanabhan Komanduru0a5db942014-04-17 16:56:04 +0530150 if (!dsi_pll_enable_seq_8916(DSI0_PLL_BASE))
151 dprintf(CRITICAL, "Not able to enable the pll\n");
Vineet Bajaje022da62014-07-24 19:13:34 +0530152 gcc_dsi_clocks_enable(pinfo->mipi.dual_dsi, pll_data->pclk_m,
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530153 pll_data->pclk_n,
154 pll_data->pclk_d);
155 } else if(!target_cont_splash_screen()) {
Vineet Bajaje022da62014-07-24 19:13:34 +0530156 gcc_dsi_clocks_disable(pinfo->mipi.dual_dsi);
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530157 mdp_clock_disable();
158 mdss_bus_clocks_disable();
159 mdp_gdsc_ctrl(enable);
160 }
161
162 return 0;
163}
164
Aparna Mallavarapu430797d2014-05-15 11:52:56 +0530165#define QRD_LCD_I2C_ADDRESS 0x3E
166#define QRD_LCD_VPOS_ADDRESS 0x00
167#define QRD_LCD_VNEG_ADDRESS 0x01
168#define QRD_LCD_DIS_ADDRESS 0x03
169#define QRD_LCD_CONTROL_ADDRESS 0xFF
170
171static struct qup_i2c_dev *i2c_dev;
172static int qrd_lcd_i2c_read(uint8_t addr)
173{
174 int ret = 0;
175 /* Create a i2c_msg buffer, that is used to put the controller into read
176 mode and then to read some data. */
177 struct i2c_msg msg_buf[] = {
178 {QRD_LCD_I2C_ADDRESS, I2C_M_WR, 1, &addr},
179 {QRD_LCD_I2C_ADDRESS, I2C_M_RD, 1, &ret}
180 };
181
182 ret = qup_i2c_xfer(i2c_dev, msg_buf, 2);
183 if(ret < 0) {
184 dprintf(CRITICAL, "qup_i2c_xfer error %d\n", ret);
185 return ret;
186 }
187 return 0;
188}
189
190static int qrd_lcd_i2c_write(uint8_t addr, uint8_t val)
191{
192 int ret = 0;
193 uint8_t data_buf[] = { addr, val };
194
195 /* Create a i2c_msg buffer, that is used to put the controller into write
196 mode and then to write some data. */
197 struct i2c_msg msg_buf[] = { {QRD_LCD_I2C_ADDRESS,
198 I2C_M_WR, 2, data_buf}
199 };
200
201 ret = qup_i2c_xfer(i2c_dev, msg_buf, 1);
202 if(ret < 0) {
203 dprintf(CRITICAL, "qup_i2c_xfer error %d\n", ret);
204 return ret;
205 }
206 return 0;
207}
208
Mao Flynn732e3c22014-07-02 17:39:02 +0800209static int target_panel_reset_skuh(uint8_t enable)
210{
211 int ret = NO_ERROR;
212 if (enable) {
213 /* for tps65132 ENP pin */
214 gpio_tlmm_config(enp_gpio.pin_id, 0,
215 enp_gpio.pin_direction, enp_gpio.pin_pull,
216 enp_gpio.pin_strength,
217 enp_gpio.pin_state);
218 gpio_set_dir(enp_gpio.pin_id, 2);
219
220 /* for tps65132 ENN pin*/
221 gpio_tlmm_config(enn_gpio.pin_id, 0,
222 enn_gpio.pin_direction, enn_gpio.pin_pull,
223 enn_gpio.pin_strength,
224 enn_gpio.pin_state);
225 gpio_set_dir(enn_gpio.pin_id, 2);
226
227 i2c_dev = qup_blsp_i2c_init(BLSP_ID_1, QUP_ID_1, 100000, 19200000);
228 if(!i2c_dev) {
229 dprintf(CRITICAL, "qup_blsp_i2c_init failed \n");
230 ASSERT(0);
231 }
232
233 ret = qrd_lcd_i2c_write(QRD_LCD_VPOS_ADDRESS, 0x0E); /* 5.4V */
234 if (ret) {
235 dprintf(CRITICAL, "VPOS Register: I2C Write failure\n");
236 }
237
238 ret = qrd_lcd_i2c_write(QRD_LCD_VNEG_ADDRESS, 0x0E); /* -5.4V */
239 if (ret) {
240 dprintf(CRITICAL, "VNEG Register: I2C write failure\n");
241 }
242
243 ret = qrd_lcd_i2c_write(QRD_LCD_DIS_ADDRESS, 0x0F);
244 if (ret) {
245 dprintf(CRITICAL, "Apps freq DIS Register: I2C write failure\n");
246 }
247
248 ret = qrd_lcd_i2c_write(QRD_LCD_CONTROL_ADDRESS, 0xF0);
249 if (ret) {
250 dprintf(CRITICAL, "Control Register: I2C write failure\n");
251 }
252 } else {
253 gpio_set_dir(enp_gpio.pin_id, 0); /* ENP */
254 gpio_set_dir(enn_gpio.pin_id, 0); /* ENN */
255 }
256 return 0;
257}
258
259static int target_panel_reset_skuk(uint8_t enable)
260{
261 if (enable) {
262 /* for tps65132 ENP pin*/
263 gpio_tlmm_config(enp_gpio_skuk.pin_id, 0,
264 enp_gpio_skuk.pin_direction, enp_gpio_skuk.pin_pull,
265 enp_gpio_skuk.pin_strength, enp_gpio_skuk.pin_state);
266 gpio_set_dir(enp_gpio_skuk.pin_id, 2);
267
268 /* for tps65132 ENN pin*/
269 gpio_tlmm_config(enn_gpio_skuk.pin_id, 0,
270 enn_gpio_skuk.pin_direction, enn_gpio_skuk.pin_pull,
271 enn_gpio_skuk.pin_strength, enn_gpio_skuk.pin_state);
272 gpio_set_dir(enn_gpio_skuk.pin_id, 2);
273
274 /* configure backlight gpio for SKUK */
275 gpio_tlmm_config(bkl_gpio_skuk.pin_id, 0,
276 bkl_gpio_skuk.pin_direction, bkl_gpio_skuk.pin_pull,
277 bkl_gpio_skuk.pin_strength, bkl_gpio_skuk.pin_state);
278 gpio_set_dir(bkl_gpio_skuk.pin_id, 2);
279 } else {
280 gpio_set_dir(bkl_gpio_skuk.pin_id, 0);
281 gpio_set_dir(enp_gpio_skuk.pin_id, 0); /* ENP */
282 gpio_set_dir(enn_gpio_skuk.pin_id, 0); /* ENN */
283 }
284 return 0;
285}
286
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530287int target_panel_reset(uint8_t enable, struct panel_reset_sequence *resetseq,
288 struct msm_panel_info *pinfo)
289{
290 int ret = NO_ERROR;
Mao Flynn81409472014-04-10 15:01:30 +0800291 uint32_t hw_id = board_hardware_id();
292 uint32_t hw_subtype = board_hardware_subtype();
Vineet Bajaj3c958dc2014-11-07 17:01:29 +0530293 uint32_t panel_id = get_panel_id();
Gustavo Solaira80c274c2014-10-22 16:21:27 -0300294 uint32_t target_id, plat_hw_ver_major;
Mao Flynn81409472014-04-10 15:01:30 +0800295
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530296 if (enable) {
297 if (pinfo->mipi.use_enable_gpio) {
Gustavo Solairafb6fdd62014-09-30 08:15:32 -0300298 /* set enable gpio pin for SKUT1 */
299 if ((hw_id == HW_PLATFORM_QRD) &&
Gustavo Solaira80c274c2014-10-22 16:21:27 -0300300 (hw_subtype == HW_PLATFORM_SUBTYPE_SKUT1)) {
301 target_id = board_target_id();
302 plat_hw_ver_major = ((target_id >> 16) & 0xFF);
303 if ((plat_hw_ver_major & 0x0F) == 0x1)
304 enable_gpio = enable_gpio_skut1;
305 else
306 enable_gpio = enable_gpio_skut2;
307 }
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530308 gpio_tlmm_config(enable_gpio.pin_id, 0,
309 enable_gpio.pin_direction, enable_gpio.pin_pull,
310 enable_gpio.pin_strength,
311 enable_gpio.pin_state);
312
313 gpio_set_dir(enable_gpio.pin_id, 2);
314 }
315
Mao Flynn732e3c22014-07-02 17:39:02 +0800316 if (platform_is_msm8939()) {
317 if ((hw_id == HW_PLATFORM_QRD) &&
318 (hw_subtype == HW_PLATFORM_SUBTYPE_SKUK))
319 target_panel_reset_skuk(enable);
320 } else { /* msm8916 */
321 if ((hw_id == HW_PLATFORM_QRD) &&
322 (hw_subtype == HW_PLATFORM_SUBTYPE_SKUH))
323 target_panel_reset_skuh(enable);
Mao Flynn81409472014-04-10 15:01:30 +0800324 }
325
Shuo Yanc8a417f2014-05-20 14:44:56 +0800326 if (hw_id == HW_PLATFORM_MTP || hw_id == HW_PLATFORM_SURF) {
327 /* configure backlight gpio for MTP & CDP */
Vineet Bajaj3c958dc2014-11-07 17:01:29 +0530328 /*JDI incell panel requires two additional GPIO's in 75->98->77 order*/
329 if (panel_id == JDI_FHD_VIDEO_PANEL) {
330 dprintf(INFO, "panel_id = %d \n", panel_id);
331 gpio_tlmm_config(bkl_gpio_1.pin_id, 0,
332 bkl_gpio_1.pin_direction, bkl_gpio_1.pin_pull,
333 bkl_gpio_1.pin_strength, bkl_gpio_1.pin_state);
334 gpio_set_dir(bkl_gpio_1.pin_id, 2);
335
336 gpio_tlmm_config(bkl_gpio.pin_id, 0,
337 bkl_gpio.pin_direction, bkl_gpio.pin_pull,
338 bkl_gpio.pin_strength, bkl_gpio.pin_state);
339 gpio_set_dir(bkl_gpio.pin_id, 2);
340
341 gpio_tlmm_config(bkl_gpio_2.pin_id, 0,
342 bkl_gpio_2.pin_direction, bkl_gpio_2.pin_pull,
343 bkl_gpio_2.pin_strength, bkl_gpio_2.pin_state);
344 gpio_set_dir(bkl_gpio_2.pin_id, 2);
345 } else {
346 gpio_tlmm_config(bkl_gpio.pin_id, 0,
347 bkl_gpio.pin_direction, bkl_gpio.pin_pull,
348 bkl_gpio.pin_strength, bkl_gpio.pin_state);
349 gpio_set_dir(bkl_gpio.pin_id, 2);
350 }
Shuo Yanc8a417f2014-05-20 14:44:56 +0800351 }
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530352
353 gpio_tlmm_config(reset_gpio.pin_id, 0,
354 reset_gpio.pin_direction, reset_gpio.pin_pull,
355 reset_gpio.pin_strength, reset_gpio.pin_state);
356
357 gpio_set_dir(reset_gpio.pin_id, 2);
358
359 /* reset */
360 for (int i = 0; i < RESET_GPIO_SEQ_LEN; i++) {
361 if (resetseq->pin_state[i] == GPIO_STATE_LOW)
362 gpio_set_dir(reset_gpio.pin_id, GPIO_STATE_LOW);
363 else
364 gpio_set_dir(reset_gpio.pin_id, GPIO_STATE_HIGH);
365 mdelay(resetseq->sleep[i]);
366 }
367 } else if(!target_cont_splash_screen()) {
368 gpio_set_dir(reset_gpio.pin_id, 0);
369 if (pinfo->mipi.use_enable_gpio)
370 gpio_set_dir(enable_gpio.pin_id, 0);
Mao Flynn81409472014-04-10 15:01:30 +0800371
Mao Flynn732e3c22014-07-02 17:39:02 +0800372 if (platform_is_msm8939()) {
373 if ((hw_id == HW_PLATFORM_QRD) &&
374 (hw_subtype == HW_PLATFORM_SUBTYPE_SKUK))
375 target_panel_reset_skuk(enable);
376 } else { /* msm8916 */
377 if ((hw_id == HW_PLATFORM_QRD) &&
378 (hw_subtype == HW_PLATFORM_SUBTYPE_SKUH))
379 target_panel_reset_skuh(enable);
Mao Flynn81409472014-04-10 15:01:30 +0800380 }
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530381 }
382
383 return ret;
384}
385
Kuogee Hsieh93bcff62014-08-22 14:02:08 -0700386int target_ldo_ctrl(uint8_t enable, struct msm_panel_info *pinfo)
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530387{
Padmanabhan Komanduru0ed51fb2014-06-04 12:22:08 +0530388 /*
389 * The PMIC regulators needed for display are enabled in SBL.
390 * There is no access to the regulators is LK.
391 */
392 return NO_ERROR;
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530393}
394
395bool target_display_panel_node(char *panel_name, char *pbuf, uint16_t buf_size)
396{
Veera Sundaram Sankaranc95d6752014-07-31 11:49:52 -0700397 return gcdb_display_cmdline_arg(panel_name, pbuf, buf_size);
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530398}
399
400void target_display_init(const char *panel_name)
401{
Padmanabhan Komanduru1869a762014-04-01 20:12:05 +0530402 uint32_t panel_loop = 0;
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530403 uint32_t ret = 0;
Jeevan Shriramb0d523a2014-05-30 12:55:17 -0700404
Sandeep Pandae07c07b2014-08-25 17:04:17 +0530405 panel_name += strspn(panel_name, " ");
Veera Sundaram Sankaran3b758822014-10-17 12:15:39 -0700406
407 if (!strcmp(panel_name, NO_PANEL_CONFIG)
408 || !strcmp(panel_name, SIM_VIDEO_PANEL)
409 || !strcmp(panel_name, SIM_CMD_PANEL)) {
Veera Sundaram Sankaranc95d6752014-07-31 11:49:52 -0700410 dprintf(INFO, "Selected panel: %s\nSkip panel configuration\n",
Veera Sundaram Sankaran3b758822014-10-17 12:15:39 -0700411 panel_name);
Jeevan Shriramb0d523a2014-05-30 12:55:17 -0700412 return;
413 }
414
Padmanabhan Komanduru1869a762014-04-01 20:12:05 +0530415 do {
Justin Philipbe9de5c2014-09-17 12:26:49 +0530416 target_force_cont_splash_disable(false);
Padmanabhan Komanduru1869a762014-04-01 20:12:05 +0530417 ret = gcdb_display_init(panel_name, MDP_REV_50, MIPI_FB_ADDR);
418 if (!ret || ret == ERR_NOT_SUPPORTED) {
419 break;
420 } else {
421 target_force_cont_splash_disable(true);
422 msm_display_off();
Padmanabhan Komanduru1869a762014-04-01 20:12:05 +0530423 }
424 } while (++panel_loop <= oem_panel_max_auto_detect_panels());
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530425}
426
427void target_display_shutdown(void)
428{
429 gcdb_display_shutdown();
430}