blob: 950815a82a9daa93be8a4da0dfa0e32ad3703c83 [file] [log] [blame]
Chintan Pandya250c2e52012-01-19 17:15:49 +05301/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13#include <linux/init.h>
14#include <linux/ioport.h>
15#include <linux/platform_device.h>
16#include <linux/bootmem.h>
17#include <linux/regulator/consumer.h>
18#include <asm/mach-types.h>
19#include <asm/io.h>
20#include <mach/msm_bus_board.h>
21#include <mach/msm_memtypes.h>
22#include <mach/board.h>
23#include <mach/gpio.h>
24#include <mach/gpiomux.h>
25#include <mach/socinfo.h>
26#include <mach/rpc_pmapp.h>
27#include "devices.h"
28#include "board-msm7627a.h"
29
30#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
Padmanabhan Komanduruede0a632012-01-25 12:01:28 +053031#define MSM_FB_SIZE 0x261000
Chintan Pandya250c2e52012-01-19 17:15:49 +053032#define MSM7x25A_MSM_FB_SIZE 0xE1000
33#else
Padmanabhan Komanduruede0a632012-01-25 12:01:28 +053034#define MSM_FB_SIZE 0x196000
Chintan Pandya250c2e52012-01-19 17:15:49 +053035#define MSM7x25A_MSM_FB_SIZE 0x96000
36#endif
37
38static unsigned fb_size = MSM_FB_SIZE;
39static int __init fb_size_setup(char *p)
40{
41 fb_size = memparse(p, NULL);
42 return 0;
43}
44
45early_param("fb_size", fb_size_setup);
46
Jeevan Shriram901a15f2012-03-09 11:53:23 +053047static uint32_t lcdc_truly_gpio_initialized;
48static struct regulator_bulk_data regs_truly_lcdc[] = {
49 { .supply = "rfrx1", .min_uV = 1800000, .max_uV = 1800000 },
50};
51
52#define SKU3_LCDC_GPIO_DISPLAY_RESET 90
53#define SKU3_LCDC_GPIO_SPI_MOSI 19
54#define SKU3_LCDC_GPIO_SPI_CLK 20
55#define SKU3_LCDC_GPIO_SPI_CS0_N 21
56#define SKU3_LCDC_LCD_CAMERA_LDO_2V8 35 /*LCD_CAMERA_LDO_2V8*/
57#define SKU3_LCDC_LCD_CAMERA_LDO_1V8 34 /*LCD_CAMERA_LDO_1V8*/
58#define SKU3_1_LCDC_LCD_CAMERA_LDO_1V8 58 /*LCD_CAMERA_LDO_1V8*/
59
60static uint32_t lcdc_truly_gpio_table[] = {
61 19,
62 20,
63 21,
64 89,
65 90,
66};
67
68static char *lcdc_gpio_name_table[5] = {
69 "spi_mosi",
70 "spi_clk",
71 "spi_cs",
72 "gpio_bkl_en",
73 "gpio_disp_reset",
74};
75
76static int lcdc_truly_gpio_init(void)
77{
78 int i;
79 int rc = 0;
80
81 if (!lcdc_truly_gpio_initialized) {
82 for (i = 0; i < ARRAY_SIZE(lcdc_truly_gpio_table); i++) {
83 rc = gpio_request(lcdc_truly_gpio_table[i],
84 lcdc_gpio_name_table[i]);
85 if (rc < 0) {
86 pr_err("Error request gpio %s\n",
87 lcdc_gpio_name_table[i]);
88 goto truly_gpio_fail;
89 }
90 rc = gpio_tlmm_config(GPIO_CFG(lcdc_truly_gpio_table[i],
91 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
92 GPIO_CFG_2MA), GPIO_CFG_ENABLE);
93 if (rc < 0) {
94 pr_err("Error config lcdc gpio:%d\n",
95 lcdc_truly_gpio_table[i]);
96 goto truly_gpio_fail;
97 }
98 rc = gpio_direction_output(lcdc_truly_gpio_table[i], 0);
99 if (rc < 0) {
100 pr_err("Error direct lcdc gpio:%d\n",
101 lcdc_truly_gpio_table[i]);
102 goto truly_gpio_fail;
103 }
104 }
105
106 lcdc_truly_gpio_initialized = 1;
107 }
108
109 return rc;
110
111truly_gpio_fail:
112 for (; i >= 0; i--) {
113 pr_err("Freeing GPIO: %d", lcdc_truly_gpio_table[i]);
114 gpio_free(lcdc_truly_gpio_table[i]);
115 }
116
117 lcdc_truly_gpio_initialized = 0;
118 return rc;
119}
120
121
122void sku3_lcdc_lcd_camera_power_init(void)
123{
124 int rc = 0;
125 u32 socinfo = socinfo_get_platform_type();
126
127 /* LDO_EXT2V8 */
128 if (gpio_request(SKU3_LCDC_LCD_CAMERA_LDO_2V8, "lcd_camera_ldo_2v8")) {
129 pr_err("failed to request gpio lcd_camera_ldo_2v8\n");
130 return;
131 }
132
133 rc = gpio_tlmm_config(GPIO_CFG(SKU3_LCDC_LCD_CAMERA_LDO_2V8, 0,
134 GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
135 GPIO_CFG_ENABLE);
136
137 if (rc < 0) {
138 pr_err("%s:unable to enable lcd_camera_ldo_2v8!\n", __func__);
139 goto fail_gpio2;
140 }
141
142 /* LDO_EVT1V8 */
143 if (socinfo == 0x0B) {
144 if (gpio_request(SKU3_LCDC_LCD_CAMERA_LDO_1V8,
145 "lcd_camera_ldo_1v8")) {
146 pr_err("failed to request gpio lcd_camera_ldo_1v8\n");
147 goto fail_gpio1;
148 }
149
150 rc = gpio_tlmm_config(GPIO_CFG(SKU3_LCDC_LCD_CAMERA_LDO_1V8, 0,
151 GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
152 GPIO_CFG_ENABLE);
153
154 if (rc < 0) {
155 pr_err("%s: unable to enable lcdc_camera_ldo_1v8!\n",
156 __func__);
157 goto fail_gpio1;
158 }
159 } else if (socinfo == 0x0F) {
160 if (gpio_request(SKU3_1_LCDC_LCD_CAMERA_LDO_1V8,
161 "lcd_camera_ldo_1v8")) {
162 pr_err("failed to request gpio lcd_camera_ldo_1v8\n");
163 goto fail_gpio1;
164 }
165
166 rc = gpio_tlmm_config(GPIO_CFG(SKU3_1_LCDC_LCD_CAMERA_LDO_1V8,
167 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
168 GPIO_CFG_ENABLE);
169
170 if (rc < 0) {
171 pr_err("%s: unable to enable lcdc_camera_ldo_1v8!\n",
172 __func__);
173 goto fail_gpio1;
174 }
175 }
176
177 rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_truly_lcdc),
178 regs_truly_lcdc);
179 if (rc)
180 pr_err("%s: could not get regulators: %d\n", __func__, rc);
181
182 rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_truly_lcdc),
183 regs_truly_lcdc);
184 if (rc)
185 pr_err("%s: could not set voltages: %d\n", __func__, rc);
186
187 return;
188
189fail_gpio1:
190 if (socinfo == 0x0B)
191 gpio_free(SKU3_LCDC_LCD_CAMERA_LDO_1V8);
192 else if (socinfo == 0x0F)
193 gpio_free(SKU3_1_LCDC_LCD_CAMERA_LDO_1V8);
194fail_gpio2:
195 gpio_free(SKU3_LCDC_LCD_CAMERA_LDO_2V8);
196 return;
197}
198
199int sku3_lcdc_lcd_camera_power_onoff(int on)
200{
201 int rc = 0;
202 u32 socinfo = socinfo_get_platform_type();
203
204 if (on) {
205 if (socinfo == 0x0B)
206 gpio_set_value_cansleep(SKU3_LCDC_LCD_CAMERA_LDO_1V8,
207 1);
208 else if (socinfo == 0x0F)
209 gpio_set_value_cansleep(SKU3_1_LCDC_LCD_CAMERA_LDO_1V8,
210 1);
211
212 gpio_set_value_cansleep(SKU3_LCDC_LCD_CAMERA_LDO_2V8, 1);
213
214 rc = regulator_bulk_enable(ARRAY_SIZE(regs_truly_lcdc),
215 regs_truly_lcdc);
216 if (rc)
217 pr_err("%s: could not enable regulators: %d\n",
218 __func__, rc);
219 } else {
220 if (socinfo == 0x0B)
221 gpio_set_value_cansleep(SKU3_LCDC_LCD_CAMERA_LDO_1V8,
222 0);
223 else if (socinfo == 0x0F)
224 gpio_set_value_cansleep(SKU3_1_LCDC_LCD_CAMERA_LDO_1V8,
225 0);
226
227 gpio_set_value_cansleep(SKU3_LCDC_LCD_CAMERA_LDO_2V8, 0);
228
229 rc = regulator_bulk_disable(ARRAY_SIZE(regs_truly_lcdc),
230 regs_truly_lcdc);
231 if (rc)
232 pr_err("%s: could not disable regulators: %d\n",
233 __func__, rc);
234 }
235
236 return rc;
237}
238
239static int sku3_lcdc_power_save(int on)
240{
241 int rc = 0;
242
243 if (on) {
244 sku3_lcdc_lcd_camera_power_onoff(1);
245 rc = lcdc_truly_gpio_init();
246 if (rc < 0) {
247 pr_err("%s(): Truly GPIO initializations failed",
248 __func__);
249 return rc;
250 }
251
252 if (lcdc_truly_gpio_initialized) {
253 /*LCD reset*/
254 gpio_set_value(SKU3_LCDC_GPIO_DISPLAY_RESET, 1);
255 msleep(20);
256 gpio_set_value(SKU3_LCDC_GPIO_DISPLAY_RESET, 0);
257 msleep(20);
258 gpio_set_value(SKU3_LCDC_GPIO_DISPLAY_RESET, 1);
259 msleep(20);
260 }
261 } else {
262 /* pull down LCD IO to avoid current leakage */
263 gpio_set_value(SKU3_LCDC_GPIO_SPI_MOSI, 0);
264 gpio_set_value(SKU3_LCDC_GPIO_SPI_CLK, 0);
265 gpio_set_value(SKU3_LCDC_GPIO_SPI_CS0_N, 0);
266 gpio_set_value(SKU3_LCDC_GPIO_DISPLAY_RESET, 0);
267
268 sku3_lcdc_lcd_camera_power_onoff(0);
269 }
270 return rc;
271}
272
273static struct msm_panel_common_pdata lcdc_truly_panel_data = {
274 .panel_config_gpio = NULL,
275 .gpio_num = lcdc_truly_gpio_table,
276};
277
278static struct platform_device lcdc_truly_panel_device = {
279 .name = "lcdc_truly_hvga_ips3p2335_pt",
280 .id = 0,
281 .dev = {
282 .platform_data = &lcdc_truly_panel_data,
283 }
284};
285
Chintan Pandya250c2e52012-01-19 17:15:49 +0530286static struct regulator_bulk_data regs_lcdc[] = {
287 { .supply = "gp2", .min_uV = 2850000, .max_uV = 2850000 },
288 { .supply = "msme1", .min_uV = 1800000, .max_uV = 1800000 },
289};
290static uint32_t lcdc_gpio_initialized;
291
292static void lcdc_toshiba_gpio_init(void)
293{
294 int rc = 0;
295 if (!lcdc_gpio_initialized) {
296 if (gpio_request(GPIO_SPI_CLK, "spi_clk")) {
297 pr_err("failed to request gpio spi_clk\n");
298 return;
299 }
300 if (gpio_request(GPIO_SPI_CS0_N, "spi_cs")) {
301 pr_err("failed to request gpio spi_cs0_N\n");
302 goto fail_gpio6;
303 }
304 if (gpio_request(GPIO_SPI_MOSI, "spi_mosi")) {
305 pr_err("failed to request gpio spi_mosi\n");
306 goto fail_gpio5;
307 }
308 if (gpio_request(GPIO_SPI_MISO, "spi_miso")) {
309 pr_err("failed to request gpio spi_miso\n");
310 goto fail_gpio4;
311 }
312 if (gpio_request(GPIO_DISPLAY_PWR_EN, "gpio_disp_pwr")) {
313 pr_err("failed to request gpio_disp_pwr\n");
314 goto fail_gpio3;
315 }
316 if (gpio_request(GPIO_BACKLIGHT_EN, "gpio_bkl_en")) {
317 pr_err("failed to request gpio_bkl_en\n");
318 goto fail_gpio2;
319 }
320 pmapp_disp_backlight_init();
321
322 rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_lcdc),
323 regs_lcdc);
324 if (rc) {
325 pr_err("%s: could not get regulators: %d\n",
326 __func__, rc);
327 goto fail_gpio1;
328 }
329
330 rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_lcdc),
331 regs_lcdc);
332 if (rc) {
333 pr_err("%s: could not set voltages: %d\n",
334 __func__, rc);
335 goto fail_vreg;
336 }
337 lcdc_gpio_initialized = 1;
338 }
339 return;
340fail_vreg:
341 regulator_bulk_free(ARRAY_SIZE(regs_lcdc), regs_lcdc);
342fail_gpio1:
343 gpio_free(GPIO_BACKLIGHT_EN);
344fail_gpio2:
345 gpio_free(GPIO_DISPLAY_PWR_EN);
346fail_gpio3:
347 gpio_free(GPIO_SPI_MISO);
348fail_gpio4:
349 gpio_free(GPIO_SPI_MOSI);
350fail_gpio5:
351 gpio_free(GPIO_SPI_CS0_N);
352fail_gpio6:
353 gpio_free(GPIO_SPI_CLK);
354 lcdc_gpio_initialized = 0;
355}
356
357static uint32_t lcdc_gpio_table[] = {
358 GPIO_SPI_CLK,
359 GPIO_SPI_CS0_N,
360 GPIO_SPI_MOSI,
361 GPIO_DISPLAY_PWR_EN,
362 GPIO_BACKLIGHT_EN,
363 GPIO_SPI_MISO,
364};
365
366static void config_lcdc_gpio_table(uint32_t *table, int len, unsigned enable)
367{
368 int n;
369
370 if (lcdc_gpio_initialized) {
371 /* All are IO Expander GPIOs */
372 for (n = 0; n < (len - 1); n++)
373 gpio_direction_output(table[n], 1);
374 }
375}
376
377static void lcdc_toshiba_config_gpios(int enable)
378{
379 config_lcdc_gpio_table(lcdc_gpio_table,
380 ARRAY_SIZE(lcdc_gpio_table), enable);
381}
382
383static int msm_fb_lcdc_power_save(int on)
384{
385 int rc = 0;
386 /* Doing the init of the LCDC GPIOs very late as they are from
387 an I2C-controlled IO Expander */
388 lcdc_toshiba_gpio_init();
389
390 if (lcdc_gpio_initialized) {
391 gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, on);
392 gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, on);
393
394 rc = on ? regulator_bulk_enable(
395 ARRAY_SIZE(regs_lcdc), regs_lcdc) :
396 regulator_bulk_disable(
397 ARRAY_SIZE(regs_lcdc), regs_lcdc);
398
399 if (rc)
400 pr_err("%s: could not %sable regulators: %d\n",
401 __func__, on ? "en" : "dis", rc);
402 }
403
404 return rc;
405}
406
407static int lcdc_toshiba_set_bl(int level)
408{
409 int ret;
410
411 ret = pmapp_disp_backlight_set_brightness(level);
412 if (ret)
413 pr_err("%s: can't set lcd backlight!\n", __func__);
414
415 return ret;
416}
417
Jeevan Shriram901a15f2012-03-09 11:53:23 +0530418
419static int msm_lcdc_power_save(int on)
420{
421 int rc = 0;
422 if (machine_is_msm7627a_qrd3())
423 rc = sku3_lcdc_power_save(on);
424 else
425 rc = msm_fb_lcdc_power_save(on);
426
427 return rc;
428}
429
Chintan Pandya250c2e52012-01-19 17:15:49 +0530430static struct lcdc_platform_data lcdc_pdata = {
431 .lcdc_gpio_config = NULL,
Jeevan Shriram901a15f2012-03-09 11:53:23 +0530432 .lcdc_power_save = msm_lcdc_power_save,
Chintan Pandya250c2e52012-01-19 17:15:49 +0530433};
434
435static int lcd_panel_spi_gpio_num[] = {
436 GPIO_SPI_MOSI, /* spi_sdi */
437 GPIO_SPI_MISO, /* spi_sdoi */
438 GPIO_SPI_CLK, /* spi_clk */
439 GPIO_SPI_CS0_N, /* spi_cs */
440};
441
442static struct msm_panel_common_pdata lcdc_toshiba_panel_data = {
443 .panel_config_gpio = lcdc_toshiba_config_gpios,
444 .pmic_backlight = lcdc_toshiba_set_bl,
445 .gpio_num = lcd_panel_spi_gpio_num,
446};
447
448static struct platform_device lcdc_toshiba_panel_device = {
449 .name = "lcdc_toshiba_fwvga_pt",
450 .id = 0,
451 .dev = {
452 .platform_data = &lcdc_toshiba_panel_data,
453 }
454};
455
456static struct resource msm_fb_resources[] = {
457 {
458 .flags = IORESOURCE_DMA,
459 }
460};
461
Chintan Pandya250c2e52012-01-19 17:15:49 +0530462#define LCDC_TOSHIBA_FWVGA_PANEL_NAME "lcdc_toshiba_fwvga_pt"
463#define MIPI_CMD_RENESAS_FWVGA_PANEL_NAME "mipi_cmd_renesas_fwvga"
464
465static int msm_fb_detect_panel(const char *name)
466{
467 int ret = -ENODEV;
468
Taniya Dase3027e22012-02-27 16:32:27 +0530469 if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf() ||
470 machine_is_msm8625_surf()) {
Chintan Pandya250c2e52012-01-19 17:15:49 +0530471 if (!strncmp(name, "lcdc_toshiba_fwvga_pt", 21) ||
472 !strncmp(name, "mipi_cmd_renesas_fwvga", 22))
473 ret = 0;
474 } else if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()) {
475 if (!strncmp(name, "mipi_cmd_renesas_fwvga", 22))
476 ret = 0;
477 } else if (machine_is_msm7627a_qrd1()) {
478 if (!strncmp(name, "mipi_video_truly_wvga", 21))
479 ret = 0;
Jeevan Shriram901a15f2012-03-09 11:53:23 +0530480 } else if (machine_is_msm7627a_qrd3()) {
481 if (!strncmp(name, "lcdc_truly_hvga_ips3p2335_pt", 28))
482 ret = 0;
Chintan Pandyaf4ad4002012-02-28 19:49:03 +0530483 } else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
Jeevan Shrirame941df42012-01-23 12:40:21 +0530484 if (!strncmp(name, "mipi_cmd_nt35510_wvga", 21))
485 ret = 0;
Chintan Pandya250c2e52012-01-19 17:15:49 +0530486 }
487
488#if !defined(CONFIG_FB_MSM_LCDC_AUTO_DETECT) && \
489 !defined(CONFIG_FB_MSM_MIPI_PANEL_AUTO_DETECT) && \
490 !defined(CONFIG_FB_MSM_LCDC_MIPI_PANEL_AUTO_DETECT)
491 if (machine_is_msm7x27a_surf() ||
Taniya Dase3027e22012-02-27 16:32:27 +0530492 machine_is_msm7625a_surf() ||
493 machine_is_msm8625_surf()) {
Chintan Pandya250c2e52012-01-19 17:15:49 +0530494 if (!strncmp(name, LCDC_TOSHIBA_FWVGA_PANEL_NAME,
495 strnlen(LCDC_TOSHIBA_FWVGA_PANEL_NAME,
496 PANEL_NAME_MAX_LEN)))
497 return 0;
498 }
499#endif
500
501 return ret;
502}
503
504static int mipi_truly_set_bl(int on)
505{
506 gpio_set_value_cansleep(QRD_GPIO_BACKLIGHT_EN, !!on);
507
508 return 1;
509}
510
511static struct msm_fb_platform_data msm_fb_pdata = {
512 .detect_client = msm_fb_detect_panel,
513};
514
515static struct platform_device msm_fb_device = {
516 .name = "msm_fb",
517 .id = 0,
518 .num_resources = ARRAY_SIZE(msm_fb_resources),
519 .resource = msm_fb_resources,
520 .dev = {
521 .platform_data = &msm_fb_pdata,
522 }
523};
524
525#ifdef CONFIG_FB_MSM_MIPI_DSI
526static int mipi_renesas_set_bl(int level)
527{
528 int ret;
529
530 ret = pmapp_disp_backlight_set_brightness(level);
531
532 if (ret)
533 pr_err("%s: can't set lcd backlight!\n", __func__);
534
535 return ret;
536}
537
538static struct msm_panel_common_pdata mipi_renesas_pdata = {
539 .pmic_backlight = mipi_renesas_set_bl,
540};
541
542
543static struct platform_device mipi_dsi_renesas_panel_device = {
544 .name = "mipi_renesas",
545 .id = 0,
546 .dev = {
547 .platform_data = &mipi_renesas_pdata,
548 }
549};
550#endif
551
552static struct msm_panel_common_pdata mipi_truly_pdata = {
553 .pmic_backlight = mipi_truly_set_bl,
554};
555
556static struct platform_device mipi_dsi_truly_panel_device = {
557 .name = "mipi_truly",
558 .id = 0,
559 .dev = {
560 .platform_data = &mipi_truly_pdata,
561 }
562};
563
Jeevan Shrirame941df42012-01-23 12:40:21 +0530564static struct msm_panel_common_pdata mipi_NT35510_pdata = {
565 .pmic_backlight = NULL,/*mipi_NT35510_set_bl,*/
566};
567
568static struct platform_device mipi_dsi_NT35510_panel_device = {
569 .name = "mipi_NT35510",
570 .id = 0,
571 .dev = {
572 .platform_data = &mipi_NT35510_pdata,
573 }
574};
575
Chintan Pandya250c2e52012-01-19 17:15:49 +0530576static struct platform_device *msm_fb_devices[] __initdata = {
577 &msm_fb_device,
578 &lcdc_toshiba_panel_device,
579#ifdef CONFIG_FB_MSM_MIPI_DSI
580 &mipi_dsi_renesas_panel_device,
581#endif
582};
583
584static struct platform_device *qrd_fb_devices[] __initdata = {
585 &msm_fb_device,
586 &mipi_dsi_truly_panel_device,
587};
588
Jeevan Shriram901a15f2012-03-09 11:53:23 +0530589static struct platform_device *qrd3_fb_devices[] __initdata = {
590 &msm_fb_device,
591 &lcdc_truly_panel_device,
592};
593
Taniya Dasc868a2e2012-01-03 10:18:47 +0530594static struct platform_device *evb_fb_devices[] __initdata = {
Jeevan Shrirame941df42012-01-23 12:40:21 +0530595 &msm_fb_device,
596 &mipi_dsi_NT35510_panel_device,
Taniya Dasc868a2e2012-01-03 10:18:47 +0530597};
598
Chintan Pandya250c2e52012-01-19 17:15:49 +0530599void __init msm_msm7627a_allocate_memory_regions(void)
600{
601 void *addr;
602 unsigned long fb_size;
603
604 if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa())
605 fb_size = MSM7x25A_MSM_FB_SIZE;
606 else
607 fb_size = MSM_FB_SIZE;
608 addr = alloc_bootmem_align(fb_size, 0x1000);
609 msm_fb_resources[0].start = __pa(addr);
610 msm_fb_resources[0].end = msm_fb_resources[0].start + fb_size - 1;
611 pr_info("allocating %lu bytes at %p (%lx physical) for fb\n", fb_size,
612 addr, __pa(addr));
613}
614
615static struct msm_panel_common_pdata mdp_pdata = {
616 .gpio = 97,
617 .mdp_rev = MDP_REV_303,
618};
619
620#define GPIO_LCDC_BRDG_PD 128
621#define GPIO_LCDC_BRDG_RESET_N 129
622#define GPIO_LCD_DSI_SEL 125
623#define LCDC_RESET_PHYS 0x90008014
624
625static void __iomem *lcdc_reset_ptr;
626
627static unsigned mipi_dsi_gpio[] = {
628 GPIO_CFG(GPIO_LCDC_BRDG_RESET_N, 0, GPIO_CFG_OUTPUT,
629 GPIO_CFG_NO_PULL, GPIO_CFG_2MA), /* LCDC_BRDG_RESET_N */
630 GPIO_CFG(GPIO_LCDC_BRDG_PD, 0, GPIO_CFG_OUTPUT,
631 GPIO_CFG_NO_PULL, GPIO_CFG_2MA), /* LCDC_BRDG_PD */
632};
633
634static unsigned lcd_dsi_sel_gpio[] = {
635 GPIO_CFG(GPIO_LCD_DSI_SEL, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
636 GPIO_CFG_2MA),
637};
638
639enum {
640 DSI_SINGLE_LANE = 1,
641 DSI_TWO_LANES,
642};
643
644static int msm_fb_get_lane_config(void)
645{
646 /* For MSM7627A SURF/FFA and QRD */
647 int rc = DSI_TWO_LANES;
648 if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
649 rc = DSI_SINGLE_LANE;
650 pr_info("DSI_SINGLE_LANES\n");
651 } else {
652 pr_info("DSI_TWO_LANES\n");
653 }
654 return rc;
655}
656
657static int msm_fb_dsi_client_msm_reset(void)
658{
659 int rc = 0;
660
661 rc = gpio_request(GPIO_LCDC_BRDG_RESET_N, "lcdc_brdg_reset_n");
662 if (rc < 0) {
663 pr_err("failed to request lcd brdg reset_n\n");
664 return rc;
665 }
666
667 rc = gpio_request(GPIO_LCDC_BRDG_PD, "lcdc_brdg_pd");
668 if (rc < 0) {
669 pr_err("failed to request lcd brdg pd\n");
670 return rc;
671 }
672
673 rc = gpio_tlmm_config(mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
674 if (rc) {
675 pr_err("Failed to enable LCDC Bridge reset enable\n");
676 goto gpio_error;
677 }
678
679 rc = gpio_tlmm_config(mipi_dsi_gpio[1], GPIO_CFG_ENABLE);
680 if (rc) {
681 pr_err("Failed to enable LCDC Bridge pd enable\n");
682 goto gpio_error2;
683 }
684
685 rc = gpio_direction_output(GPIO_LCDC_BRDG_RESET_N, 1);
686 rc |= gpio_direction_output(GPIO_LCDC_BRDG_PD, 1);
687 gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 0);
688
689 if (!rc) {
Taniya Dase3027e22012-02-27 16:32:27 +0530690 if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
691 || machine_is_msm8625_surf()) {
Chintan Pandya250c2e52012-01-19 17:15:49 +0530692 lcdc_reset_ptr = ioremap_nocache(LCDC_RESET_PHYS,
693 sizeof(uint32_t));
694
695 if (!lcdc_reset_ptr)
696 return 0;
697 }
698 return rc;
699 } else {
700 goto gpio_error;
701 }
702
703gpio_error2:
704 pr_err("Failed GPIO bridge pd\n");
705 gpio_free(GPIO_LCDC_BRDG_PD);
706
707gpio_error:
708 pr_err("Failed GPIO bridge reset\n");
709 gpio_free(GPIO_LCDC_BRDG_RESET_N);
710 return rc;
711}
712
713static int mipi_truly_sel_mode(int video_mode)
714{
715 int rc = 0;
716
717 rc = gpio_request(GPIO_LCD_DSI_SEL, "lcd_dsi_sel");
718 if (rc < 0)
719 goto gpio_error;
720
721 rc = gpio_tlmm_config(lcd_dsi_sel_gpio[0], GPIO_CFG_ENABLE);
722 if (rc)
723 goto gpio_error;
724
725 rc = gpio_direction_output(GPIO_LCD_DSI_SEL, 1);
726 if (!rc) {
727 gpio_set_value_cansleep(GPIO_LCD_DSI_SEL, video_mode);
728 return rc;
729 } else {
730 goto gpio_error;
731 }
732
733gpio_error:
734 pr_err("mipi_truly_sel_mode failed\n");
735 gpio_free(GPIO_LCD_DSI_SEL);
736 return rc;
737}
738
739static int msm_fb_dsi_client_qrd1_reset(void)
740{
741 int rc = 0;
742
743 rc = gpio_request(GPIO_LCDC_BRDG_RESET_N, "lcdc_brdg_reset_n");
744 if (rc < 0) {
745 pr_err("failed to request lcd brdg reset_n\n");
746 return rc;
747 }
748
749 rc = gpio_tlmm_config(mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
750 if (rc < 0) {
751 pr_err("Failed to enable LCDC Bridge reset enable\n");
752 return rc;
753 }
754
755 rc = gpio_direction_output(GPIO_LCDC_BRDG_RESET_N, 1);
756 if (rc < 0) {
757 pr_err("Failed GPIO bridge pd\n");
758 gpio_free(GPIO_LCDC_BRDG_RESET_N);
759 return rc;
760 }
761
762 mipi_truly_sel_mode(1);
763
764 return rc;
765}
766
Jeevan Shrirame941df42012-01-23 12:40:21 +0530767#define GPIO_QRD3_LCD_BRDG_RESET_N 85
768#define GPIO_QRD3_LCD_BACKLIGHT_EN 96
769#define GPIO_QRD3_LCD_EXT_2V85_EN 35
770#define GPIO_QRD3_LCD_EXT_1V8_EN 40
771
772static unsigned qrd3_mipi_dsi_gpio[] = {
773 GPIO_CFG(GPIO_QRD3_LCD_BRDG_RESET_N, 0, GPIO_CFG_OUTPUT,
774 GPIO_CFG_NO_PULL,
775 GPIO_CFG_2MA), /* GPIO_QRD3_LCD_BRDG_RESET_N */
776 GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0, GPIO_CFG_OUTPUT,
777 GPIO_CFG_NO_PULL,
778 GPIO_CFG_2MA), /* GPIO_QRD3_LCD_BACKLIGHT_EN */
779 GPIO_CFG(GPIO_QRD3_LCD_EXT_2V85_EN, 0, GPIO_CFG_OUTPUT,
780 GPIO_CFG_NO_PULL,
781 GPIO_CFG_2MA), /* GPIO_QRD3_LCD_EXT_2V85_EN */
782 GPIO_CFG(GPIO_QRD3_LCD_EXT_1V8_EN, 0, GPIO_CFG_OUTPUT,
783 GPIO_CFG_NO_PULL,
784 GPIO_CFG_2MA), /* GPIO_QRD3_LCD_EXT_1V8_EN */
785};
786
787static int msm_fb_dsi_client_qrd3_reset(void)
788{
789 int rc = 0;
790
791 rc = gpio_request(GPIO_QRD3_LCD_BRDG_RESET_N, "qrd3_lcd_brdg_reset_n");
792 if (rc < 0) {
793 pr_err("failed to request qrd3 lcd brdg reset_n\n");
794 return rc;
795 }
796
Jeevan Shrirame941df42012-01-23 12:40:21 +0530797 return rc;
798}
799
Chintan Pandya250c2e52012-01-19 17:15:49 +0530800static int msm_fb_dsi_client_reset(void)
801{
802 int rc = 0;
803
804 if (machine_is_msm7627a_qrd1())
805 rc = msm_fb_dsi_client_qrd1_reset();
Chintan Pandyaf4ad4002012-02-28 19:49:03 +0530806 else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
Jeevan Shrirame941df42012-01-23 12:40:21 +0530807 rc = msm_fb_dsi_client_qrd3_reset();
Chintan Pandya250c2e52012-01-19 17:15:49 +0530808 else
809 rc = msm_fb_dsi_client_msm_reset();
810
811 return rc;
812
813}
814
815static struct regulator_bulk_data regs_dsi[] = {
816 { .supply = "gp2", .min_uV = 2850000, .max_uV = 2850000 },
817 { .supply = "msme1", .min_uV = 1800000, .max_uV = 1800000 },
818};
819
820static int dsi_gpio_initialized;
821
822static int mipi_dsi_panel_msm_power(int on)
823{
824 int rc = 0;
825 uint32_t lcdc_reset_cfg;
826
827 /* I2C-controlled GPIO Expander -init of the GPIOs very late */
828 if (unlikely(!dsi_gpio_initialized)) {
829 pmapp_disp_backlight_init();
830
831 rc = gpio_request(GPIO_DISPLAY_PWR_EN, "gpio_disp_pwr");
832 if (rc < 0) {
833 pr_err("failed to request gpio_disp_pwr\n");
834 return rc;
835 }
836
Taniya Dase3027e22012-02-27 16:32:27 +0530837 if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
838 || machine_is_msm8625_surf()) {
Chintan Pandya250c2e52012-01-19 17:15:49 +0530839 rc = gpio_direction_output(GPIO_DISPLAY_PWR_EN, 1);
840 if (rc < 0) {
841 pr_err("failed to enable display pwr\n");
842 goto fail_gpio1;
843 }
844
845 rc = gpio_request(GPIO_BACKLIGHT_EN, "gpio_bkl_en");
846 if (rc < 0) {
847 pr_err("failed to request gpio_bkl_en\n");
848 goto fail_gpio1;
849 }
850
851 rc = gpio_direction_output(GPIO_BACKLIGHT_EN, 1);
852 if (rc < 0) {
853 pr_err("failed to enable backlight\n");
854 goto fail_gpio2;
855 }
856 }
857
858 rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_dsi), regs_dsi);
859 if (rc) {
860 pr_err("%s: could not get regulators: %d\n",
861 __func__, rc);
862 goto fail_gpio2;
863 }
864
865 rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_dsi),
866 regs_dsi);
867 if (rc) {
868 pr_err("%s: could not set voltages: %d\n",
869 __func__, rc);
870 goto fail_vreg;
871 }
872 if (pmapp_disp_backlight_set_brightness(100))
873 pr_err("backlight set brightness failed\n");
874
875 dsi_gpio_initialized = 1;
876 }
Taniya Dase3027e22012-02-27 16:32:27 +0530877 if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf() ||
878 machine_is_msm8625_surf()) {
Chintan Pandya250c2e52012-01-19 17:15:49 +0530879 gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, on);
880 gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, on);
881 } else if (machine_is_msm7x27a_ffa() ||
882 machine_is_msm7625a_ffa()) {
883 if (on) {
884 /* This line drives an active low pin on FFA */
885 rc = gpio_direction_output(GPIO_DISPLAY_PWR_EN, !on);
886 if (rc < 0)
887 pr_err("failed to set direction for "
888 "display pwr\n");
889 } else {
890 gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, !on);
891 rc = gpio_direction_input(GPIO_DISPLAY_PWR_EN);
892 if (rc < 0)
893 pr_err("failed to set direction for "
894 "display pwr\n");
895 }
896 }
897
898 if (on) {
899 gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 0);
900
901 if (machine_is_msm7x27a_surf() ||
Taniya Dase3027e22012-02-27 16:32:27 +0530902 machine_is_msm7625a_surf() ||
903 machine_is_msm8625_surf()) {
Chintan Pandya250c2e52012-01-19 17:15:49 +0530904 lcdc_reset_cfg = readl_relaxed(lcdc_reset_ptr);
905 rmb();
906 lcdc_reset_cfg &= ~1;
907
908 writel_relaxed(lcdc_reset_cfg, lcdc_reset_ptr);
909 msleep(20);
910 wmb();
911 lcdc_reset_cfg |= 1;
912 writel_relaxed(lcdc_reset_cfg, lcdc_reset_ptr);
913 } else {
914 gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 0);
915 msleep(20);
916 gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
917 }
918 } else {
919 gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 1);
Chintan Pandya250c2e52012-01-19 17:15:49 +0530920 }
921
922 rc = on ? regulator_bulk_enable(ARRAY_SIZE(regs_dsi), regs_dsi) :
923 regulator_bulk_disable(ARRAY_SIZE(regs_dsi), regs_dsi);
924
925 if (rc)
926 pr_err("%s: could not %sable regulators: %d\n",
927 __func__, on ? "en" : "dis", rc);
928
929 return rc;
930fail_vreg:
931 regulator_bulk_free(ARRAY_SIZE(regs_dsi), regs_dsi);
932fail_gpio2:
933 gpio_free(GPIO_BACKLIGHT_EN);
934fail_gpio1:
935 gpio_free(GPIO_DISPLAY_PWR_EN);
936 dsi_gpio_initialized = 0;
937 return rc;
938}
939
940static int mipi_dsi_panel_qrd1_power(int on)
941{
942 int rc = 0;
943
944 if (!dsi_gpio_initialized) {
945 rc = gpio_request(QRD_GPIO_BACKLIGHT_EN, "gpio_bkl_en");
946 if (rc < 0)
947 return rc;
948
949 rc = gpio_tlmm_config(GPIO_CFG(QRD_GPIO_BACKLIGHT_EN, 0,
950 GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
951 GPIO_CFG_ENABLE);
952 if (rc < 0) {
953 pr_err("failed GPIO_BACKLIGHT_EN tlmm config\n");
954 return rc;
955 }
956
957 rc = gpio_direction_output(QRD_GPIO_BACKLIGHT_EN, 1);
958 if (rc < 0) {
959 pr_err("failed to enable backlight\n");
960 gpio_free(QRD_GPIO_BACKLIGHT_EN);
961 return rc;
962 }
963 dsi_gpio_initialized = 1;
964 }
965
966 gpio_set_value_cansleep(QRD_GPIO_BACKLIGHT_EN, !!on);
967
Jeevan Shrirame941df42012-01-23 12:40:21 +0530968 if (on) {
Chintan Pandya250c2e52012-01-19 17:15:49 +0530969 gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
970 msleep(20);
971 gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 0);
972 msleep(20);
973 gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
974
975 }
976
977 return rc;
978}
979
Jeevan Shrirame941df42012-01-23 12:40:21 +0530980static int qrd3_dsi_gpio_initialized;
981
982static int mipi_dsi_panel_qrd3_power(int on)
983{
984 int rc = 0;
985
986 if (!qrd3_dsi_gpio_initialized) {
987 rc = gpio_request(GPIO_QRD3_LCD_BACKLIGHT_EN,
988 "qrd3_gpio_bkl_en");
989 if (rc < 0)
990 return rc;
991
992 rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0,
993 GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
994 GPIO_CFG_ENABLE);
995 if (rc < 0) {
996 pr_err("failed QRD3 GPIO_BACKLIGHT_EN tlmm config\n");
997 return rc;
998 }
999 rc = gpio_direction_output(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
1000 if (rc < 0) {
1001 pr_err("failed to enable backlight\n");
1002 gpio_free(GPIO_QRD3_LCD_BACKLIGHT_EN);
1003 return rc;
1004 }
1005
1006 rc = gpio_request(GPIO_QRD3_LCD_EXT_2V85_EN,
1007 "qrd3_gpio_ext_2v85_en");
1008 if (rc < 0)
1009 return rc;
1010
1011 rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_EXT_2V85_EN, 0,
1012 GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
1013 GPIO_CFG_ENABLE);
1014 if (rc < 0) {
1015 pr_err("failed QRD3 GPIO_QRD3_LCD_EXT_2V85_EN tlmm config\n");
1016 return rc;
1017 }
1018
1019 rc = gpio_direction_output(GPIO_QRD3_LCD_EXT_2V85_EN, 1);
1020 if (rc < 0) {
1021 pr_err("failed to enable external 2V85\n");
1022 gpio_free(GPIO_QRD3_LCD_EXT_2V85_EN);
1023 return rc;
1024 }
1025
1026 rc = gpio_request(GPIO_QRD3_LCD_EXT_1V8_EN,
1027 "qrd3_gpio_ext_1v8_en");
1028 if (rc < 0)
1029 return rc;
1030
1031 rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_EXT_1V8_EN, 0,
1032 GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
1033 GPIO_CFG_ENABLE);
1034 if (rc < 0) {
1035 pr_err("failed QRD3 GPIO_QRD3_LCD_EXT_1V8_EN tlmm config\n");
1036 return rc;
1037 }
1038
1039 rc = gpio_direction_output(GPIO_QRD3_LCD_EXT_1V8_EN, 1);
1040 if (rc < 0) {
1041 pr_err("failed to enable external 1v8\n");
1042 gpio_free(GPIO_QRD3_LCD_EXT_1V8_EN);
1043 return rc;
1044 }
1045
1046 qrd3_dsi_gpio_initialized = 1;
1047 }
1048
1049 gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, !!on);
1050 gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_2V85_EN, !!on);
1051 gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_1V8_EN, !!on);
1052
1053 if (on) {
Padmanabhan Komanduru599d3552012-02-21 16:53:05 +05301054 rc = gpio_tlmm_config(qrd3_mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
1055
1056 if (rc < 0) {
1057 pr_err("Failed to enable LCD Bridge reset enable\n");
1058 return rc;
1059 }
1060
1061 rc = gpio_direction_output(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
1062
1063 if (rc < 0) {
1064 pr_err("Failed GPIO bridge Reset\n");
1065 gpio_free(GPIO_QRD3_LCD_BRDG_RESET_N);
1066 return rc;
1067 }
1068
Jeevan Shrirame941df42012-01-23 12:40:21 +05301069 msleep(20);
1070 gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 0);
1071 msleep(20);
1072 gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
1073 msleep(20);
Padmanabhan Komanduru599d3552012-02-21 16:53:05 +05301074 } else {
1075 gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BRDG_RESET_N, 0,
1076 GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
1077 GPIO_CFG_DISABLE);
Jeevan Shrirame941df42012-01-23 12:40:21 +05301078 }
1079
1080 return rc;
1081}
1082
Chintan Pandya250c2e52012-01-19 17:15:49 +05301083static int mipi_dsi_panel_power(int on)
1084{
1085 int rc = 0;
1086
1087 if (machine_is_msm7627a_qrd1())
1088 rc = mipi_dsi_panel_qrd1_power(on);
Chintan Pandyaf4ad4002012-02-28 19:49:03 +05301089 else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
Jeevan Shrirame941df42012-01-23 12:40:21 +05301090 rc = mipi_dsi_panel_qrd3_power(on);
Chintan Pandya250c2e52012-01-19 17:15:49 +05301091 else
1092 rc = mipi_dsi_panel_msm_power(on);
1093 return rc;
1094}
1095
1096#define MDP_303_VSYNC_GPIO 97
1097
Jeevan Shriram901a15f2012-03-09 11:53:23 +05301098#ifdef CONFIG_FB_MSM_MIPI_DSI
Chintan Pandya250c2e52012-01-19 17:15:49 +05301099static struct mipi_dsi_platform_data mipi_dsi_pdata = {
1100 .vsync_gpio = MDP_303_VSYNC_GPIO,
1101 .dsi_power_save = mipi_dsi_panel_power,
1102 .dsi_client_reset = msm_fb_dsi_client_reset,
1103 .get_lane_config = msm_fb_get_lane_config,
1104};
1105#endif
1106
1107void __init msm_fb_add_devices(void)
1108{
1109 if (machine_is_msm7627a_qrd1())
1110 platform_add_devices(qrd_fb_devices,
1111 ARRAY_SIZE(qrd_fb_devices));
Chintan Pandyaf4ad4002012-02-28 19:49:03 +05301112 else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
Taniya Dasc868a2e2012-01-03 10:18:47 +05301113 platform_add_devices(evb_fb_devices,
1114 ARRAY_SIZE(evb_fb_devices));
Jeevan Shriram901a15f2012-03-09 11:53:23 +05301115 else if (machine_is_msm7627a_qrd3()) {
1116 sku3_lcdc_lcd_camera_power_init();
1117 platform_add_devices(qrd3_fb_devices,
1118 ARRAY_SIZE(qrd3_fb_devices));
1119 } else
Chintan Pandya250c2e52012-01-19 17:15:49 +05301120 platform_add_devices(msm_fb_devices,
1121 ARRAY_SIZE(msm_fb_devices));
1122
1123 msm_fb_register_device("mdp", &mdp_pdata);
Taniya Dase3027e22012-02-27 16:32:27 +05301124 if (machine_is_msm7625a_surf() || machine_is_msm7x27a_surf() ||
Jeevan Shriram901a15f2012-03-09 11:53:23 +05301125 machine_is_msm8625_surf() || machine_is_msm7627a_qrd3())
Chintan Pandya250c2e52012-01-19 17:15:49 +05301126 msm_fb_register_device("lcdc", &lcdc_pdata);
Jeevan Shriram901a15f2012-03-09 11:53:23 +05301127#ifdef CONFIG_FB_MSM_MIPI_DSI
Chintan Pandya250c2e52012-01-19 17:15:49 +05301128 msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
1129#endif
1130}