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