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