blob: d341d62883e4c08b5c3e65f8dd4d75b263fe9e9d [file] [log] [blame]
Kuogee Hsiehdf961742013-12-18 14:13:45 -08001/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
Dhaval Patelf9986272013-10-18 19:06:05 -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 <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 <endian.h>
40#include <platform/gpio.h>
41#include <platform/clock.h>
42#include <platform/iomap.h>
43#include <target/display.h>
44#include "include/panel.h"
45#include "include/display_resource.h"
46
47#define HFPLL_LDO_ID 12
48
49#define GPIO_STATE_LOW 0
50#define GPIO_STATE_HIGH 2
51#define RESET_GPIO_SEQ_LEN 3
52
Dhaval Patelbb408712014-03-18 11:45:53 -070053static uint32_t dsi_pll_lock_status(uint32_t ctl_base)
Dhaval Patelf9986272013-10-18 19:06:05 -070054{
Dhaval Patelbb408712014-03-18 11:45:53 -070055 uint32_t counter, status;
Dhaval Patelf9986272013-10-18 19:06:05 -070056
Dhaval Patelbb408712014-03-18 11:45:53 -070057 udelay(100);
58 mdss_dsi_uniphy_pll_lock_detect_setting(ctl_base);
59
60 status = readl(ctl_base + 0x02c0) & 0x01;
61 for (counter = 0; counter < 5 && !status; counter++) {
62 udelay(100);
63 status = readl(ctl_base + 0x02c0) & 0x01;
64 }
65
66 return status;
67}
68
69static uint32_t dsi_pll_enable_seq_b(uint32_t ctl_base)
70{
Dhaval Patelf9986272013-10-18 19:06:05 -070071 mdss_dsi_uniphy_pll_sw_reset(ctl_base);
72
73 writel(0x01, ctl_base + 0x0220); /* GLB CFG */
Dhaval Patelbb408712014-03-18 11:45:53 -070074 udelay(1);
Dhaval Patelf9986272013-10-18 19:06:05 -070075 writel(0x05, ctl_base + 0x0220); /* GLB CFG */
Dhaval Patelbb408712014-03-18 11:45:53 -070076 udelay(200);
Dhaval Patelf9986272013-10-18 19:06:05 -070077 writel(0x07, ctl_base + 0x0220); /* GLB CFG */
Dhaval Patelbb408712014-03-18 11:45:53 -070078 udelay(500);
Dhaval Patelf9986272013-10-18 19:06:05 -070079 writel(0x0f, ctl_base + 0x0220); /* GLB CFG */
Dhaval Patelbb408712014-03-18 11:45:53 -070080 udelay(500);
Dhaval Patelf9986272013-10-18 19:06:05 -070081
Dhaval Patelbb408712014-03-18 11:45:53 -070082 return dsi_pll_lock_status(ctl_base);
83}
Dhaval Patelf9986272013-10-18 19:06:05 -070084
Dhaval Patelbb408712014-03-18 11:45:53 -070085static uint32_t dsi_pll_enable_seq_d(uint32_t ctl_base)
86{
87 mdss_dsi_uniphy_pll_sw_reset(ctl_base);
88
89 writel(0x01, ctl_base + 0x0220); /* GLB CFG */
90 udelay(1);
91 writel(0x05, ctl_base + 0x0220); /* GLB CFG */
92 udelay(200);
93 writel(0x07, ctl_base + 0x0220); /* GLB CFG */
94 udelay(250);
95 writel(0x05, ctl_base + 0x0220); /* GLB CFG */
96 udelay(200);
97 writel(0x07, ctl_base + 0x0220); /* GLB CFG */
98 udelay(500);
99 writel(0x0f, ctl_base + 0x0220); /* GLB CFG */
100 udelay(500);
101
102 return dsi_pll_lock_status(ctl_base);
103}
104
105static void dsi_pll_enable_seq(uint32_t ctl_base)
106{
107 uint32_t counter, status;
108
109 for (counter = 0; counter < 3; counter++) {
110 status = dsi_pll_enable_seq_b(ctl_base);
111 if (status)
112 break;
113 status = dsi_pll_enable_seq_d(ctl_base);
114 if (status)
115 break;
116 status = dsi_pll_enable_seq_d(ctl_base);
117 if(status)
118 break;
Dhaval Patelf9986272013-10-18 19:06:05 -0700119 }
Dhaval Patelbb408712014-03-18 11:45:53 -0700120
121 if (!status)
122 dprintf(CRITICAL, "Pll lock sequence failed\n");
Dhaval Patelf9986272013-10-18 19:06:05 -0700123}
124
Kuogee Hsiehdf961742013-12-18 14:13:45 -0800125int target_backlight_ctrl(struct backlight *bl, uint8_t enable)
Dhaval Patelf9986272013-10-18 19:06:05 -0700126{
127 struct pm8x41_gpio pwmgpio_param = {
128 .direction = PM_GPIO_DIR_OUT,
129 .function = PM_GPIO_FUNC_1,
130 .vin_sel = 2, /* VIN_2 */
131 .pull = PM_GPIO_PULL_UP_1_5 | PM_GPIO_PULLDOWN_10,
132 .output_buffer = PM_GPIO_OUT_CMOS,
133 .out_strength = 0x03,
134 };
Kuogee Hsiehdf961742013-12-18 14:13:45 -0800135
Dhaval Patelf9986272013-10-18 19:06:05 -0700136 if (enable) {
Dhaval Patel499b7d22014-01-07 21:57:30 -0800137 pm8x41_gpio_config(pwm_gpio.pin_id, &pwmgpio_param);
Dhaval Patelf9986272013-10-18 19:06:05 -0700138
139 /* lpg channel 2 */
Dhaval Patel499b7d22014-01-07 21:57:30 -0800140 pm8x41_lpg_write(PWM_BL_LPG_CHAN_ID, 0x41, 0x33); /* LPG_PWM_SIZE_CLK, */
141 pm8x41_lpg_write(PWM_BL_LPG_CHAN_ID, 0x42, 0x01); /* LPG_PWM_FREQ_PREDIV */
142 pm8x41_lpg_write(PWM_BL_LPG_CHAN_ID, 0x43, 0x20); /* LPG_PWM_TYPE_CONFIG */
143 pm8x41_lpg_write(PWM_BL_LPG_CHAN_ID, 0x44, 0xcc); /* LPG_VALUE_LSB */
144 pm8x41_lpg_write(PWM_BL_LPG_CHAN_ID, 0x45, 0x00); /* LPG_VALUE_MSB */
145 pm8x41_lpg_write(PWM_BL_LPG_CHAN_ID, 0x46, 0xe4); /* LPG_ENABLE_CONTROL */
Dhaval Patelf9986272013-10-18 19:06:05 -0700146 } else {
Dhaval Patel499b7d22014-01-07 21:57:30 -0800147 pm8x41_lpg_write(PWM_BL_LPG_CHAN_ID, 0x46, 0x0); /* LPG_ENABLE_CONTROL */
Dhaval Patelf9986272013-10-18 19:06:05 -0700148 }
149
150 return NO_ERROR;
151}
152
153int target_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
154{
155 struct mdss_dsi_pll_config *pll_data;
156 uint32_t dual_dsi = pinfo->mipi.dual_dsi;
157 dprintf(SPEW, "target_panel_clock\n");
158
159 pll_data = pinfo->mipi.dsi_pll_config;
160 if (enable) {
161 mdp_gdsc_ctrl(enable);
162 mmss_bus_clock_enable();
163 mdp_clock_enable();
164 mdss_dsi_auto_pll_config(MIPI_DSI0_BASE, pll_data);
165 dsi_pll_enable_seq(MIPI_DSI0_BASE);
166 if (pinfo->mipi.dual_dsi &&
167 !(pinfo->mipi.broadcast)) {
168 mdss_dsi_auto_pll_config(MIPI_DSI1_BASE, pll_data);
169 dsi_pll_enable_seq(MIPI_DSI1_BASE);
170 }
171 mmss_dsi_clock_enable(DSI0_PHY_PLL_OUT, dual_dsi,
172 pll_data->pclk_m,
173 pll_data->pclk_n,
174 pll_data->pclk_d);
175 } else if(!target_cont_splash_screen()) {
176 /* Disable clocks if continuous splash off */
Dhaval Patelf14af122013-10-29 12:48:41 -0700177 mmss_dsi_clock_disable(dual_dsi);
Dhaval Patelf9986272013-10-18 19:06:05 -0700178 mdp_clock_disable();
179 mmss_bus_clock_disable();
180 mdp_gdsc_ctrl(enable);
181 }
182
183 return NO_ERROR;
184}
185
186/* Pull DISP_RST_N high to get panel out of reset */
187int target_panel_reset(uint8_t enable, struct panel_reset_sequence *resetseq,
188 struct msm_panel_info *pinfo)
189{
190 uint32_t i = 0;
191
192 if (enable) {
193 gpio_tlmm_config(reset_gpio.pin_id, 0,
194 reset_gpio.pin_direction, reset_gpio.pin_pull,
195 reset_gpio.pin_strength, reset_gpio.pin_state);
196
197 gpio_tlmm_config(enable_gpio.pin_id, 0,
198 enable_gpio.pin_direction, enable_gpio.pin_pull,
199 enable_gpio.pin_strength, enable_gpio.pin_state);
200
201 gpio_tlmm_config(bkl_gpio.pin_id, 0,
202 bkl_gpio.pin_direction, bkl_gpio.pin_pull,
203 bkl_gpio.pin_strength, bkl_gpio.pin_state);
204
205 gpio_set(enable_gpio.pin_id, 2);
206 gpio_set(bkl_gpio.pin_id, 2);
207 /* reset */
208 for (i = 0; i < RESET_GPIO_SEQ_LEN; i++) {
209 if (resetseq->pin_state[i] == GPIO_STATE_LOW)
210 gpio_set(reset_gpio.pin_id, GPIO_STATE_LOW);
211 else
212 gpio_set(reset_gpio.pin_id, GPIO_STATE_HIGH);
213 mdelay(resetseq->sleep[i]);
214 }
215 } else {
216 gpio_set(reset_gpio.pin_id, 0);
217 gpio_set(enable_gpio.pin_id, 0);
218 gpio_set(bkl_gpio.pin_id, 0);
219 }
220
221 return NO_ERROR;
222}
223
224int target_ldo_ctrl(uint8_t enable)
225{
226 uint32_t ldocounter = 0;
227 uint32_t pm8x41_ldo_base = 0x13F00;
228
229 while (ldocounter < TOTAL_LDO_DEFINED) {
230 struct pm8x41_ldo ldo_entry = LDO((pm8x41_ldo_base +
231 0x100 * ldo_entry_array[ldocounter].ldo_id),
232 ldo_entry_array[ldocounter].ldo_type);
233
234 dprintf(SPEW, "Setting %s\n",
235 ldo_entry_array[ldocounter].ldo_id);
236
237 /* Set voltage during power on */
238 if (enable) {
239 pm8x41_ldo_set_voltage(&ldo_entry,
240 ldo_entry_array[ldocounter].ldo_voltage);
241 pm8x41_ldo_control(&ldo_entry, enable);
242 } else if(ldo_entry_array[ldocounter].ldo_id != HFPLL_LDO_ID) {
243 pm8x41_ldo_control(&ldo_entry, enable);
244 }
245 ldocounter++;
246 }
247
248 return NO_ERROR;
249}
250
Dhaval Patelab2de892013-10-25 10:40:58 -0700251int target_display_pre_on()
252{
253 writel(0x000000FA, MDP_QOS_REMAPPER_CLASS_0);
254 writel(0x00000055, MDP_QOS_REMAPPER_CLASS_1);
255 writel(0xC0000CCD, MDP_CLK_CTRL0);
256 writel(0xD0000CCC, MDP_CLK_CTRL1);
257 writel(0x00CCCCCC, MDP_CLK_CTRL2);
258 writel(0x000000CC, MDP_CLK_CTRL6);
259 writel(0x0CCCC0C0, MDP_CLK_CTRL3);
260 writel(0xCCCCC0C0, MDP_CLK_CTRL4);
261 writel(0xCCCCC0C0, MDP_CLK_CTRL5);
262 writel(0x00CCC000, MDP_CLK_CTRL7);
263
Dhaval Patelab2de892013-10-25 10:40:58 -0700264 writel(0x00080808, VBIF_VBIF_IN_RD_LIM_CONF0);
265 writel(0x08000808, VBIF_VBIF_IN_RD_LIM_CONF1);
266 writel(0x00080808, VBIF_VBIF_IN_RD_LIM_CONF2);
267 writel(0x00000808, VBIF_VBIF_IN_RD_LIM_CONF3);
268 writel(0x10000000, VBIF_VBIF_IN_WR_LIM_CONF0);
269 writel(0x00100000, VBIF_VBIF_IN_WR_LIM_CONF1);
270 writel(0x10000000, VBIF_VBIF_IN_WR_LIM_CONF2);
271 writel(0x00000000, VBIF_VBIF_IN_WR_LIM_CONF3);
272 writel(0x00013fff, VBIF_VBIF_ABIT_SHORT);
273 writel(0x000000A4, VBIF_VBIF_ABIT_SHORT_CONF);
274 writel(0x00003FFF, VBIF_VBIF_GATE_OFF_WRREQ_EN);
275 writel(0x00000003, VBIF_VBIF_DDR_RND_RBN_QOS_ARB);
276
277 return NO_ERROR;
278}
279
Ajay Singh Parmareef1d602014-03-15 17:41:52 -0700280bool target_display_panel_node(char *panel_name, char *pbuf, uint16_t buf_size)
281{
282 int prefix_string_len = strlen(DISPLAY_CMDLINE_PREFIX);
283 bool ret = true;
284
285 panel_name += strspn(panel_name, " ");
286
287 if (!strcmp(panel_name, HDMI_PANEL_NAME)) {
288 if (buf_size < (prefix_string_len + LK_OVERRIDE_PANEL_LEN +
289 HDMI_CONTROLLER_STRING)) {
290 dprintf(CRITICAL, "command line argument is greater than buffer size\n");
291 return false;
292 }
293
294 strlcpy(pbuf, DISPLAY_CMDLINE_PREFIX, buf_size);
295 buf_size -= prefix_string_len;
296 strlcat(pbuf, LK_OVERRIDE_PANEL, buf_size);
297 buf_size -= LK_OVERRIDE_PANEL_LEN;
298 strlcat(pbuf, HDMI_CONTROLLER_STRING, buf_size);
299 } else {
300 ret = gcdb_display_cmdline_arg(pbuf, buf_size);
301 }
302
303 return ret;
304}
305
Aravind Venkateswaran6385f7e2014-02-25 16:45:11 -0800306void target_display_init(const char *panel_name)
Dhaval Patelf9986272013-10-18 19:06:05 -0700307{
308 uint32_t ret = 0;
Ajay Singh Parmareef1d602014-03-15 17:41:52 -0700309
310 panel_name += strspn(panel_name, " ");
311
312 if (!strcmp(panel_name, HDMI_PANEL_NAME)) {
313 dprintf(INFO, "%s: HDMI is primary\n", __func__);
314 return;
315 }
316
Aravind Venkateswarand494f962014-02-25 17:16:49 -0800317 ret = gcdb_display_init(panel_name, MDP_REV_50, MIPI_FB_ADDR);
Dhaval Patelf9986272013-10-18 19:06:05 -0700318 if (ret) {
319 msm_display_off();
320 }
321}
322
Aravind Venkateswarandd50c1a2014-02-25 14:42:43 -0800323void target_display_shutdown(void)
Dhaval Patelf9986272013-10-18 19:06:05 -0700324{
325 gcdb_display_shutdown();
326}