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