blob: 644b7504ccbd3d9bc1c431eb086c9b523d0c6536 [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();
293
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530294 if (enable) {
295 if (pinfo->mipi.use_enable_gpio) {
296 gpio_tlmm_config(enable_gpio.pin_id, 0,
297 enable_gpio.pin_direction, enable_gpio.pin_pull,
298 enable_gpio.pin_strength,
299 enable_gpio.pin_state);
300
301 gpio_set_dir(enable_gpio.pin_id, 2);
302 }
303
Mao Flynn732e3c22014-07-02 17:39:02 +0800304 if (platform_is_msm8939()) {
305 if ((hw_id == HW_PLATFORM_QRD) &&
306 (hw_subtype == HW_PLATFORM_SUBTYPE_SKUK))
307 target_panel_reset_skuk(enable);
308 } else { /* msm8916 */
309 if ((hw_id == HW_PLATFORM_QRD) &&
310 (hw_subtype == HW_PLATFORM_SUBTYPE_SKUH))
311 target_panel_reset_skuh(enable);
Mao Flynn81409472014-04-10 15:01:30 +0800312 }
313
Shuo Yanc8a417f2014-05-20 14:44:56 +0800314 if (hw_id == HW_PLATFORM_MTP || hw_id == HW_PLATFORM_SURF) {
315 /* configure backlight gpio for MTP & CDP */
316 gpio_tlmm_config(bkl_gpio.pin_id, 0,
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530317 bkl_gpio.pin_direction, bkl_gpio.pin_pull,
318 bkl_gpio.pin_strength, bkl_gpio.pin_state);
Shuo Yanc8a417f2014-05-20 14:44:56 +0800319 gpio_set_dir(bkl_gpio.pin_id, 2);
320 }
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530321
322 gpio_tlmm_config(reset_gpio.pin_id, 0,
323 reset_gpio.pin_direction, reset_gpio.pin_pull,
324 reset_gpio.pin_strength, reset_gpio.pin_state);
325
326 gpio_set_dir(reset_gpio.pin_id, 2);
327
328 /* reset */
329 for (int i = 0; i < RESET_GPIO_SEQ_LEN; i++) {
330 if (resetseq->pin_state[i] == GPIO_STATE_LOW)
331 gpio_set_dir(reset_gpio.pin_id, GPIO_STATE_LOW);
332 else
333 gpio_set_dir(reset_gpio.pin_id, GPIO_STATE_HIGH);
334 mdelay(resetseq->sleep[i]);
335 }
336 } else if(!target_cont_splash_screen()) {
337 gpio_set_dir(reset_gpio.pin_id, 0);
338 if (pinfo->mipi.use_enable_gpio)
339 gpio_set_dir(enable_gpio.pin_id, 0);
Mao Flynn81409472014-04-10 15:01:30 +0800340
Mao Flynn732e3c22014-07-02 17:39:02 +0800341 if (platform_is_msm8939()) {
342 if ((hw_id == HW_PLATFORM_QRD) &&
343 (hw_subtype == HW_PLATFORM_SUBTYPE_SKUK))
344 target_panel_reset_skuk(enable);
345 } else { /* msm8916 */
346 if ((hw_id == HW_PLATFORM_QRD) &&
347 (hw_subtype == HW_PLATFORM_SUBTYPE_SKUH))
348 target_panel_reset_skuh(enable);
Mao Flynn81409472014-04-10 15:01:30 +0800349 }
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530350 }
351
352 return ret;
353}
354
Kuogee Hsieh93bcff62014-08-22 14:02:08 -0700355int target_ldo_ctrl(uint8_t enable, struct msm_panel_info *pinfo)
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530356{
Padmanabhan Komanduru0ed51fb2014-06-04 12:22:08 +0530357 /*
358 * The PMIC regulators needed for display are enabled in SBL.
359 * There is no access to the regulators is LK.
360 */
361 return NO_ERROR;
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530362}
363
364bool target_display_panel_node(char *panel_name, char *pbuf, uint16_t buf_size)
365{
Veera Sundaram Sankaranc95d6752014-07-31 11:49:52 -0700366 return gcdb_display_cmdline_arg(panel_name, pbuf, buf_size);
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530367}
368
369void target_display_init(const char *panel_name)
370{
Padmanabhan Komanduru1869a762014-04-01 20:12:05 +0530371 uint32_t panel_loop = 0;
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530372 uint32_t ret = 0;
Jeevan Shriramb0d523a2014-05-30 12:55:17 -0700373
Veera Sundaram Sankaranc95d6752014-07-31 11:49:52 -0700374 if ((!strcmp(panel_name, NO_PANEL_CONFIG))
375 || (!strcmp(panel_name, SIM_VIDEO_PANEL))) {
376 dprintf(INFO, "Selected panel: %s\nSkip panel configuration\n",
377 panel_name);
Jeevan Shriramb0d523a2014-05-30 12:55:17 -0700378 return;
379 }
380
Padmanabhan Komanduru1869a762014-04-01 20:12:05 +0530381 do {
382 ret = gcdb_display_init(panel_name, MDP_REV_50, MIPI_FB_ADDR);
383 if (!ret || ret == ERR_NOT_SUPPORTED) {
384 break;
385 } else {
386 target_force_cont_splash_disable(true);
387 msm_display_off();
388 target_force_cont_splash_disable(false);
389 }
390 } while (++panel_loop <= oem_panel_max_auto_detect_panels());
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530391}
392
393void target_display_shutdown(void)
394{
395 gcdb_display_shutdown();
396}