blob: 433fb2e478528edaed9a212d3880496fccff10ae [file] [log] [blame]
Huaibin Yang4a084e32011-12-15 15:25:52 -08001/* 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
14#include <linux/init.h>
15#include <linux/ioport.h>
16#include <linux/platform_device.h>
17#include <linux/bootmem.h>
Ravishangar Kalyanam59a67b12012-02-13 14:29:56 -080018#include <linux/ion.h>
Huaibin Yang4a084e32011-12-15 15:25:52 -080019#include <asm/mach-types.h>
20#include <mach/msm_memtypes.h>
21#include <mach/board.h>
22#include <mach/gpio.h>
23#include <mach/gpiomux.h>
Huaibin Yang4a084e32011-12-15 15:25:52 -080024#include <mach/ion.h>
Ravishangar Kalyanam59a67b12012-02-13 14:29:56 -080025#include <mach/msm_bus_board.h>
Huaibin Yang02f981c2012-02-27 16:58:41 -080026#include <mach/socinfo.h>
Huaibin Yang4a084e32011-12-15 15:25:52 -080027
28#include "devices.h"
29#include "board-8064.h"
30
31#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
32/* prim = 1366 x 768 x 3(bpp) x 3(pages) */
Aravind Venkateswaran8ac7f412012-03-16 17:57:30 -070033#define MSM_FB_PRIM_BUF_SIZE roundup(1920 * 1080 * 4 * 3, 0x10000)
Huaibin Yang4a084e32011-12-15 15:25:52 -080034#else
35/* prim = 1366 x 768 x 3(bpp) x 2(pages) */
Aravind Venkateswaran8ac7f412012-03-16 17:57:30 -070036#define MSM_FB_PRIM_BUF_SIZE roundup(1920 * 1080 * 4 * 2, 0x10000)
Huaibin Yang4a084e32011-12-15 15:25:52 -080037#endif
38
39#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
Aravind Venkateswaran8ac7f412012-03-16 17:57:30 -070040#define MSM_FB_EXT_BUF_SIZE \
41 (roundup((1920 * 1088 * 2), 4096) * 1) /* 2 bpp x 1 page */
Huaibin Yang4a084e32011-12-15 15:25:52 -080042#elif defined(CONFIG_FB_MSM_TVOUT)
Aravind Venkateswaran8ac7f412012-03-16 17:57:30 -070043#define MSM_FB_EXT_BUF_SIZE \
44 (roundup((720 * 576 * 2), 4096) * 2) /* 2 bpp x 2 pages */
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -080045#else
46#define MSM_FB_EXT_BUF_SIZE 0
47#endif
Huaibin Yang4a084e32011-12-15 15:25:52 -080048
49#define MSM_FB_SIZE roundup(MSM_FB_PRIM_BUF_SIZE + MSM_FB_EXT_BUF_SIZE, 4096)
50
51#ifdef CONFIG_FB_MSM_OVERLAY0_WRITEBACK
52#define MSM_FB_OVERLAY0_WRITEBACK_SIZE roundup((1376 * 768 * 3 * 2), 4096)
53#else
54#define MSM_FB_OVERLAY0_WRITEBACK_SIZE (0)
55#endif /* CONFIG_FB_MSM_OVERLAY0_WRITEBACK */
56
57#ifdef CONFIG_FB_MSM_OVERLAY1_WRITEBACK
58#define MSM_FB_OVERLAY1_WRITEBACK_SIZE roundup((1920 * 1088 * 3 * 2), 4096)
59#else
60#define MSM_FB_OVERLAY1_WRITEBACK_SIZE (0)
61#endif /* CONFIG_FB_MSM_OVERLAY1_WRITEBACK */
62
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -080063
Huaibin Yang4a084e32011-12-15 15:25:52 -080064static struct resource msm_fb_resources[] = {
65 {
66 .flags = IORESOURCE_DMA,
67 }
68};
69
Huaibin Yang4a084e32011-12-15 15:25:52 -080070#define LVDS_CHIMEI_PANEL_NAME "lvds_chimei_wxga"
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -080071#define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
72#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
73#define HDMI_PANEL_NAME "hdmi_msm"
74#define TVOUT_PANEL_NAME "tvout_msm"
Huaibin Yang4a084e32011-12-15 15:25:52 -080075
Aravind Venkateswaran8ac7f412012-03-16 17:57:30 -070076static void set_mdp_clocks_for_wuxga(void);
77
Huaibin Yang4a084e32011-12-15 15:25:52 -080078static int msm_fb_detect_panel(const char *name)
79{
Ravishangar Kalyanamed3593c2012-03-08 10:15:04 -080080 u32 version;
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -080081 if (machine_is_apq8064_liquid()) {
Ravishangar Kalyanamed3593c2012-03-08 10:15:04 -080082 version = socinfo_get_platform_version();
83 if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
84 (SOCINFO_VERSION_MINOR(version) == 1)) {
85 if (!strncmp(name, MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
86 strnlen(MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
87 PANEL_NAME_MAX_LEN)))
88 return 0;
89 } else {
90 if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
91 strnlen(LVDS_CHIMEI_PANEL_NAME,
92 PANEL_NAME_MAX_LEN)))
93 return 0;
94 }
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -080095 } else if (machine_is_apq8064_mtp()) {
96 if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
97 strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
98 PANEL_NAME_MAX_LEN)))
99 return 0;
100 } else if (machine_is_apq8064_cdp()) {
101 if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
102 strnlen(LVDS_CHIMEI_PANEL_NAME,
103 PANEL_NAME_MAX_LEN)))
104 return 0;
105 }
106
107 if (!strncmp(name, HDMI_PANEL_NAME,
Aravind Venkateswaran8ac7f412012-03-16 17:57:30 -0700108 strnlen(HDMI_PANEL_NAME,
109 PANEL_NAME_MAX_LEN))) {
110 if (hdmi_is_primary)
111 set_mdp_clocks_for_wuxga();
Huaibin Yang4a084e32011-12-15 15:25:52 -0800112 return 0;
Aravind Venkateswaran8ac7f412012-03-16 17:57:30 -0700113 }
114
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800115
Huaibin Yang4a084e32011-12-15 15:25:52 -0800116 return -ENODEV;
117}
118
119static struct msm_fb_platform_data msm_fb_pdata = {
120 .detect_client = msm_fb_detect_panel,
121};
122
123static struct platform_device msm_fb_device = {
124 .name = "msm_fb",
125 .id = 0,
126 .num_resources = ARRAY_SIZE(msm_fb_resources),
127 .resource = msm_fb_resources,
128 .dev.platform_data = &msm_fb_pdata,
129};
130
131void __init apq8064_allocate_fb_region(void)
132{
133 void *addr;
134 unsigned long size;
135
136 size = MSM_FB_SIZE;
137 addr = alloc_bootmem_align(size, 0x1000);
138 msm_fb_resources[0].start = __pa(addr);
139 msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
140 pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
141 size, addr, __pa(addr));
142}
143
144#define MDP_VSYNC_GPIO 0
145
Ravishangar Kalyanam59a67b12012-02-13 14:29:56 -0800146static struct msm_bus_vectors mdp_init_vectors[] = {
147 {
148 .src = MSM_BUS_MASTER_MDP_PORT0,
149 .dst = MSM_BUS_SLAVE_EBI_CH0,
150 .ab = 0,
151 .ib = 0,
152 },
153};
154
155static struct msm_bus_vectors mdp_ui_vectors[] = {
156 {
157 .src = MSM_BUS_MASTER_MDP_PORT0,
158 .dst = MSM_BUS_SLAVE_EBI_CH0,
159 .ab = 216000000 * 2,
160 .ib = 270000000 * 2,
161 },
162};
163
164static struct msm_bus_vectors mdp_vga_vectors[] = {
165 /* VGA and less video */
166 {
167 .src = MSM_BUS_MASTER_MDP_PORT0,
168 .dst = MSM_BUS_SLAVE_EBI_CH0,
169 .ab = 216000000 * 2,
170 .ib = 270000000 * 2,
171 },
172};
173
174static struct msm_bus_vectors mdp_720p_vectors[] = {
175 /* 720p and less video */
176 {
177 .src = MSM_BUS_MASTER_MDP_PORT0,
178 .dst = MSM_BUS_SLAVE_EBI_CH0,
179 .ab = 230400000 * 2,
180 .ib = 288000000 * 2,
181 },
182};
183
184static struct msm_bus_vectors mdp_1080p_vectors[] = {
185 /* 1080p and less video */
186 {
187 .src = MSM_BUS_MASTER_MDP_PORT0,
188 .dst = MSM_BUS_SLAVE_EBI_CH0,
189 .ab = 334080000 * 2,
190 .ib = 417600000 * 2,
191 },
192};
193
194static struct msm_bus_paths mdp_bus_scale_usecases[] = {
195 {
196 ARRAY_SIZE(mdp_init_vectors),
197 mdp_init_vectors,
198 },
199 {
200 ARRAY_SIZE(mdp_ui_vectors),
201 mdp_ui_vectors,
202 },
203 {
204 ARRAY_SIZE(mdp_ui_vectors),
205 mdp_ui_vectors,
206 },
207 {
208 ARRAY_SIZE(mdp_vga_vectors),
209 mdp_vga_vectors,
210 },
211 {
212 ARRAY_SIZE(mdp_720p_vectors),
213 mdp_720p_vectors,
214 },
215 {
216 ARRAY_SIZE(mdp_1080p_vectors),
217 mdp_1080p_vectors,
218 },
219};
220
221static struct msm_bus_scale_pdata mdp_bus_scale_pdata = {
222 mdp_bus_scale_usecases,
223 ARRAY_SIZE(mdp_bus_scale_usecases),
224 .name = "mdp",
225};
226
Huaibin Yang4a084e32011-12-15 15:25:52 -0800227static int mdp_core_clk_rate_table[] = {
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800228 200000000,
229 200000000,
230 200000000,
231 200000000,
Huaibin Yang4a084e32011-12-15 15:25:52 -0800232};
233
234static struct msm_panel_common_pdata mdp_pdata = {
235 .gpio = MDP_VSYNC_GPIO,
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800236 .mdp_core_clk_rate = 200000000,
Huaibin Yang4a084e32011-12-15 15:25:52 -0800237 .mdp_core_clk_table = mdp_core_clk_rate_table,
238 .num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
Ravishangar Kalyanam59a67b12012-02-13 14:29:56 -0800239 .mdp_bus_scale_table = &mdp_bus_scale_pdata,
Huaibin Yang4a084e32011-12-15 15:25:52 -0800240 .mdp_rev = MDP_REV_44,
241#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
Ravishangar Kalyanama3b168b2012-03-26 11:13:11 -0700242 .mem_hid = BIT(ION_CP_MM_HEAP_ID),
Huaibin Yang4a084e32011-12-15 15:25:52 -0800243#else
244 .mem_hid = MEMTYPE_EBI1,
245#endif
246};
247
248void __init apq8064_mdp_writeback(struct memtype_reserve* reserve_table)
249{
250 mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
251 mdp_pdata.ov1_wb_size = MSM_FB_OVERLAY1_WRITEBACK_SIZE;
252#if defined(CONFIG_ANDROID_PMEM) && !defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
253 reserve_table[mdp_pdata.mem_hid].size +=
254 mdp_pdata.ov0_wb_size;
255 reserve_table[mdp_pdata.mem_hid].size +=
256 mdp_pdata.ov1_wb_size;
257#endif
258}
259
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800260static struct resource hdmi_msm_resources[] = {
261 {
262 .name = "hdmi_msm_qfprom_addr",
263 .start = 0x00700000,
264 .end = 0x007060FF,
265 .flags = IORESOURCE_MEM,
266 },
267 {
268 .name = "hdmi_msm_hdmi_addr",
269 .start = 0x04A00000,
270 .end = 0x04A00FFF,
271 .flags = IORESOURCE_MEM,
272 },
273 {
274 .name = "hdmi_msm_irq",
275 .start = HDMI_IRQ,
276 .end = HDMI_IRQ,
277 .flags = IORESOURCE_IRQ,
278 },
279};
280
281static int hdmi_enable_5v(int on);
282static int hdmi_core_power(int on, int show);
283static int hdmi_cec_power(int on);
284
285static struct msm_hdmi_platform_data hdmi_msm_data = {
286 .irq = HDMI_IRQ,
287 .enable_5v = hdmi_enable_5v,
288 .core_power = hdmi_core_power,
289 .cec_power = hdmi_cec_power,
290};
291
292static struct platform_device hdmi_msm_device = {
293 .name = "hdmi_msm",
294 .id = 0,
295 .num_resources = ARRAY_SIZE(hdmi_msm_resources),
296 .resource = hdmi_msm_resources,
297 .dev.platform_data = &hdmi_msm_data,
298};
299
300/* HDMI related GPIOs */
301#define HDMI_CEC_VAR_GPIO 69
302#define HDMI_DDC_CLK_GPIO 70
303#define HDMI_DDC_DATA_GPIO 71
304#define HDMI_HPD_GPIO 72
305
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800306static bool dsi_power_on;
307static int mipi_dsi_panel_power(int on)
308{
309 static struct regulator *reg_lvs7, *reg_l2, *reg_l11, *reg_ext_3p3v;
310 static int gpio36, gpio25, gpio26, mpp3;
311 int rc;
312
313 pr_debug("%s: on=%d\n", __func__, on);
314
315 if (!dsi_power_on) {
316 reg_lvs7 = regulator_get(&msm_mipi_dsi1_device.dev,
317 "dsi1_vddio");
318 if (IS_ERR_OR_NULL(reg_lvs7)) {
319 pr_err("could not get 8921_lvs7, rc = %ld\n",
320 PTR_ERR(reg_lvs7));
321 return -ENODEV;
322 }
323
324 reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
325 "dsi1_pll_vdda");
326 if (IS_ERR_OR_NULL(reg_l2)) {
327 pr_err("could not get 8921_l2, rc = %ld\n",
328 PTR_ERR(reg_l2));
329 return -ENODEV;
330 }
331
332 rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
333 if (rc) {
334 pr_err("set_voltage l2 failed, rc=%d\n", rc);
335 return -EINVAL;
336 }
337 reg_l11 = regulator_get(&msm_mipi_dsi1_device.dev,
338 "dsi1_avdd");
339 if (IS_ERR(reg_l11)) {
340 pr_err("could not get 8921_l11, rc = %ld\n",
341 PTR_ERR(reg_l11));
342 return -ENODEV;
343 }
344 rc = regulator_set_voltage(reg_l11, 3000000, 3000000);
345 if (rc) {
346 pr_err("set_voltage l11 failed, rc=%d\n", rc);
347 return -EINVAL;
348 }
349
350 if (machine_is_apq8064_liquid()) {
351 reg_ext_3p3v = regulator_get(&msm_mipi_dsi1_device.dev,
352 "dsi1_vccs_3p3v");
353 if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
354 pr_err("could not get reg_ext_3p3v, rc = %ld\n",
355 PTR_ERR(reg_ext_3p3v));
356 reg_ext_3p3v = NULL;
357 return -ENODEV;
358 }
359 mpp3 = PM8921_MPP_PM_TO_SYS(3);
360 rc = gpio_request(mpp3, "backlight_en");
361 if (rc) {
362 pr_err("request mpp3 failed, rc=%d\n", rc);
363 return -ENODEV;
364 }
365 }
366
367 gpio25 = PM8921_GPIO_PM_TO_SYS(25);
368 rc = gpio_request(gpio25, "disp_rst_n");
369 if (rc) {
370 pr_err("request gpio 25 failed, rc=%d\n", rc);
371 return -ENODEV;
372 }
373
374 gpio26 = PM8921_GPIO_PM_TO_SYS(26);
375 rc = gpio_request(gpio26, "pwm_backlight_ctrl");
376 if (rc) {
377 pr_err("request gpio 26 failed, rc=%d\n", rc);
378 return -ENODEV;
379 }
380
381 gpio36 = PM8921_GPIO_PM_TO_SYS(36); /* lcd1_pwr_en_n */
382 rc = gpio_request(gpio36, "lcd1_pwr_en_n");
383 if (rc) {
384 pr_err("request gpio 36 failed, rc=%d\n", rc);
385 return -ENODEV;
386 }
387
388 dsi_power_on = true;
389 }
390
391 if (on) {
392 rc = regulator_enable(reg_lvs7);
393 if (rc) {
394 pr_err("enable lvs7 failed, rc=%d\n", rc);
395 return -ENODEV;
396 }
397
398 rc = regulator_set_optimum_mode(reg_l11, 110000);
399 if (rc < 0) {
400 pr_err("set_optimum_mode l11 failed, rc=%d\n", rc);
401 return -EINVAL;
402 }
403 rc = regulator_enable(reg_l11);
404 if (rc) {
405 pr_err("enable l11 failed, rc=%d\n", rc);
406 return -ENODEV;
407 }
408
409 rc = regulator_set_optimum_mode(reg_l2, 100000);
410 if (rc < 0) {
411 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
412 return -EINVAL;
413 }
414 rc = regulator_enable(reg_l2);
415 if (rc) {
416 pr_err("enable l2 failed, rc=%d\n", rc);
417 return -ENODEV;
418 }
419
420 if (machine_is_apq8064_liquid()) {
421 rc = regulator_enable(reg_ext_3p3v);
422 if (rc) {
423 pr_err("enable reg_ext_3p3v failed, rc=%d\n",
424 rc);
425 return -ENODEV;
426 }
427 gpio_set_value_cansleep(mpp3, 1);
428 }
429
430 gpio_set_value_cansleep(gpio36, 0);
431 gpio_set_value_cansleep(gpio25, 1);
432 } else {
433 gpio_set_value_cansleep(gpio25, 0);
434 gpio_set_value_cansleep(gpio36, 1);
435
436 if (machine_is_apq8064_liquid()) {
437 gpio_set_value_cansleep(mpp3, 0);
438
439 rc = regulator_disable(reg_ext_3p3v);
440 if (rc) {
441 pr_err("disable reg_ext_3p3v failed, rc=%d\n",
442 rc);
443 return -ENODEV;
444 }
445 }
446
447 rc = regulator_disable(reg_lvs7);
448 if (rc) {
449 pr_err("disable reg_lvs7 failed, rc=%d\n", rc);
450 return -ENODEV;
451 }
452 rc = regulator_disable(reg_l2);
453 if (rc) {
454 pr_err("disable reg_l2 failed, rc=%d\n", rc);
455 return -ENODEV;
456 }
457 }
458
459 return 0;
460}
461
462static struct mipi_dsi_platform_data mipi_dsi_pdata = {
463 .dsi_power_save = mipi_dsi_panel_power,
464};
465
466static bool lvds_power_on;
467static int lvds_panel_power(int on)
468{
469 static struct regulator *reg_lvs7, *reg_l2, *reg_ext_3p3v;
470 static int gpio36, gpio26, mpp3;
471 int rc;
472
473 pr_debug("%s: on=%d\n", __func__, on);
474
475 if (!lvds_power_on) {
476 reg_lvs7 = regulator_get(&msm_lvds_device.dev,
477 "lvds_vdda");
478 if (IS_ERR_OR_NULL(reg_lvs7)) {
479 pr_err("could not get 8921_lvs7, rc = %ld\n",
480 PTR_ERR(reg_lvs7));
481 return -ENODEV;
482 }
483
484 reg_l2 = regulator_get(&msm_lvds_device.dev,
485 "lvds_pll_vdda");
486 if (IS_ERR_OR_NULL(reg_l2)) {
487 pr_err("could not get 8921_l2, rc = %ld\n",
488 PTR_ERR(reg_l2));
489 return -ENODEV;
490 }
491
492 rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
493 if (rc) {
494 pr_err("set_voltage l2 failed, rc=%d\n", rc);
495 return -EINVAL;
496 }
497
498 reg_ext_3p3v = regulator_get(&msm_lvds_device.dev,
499 "lvds_vccs_3p3v");
500 if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
501 pr_err("could not get reg_ext_3p3v, rc = %ld\n",
502 PTR_ERR(reg_ext_3p3v));
503 return -ENODEV;
504 }
505
506 gpio26 = PM8921_GPIO_PM_TO_SYS(26);
507 rc = gpio_request(gpio26, "pwm_backlight_ctrl");
508 if (rc) {
509 pr_err("request gpio 26 failed, rc=%d\n", rc);
510 return -ENODEV;
511 }
512
513 gpio36 = PM8921_GPIO_PM_TO_SYS(36); /* lcd1_pwr_en_n */
514 rc = gpio_request(gpio36, "lcd1_pwr_en_n");
515 if (rc) {
516 pr_err("request gpio 36 failed, rc=%d\n", rc);
517 return -ENODEV;
518 }
519
520 mpp3 = PM8921_MPP_PM_TO_SYS(3);
521 rc = gpio_request(mpp3, "backlight_en");
522 if (rc) {
523 pr_err("request mpp3 failed, rc=%d\n", rc);
524 return -ENODEV;
525 }
526
527 lvds_power_on = true;
528 }
529
530 if (on) {
531 rc = regulator_enable(reg_lvs7);
532 if (rc) {
533 pr_err("enable lvs7 failed, rc=%d\n", rc);
534 return -ENODEV;
535 }
536
537 rc = regulator_set_optimum_mode(reg_l2, 100000);
538 if (rc < 0) {
539 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
540 return -EINVAL;
541 }
542 rc = regulator_enable(reg_l2);
543 if (rc) {
544 pr_err("enable l2 failed, rc=%d\n", rc);
545 return -ENODEV;
546 }
547
548 rc = regulator_enable(reg_ext_3p3v);
549 if (rc) {
550 pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
551 return -ENODEV;
552 }
553
554 gpio_set_value_cansleep(gpio36, 0);
555 gpio_set_value_cansleep(mpp3, 1);
556 } else {
557 gpio_set_value_cansleep(mpp3, 0);
558 gpio_set_value_cansleep(gpio36, 1);
559
560 rc = regulator_disable(reg_lvs7);
561 if (rc) {
562 pr_err("disable reg_lvs7 failed, rc=%d\n", rc);
563 return -ENODEV;
564 }
565 rc = regulator_disable(reg_l2);
566 if (rc) {
567 pr_err("disable reg_l2 failed, rc=%d\n", rc);
568 return -ENODEV;
569 }
570 rc = regulator_disable(reg_ext_3p3v);
571 if (rc) {
572 pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
573 return -ENODEV;
574 }
575 }
576
577 return 0;
578}
579
Huaibin Yang02f981c2012-02-27 16:58:41 -0800580static int lvds_pixel_remap(void)
581{
582 if (machine_is_apq8064_cdp() ||
583 machine_is_apq8064_liquid()) {
584 u32 ver = socinfo_get_platform_version();
585 if ((SOCINFO_VERSION_MAJOR(ver) == 1) &&
586 (SOCINFO_VERSION_MINOR(ver) == 0))
587 return 1;
588 }
589 return 0;
590}
591
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800592static struct lcdc_platform_data lvds_pdata = {
593 .lcdc_power_save = lvds_panel_power,
Huaibin Yang02f981c2012-02-27 16:58:41 -0800594 .lvds_pixel_remap = lvds_pixel_remap
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800595};
596
597#define LPM_CHANNEL 2
598static int lvds_chimei_gpio[] = {LPM_CHANNEL};
599
600static struct lvds_panel_platform_data lvds_chimei_pdata = {
601 .gpio = lvds_chimei_gpio,
602};
603
604static struct platform_device lvds_chimei_panel_device = {
605 .name = "lvds_chimei_wxga",
606 .id = 0,
607 .dev = {
608 .platform_data = &lvds_chimei_pdata,
609 }
610};
611
612static int dsi2lvds_gpio[2] = {
613 LPM_CHANNEL,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
614 0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
615};
616static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
617 .gpio_num = dsi2lvds_gpio,
618};
619
620static struct platform_device mipi_dsi2lvds_bridge_device = {
621 .name = "mipi_tc358764",
622 .id = 0,
623 .dev.platform_data = &mipi_dsi2lvds_pdata,
624};
625
626static int toshiba_gpio[] = {LPM_CHANNEL};
627static struct mipi_dsi_panel_platform_data toshiba_pdata = {
628 .gpio = toshiba_gpio,
629};
630
631static struct platform_device mipi_dsi_toshiba_panel_device = {
632 .name = "mipi_toshiba",
633 .id = 0,
634 .dev = {
635 .platform_data = &toshiba_pdata,
636 }
637};
638
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800639static struct msm_bus_vectors dtv_bus_init_vectors[] = {
640 {
641 .src = MSM_BUS_MASTER_MDP_PORT0,
642 .dst = MSM_BUS_SLAVE_EBI_CH0,
643 .ab = 0,
644 .ib = 0,
645 },
646};
647
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800648static struct msm_bus_vectors dtv_bus_def_vectors[] = {
649 {
650 .src = MSM_BUS_MASTER_MDP_PORT0,
651 .dst = MSM_BUS_SLAVE_EBI_CH0,
652 .ab = 566092800 * 2,
653 .ib = 707616000 * 2,
654 },
655};
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800656
657static struct msm_bus_paths dtv_bus_scale_usecases[] = {
658 {
659 ARRAY_SIZE(dtv_bus_init_vectors),
660 dtv_bus_init_vectors,
661 },
662 {
663 ARRAY_SIZE(dtv_bus_def_vectors),
664 dtv_bus_def_vectors,
665 },
666};
667static struct msm_bus_scale_pdata dtv_bus_scale_pdata = {
668 dtv_bus_scale_usecases,
669 ARRAY_SIZE(dtv_bus_scale_usecases),
670 .name = "dtv",
671};
672
673static struct lcdc_platform_data dtv_pdata = {
674 .bus_scale_table = &dtv_bus_scale_pdata,
675};
676
677static int hdmi_enable_5v(int on)
678{
679 /* TBD: PM8921 regulator instead of 8901 */
680 static struct regulator *reg_8921_hdmi_mvs; /* HDMI_5V */
681 static int prev_on;
682 int rc;
683
684 if (on == prev_on)
685 return 0;
686
687 if (!reg_8921_hdmi_mvs) {
688 reg_8921_hdmi_mvs = regulator_get(&hdmi_msm_device.dev,
689 "hdmi_mvs");
690 if (IS_ERR(reg_8921_hdmi_mvs)) {
691 pr_err("could not get reg_8921_hdmi_mvs, rc = %ld\n",
692 PTR_ERR(reg_8921_hdmi_mvs));
693 reg_8921_hdmi_mvs = NULL;
694 return -ENODEV;
695 }
696 }
697
698 if (on) {
699 rc = regulator_enable(reg_8921_hdmi_mvs);
700 if (rc) {
701 pr_err("'%s' regulator enable failed, rc=%d\n",
702 "8921_hdmi_mvs", rc);
703 return rc;
704 }
705 pr_debug("%s(on): success\n", __func__);
706 } else {
707 rc = regulator_disable(reg_8921_hdmi_mvs);
708 if (rc)
709 pr_warning("'%s' regulator disable failed, rc=%d\n",
710 "8921_hdmi_mvs", rc);
711 pr_debug("%s(off): success\n", __func__);
712 }
713
714 prev_on = on;
715
716 return 0;
717}
718
719static int hdmi_core_power(int on, int show)
720{
721 static struct regulator *reg_8921_lvs7, *reg_8921_s4, *reg_ext_3p3v;
722 static int prev_on;
723 int rc;
724 int pmic_gpio14 = PM8921_GPIO_PM_TO_SYS(14);
725
726 if (on == prev_on)
727 return 0;
728
729 /* TBD: PM8921 regulator instead of 8901 */
730 if (!reg_ext_3p3v) {
731 reg_ext_3p3v = regulator_get(&hdmi_msm_device.dev,
732 "hdmi_mux_vdd");
733 if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
734 pr_err("could not get reg_ext_3p3v, rc = %ld\n",
735 PTR_ERR(reg_ext_3p3v));
736 reg_ext_3p3v = NULL;
737 return -ENODEV;
738 }
739 }
740
741 if (!reg_8921_lvs7) {
742 reg_8921_lvs7 = regulator_get(&hdmi_msm_device.dev,
743 "hdmi_vdda");
744 if (IS_ERR(reg_8921_lvs7)) {
745 pr_err("could not get reg_8921_lvs7, rc = %ld\n",
746 PTR_ERR(reg_8921_lvs7));
747 reg_8921_lvs7 = NULL;
748 return -ENODEV;
749 }
750 }
751 if (!reg_8921_s4) {
752 reg_8921_s4 = regulator_get(&hdmi_msm_device.dev,
753 "hdmi_lvl_tsl");
754 if (IS_ERR(reg_8921_s4)) {
755 pr_err("could not get reg_8921_s4, rc = %ld\n",
756 PTR_ERR(reg_8921_s4));
757 reg_8921_s4 = NULL;
758 return -ENODEV;
759 }
760 rc = regulator_set_voltage(reg_8921_s4, 1800000, 1800000);
761 if (rc) {
762 pr_err("set_voltage failed for 8921_s4, rc=%d\n", rc);
763 return -EINVAL;
764 }
765 }
766
767 if (on) {
768 /*
769 * Configure 3P3V_BOOST_EN as GPIO, 8mA drive strength,
770 * pull none, out-high
771 */
772 rc = regulator_set_optimum_mode(reg_ext_3p3v, 290000);
773 if (rc < 0) {
774 pr_err("set_optimum_mode ext_3p3v failed, rc=%d\n", rc);
775 return -EINVAL;
776 }
777
778 rc = regulator_enable(reg_ext_3p3v);
779 if (rc) {
780 pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
781 return -ENODEV;
782 }
783 rc = regulator_enable(reg_8921_lvs7);
784 if (rc) {
785 pr_err("'%s' regulator enable failed, rc=%d\n",
786 "hdmi_vdda", rc);
787 return rc;
788 }
789 rc = regulator_enable(reg_8921_s4);
790 if (rc) {
791 pr_err("'%s' regulator enable failed, rc=%d\n",
792 "hdmi_lvl_tsl", rc);
793 return rc;
794 }
795 rc = gpio_request(HDMI_DDC_CLK_GPIO, "HDMI_DDC_CLK");
796 if (rc) {
797 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
798 "HDMI_DDC_CLK", HDMI_DDC_CLK_GPIO, rc);
799 goto error1;
800 }
801 rc = gpio_request(HDMI_DDC_DATA_GPIO, "HDMI_DDC_DATA");
802 if (rc) {
803 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
804 "HDMI_DDC_DATA", HDMI_DDC_DATA_GPIO, rc);
805 goto error2;
806 }
807 rc = gpio_request(HDMI_HPD_GPIO, "HDMI_HPD");
808 if (rc) {
809 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
810 "HDMI_HPD", HDMI_HPD_GPIO, rc);
811 goto error3;
812 }
813 if (machine_is_apq8064_liquid()) {
814 rc = gpio_request(pmic_gpio14, "PMIC_HDMI_MUX_SEL");
815 if (rc) {
816 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
817 "PMIC_HDMI_MUX_SEL", 14, rc);
818 goto error4;
819 }
820 gpio_set_value_cansleep(pmic_gpio14, 0);
821 }
822 pr_debug("%s(on): success\n", __func__);
823 } else {
824 gpio_free(HDMI_DDC_CLK_GPIO);
825 gpio_free(HDMI_DDC_DATA_GPIO);
826 gpio_free(HDMI_HPD_GPIO);
827
828 if (machine_is_apq8064_liquid()) {
829 gpio_set_value_cansleep(pmic_gpio14, 1);
830 gpio_free(pmic_gpio14);
831 }
832
833 rc = regulator_disable(reg_ext_3p3v);
834 if (rc) {
835 pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
836 return -ENODEV;
837 }
838 rc = regulator_disable(reg_8921_lvs7);
839 if (rc) {
840 pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
841 return -ENODEV;
842 }
843 rc = regulator_disable(reg_8921_s4);
844 if (rc) {
845 pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
846 return -ENODEV;
847 }
848 pr_debug("%s(off): success\n", __func__);
849 }
850
851 prev_on = on;
852
853 return 0;
854
855error4:
856 gpio_free(HDMI_HPD_GPIO);
857error3:
858 gpio_free(HDMI_DDC_DATA_GPIO);
859error2:
860 gpio_free(HDMI_DDC_CLK_GPIO);
861error1:
862 regulator_disable(reg_8921_lvs7);
863 regulator_disable(reg_8921_s4);
864 return rc;
865}
866
867static int hdmi_cec_power(int on)
868{
869 static int prev_on;
870 int rc;
871
872 if (on == prev_on)
873 return 0;
874
875 if (on) {
876 rc = gpio_request(HDMI_CEC_VAR_GPIO, "HDMI_CEC_VAR");
877 if (rc) {
878 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
879 "HDMI_CEC_VAR", HDMI_CEC_VAR_GPIO, rc);
880 goto error;
881 }
882 pr_debug("%s(on): success\n", __func__);
883 } else {
884 gpio_free(HDMI_CEC_VAR_GPIO);
885 pr_debug("%s(off): success\n", __func__);
886 }
887
888 prev_on = on;
889
890 return 0;
891error:
892 return rc;
893}
894
Huaibin Yang4a084e32011-12-15 15:25:52 -0800895void __init apq8064_init_fb(void)
896{
897 platform_device_register(&msm_fb_device);
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800898 platform_device_register(&lvds_chimei_panel_device);
899
900 if (machine_is_apq8064_liquid())
901 platform_device_register(&mipi_dsi2lvds_bridge_device);
902 if (machine_is_apq8064_mtp())
903 platform_device_register(&mipi_dsi_toshiba_panel_device);
904
Huaibin Yang4a084e32011-12-15 15:25:52 -0800905 msm_fb_register_device("mdp", &mdp_pdata);
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800906 msm_fb_register_device("lvds", &lvds_pdata);
907 msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800908 platform_device_register(&hdmi_msm_device);
909 msm_fb_register_device("dtv", &dtv_pdata);
Huaibin Yang4a084e32011-12-15 15:25:52 -0800910}
Aravind Venkateswaran8ac7f412012-03-16 17:57:30 -0700911
912/**
913 * Set MDP clocks to high frequency to avoid DSI underflow
914 * when using high resolution 1200x1920 WUXGA panels
915 */
916static void set_mdp_clocks_for_wuxga(void)
917{
918 int i;
919
920 mdp_ui_vectors[0].ab = 2000000000;
921 mdp_ui_vectors[0].ib = 2000000000;
922 mdp_vga_vectors[0].ab = 2000000000;
923 mdp_vga_vectors[0].ib = 2000000000;
924 mdp_720p_vectors[0].ab = 2000000000;
925 mdp_720p_vectors[0].ib = 2000000000;
926 mdp_1080p_vectors[0].ab = 2000000000;
927 mdp_1080p_vectors[0].ib = 2000000000;
928
929 mdp_pdata.mdp_core_clk_rate = 200000000;
930
931 for (i = 0; i < ARRAY_SIZE(mdp_core_clk_rate_table); i++)
932 mdp_core_clk_rate_table[i] = 200000000;
933
934 if (hdmi_is_primary) {
935 dtv_bus_def_vectors[0].ab = 2000000000;
936 dtv_bus_def_vectors[0].ib = 2000000000;
937 }
938}
939
940void __init apq8064_set_display_params(char *prim_panel, char *ext_panel)
941{
942 if (strnlen(prim_panel, PANEL_NAME_MAX_LEN)) {
943 strlcpy(msm_fb_pdata.prim_panel_name, prim_panel,
944 PANEL_NAME_MAX_LEN);
945 pr_debug("msm_fb_pdata.prim_panel_name %s\n",
946 msm_fb_pdata.prim_panel_name);
947
948 if (!strncmp((char *)msm_fb_pdata.prim_panel_name,
949 HDMI_PANEL_NAME, strnlen(HDMI_PANEL_NAME,
950 PANEL_NAME_MAX_LEN))) {
951 pr_debug("HDMI is the primary display by"
952 " boot parameter\n");
953 hdmi_is_primary = 1;
954 set_mdp_clocks_for_wuxga();
955 }
956 }
957 if (strnlen(ext_panel, PANEL_NAME_MAX_LEN)) {
958 strlcpy(msm_fb_pdata.ext_panel_name, ext_panel,
959 PANEL_NAME_MAX_LEN);
960 pr_debug("msm_fb_pdata.ext_panel_name %s\n",
961 msm_fb_pdata.ext_panel_name);
962 }
963}