blob: 45bfaed5a3b4f5385639a29437b8c008b443031f [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
47static struct regulator_bulk_data regs_lcdc[] = {
48 { .supply = "gp2", .min_uV = 2850000, .max_uV = 2850000 },
49 { .supply = "msme1", .min_uV = 1800000, .max_uV = 1800000 },
50};
51static uint32_t lcdc_gpio_initialized;
52
53static void lcdc_toshiba_gpio_init(void)
54{
55 int rc = 0;
56 if (!lcdc_gpio_initialized) {
57 if (gpio_request(GPIO_SPI_CLK, "spi_clk")) {
58 pr_err("failed to request gpio spi_clk\n");
59 return;
60 }
61 if (gpio_request(GPIO_SPI_CS0_N, "spi_cs")) {
62 pr_err("failed to request gpio spi_cs0_N\n");
63 goto fail_gpio6;
64 }
65 if (gpio_request(GPIO_SPI_MOSI, "spi_mosi")) {
66 pr_err("failed to request gpio spi_mosi\n");
67 goto fail_gpio5;
68 }
69 if (gpio_request(GPIO_SPI_MISO, "spi_miso")) {
70 pr_err("failed to request gpio spi_miso\n");
71 goto fail_gpio4;
72 }
73 if (gpio_request(GPIO_DISPLAY_PWR_EN, "gpio_disp_pwr")) {
74 pr_err("failed to request gpio_disp_pwr\n");
75 goto fail_gpio3;
76 }
77 if (gpio_request(GPIO_BACKLIGHT_EN, "gpio_bkl_en")) {
78 pr_err("failed to request gpio_bkl_en\n");
79 goto fail_gpio2;
80 }
81 pmapp_disp_backlight_init();
82
83 rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_lcdc),
84 regs_lcdc);
85 if (rc) {
86 pr_err("%s: could not get regulators: %d\n",
87 __func__, rc);
88 goto fail_gpio1;
89 }
90
91 rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_lcdc),
92 regs_lcdc);
93 if (rc) {
94 pr_err("%s: could not set voltages: %d\n",
95 __func__, rc);
96 goto fail_vreg;
97 }
98 lcdc_gpio_initialized = 1;
99 }
100 return;
101fail_vreg:
102 regulator_bulk_free(ARRAY_SIZE(regs_lcdc), regs_lcdc);
103fail_gpio1:
104 gpio_free(GPIO_BACKLIGHT_EN);
105fail_gpio2:
106 gpio_free(GPIO_DISPLAY_PWR_EN);
107fail_gpio3:
108 gpio_free(GPIO_SPI_MISO);
109fail_gpio4:
110 gpio_free(GPIO_SPI_MOSI);
111fail_gpio5:
112 gpio_free(GPIO_SPI_CS0_N);
113fail_gpio6:
114 gpio_free(GPIO_SPI_CLK);
115 lcdc_gpio_initialized = 0;
116}
117
118static uint32_t lcdc_gpio_table[] = {
119 GPIO_SPI_CLK,
120 GPIO_SPI_CS0_N,
121 GPIO_SPI_MOSI,
122 GPIO_DISPLAY_PWR_EN,
123 GPIO_BACKLIGHT_EN,
124 GPIO_SPI_MISO,
125};
126
127static void config_lcdc_gpio_table(uint32_t *table, int len, unsigned enable)
128{
129 int n;
130
131 if (lcdc_gpio_initialized) {
132 /* All are IO Expander GPIOs */
133 for (n = 0; n < (len - 1); n++)
134 gpio_direction_output(table[n], 1);
135 }
136}
137
138static void lcdc_toshiba_config_gpios(int enable)
139{
140 config_lcdc_gpio_table(lcdc_gpio_table,
141 ARRAY_SIZE(lcdc_gpio_table), enable);
142}
143
144static int msm_fb_lcdc_power_save(int on)
145{
146 int rc = 0;
147 /* Doing the init of the LCDC GPIOs very late as they are from
148 an I2C-controlled IO Expander */
149 lcdc_toshiba_gpio_init();
150
151 if (lcdc_gpio_initialized) {
152 gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, on);
153 gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, on);
154
155 rc = on ? regulator_bulk_enable(
156 ARRAY_SIZE(regs_lcdc), regs_lcdc) :
157 regulator_bulk_disable(
158 ARRAY_SIZE(regs_lcdc), regs_lcdc);
159
160 if (rc)
161 pr_err("%s: could not %sable regulators: %d\n",
162 __func__, on ? "en" : "dis", rc);
163 }
164
165 return rc;
166}
167
168static int lcdc_toshiba_set_bl(int level)
169{
170 int ret;
171
172 ret = pmapp_disp_backlight_set_brightness(level);
173 if (ret)
174 pr_err("%s: can't set lcd backlight!\n", __func__);
175
176 return ret;
177}
178
179static struct lcdc_platform_data lcdc_pdata = {
180 .lcdc_gpio_config = NULL,
181 .lcdc_power_save = msm_fb_lcdc_power_save,
182};
183
184static int lcd_panel_spi_gpio_num[] = {
185 GPIO_SPI_MOSI, /* spi_sdi */
186 GPIO_SPI_MISO, /* spi_sdoi */
187 GPIO_SPI_CLK, /* spi_clk */
188 GPIO_SPI_CS0_N, /* spi_cs */
189};
190
191static struct msm_panel_common_pdata lcdc_toshiba_panel_data = {
192 .panel_config_gpio = lcdc_toshiba_config_gpios,
193 .pmic_backlight = lcdc_toshiba_set_bl,
194 .gpio_num = lcd_panel_spi_gpio_num,
195};
196
197static struct platform_device lcdc_toshiba_panel_device = {
198 .name = "lcdc_toshiba_fwvga_pt",
199 .id = 0,
200 .dev = {
201 .platform_data = &lcdc_toshiba_panel_data,
202 }
203};
204
205static struct resource msm_fb_resources[] = {
206 {
207 .flags = IORESOURCE_DMA,
208 }
209};
210
211#define PANEL_NAME_MAX_LEN 30
212#define LCDC_TOSHIBA_FWVGA_PANEL_NAME "lcdc_toshiba_fwvga_pt"
213#define MIPI_CMD_RENESAS_FWVGA_PANEL_NAME "mipi_cmd_renesas_fwvga"
214
215static int msm_fb_detect_panel(const char *name)
216{
217 int ret = -ENODEV;
218
Taniya Dase3027e22012-02-27 16:32:27 +0530219 if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf() ||
220 machine_is_msm8625_surf()) {
Chintan Pandya250c2e52012-01-19 17:15:49 +0530221 if (!strncmp(name, "lcdc_toshiba_fwvga_pt", 21) ||
222 !strncmp(name, "mipi_cmd_renesas_fwvga", 22))
223 ret = 0;
224 } else if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()) {
225 if (!strncmp(name, "mipi_cmd_renesas_fwvga", 22))
226 ret = 0;
227 } else if (machine_is_msm7627a_qrd1()) {
228 if (!strncmp(name, "mipi_video_truly_wvga", 21))
229 ret = 0;
Chintan Pandyaf4ad4002012-02-28 19:49:03 +0530230 } else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
Jeevan Shrirame941df42012-01-23 12:40:21 +0530231 if (!strncmp(name, "mipi_cmd_nt35510_wvga", 21))
232 ret = 0;
Chintan Pandya250c2e52012-01-19 17:15:49 +0530233 }
234
235#if !defined(CONFIG_FB_MSM_LCDC_AUTO_DETECT) && \
236 !defined(CONFIG_FB_MSM_MIPI_PANEL_AUTO_DETECT) && \
237 !defined(CONFIG_FB_MSM_LCDC_MIPI_PANEL_AUTO_DETECT)
238 if (machine_is_msm7x27a_surf() ||
Taniya Dase3027e22012-02-27 16:32:27 +0530239 machine_is_msm7625a_surf() ||
240 machine_is_msm8625_surf()) {
Chintan Pandya250c2e52012-01-19 17:15:49 +0530241 if (!strncmp(name, LCDC_TOSHIBA_FWVGA_PANEL_NAME,
242 strnlen(LCDC_TOSHIBA_FWVGA_PANEL_NAME,
243 PANEL_NAME_MAX_LEN)))
244 return 0;
245 }
246#endif
247
248 return ret;
249}
250
251static int mipi_truly_set_bl(int on)
252{
253 gpio_set_value_cansleep(QRD_GPIO_BACKLIGHT_EN, !!on);
254
255 return 1;
256}
257
258static struct msm_fb_platform_data msm_fb_pdata = {
259 .detect_client = msm_fb_detect_panel,
260};
261
262static struct platform_device msm_fb_device = {
263 .name = "msm_fb",
264 .id = 0,
265 .num_resources = ARRAY_SIZE(msm_fb_resources),
266 .resource = msm_fb_resources,
267 .dev = {
268 .platform_data = &msm_fb_pdata,
269 }
270};
271
272#ifdef CONFIG_FB_MSM_MIPI_DSI
273static int mipi_renesas_set_bl(int level)
274{
275 int ret;
276
277 ret = pmapp_disp_backlight_set_brightness(level);
278
279 if (ret)
280 pr_err("%s: can't set lcd backlight!\n", __func__);
281
282 return ret;
283}
284
285static struct msm_panel_common_pdata mipi_renesas_pdata = {
286 .pmic_backlight = mipi_renesas_set_bl,
287};
288
289
290static struct platform_device mipi_dsi_renesas_panel_device = {
291 .name = "mipi_renesas",
292 .id = 0,
293 .dev = {
294 .platform_data = &mipi_renesas_pdata,
295 }
296};
297#endif
298
299static struct msm_panel_common_pdata mipi_truly_pdata = {
300 .pmic_backlight = mipi_truly_set_bl,
301};
302
303static struct platform_device mipi_dsi_truly_panel_device = {
304 .name = "mipi_truly",
305 .id = 0,
306 .dev = {
307 .platform_data = &mipi_truly_pdata,
308 }
309};
310
Jeevan Shrirame941df42012-01-23 12:40:21 +0530311static struct msm_panel_common_pdata mipi_NT35510_pdata = {
312 .pmic_backlight = NULL,/*mipi_NT35510_set_bl,*/
313};
314
315static struct platform_device mipi_dsi_NT35510_panel_device = {
316 .name = "mipi_NT35510",
317 .id = 0,
318 .dev = {
319 .platform_data = &mipi_NT35510_pdata,
320 }
321};
322
Chintan Pandya250c2e52012-01-19 17:15:49 +0530323static struct platform_device *msm_fb_devices[] __initdata = {
324 &msm_fb_device,
325 &lcdc_toshiba_panel_device,
326#ifdef CONFIG_FB_MSM_MIPI_DSI
327 &mipi_dsi_renesas_panel_device,
328#endif
329};
330
331static struct platform_device *qrd_fb_devices[] __initdata = {
332 &msm_fb_device,
333 &mipi_dsi_truly_panel_device,
334};
335
Taniya Dasc868a2e2012-01-03 10:18:47 +0530336static struct platform_device *evb_fb_devices[] __initdata = {
Jeevan Shrirame941df42012-01-23 12:40:21 +0530337 &msm_fb_device,
338 &mipi_dsi_NT35510_panel_device,
Taniya Dasc868a2e2012-01-03 10:18:47 +0530339};
340
Chintan Pandya250c2e52012-01-19 17:15:49 +0530341void __init msm_msm7627a_allocate_memory_regions(void)
342{
343 void *addr;
344 unsigned long fb_size;
345
346 if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa())
347 fb_size = MSM7x25A_MSM_FB_SIZE;
348 else
349 fb_size = MSM_FB_SIZE;
350 addr = alloc_bootmem_align(fb_size, 0x1000);
351 msm_fb_resources[0].start = __pa(addr);
352 msm_fb_resources[0].end = msm_fb_resources[0].start + fb_size - 1;
353 pr_info("allocating %lu bytes at %p (%lx physical) for fb\n", fb_size,
354 addr, __pa(addr));
355}
356
357static struct msm_panel_common_pdata mdp_pdata = {
358 .gpio = 97,
359 .mdp_rev = MDP_REV_303,
360};
361
362#define GPIO_LCDC_BRDG_PD 128
363#define GPIO_LCDC_BRDG_RESET_N 129
364#define GPIO_LCD_DSI_SEL 125
365#define LCDC_RESET_PHYS 0x90008014
366
367static void __iomem *lcdc_reset_ptr;
368
369static unsigned mipi_dsi_gpio[] = {
370 GPIO_CFG(GPIO_LCDC_BRDG_RESET_N, 0, GPIO_CFG_OUTPUT,
371 GPIO_CFG_NO_PULL, GPIO_CFG_2MA), /* LCDC_BRDG_RESET_N */
372 GPIO_CFG(GPIO_LCDC_BRDG_PD, 0, GPIO_CFG_OUTPUT,
373 GPIO_CFG_NO_PULL, GPIO_CFG_2MA), /* LCDC_BRDG_PD */
374};
375
376static unsigned lcd_dsi_sel_gpio[] = {
377 GPIO_CFG(GPIO_LCD_DSI_SEL, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
378 GPIO_CFG_2MA),
379};
380
381enum {
382 DSI_SINGLE_LANE = 1,
383 DSI_TWO_LANES,
384};
385
386static int msm_fb_get_lane_config(void)
387{
388 /* For MSM7627A SURF/FFA and QRD */
389 int rc = DSI_TWO_LANES;
390 if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
391 rc = DSI_SINGLE_LANE;
392 pr_info("DSI_SINGLE_LANES\n");
393 } else {
394 pr_info("DSI_TWO_LANES\n");
395 }
396 return rc;
397}
398
399static int msm_fb_dsi_client_msm_reset(void)
400{
401 int rc = 0;
402
403 rc = gpio_request(GPIO_LCDC_BRDG_RESET_N, "lcdc_brdg_reset_n");
404 if (rc < 0) {
405 pr_err("failed to request lcd brdg reset_n\n");
406 return rc;
407 }
408
409 rc = gpio_request(GPIO_LCDC_BRDG_PD, "lcdc_brdg_pd");
410 if (rc < 0) {
411 pr_err("failed to request lcd brdg pd\n");
412 return rc;
413 }
414
415 rc = gpio_tlmm_config(mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
416 if (rc) {
417 pr_err("Failed to enable LCDC Bridge reset enable\n");
418 goto gpio_error;
419 }
420
421 rc = gpio_tlmm_config(mipi_dsi_gpio[1], GPIO_CFG_ENABLE);
422 if (rc) {
423 pr_err("Failed to enable LCDC Bridge pd enable\n");
424 goto gpio_error2;
425 }
426
427 rc = gpio_direction_output(GPIO_LCDC_BRDG_RESET_N, 1);
428 rc |= gpio_direction_output(GPIO_LCDC_BRDG_PD, 1);
429 gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 0);
430
431 if (!rc) {
Taniya Dase3027e22012-02-27 16:32:27 +0530432 if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
433 || machine_is_msm8625_surf()) {
Chintan Pandya250c2e52012-01-19 17:15:49 +0530434 lcdc_reset_ptr = ioremap_nocache(LCDC_RESET_PHYS,
435 sizeof(uint32_t));
436
437 if (!lcdc_reset_ptr)
438 return 0;
439 }
440 return rc;
441 } else {
442 goto gpio_error;
443 }
444
445gpio_error2:
446 pr_err("Failed GPIO bridge pd\n");
447 gpio_free(GPIO_LCDC_BRDG_PD);
448
449gpio_error:
450 pr_err("Failed GPIO bridge reset\n");
451 gpio_free(GPIO_LCDC_BRDG_RESET_N);
452 return rc;
453}
454
455static int mipi_truly_sel_mode(int video_mode)
456{
457 int rc = 0;
458
459 rc = gpio_request(GPIO_LCD_DSI_SEL, "lcd_dsi_sel");
460 if (rc < 0)
461 goto gpio_error;
462
463 rc = gpio_tlmm_config(lcd_dsi_sel_gpio[0], GPIO_CFG_ENABLE);
464 if (rc)
465 goto gpio_error;
466
467 rc = gpio_direction_output(GPIO_LCD_DSI_SEL, 1);
468 if (!rc) {
469 gpio_set_value_cansleep(GPIO_LCD_DSI_SEL, video_mode);
470 return rc;
471 } else {
472 goto gpio_error;
473 }
474
475gpio_error:
476 pr_err("mipi_truly_sel_mode failed\n");
477 gpio_free(GPIO_LCD_DSI_SEL);
478 return rc;
479}
480
481static int msm_fb_dsi_client_qrd1_reset(void)
482{
483 int rc = 0;
484
485 rc = gpio_request(GPIO_LCDC_BRDG_RESET_N, "lcdc_brdg_reset_n");
486 if (rc < 0) {
487 pr_err("failed to request lcd brdg reset_n\n");
488 return rc;
489 }
490
491 rc = gpio_tlmm_config(mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
492 if (rc < 0) {
493 pr_err("Failed to enable LCDC Bridge reset enable\n");
494 return rc;
495 }
496
497 rc = gpio_direction_output(GPIO_LCDC_BRDG_RESET_N, 1);
498 if (rc < 0) {
499 pr_err("Failed GPIO bridge pd\n");
500 gpio_free(GPIO_LCDC_BRDG_RESET_N);
501 return rc;
502 }
503
504 mipi_truly_sel_mode(1);
505
506 return rc;
507}
508
Jeevan Shrirame941df42012-01-23 12:40:21 +0530509#define GPIO_QRD3_LCD_BRDG_RESET_N 85
510#define GPIO_QRD3_LCD_BACKLIGHT_EN 96
511#define GPIO_QRD3_LCD_EXT_2V85_EN 35
512#define GPIO_QRD3_LCD_EXT_1V8_EN 40
513
514static unsigned qrd3_mipi_dsi_gpio[] = {
515 GPIO_CFG(GPIO_QRD3_LCD_BRDG_RESET_N, 0, GPIO_CFG_OUTPUT,
516 GPIO_CFG_NO_PULL,
517 GPIO_CFG_2MA), /* GPIO_QRD3_LCD_BRDG_RESET_N */
518 GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0, GPIO_CFG_OUTPUT,
519 GPIO_CFG_NO_PULL,
520 GPIO_CFG_2MA), /* GPIO_QRD3_LCD_BACKLIGHT_EN */
521 GPIO_CFG(GPIO_QRD3_LCD_EXT_2V85_EN, 0, GPIO_CFG_OUTPUT,
522 GPIO_CFG_NO_PULL,
523 GPIO_CFG_2MA), /* GPIO_QRD3_LCD_EXT_2V85_EN */
524 GPIO_CFG(GPIO_QRD3_LCD_EXT_1V8_EN, 0, GPIO_CFG_OUTPUT,
525 GPIO_CFG_NO_PULL,
526 GPIO_CFG_2MA), /* GPIO_QRD3_LCD_EXT_1V8_EN */
527};
528
529static int msm_fb_dsi_client_qrd3_reset(void)
530{
531 int rc = 0;
532
533 rc = gpio_request(GPIO_QRD3_LCD_BRDG_RESET_N, "qrd3_lcd_brdg_reset_n");
534 if (rc < 0) {
535 pr_err("failed to request qrd3 lcd brdg reset_n\n");
536 return rc;
537 }
538
539 rc = gpio_tlmm_config(qrd3_mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
540 if (rc < 0) {
541 pr_err("Failed to enable LCD Bridge reset enable\n");
542 return rc;
543 }
544
545 rc = gpio_direction_output(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
546 if (rc < 0) {
547 pr_err("Failed GPIO bridge Reset\n");
548 gpio_free(GPIO_QRD3_LCD_BRDG_RESET_N);
549 return rc;
550 }
551
552 return rc;
553}
554
Chintan Pandya250c2e52012-01-19 17:15:49 +0530555static int msm_fb_dsi_client_reset(void)
556{
557 int rc = 0;
558
559 if (machine_is_msm7627a_qrd1())
560 rc = msm_fb_dsi_client_qrd1_reset();
Chintan Pandyaf4ad4002012-02-28 19:49:03 +0530561 else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
Jeevan Shrirame941df42012-01-23 12:40:21 +0530562 rc = msm_fb_dsi_client_qrd3_reset();
Chintan Pandya250c2e52012-01-19 17:15:49 +0530563 else
564 rc = msm_fb_dsi_client_msm_reset();
565
566 return rc;
567
568}
569
570static struct regulator_bulk_data regs_dsi[] = {
571 { .supply = "gp2", .min_uV = 2850000, .max_uV = 2850000 },
572 { .supply = "msme1", .min_uV = 1800000, .max_uV = 1800000 },
573};
574
575static int dsi_gpio_initialized;
576
577static int mipi_dsi_panel_msm_power(int on)
578{
579 int rc = 0;
580 uint32_t lcdc_reset_cfg;
581
582 /* I2C-controlled GPIO Expander -init of the GPIOs very late */
583 if (unlikely(!dsi_gpio_initialized)) {
584 pmapp_disp_backlight_init();
585
586 rc = gpio_request(GPIO_DISPLAY_PWR_EN, "gpio_disp_pwr");
587 if (rc < 0) {
588 pr_err("failed to request gpio_disp_pwr\n");
589 return rc;
590 }
591
Taniya Dase3027e22012-02-27 16:32:27 +0530592 if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
593 || machine_is_msm8625_surf()) {
Chintan Pandya250c2e52012-01-19 17:15:49 +0530594 rc = gpio_direction_output(GPIO_DISPLAY_PWR_EN, 1);
595 if (rc < 0) {
596 pr_err("failed to enable display pwr\n");
597 goto fail_gpio1;
598 }
599
600 rc = gpio_request(GPIO_BACKLIGHT_EN, "gpio_bkl_en");
601 if (rc < 0) {
602 pr_err("failed to request gpio_bkl_en\n");
603 goto fail_gpio1;
604 }
605
606 rc = gpio_direction_output(GPIO_BACKLIGHT_EN, 1);
607 if (rc < 0) {
608 pr_err("failed to enable backlight\n");
609 goto fail_gpio2;
610 }
611 }
612
613 rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_dsi), regs_dsi);
614 if (rc) {
615 pr_err("%s: could not get regulators: %d\n",
616 __func__, rc);
617 goto fail_gpio2;
618 }
619
620 rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_dsi),
621 regs_dsi);
622 if (rc) {
623 pr_err("%s: could not set voltages: %d\n",
624 __func__, rc);
625 goto fail_vreg;
626 }
627 if (pmapp_disp_backlight_set_brightness(100))
628 pr_err("backlight set brightness failed\n");
629
630 dsi_gpio_initialized = 1;
631 }
Taniya Dase3027e22012-02-27 16:32:27 +0530632 if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf() ||
633 machine_is_msm8625_surf()) {
Chintan Pandya250c2e52012-01-19 17:15:49 +0530634 gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, on);
635 gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, on);
636 } else if (machine_is_msm7x27a_ffa() ||
637 machine_is_msm7625a_ffa()) {
638 if (on) {
639 /* This line drives an active low pin on FFA */
640 rc = gpio_direction_output(GPIO_DISPLAY_PWR_EN, !on);
641 if (rc < 0)
642 pr_err("failed to set direction for "
643 "display pwr\n");
644 } else {
645 gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, !on);
646 rc = gpio_direction_input(GPIO_DISPLAY_PWR_EN);
647 if (rc < 0)
648 pr_err("failed to set direction for "
649 "display pwr\n");
650 }
651 }
652
653 if (on) {
654 gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 0);
655
656 if (machine_is_msm7x27a_surf() ||
Taniya Dase3027e22012-02-27 16:32:27 +0530657 machine_is_msm7625a_surf() ||
658 machine_is_msm8625_surf()) {
Chintan Pandya250c2e52012-01-19 17:15:49 +0530659 lcdc_reset_cfg = readl_relaxed(lcdc_reset_ptr);
660 rmb();
661 lcdc_reset_cfg &= ~1;
662
663 writel_relaxed(lcdc_reset_cfg, lcdc_reset_ptr);
664 msleep(20);
665 wmb();
666 lcdc_reset_cfg |= 1;
667 writel_relaxed(lcdc_reset_cfg, lcdc_reset_ptr);
668 } else {
669 gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 0);
670 msleep(20);
671 gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
672 }
673 } else {
674 gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 1);
Chintan Pandya250c2e52012-01-19 17:15:49 +0530675 }
676
677 rc = on ? regulator_bulk_enable(ARRAY_SIZE(regs_dsi), regs_dsi) :
678 regulator_bulk_disable(ARRAY_SIZE(regs_dsi), regs_dsi);
679
680 if (rc)
681 pr_err("%s: could not %sable regulators: %d\n",
682 __func__, on ? "en" : "dis", rc);
683
684 return rc;
685fail_vreg:
686 regulator_bulk_free(ARRAY_SIZE(regs_dsi), regs_dsi);
687fail_gpio2:
688 gpio_free(GPIO_BACKLIGHT_EN);
689fail_gpio1:
690 gpio_free(GPIO_DISPLAY_PWR_EN);
691 dsi_gpio_initialized = 0;
692 return rc;
693}
694
695static int mipi_dsi_panel_qrd1_power(int on)
696{
697 int rc = 0;
698
699 if (!dsi_gpio_initialized) {
700 rc = gpio_request(QRD_GPIO_BACKLIGHT_EN, "gpio_bkl_en");
701 if (rc < 0)
702 return rc;
703
704 rc = gpio_tlmm_config(GPIO_CFG(QRD_GPIO_BACKLIGHT_EN, 0,
705 GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
706 GPIO_CFG_ENABLE);
707 if (rc < 0) {
708 pr_err("failed GPIO_BACKLIGHT_EN tlmm config\n");
709 return rc;
710 }
711
712 rc = gpio_direction_output(QRD_GPIO_BACKLIGHT_EN, 1);
713 if (rc < 0) {
714 pr_err("failed to enable backlight\n");
715 gpio_free(QRD_GPIO_BACKLIGHT_EN);
716 return rc;
717 }
718 dsi_gpio_initialized = 1;
719 }
720
721 gpio_set_value_cansleep(QRD_GPIO_BACKLIGHT_EN, !!on);
722
Jeevan Shrirame941df42012-01-23 12:40:21 +0530723 if (on) {
Chintan Pandya250c2e52012-01-19 17:15:49 +0530724 gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
725 msleep(20);
726 gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 0);
727 msleep(20);
728 gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
729
730 }
731
732 return rc;
733}
734
Jeevan Shrirame941df42012-01-23 12:40:21 +0530735static int qrd3_dsi_gpio_initialized;
736
737static int mipi_dsi_panel_qrd3_power(int on)
738{
739 int rc = 0;
740
741 if (!qrd3_dsi_gpio_initialized) {
742 rc = gpio_request(GPIO_QRD3_LCD_BACKLIGHT_EN,
743 "qrd3_gpio_bkl_en");
744 if (rc < 0)
745 return rc;
746
747 rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0,
748 GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
749 GPIO_CFG_ENABLE);
750 if (rc < 0) {
751 pr_err("failed QRD3 GPIO_BACKLIGHT_EN tlmm config\n");
752 return rc;
753 }
754 rc = gpio_direction_output(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
755 if (rc < 0) {
756 pr_err("failed to enable backlight\n");
757 gpio_free(GPIO_QRD3_LCD_BACKLIGHT_EN);
758 return rc;
759 }
760
761 rc = gpio_request(GPIO_QRD3_LCD_EXT_2V85_EN,
762 "qrd3_gpio_ext_2v85_en");
763 if (rc < 0)
764 return rc;
765
766 rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_EXT_2V85_EN, 0,
767 GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
768 GPIO_CFG_ENABLE);
769 if (rc < 0) {
770 pr_err("failed QRD3 GPIO_QRD3_LCD_EXT_2V85_EN tlmm config\n");
771 return rc;
772 }
773
774 rc = gpio_direction_output(GPIO_QRD3_LCD_EXT_2V85_EN, 1);
775 if (rc < 0) {
776 pr_err("failed to enable external 2V85\n");
777 gpio_free(GPIO_QRD3_LCD_EXT_2V85_EN);
778 return rc;
779 }
780
781 rc = gpio_request(GPIO_QRD3_LCD_EXT_1V8_EN,
782 "qrd3_gpio_ext_1v8_en");
783 if (rc < 0)
784 return rc;
785
786 rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_EXT_1V8_EN, 0,
787 GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
788 GPIO_CFG_ENABLE);
789 if (rc < 0) {
790 pr_err("failed QRD3 GPIO_QRD3_LCD_EXT_1V8_EN tlmm config\n");
791 return rc;
792 }
793
794 rc = gpio_direction_output(GPIO_QRD3_LCD_EXT_1V8_EN, 1);
795 if (rc < 0) {
796 pr_err("failed to enable external 1v8\n");
797 gpio_free(GPIO_QRD3_LCD_EXT_1V8_EN);
798 return rc;
799 }
800
801 qrd3_dsi_gpio_initialized = 1;
802 }
803
804 gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, !!on);
805 gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_2V85_EN, !!on);
806 gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_1V8_EN, !!on);
807
808 if (on) {
809 gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
810 msleep(20);
811 gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 0);
812 msleep(20);
813 gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
814 msleep(20);
815 }
816
817 return rc;
818}
819
Chintan Pandya250c2e52012-01-19 17:15:49 +0530820static int mipi_dsi_panel_power(int on)
821{
822 int rc = 0;
823
824 if (machine_is_msm7627a_qrd1())
825 rc = mipi_dsi_panel_qrd1_power(on);
Chintan Pandyaf4ad4002012-02-28 19:49:03 +0530826 else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
Jeevan Shrirame941df42012-01-23 12:40:21 +0530827 rc = mipi_dsi_panel_qrd3_power(on);
Chintan Pandya250c2e52012-01-19 17:15:49 +0530828 else
829 rc = mipi_dsi_panel_msm_power(on);
830 return rc;
831}
832
833#define MDP_303_VSYNC_GPIO 97
834
835#ifdef CONFIG_FB_MSM_MDP303
836static struct mipi_dsi_platform_data mipi_dsi_pdata = {
837 .vsync_gpio = MDP_303_VSYNC_GPIO,
838 .dsi_power_save = mipi_dsi_panel_power,
839 .dsi_client_reset = msm_fb_dsi_client_reset,
840 .get_lane_config = msm_fb_get_lane_config,
841};
842#endif
843
844void __init msm_fb_add_devices(void)
845{
846 if (machine_is_msm7627a_qrd1())
847 platform_add_devices(qrd_fb_devices,
848 ARRAY_SIZE(qrd_fb_devices));
Chintan Pandyaf4ad4002012-02-28 19:49:03 +0530849 else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
Taniya Dasc868a2e2012-01-03 10:18:47 +0530850 platform_add_devices(evb_fb_devices,
851 ARRAY_SIZE(evb_fb_devices));
Chintan Pandyab1bad0e2012-02-06 19:04:51 +0530852 else if (machine_is_msm7627a_qrd3())
853 return;
Chintan Pandya250c2e52012-01-19 17:15:49 +0530854 else
855 platform_add_devices(msm_fb_devices,
856 ARRAY_SIZE(msm_fb_devices));
857
858 msm_fb_register_device("mdp", &mdp_pdata);
Taniya Dase3027e22012-02-27 16:32:27 +0530859 if (machine_is_msm7625a_surf() || machine_is_msm7x27a_surf() ||
860 machine_is_msm8625_surf())
Chintan Pandya250c2e52012-01-19 17:15:49 +0530861 msm_fb_register_device("lcdc", &lcdc_pdata);
862#ifdef CONFIG_FB_MSM_MDP303
863 msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
864#endif
865}