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