blob: c318253e51e5298c8988c19447fd4634bc1e8cab [file] [log] [blame]
Dhaval Patel019057a2014-08-12 13:52:25 -07001/* Copyright (c) 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 <qpnp_wled.h>
38#include <board.h>
39#include <mdp5.h>
40#include <scm.h>
41#include <endian.h>
42#include <platform/gpio.h>
43#include <platform/clock.h>
44#include <platform/iomap.h>
45#include <target/display.h>
46#include "include/panel.h"
47#include "include/display_resource.h"
48
49#define HFPLL_LDO_ID 12
50
51#define GPIO_STATE_LOW 0
52#define GPIO_STATE_HIGH 2
53#define RESET_GPIO_SEQ_LEN 3
54
55#define PWM_DUTY_US 13
56#define PWM_PERIOD_US 27
57#define PMIC_WLED_SLAVE_ID 3
58#define PMIC_MPP_SLAVE_ID 2
59
60static void dsi_pll_20nm_phy_init( uint32_t pll_base, int off)
61{
62 mdss_dsi_pll_20nm_sw_reset_st_machine(pll_base);
63
64 dmb();
65
66 /* MMSS_DSI_0_PHY_DSIPHY_CTRL_1 */
67 writel(0x80, pll_base + off + 0x0174);
68
69 /* MMSS_DSI_0_PHY_DSIPHY_CTRL_1 */
70 writel(0x00, pll_base + off + 0x0174);
71 udelay(5000);
72 /* Strength ctrl 0 */
73 writel(0x77, pll_base + off + 0x0184);
74 /* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */
75 writel(0x7f, pll_base + off + 0x0170);
76
77 /* DSI_0_PHY_DSIPHY_GLBL_TEST_CTRL */
78 writel(0x00, pll_base + off + 0x01d4);
79
80 /* MMSS_DSI_0_PHY_DSIPHY_CTRL_2 */
81 writel(0x00, pll_base + off + 0x0178);
82}
83
84static uint32_t dsi_pll_20nm_enable_seq(uint32_t pll_base)
85{
86 uint32_t pll_locked;
87
88 /*
89 * PLL power up sequence.
90 * Add necessary delays recommeded by hardware.
91 */
92 writel(0x0D, pll_base + 0x9c); /* MMSS_DSI_PHY_PLL_PLLLOCK_CMP_EN */
93 writel(0x07, pll_base + 0x14); /* MMSS_DSI_PHY_PLL_PLL_CNTRL */
94 writel(0x00, pll_base + 0x2c); /* MMSS_DSI_PHY_PLL_PLL_BKG_KVCO_CAL_EN */
95 udelay(500);
96
97 dsi_pll_20nm_phy_init(pll_base, 0x200); /* Ctrl 0 */
98 dmb();
99
100 pll_locked = mdss_dsi_pll_20nm_lock_status(pll_base);
101 if (!pll_locked)
102 dprintf(INFO, "%s: DSI PLL lock failed\n", __func__);
103 else
104 dprintf(INFO, "%s: DSI PLL lock Success\n", __func__);
105
106 return pll_locked;
107}
108
109static int msm8994_wled_backlight_ctrl(uint8_t enable)
110{
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700111 uint8_t slave_id = 3; /* pmi */
Dhaval Patel019057a2014-08-12 13:52:25 -0700112
Veera Sundaram Sankaranf9ddd6c2014-12-02 11:04:52 -0800113 pm8x41_wled_config_slave_id(slave_id);
114 qpnp_wled_enable_backlight(enable);
Dhaval Patel019057a2014-08-12 13:52:25 -0700115 qpnp_ibb_enable(enable);
116 return NO_ERROR;
117}
118
119static int msm8994_pwm_backlight_ctrl(uint8_t enable)
120{
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700121 uint8_t slave_id = 3; /* lpg at pmi */
122
123 if (enable) {
124 /* mpp-1 had been configured already */
125 /* lpg channel 4 */
126
127 /* LPG_ENABLE_CONTROL */
128 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x0);
129 mdelay(100);
130
131 /* LPG_VALUE_LSB, duty cycle = 0x80/0x200 = 1/4 */
132 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x44, 0x80);
133 /* LPG_VALUE_MSB */
134 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x45, 0x00);
135 /* LPG_PWM_SYNC */
136 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x47, 0x01);
137
138 /* LPG_PWM_SIZE_CLK, */
139 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x41, 0x13);
140 /* LPG_PWM_FREQ_PREDIV */
141 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x42, 0x02);
142 /* LPG_PWM_TYPE_CONFIG */
143 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x43, 0x20);
144 /* LPG_ENABLE_CONTROL */
145 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x04);
146
147 /* SEC_ACCESS */
148 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0xD0, 0xA5);
149 /* DTEST4, OUT_HI */
150 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0xE5, 0x01);
151 /* LPG_ENABLE_CONTROL */
152 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0xA4);
153 } else {
154 /* LPG_ENABLE_CONTROL */
155 pm8x41_lpg_write_sid(slave_id, PWM_BL_LPG_CHAN_ID, 0x46, 0x0);
156 }
157
158 return NO_ERROR;
159}
160
161void lcd_bklt_reg_enable(void)
162{
163 uint8_t slave_id = 2; /* gpio at pmi */
164
165 struct pm8x41_gpio gpio = {
166 .direction = PM_GPIO_DIR_OUT,
167 .function = PM_GPIO_FUNC_HIGH,
168 .vin_sel = 2, /* VIN_2 */
169 .output_buffer = PM_GPIO_OUT_CMOS,
170 .out_strength = PM_GPIO_OUT_DRIVE_LOW,
171 };
172
173 pm8x41_gpio_config_sid(slave_id, bklt_gpio.pin_id, &gpio);
174 pm8x41_gpio_set_sid(slave_id, bklt_gpio.pin_id, 1);
175}
176
177void lcd_bklt_reg_disable(void)
178{
179 uint8_t slave_id = 2; /* gpio at pmi */
180
181 pm8x41_gpio_set_sid(slave_id, bklt_gpio.pin_id, 0);
Dhaval Patel019057a2014-08-12 13:52:25 -0700182}
183
Kuogee Hsieh208736d2014-08-22 14:16:55 -0700184void lcd_reg_enable(void)
Dhaval Patel019057a2014-08-12 13:52:25 -0700185{
186 struct pm8x41_gpio gpio = {
187 .direction = PM_GPIO_DIR_OUT,
188 .function = PM_GPIO_FUNC_HIGH,
189 .vin_sel = 2, /* VIN_2 */
190 .output_buffer = PM_GPIO_OUT_CMOS,
191 .out_strength = PM_GPIO_OUT_DRIVE_MED,
192 };
193
Kuogee Hsieh208736d2014-08-22 14:16:55 -0700194 pm8x41_gpio_config(lcd_reg_en.pin_id, &gpio);
195 pm8x41_gpio_set(lcd_reg_en.pin_id, 1);
196}
197
198void lcd_reg_disable(void)
199{
200 pm8x41_gpio_set(lcd_reg_en.pin_id, 0);
Dhaval Patel019057a2014-08-12 13:52:25 -0700201}
202
203int target_backlight_ctrl(struct backlight *bl, uint8_t enable)
204{
205 uint32_t ret = NO_ERROR;
206 struct pm8x41_mpp mpp;
207 int rc;
208
209 if (!bl) {
210 dprintf(CRITICAL, "backlight structure is not available\n");
211 return ERR_INVALID_ARGS;
212 }
213
214 switch (bl->bl_interface_type) {
215 case BL_WLED:
216 /* Enable MPP4 */
217 pmi8994_config_mpp_slave_id(PMIC_MPP_SLAVE_ID);
218 mpp.base = PM8x41_MMP4_BASE;
219 mpp.vin = MPP_VIN2;
220 if (enable) {
221 pm_pwm_enable(false);
222 rc = pm_pwm_config(PWM_DUTY_US, PWM_PERIOD_US);
223 if (rc < 0) {
224 mpp.mode = MPP_HIGH;
225 } else {
226 mpp.mode = MPP_DTEST1;
227 pm_pwm_enable(true);
228 }
229 pm8x41_config_output_mpp(&mpp);
230 pm8x41_enable_mpp(&mpp, MPP_ENABLE);
231 } else {
232 pm_pwm_enable(false);
233 pm8x41_enable_mpp(&mpp, MPP_DISABLE);
234 }
235 /* Need delay before power on regulators */
236 mdelay(20);
237 /* Enable WLED backlight control */
238 ret = msm8994_wled_backlight_ctrl(enable);
239 break;
240 case BL_PWM:
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700241 /* Enable MPP1 */
242 pmi8994_config_mpp_slave_id(PMIC_MPP_SLAVE_ID);
243 mpp.base = PM8x41_MMP1_BASE;
244 mpp.vin = MPP_VIN2;
245 mpp.mode = MPP_DTEST4;
246 if (enable) {
247 pm8x41_config_output_mpp(&mpp);
248 pm8x41_enable_mpp(&mpp, MPP_ENABLE);
249 } else {
250 pm8x41_enable_mpp(&mpp, MPP_DISABLE);
251 }
252 /* Need delay before power on regulators */
253 mdelay(20);
Dhaval Patel019057a2014-08-12 13:52:25 -0700254 ret = msm8994_pwm_backlight_ctrl(enable);
255 break;
256 default:
257 dprintf(CRITICAL, "backlight type:%d not supported\n",
258 bl->bl_interface_type);
259 return ERR_NOT_SUPPORTED;
260 }
261
262 return ret;
263}
264
265int target_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
266{
267 uint32_t ret;
268 struct mdss_dsi_pll_config *pll_data;
269 uint32_t dual_dsi = pinfo->mipi.dual_dsi;
270
271 pll_data = pinfo->mipi.dsi_pll_config;
272 if (enable) {
273 mdp_gdsc_ctrl(enable);
274 mmss_bus_clock_enable();
275 mdp_clock_enable();
276 ret = restore_secure_cfg(SECURE_DEVICE_MDSS);
277 if (ret) {
278 dprintf(CRITICAL,
279 "%s: Failed to restore MDP security configs",
280 __func__);
281 mdp_clock_disable();
282 mmss_bus_clock_disable();
283 mdp_gdsc_ctrl(0);
284 return ret;
285 }
286 mdss_dsi_auto_pll_20nm_config(DSI0_PLL_BASE,
287 MIPI_DSI0_BASE, pll_data);
288 dsi_pll_20nm_enable_seq(DSI0_PLL_BASE);
289 mmss_dsi_clock_enable(DSI0_PHY_PLL_OUT, dual_dsi,
290 pll_data->pclk_m,
291 pll_data->pclk_n,
292 pll_data->pclk_d);
293 } else if(!target_cont_splash_screen()) {
294 /* Disable clocks if continuous splash off */
295 mmss_dsi_clock_disable(dual_dsi);
296 mdp_clock_disable();
297 mmss_bus_clock_disable();
298 mdp_gdsc_ctrl(enable);
299 }
300
301 return NO_ERROR;
302}
303
304int target_panel_reset(uint8_t enable, struct panel_reset_sequence *resetseq,
305 struct msm_panel_info *pinfo)
306{
307 uint32_t i = 0;
308
309 if (enable) {
310 gpio_tlmm_config(reset_gpio.pin_id, 0,
311 reset_gpio.pin_direction, reset_gpio.pin_pull,
312 reset_gpio.pin_strength, reset_gpio.pin_state);
313 /* reset */
314 for (i = 0; i < RESET_GPIO_SEQ_LEN; i++) {
315 if (resetseq->pin_state[i] == GPIO_STATE_LOW)
316 gpio_set(reset_gpio.pin_id, GPIO_STATE_LOW);
317 else
318 gpio_set(reset_gpio.pin_id, GPIO_STATE_HIGH);
319 mdelay(resetseq->sleep[i]);
320 }
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700321 lcd_bklt_reg_enable();
Dhaval Patel019057a2014-08-12 13:52:25 -0700322 } else {
Kuogee Hsieh911866e2014-09-02 16:41:18 -0700323 lcd_bklt_reg_disable();
Dhaval Patel019057a2014-08-12 13:52:25 -0700324 gpio_set(reset_gpio.pin_id, 0);
325 }
326
327 return NO_ERROR;
328}
329
Kuogee Hsieh93bcff62014-08-22 14:02:08 -0700330int target_ldo_ctrl(uint8_t enable, struct msm_panel_info *pinfo)
Dhaval Patel019057a2014-08-12 13:52:25 -0700331{
332 if (enable) {
333 regulator_enable(); /* L2, L12, L14, and L28 */
334 mdelay(10);
335 qpnp_ibb_enable(true); /* +5V and -5V */
336 mdelay(50);
Kuogee Hsieh208736d2014-08-22 14:16:55 -0700337
338 if (pinfo->lcd_reg_en)
339 lcd_reg_enable();
Dhaval Patel019057a2014-08-12 13:52:25 -0700340 } else {
Kuogee Hsieh208736d2014-08-22 14:16:55 -0700341 if (pinfo->lcd_reg_en)
342 lcd_reg_disable();
343
Dhaval Patel019057a2014-08-12 13:52:25 -0700344 regulator_disable();
345 }
346
347 return NO_ERROR;
348}
349
350int target_display_pre_on()
351{
Ingrid Gallardoc9776bd2014-09-04 14:13:28 -0700352 writel(0xC0000CCC, MDP_CLK_CTRL0);
353 writel(0xC0000CCC, MDP_CLK_CTRL1);
Dhaval Patel019057a2014-08-12 13:52:25 -0700354 writel(0x00CCCCCC, MDP_CLK_CTRL2);
355 writel(0x000000CC, MDP_CLK_CTRL6);
356 writel(0x0CCCC0C0, MDP_CLK_CTRL3);
357 writel(0xCCCCC0C0, MDP_CLK_CTRL4);
358 writel(0xCCCCC0C0, MDP_CLK_CTRL5);
359 writel(0x00CCC000, MDP_CLK_CTRL7);
360
Dhaval Patel019057a2014-08-12 13:52:25 -0700361 return NO_ERROR;
362}
363
364bool target_display_panel_node(char *panel_name, char *pbuf, uint16_t buf_size)
365{
366 int prefix_string_len = strlen(DISPLAY_CMDLINE_PREFIX);
367 bool ret = true;
368
369 ret = gcdb_display_cmdline_arg(panel_name, pbuf, buf_size);
370
371 return ret;
372}
373
374void target_display_init(const char *panel_name)
375{
Veera Sundaram Sankaran3b758822014-10-17 12:15:39 -0700376 panel_name += strspn(panel_name, " ");
377
378 if (!strcmp(panel_name, NO_PANEL_CONFIG)
379 || !strcmp(panel_name, SIM_VIDEO_PANEL)
380 || !strcmp(panel_name, SIM_DUALDSI_VIDEO_PANEL)
381 || !strcmp(panel_name, SIM_CMD_PANEL)
382 || !strcmp(panel_name, SIM_DUALDSI_CMD_PANEL)) {
Veera Sundaram Sankaranb620f232014-09-03 22:43:53 -0700383 dprintf(INFO, "Selected panel: %s\nSkip panel configuration\n",
Veera Sundaram Sankaran3b758822014-10-17 12:15:39 -0700384 panel_name);
Veera Sundaram Sankaranb620f232014-09-03 22:43:53 -0700385 return;
386 }
Justin Philipbe9de5c2014-09-17 12:26:49 +0530387 if (gcdb_display_init(panel_name, MDP_REV_50, MIPI_FB_ADDR)) {
388 target_force_cont_splash_disable(true);
Dhaval Patel019057a2014-08-12 13:52:25 -0700389 msm_display_off();
Justin Philipbe9de5c2014-09-17 12:26:49 +0530390 }
Dhaval Patel019057a2014-08-12 13:52:25 -0700391}
392
393void target_display_shutdown(void)
394{
395 gcdb_display_shutdown();
396}