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