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