blob: 0e78ed3529ba95b180971b0c21e3b5a416d40ced [file] [log] [blame]
Shashank Mittal402d0972010-09-29 10:09:52 -07001/*
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -07002 * * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
Shashank Mittal402d0972010-09-29 10:09:52 -07003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of Code Aurora Forum, Inc. nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <debug.h>
31#include <kernel/thread.h>
32#include <i2c_qup.h>
33#include <platform/iomap.h>
Amol Jadic52c8a32011-07-12 11:27:04 -070034#include <platform/gpio.h>
Shashank Mittal402d0972010-09-29 10:09:52 -070035#include <platform/clock.h>
36#include <platform/pmic.h>
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -070037#include <platform/pmic_pwm.h>
Amol Jadic52c8a32011-07-12 11:27:04 -070038#include <gsbi.h>
Shashank Mittal402d0972010-09-29 10:09:52 -070039
40#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
41
42static struct qup_i2c_dev *dev = NULL;
43
44uint8_t expander_read(uint8_t addr)
45{
46 uint8_t ret = 0;
47 /* Create a i2c_msg buffer, that is used to put the controller into read
48 mode and then to read some data. */
49 struct i2c_msg msg_buf[] = {
50 {CORE_GPIO_EXPANDER_I2C_ADDRESS, I2C_M_WR, 1, &addr},
51 {CORE_GPIO_EXPANDER_I2C_ADDRESS, I2C_M_RD, 1, &ret}
52 };
53
54 qup_i2c_xfer(dev, msg_buf, 2);
55
56 return ret;
57}
58
59uint8_t expander_write(uint8_t addr, uint8_t val)
60{
61 uint8_t data_buf[] = { addr, val };
62
63 /* Create a i2c_msg buffer, that is used to put the controller into write
64 mode and then to write some data. */
65 struct i2c_msg msg_buf[] = { {CORE_GPIO_EXPANDER_I2C_ADDRESS,
66 I2C_M_WR, 2, data_buf}
67 };
68
69 qup_i2c_xfer(dev, msg_buf, 1);
70
71 /* Double check that the write worked. */
72 if (val != expander_read(addr)) {
73 return -1;
74 }
75
76 return 0;
77}
78
79void panel_poweron(void)
80{
81 panel_backlight(1);
82 lcdc_on();
83}
84
85void panel_backlight(int on)
86{
87}
88
89static int display_common_power(int on)
90{
91}
92
93static int lcd_power_on()
94{
95 uint8_t buffer = 0x0, mask = 0x0, prev_val = 0x0;
96 int ret = 0;
97
98 /* Configure LDO L2 TEST Bank 2, to Range Select 0 */
Subbaraman Narayanamurthy83019a42011-02-15 20:08:02 -080099 /* Not updating reference voltage */
Shashank Mittal402d0972010-09-29 10:09:52 -0700100 buffer = (0x80); /* Write mode */
101 buffer |= (PM8901_LDO_TEST_BANK(2)); /* Test Bank 2 */
102 mask = buffer | LDO_TEST_RANGE_SELECT_MASK;
103
104 if ((ret = pm8901_test_bank_read(&prev_val,
105 PM8901_LDO_TEST_BANK(2),
106 PM8901_LDO_L2_TEST_BANK))) {
107 return ret;
108 }
109 if ((ret = pm8901_vreg_write(&buffer, mask, PM8901_LDO_L2_TEST_BANK,
110 prev_val))) {
111 return ret;
112 }
113
Subbaraman Narayanamurthy83019a42011-02-15 20:08:02 -0800114 /* Enable LDO L2 at Max Voltage (should be around 3.3v) */
115 buffer = (0x0 << PM8901_LDO_CTL_ENABLE__S);
116 /* Disable Pull Down */
117 buffer |= (0x1 << PM8901_LDO_CTL_PULL_DOWN__S);
118 /* Put LDO into normal mode instead of low power mode */
119 buffer |= (0x0 << PM8901_LDO_CTL_MODE__S);
120 /* Write a 31 into the Voltage Programming value to obtain 3.3v VREG =
121 1.75V + X * 100mV */
122 buffer |= (0xF);
123 mask = buffer | LDO_CTL_ENABLE_MASK |
124 LDO_CTL_PULL_DOWN_MASK |
125 LDO_CTL_NORMAL_POWER_MODE_MASK | LDO_CTL_VOLTAGE_SET_MASK;
126
127 /* Do a normal read here, as to not destroy the value in LDO control */
128 if ((ret = pm8901_read(&prev_val, 1, PM8901_LDO_L2))) {
129 return ret;
130 }
131 /* Configure the LDO2 for 3.3v */
132 ret = pm8901_vreg_write(&buffer, mask, PM8901_LDO_L2, prev_val);
133
Shashank Mittal402d0972010-09-29 10:09:52 -0700134 /* Configure LDO L2 TEST Bank 4, for High Range Mode */
135 buffer = (0x80); /* Write mode */
136 buffer |= (PM8901_LDO_TEST_BANK(4)); /* Test Bank 4 */
137 buffer |= (0x01); /* Put into High Range Mode */
138 mask = buffer | LDO_TEST_OUTPUT_RANGE_MASK;
139
140 if ((ret = pm8901_test_bank_read(&prev_val,
141 PM8901_LDO_TEST_BANK(4),
142 PM8901_LDO_L2_TEST_BANK))) {
143 return ret;
144 }
145 if ((ret = pm8901_vreg_write(&buffer, mask, PM8901_LDO_L2_TEST_BANK,
146 prev_val))) {
147 return ret;
148 }
149
Subbaraman Narayanamurthy83019a42011-02-15 20:08:02 -0800150 /* Configure LDO L2 TEST Bank 2, to Range Select 0 */
Shashank Mittal402d0972010-09-29 10:09:52 -0700151 buffer = (0x80); /* Write mode */
Subbaraman Narayanamurthy83019a42011-02-15 20:08:02 -0800152 buffer |= (PM8901_LDO_TEST_BANK(2)); /* Test Bank 2 */
153 buffer |= (1<<1); /* For fine step 50 mV */
154 buffer |= (1<<3); /* to update reference voltage */
155 mask = buffer | LDO_TEST_RANGE_SELECT_MASK;
156 mask |= (1<<2); /* Setting mask to make ref voltage as 1.25 V */
Shashank Mittal402d0972010-09-29 10:09:52 -0700157
158 if ((ret = pm8901_test_bank_read(&prev_val,
Subbaraman Narayanamurthy83019a42011-02-15 20:08:02 -0800159 PM8901_LDO_TEST_BANK(2),
Shashank Mittal402d0972010-09-29 10:09:52 -0700160 PM8901_LDO_L2_TEST_BANK))) {
161 return ret;
162 }
163 if ((ret = pm8901_vreg_write(&buffer, mask, PM8901_LDO_L2_TEST_BANK,
164 prev_val))) {
165 return ret;
166 }
167
Subbaraman Narayanamurthy83019a42011-02-15 20:08:02 -0800168 /* Enable PMR for LDO L2 */
169 buffer = 0x7F;
170 mask = 0x7F;
171 if ((ret = pm8901_read(&prev_val, 1, PM8901_PMR_7))) {
Shashank Mittal402d0972010-09-29 10:09:52 -0700172 return ret;
173 }
Subbaraman Narayanamurthy83019a42011-02-15 20:08:02 -0800174 ret = pm8901_vreg_write(&buffer, mask, PM8901_PMR_7, prev_val);
Shashank Mittal402d0972010-09-29 10:09:52 -0700175 return ret;
176}
177
178/* Configures the GPIO that are needed to enable LCD.
179 * This function also configures the PMIC for PWM control of the LCD backlight.
180 */
181static void lcd_gpio_cfg(uint8_t on)
182{
183 uint32_t func;
184 uint32_t pull;
185 uint32_t dir;
186 uint32_t enable = 0; /* not used in gpio_tlmm_config */
187 uint32_t drv;
188 if (on) {
189 func = 1; /* Configure GPIO for LCDC function */
190 pull = GPIO_NO_PULL;
191 dir = 1; /* doesn't matter since it is not configured as
192 GPIO */
193 drv = GPIO_16MA;
194 } else {
195 /* As discussed in the MSM8660 FFA HW SW Control Doc configure these
196 GPIO as input and pull down. */
197 func = 0; /* GPIO */
198 pull = GPIO_PULL_DOWN;
199 dir = 0; /* Input */
200 drv = 0; /* does not matter configured as input */
201 }
202
203 gpio_tlmm_config(0, func, dir, pull, drv, enable); /* lcdc_pclk */
204 gpio_tlmm_config(1, func, dir, pull, drv, enable); /* lcdc_hsync */
205 gpio_tlmm_config(2, func, dir, pull, drv, enable); /* lcdc_vsync */
206 gpio_tlmm_config(3, func, dir, pull, drv, enable); /* lcdc_den */
207 gpio_tlmm_config(4, func, dir, pull, drv, enable); /* lcdc_red7 */
208 gpio_tlmm_config(5, func, dir, pull, drv, enable); /* lcdc_red6 */
209 gpio_tlmm_config(6, func, dir, pull, drv, enable); /* lcdc_red5 */
210 gpio_tlmm_config(7, func, dir, pull, drv, enable); /* lcdc_red4 */
211 gpio_tlmm_config(8, func, dir, pull, drv, enable); /* lcdc_red3 */
212 gpio_tlmm_config(9, func, dir, pull, drv, enable); /* lcdc_red2 */
213 gpio_tlmm_config(10, func, dir, pull, drv, enable); /* lcdc_red1 */
214 gpio_tlmm_config(11, func, dir, pull, drv, enable); /* lcdc_red0 */
215 gpio_tlmm_config(12, func, dir, pull, drv, enable); /* lcdc_rgn7 */
216 gpio_tlmm_config(13, func, dir, pull, drv, enable); /* lcdc_rgn6 */
217 gpio_tlmm_config(14, func, dir, pull, drv, enable); /* lcdc_rgn5 */
218 gpio_tlmm_config(15, func, dir, pull, drv, enable); /* lcdc_rgn4 */
219 gpio_tlmm_config(16, func, dir, pull, drv, enable); /* lcdc_rgn3 */
220 gpio_tlmm_config(17, func, dir, pull, drv, enable); /* lcdc_rgn2 */
221 gpio_tlmm_config(18, func, dir, pull, drv, enable); /* lcdc_rgn1 */
222 gpio_tlmm_config(19, func, dir, pull, drv, enable); /* lcdc_rgn0 */
223 gpio_tlmm_config(20, func, dir, pull, drv, enable); /* lcdc_blu7 */
224 gpio_tlmm_config(21, func, dir, pull, drv, enable); /* lcdc_blu6 */
225 gpio_tlmm_config(22, func, dir, pull, drv, enable); /* lcdc_blu5 */
226 gpio_tlmm_config(23, func, dir, pull, drv, enable); /* lcdc_blu4 */
227 gpio_tlmm_config(24, func, dir, pull, drv, enable); /* lcdc_blu3 */
228 gpio_tlmm_config(25, func, dir, pull, drv, enable); /* lcdc_blu2 */
229 gpio_tlmm_config(26, func, dir, pull, drv, enable); /* lcdc_blu1 */
230 gpio_tlmm_config(27, func, dir, pull, drv, enable); /* lcdc_blu0 */
231}
232
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700233/* API to set backlight level configuring PWM in PM8058 */
234
235int panel_set_backlight(uint8_t bt_level)
Shashank Mittal402d0972010-09-29 10:09:52 -0700236{
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700237 int rc = -1;
238 uint32_t duty_us, period_us;
Shashank Mittal402d0972010-09-29 10:09:52 -0700239
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700240 if((bt_level <= 0) || (bt_level > 15))
241 {
242 dprintf(CRITICAL, "Error in brightness level (1-15 allowed)\n");
243 goto bail_out;
244 }
245
246 duty_us = bt_level*PWM_DUTY_LEVEL;
247 period_us = PWM_PERIOD_USEC;
248 rc = pm_pwm_config(0, duty_us, period_us);
249 if(rc)
250 {
251 dprintf(CRITICAL, "Error in pwm_config0\n");
252 goto bail_out;
253 }
254
255 duty_us = PWM_PERIOD_USEC - (bt_level*PWM_DUTY_LEVEL);
256 period_us = PWM_PERIOD_USEC;
257 rc = pm_pwm_config(1, duty_us, period_us);
258 if(rc)
259 {
260 dprintf(CRITICAL, "Error in pwm_config1\n");
261 goto bail_out;
262 }
263
264 rc = pm_pwm_enable(0);
265 if(rc)
266 {
267 dprintf(CRITICAL, "Error in pwm_enable0\n");
268 goto bail_out;
269 }
270
271 rc = pm_pwm_enable(1);
272 if(rc)
273 dprintf(CRITICAL, "Error in pwm_enable1\n");
274
275bail_out:
276 return rc;
277}
278
279void bl_gpio_init(void)
280{
281 /* Configure PM8058 GPIO24 as a PWM driver (LPG ch0) for chain 1 of 6 LEDs */
282 pm8058_write_one(0x81, GPIO24_GPIO_CNTRL); /* Write, Bank0, VIN0, Mode
Shashank Mittal402d0972010-09-29 10:09:52 -0700283 selection enabled */
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700284 pm8058_write_one(0x98, GPIO24_GPIO_CNTRL); /* Write, Bank1, OutOn/InOff,
Shashank Mittal402d0972010-09-29 10:09:52 -0700285 CMOS, Don't Invert Output */
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700286 pm8058_write_one(0xAA, GPIO24_GPIO_CNTRL); /* Write, Bank2, GPIO no pull */
287 pm8058_write_one(0xB4, GPIO24_GPIO_CNTRL); /* Write, Bank3, high drv
Shashank Mittal402d0972010-09-29 10:09:52 -0700288 strength */
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700289 pm8058_write_one(0xC6, GPIO24_GPIO_CNTRL); /* Write, Bank4, Src: LPG_DRV1
Shashank Mittal402d0972010-09-29 10:09:52 -0700290 (Spec. Fnc 2) */
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700291 pm8058_write_one(0xD8, GPIO24_GPIO_CNTRL); /* Write, Bank5, Interrupt
Shashank Mittal402d0972010-09-29 10:09:52 -0700292 polarity noninversion */
293
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700294 /* Configure PM8058 GPIO25 as a PWM driver (LPG ch1) for chain 2 of 5 LEDs */
295 pm8058_write_one(0x81, GPIO25_GPIO_CNTRL); /* Write, Bank0, VIN0, Mode
Shashank Mittal402d0972010-09-29 10:09:52 -0700296 selection enabled */
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700297 pm8058_write_one(0x98, GPIO25_GPIO_CNTRL); /* Write, Bank1, OutOn/InOff,
Shashank Mittal402d0972010-09-29 10:09:52 -0700298 CMOS, Don't Invert Output */
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700299 pm8058_write_one(0xAA, GPIO25_GPIO_CNTRL); /* Write, Bank2, GPIO no pull */
300 pm8058_write_one(0xB4, GPIO25_GPIO_CNTRL); /* Write, Bank3, high drv
Shashank Mittal402d0972010-09-29 10:09:52 -0700301 strength */
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700302 pm8058_write_one(0xC6, GPIO25_GPIO_CNTRL); /* Write, Bank4, Src: LPG_DRV2
Shashank Mittal402d0972010-09-29 10:09:52 -0700303 (Spec. Fnc 2) */
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700304 pm8058_write_one(0xD8, GPIO25_GPIO_CNTRL); /* Write, Bank5, Interrupt
Shashank Mittal402d0972010-09-29 10:09:52 -0700305 polarity noninversion */
Shashank Mittal402d0972010-09-29 10:09:52 -0700306}
307
308void board_lcd_enable(void)
309{
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700310 int rc = -1;
Amol Jadic52c8a32011-07-12 11:27:04 -0700311 dev = qup_i2c_init(GSBI_ID_8, 100000, 24000000);
Shashank Mittal402d0972010-09-29 10:09:52 -0700312
313 /* Make sure dev is created and initialized properly */
314 if (!dev) {
315 while (1) ;
316 return;
317 }
318
319 /* Store current value of these registers as to not destroy their previous
320 state. */
321 uint8_t open_drain_a = expander_read(GPIO_EXPANDER_REG_OPEN_DRAIN_A);
322 uint8_t dir_b = expander_read(GPIO_EXPANDER_REG_DIR_B);
323 uint8_t dir_a = expander_read(GPIO_EXPANDER_REG_DIR_A);
324 uint8_t data_b = expander_read(GPIO_EXPANDER_REG_DATA_B);
325 uint8_t data_a = expander_read(GPIO_EXPANDER_REG_DATA_A);
326
327 /* Set the LVDS_SHUTDOWN_N to open drain and output low. */
328 dprintf(INFO, "Enable lvds_shutdown_n line for Open Drain.\n");
329 expander_write(GPIO_EXPANDER_REG_OPEN_DRAIN_A, 0x04 | open_drain_a);
330
331 dprintf(INFO, "Enable lvds_shutdown_n line for output.\n");
332 expander_write(GPIO_EXPANDER_REG_DIR_A, ~0x04 & dir_a);
333
334 dprintf(INFO, "Drive the LVDS_SHUTDOWN_N pin high here.\n");
335 expander_write(GPIO_EXPANDER_REG_DATA_A, 0x04 | data_a);
336
337 /* Turn on the VREG_L2B to 3.3V. */
338
339 /* Power on the appropiate PMIC LDO power rails */
340 if (lcd_power_on())
341 return;
342
343 /* Enable the GPIO as LCDC mode LCD. */
344 lcd_gpio_cfg(1);
345
346 /* Arbitrary delay */
347 udelay(20000);
348
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700349 /* Set the GPIOs needed for backlight */
350 bl_gpio_init();
351 /* Set backlight level with API (to 8 by default) */
352 rc = panel_set_backlight(8);
353 if(rc)
354 dprintf(CRITICAL,"Error in setting panel backlight\n");
Shashank Mittal402d0972010-09-29 10:09:52 -0700355
356 dprintf(INFO, "Enable BACKLIGHT_EN line for output.\n");
357 expander_write(GPIO_EXPANDER_REG_DIR_B, ~0x10 & dir_b);
358
359 dprintf(INFO, "Drive BACKLIGHT_EN to high\n");
360 expander_write(GPIO_EXPANDER_REG_DATA_B, 0x10 | data_b);
361
362}
363
364void mdp_clock_init(void)
365{
Shashank Mittal402d0972010-09-29 10:09:52 -0700366 /* Turn on the PLL2, to ramp up the MDP clock to max (200MHz) */
367 nt_pll_enable(PLL_2, 1);
368
369 config_mdp_clk(MDP_NS_VAL, MDP_MD_VAL,
370 MDP_CC_VAL, MDP_NS_REG, MDP_MD_REG, MDP_CC_REG);
371
372 config_pixel_clk(PIXEL_NS_VAL, PIXEL_MD_VAL,
373 PIXEL_CC_VAL, LCD_PIXEL_NS_REG,
374 LCD_PIXEL_MD_REG, LCD_PIXEL_CC_REG);
375}
376
377void lcdc_on(void)
378{
379 board_lcd_enable();
380}