blob: b47f1e0f7b8cc06e771088327d29b1dfdaeaca48 [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) {
Gustavo Solairafb6fdd62014-09-30 08:15:32 -0300296 /* set enable gpio pin for SKUT1 */
297 if ((hw_id == HW_PLATFORM_QRD) &&
298 (hw_subtype == HW_PLATFORM_SUBTYPE_SKUT1))
299 enable_gpio = enable_gpio_skut1;
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530300 gpio_tlmm_config(enable_gpio.pin_id, 0,
301 enable_gpio.pin_direction, enable_gpio.pin_pull,
302 enable_gpio.pin_strength,
303 enable_gpio.pin_state);
304
305 gpio_set_dir(enable_gpio.pin_id, 2);
306 }
307
Mao Flynn732e3c22014-07-02 17:39:02 +0800308 if (platform_is_msm8939()) {
309 if ((hw_id == HW_PLATFORM_QRD) &&
310 (hw_subtype == HW_PLATFORM_SUBTYPE_SKUK))
311 target_panel_reset_skuk(enable);
312 } else { /* msm8916 */
313 if ((hw_id == HW_PLATFORM_QRD) &&
314 (hw_subtype == HW_PLATFORM_SUBTYPE_SKUH))
315 target_panel_reset_skuh(enable);
Mao Flynn81409472014-04-10 15:01:30 +0800316 }
317
Shuo Yanc8a417f2014-05-20 14:44:56 +0800318 if (hw_id == HW_PLATFORM_MTP || hw_id == HW_PLATFORM_SURF) {
319 /* configure backlight gpio for MTP & CDP */
320 gpio_tlmm_config(bkl_gpio.pin_id, 0,
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530321 bkl_gpio.pin_direction, bkl_gpio.pin_pull,
322 bkl_gpio.pin_strength, bkl_gpio.pin_state);
Shuo Yanc8a417f2014-05-20 14:44:56 +0800323 gpio_set_dir(bkl_gpio.pin_id, 2);
324 }
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530325
326 gpio_tlmm_config(reset_gpio.pin_id, 0,
327 reset_gpio.pin_direction, reset_gpio.pin_pull,
328 reset_gpio.pin_strength, reset_gpio.pin_state);
329
330 gpio_set_dir(reset_gpio.pin_id, 2);
331
332 /* reset */
333 for (int i = 0; i < RESET_GPIO_SEQ_LEN; i++) {
334 if (resetseq->pin_state[i] == GPIO_STATE_LOW)
335 gpio_set_dir(reset_gpio.pin_id, GPIO_STATE_LOW);
336 else
337 gpio_set_dir(reset_gpio.pin_id, GPIO_STATE_HIGH);
338 mdelay(resetseq->sleep[i]);
339 }
340 } else if(!target_cont_splash_screen()) {
341 gpio_set_dir(reset_gpio.pin_id, 0);
342 if (pinfo->mipi.use_enable_gpio)
343 gpio_set_dir(enable_gpio.pin_id, 0);
Mao Flynn81409472014-04-10 15:01:30 +0800344
Mao Flynn732e3c22014-07-02 17:39:02 +0800345 if (platform_is_msm8939()) {
346 if ((hw_id == HW_PLATFORM_QRD) &&
347 (hw_subtype == HW_PLATFORM_SUBTYPE_SKUK))
348 target_panel_reset_skuk(enable);
349 } else { /* msm8916 */
350 if ((hw_id == HW_PLATFORM_QRD) &&
351 (hw_subtype == HW_PLATFORM_SUBTYPE_SKUH))
352 target_panel_reset_skuh(enable);
Mao Flynn81409472014-04-10 15:01:30 +0800353 }
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530354 }
355
356 return ret;
357}
358
Kuogee Hsieh93bcff62014-08-22 14:02:08 -0700359int target_ldo_ctrl(uint8_t enable, struct msm_panel_info *pinfo)
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530360{
Padmanabhan Komanduru0ed51fb2014-06-04 12:22:08 +0530361 /*
362 * The PMIC regulators needed for display are enabled in SBL.
363 * There is no access to the regulators is LK.
364 */
365 return NO_ERROR;
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530366}
367
368bool target_display_panel_node(char *panel_name, char *pbuf, uint16_t buf_size)
369{
Veera Sundaram Sankaranc95d6752014-07-31 11:49:52 -0700370 return gcdb_display_cmdline_arg(panel_name, pbuf, buf_size);
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530371}
372
373void target_display_init(const char *panel_name)
374{
Padmanabhan Komanduru1869a762014-04-01 20:12:05 +0530375 uint32_t panel_loop = 0;
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530376 uint32_t ret = 0;
Jeevan Shriramb0d523a2014-05-30 12:55:17 -0700377
Sandeep Pandae07c07b2014-08-25 17:04:17 +0530378 panel_name += strspn(panel_name, " ");
Veera Sundaram Sankaranc95d6752014-07-31 11:49:52 -0700379 if ((!strcmp(panel_name, NO_PANEL_CONFIG))
380 || (!strcmp(panel_name, SIM_VIDEO_PANEL))) {
381 dprintf(INFO, "Selected panel: %s\nSkip panel configuration\n",
382 panel_name);
Jeevan Shriramb0d523a2014-05-30 12:55:17 -0700383 return;
384 }
385
Padmanabhan Komanduru1869a762014-04-01 20:12:05 +0530386 do {
Justin Philipbe9de5c2014-09-17 12:26:49 +0530387 target_force_cont_splash_disable(false);
Padmanabhan Komanduru1869a762014-04-01 20:12:05 +0530388 ret = gcdb_display_init(panel_name, MDP_REV_50, MIPI_FB_ADDR);
389 if (!ret || ret == ERR_NOT_SUPPORTED) {
390 break;
391 } else {
392 target_force_cont_splash_disable(true);
393 msm_display_off();
Padmanabhan Komanduru1869a762014-04-01 20:12:05 +0530394 }
395 } while (++panel_loop <= oem_panel_max_auto_detect_panels());
Padmanabhan Komandurucd5645e2014-03-25 20:34:18 +0530396}
397
398void target_display_shutdown(void)
399{
400 gcdb_display_shutdown();
401}