blob: 5780ca138dcd80544bcd707257b4ebad947fc519 [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 struct msm_panel_common_pdata mdp_pdata = {
240 .gpio = MDP_VSYNC_GPIO,
Siddhartha Agrawal496f9282012-08-15 17:41:34 -0700241 .mdp_max_clk = 200000000,
Ravishangar Kalyanam59a67b12012-02-13 14:29:56 -0800242 .mdp_bus_scale_table = &mdp_bus_scale_pdata,
Huaibin Yang4a084e32011-12-15 15:25:52 -0800243 .mdp_rev = MDP_REV_44,
244#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
Ravishangar Kalyanama3b168b2012-03-26 11:13:11 -0700245 .mem_hid = BIT(ION_CP_MM_HEAP_ID),
Huaibin Yang4a084e32011-12-15 15:25:52 -0800246#else
247 .mem_hid = MEMTYPE_EBI1,
248#endif
Olav Hauganef95ae32012-05-15 09:50:30 -0700249 .mdp_iommu_split_domain = 1,
Huaibin Yang4a084e32011-12-15 15:25:52 -0800250};
251
252void __init apq8064_mdp_writeback(struct memtype_reserve* reserve_table)
253{
254 mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
255 mdp_pdata.ov1_wb_size = MSM_FB_OVERLAY1_WRITEBACK_SIZE;
256#if defined(CONFIG_ANDROID_PMEM) && !defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
257 reserve_table[mdp_pdata.mem_hid].size +=
258 mdp_pdata.ov0_wb_size;
259 reserve_table[mdp_pdata.mem_hid].size +=
260 mdp_pdata.ov1_wb_size;
261#endif
262}
263
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800264static struct resource hdmi_msm_resources[] = {
265 {
266 .name = "hdmi_msm_qfprom_addr",
267 .start = 0x00700000,
268 .end = 0x007060FF,
269 .flags = IORESOURCE_MEM,
270 },
271 {
272 .name = "hdmi_msm_hdmi_addr",
273 .start = 0x04A00000,
274 .end = 0x04A00FFF,
275 .flags = IORESOURCE_MEM,
276 },
277 {
278 .name = "hdmi_msm_irq",
279 .start = HDMI_IRQ,
280 .end = HDMI_IRQ,
281 .flags = IORESOURCE_IRQ,
282 },
283};
284
285static int hdmi_enable_5v(int on);
286static int hdmi_core_power(int on, int show);
287static int hdmi_cec_power(int on);
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530288static int hdmi_gpio_config(int on);
289static int hdmi_panel_power(int on);
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800290
291static struct msm_hdmi_platform_data hdmi_msm_data = {
292 .irq = HDMI_IRQ,
293 .enable_5v = hdmi_enable_5v,
294 .core_power = hdmi_core_power,
295 .cec_power = hdmi_cec_power,
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530296 .panel_power = hdmi_panel_power,
297 .gpio_config = hdmi_gpio_config,
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800298};
299
300static struct platform_device hdmi_msm_device = {
301 .name = "hdmi_msm",
302 .id = 0,
303 .num_resources = ARRAY_SIZE(hdmi_msm_resources),
304 .resource = hdmi_msm_resources,
305 .dev.platform_data = &hdmi_msm_data,
306};
307
Olav Hauganef95ae32012-05-15 09:50:30 -0700308static char wfd_check_mdp_iommu_split_domain(void)
309{
310 return mdp_pdata.mdp_iommu_split_domain;
311}
312
Mohan Kumar Gubbihalli Lachma Naikcb7d4e72012-03-23 18:17:30 -0700313#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
Olav Hauganef95ae32012-05-15 09:50:30 -0700314static struct msm_wfd_platform_data wfd_pdata = {
315 .wfd_check_mdp_iommu_split = wfd_check_mdp_iommu_split_domain,
316};
317
Mohan Kumar Gubbihalli Lachma Naikcb7d4e72012-03-23 18:17:30 -0700318static struct platform_device wfd_panel_device = {
319 .name = "wfd_panel",
320 .id = 0,
321 .dev.platform_data = NULL,
322};
323
324static struct platform_device wfd_device = {
325 .name = "msm_wfd",
326 .id = -1,
Olav Hauganef95ae32012-05-15 09:50:30 -0700327 .dev.platform_data = &wfd_pdata,
Mohan Kumar Gubbihalli Lachma Naikcb7d4e72012-03-23 18:17:30 -0700328};
329#endif
330
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800331/* HDMI related GPIOs */
332#define HDMI_CEC_VAR_GPIO 69
333#define HDMI_DDC_CLK_GPIO 70
334#define HDMI_DDC_DATA_GPIO 71
335#define HDMI_HPD_GPIO 72
336
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800337static bool dsi_power_on;
338static int mipi_dsi_panel_power(int on)
339{
340 static struct regulator *reg_lvs7, *reg_l2, *reg_l11, *reg_ext_3p3v;
341 static int gpio36, gpio25, gpio26, mpp3;
342 int rc;
343
344 pr_debug("%s: on=%d\n", __func__, on);
345
346 if (!dsi_power_on) {
347 reg_lvs7 = regulator_get(&msm_mipi_dsi1_device.dev,
348 "dsi1_vddio");
349 if (IS_ERR_OR_NULL(reg_lvs7)) {
350 pr_err("could not get 8921_lvs7, rc = %ld\n",
351 PTR_ERR(reg_lvs7));
352 return -ENODEV;
353 }
354
355 reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
356 "dsi1_pll_vdda");
357 if (IS_ERR_OR_NULL(reg_l2)) {
358 pr_err("could not get 8921_l2, rc = %ld\n",
359 PTR_ERR(reg_l2));
360 return -ENODEV;
361 }
362
363 rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
364 if (rc) {
365 pr_err("set_voltage l2 failed, rc=%d\n", rc);
366 return -EINVAL;
367 }
368 reg_l11 = regulator_get(&msm_mipi_dsi1_device.dev,
369 "dsi1_avdd");
370 if (IS_ERR(reg_l11)) {
371 pr_err("could not get 8921_l11, rc = %ld\n",
372 PTR_ERR(reg_l11));
373 return -ENODEV;
374 }
375 rc = regulator_set_voltage(reg_l11, 3000000, 3000000);
376 if (rc) {
377 pr_err("set_voltage l11 failed, rc=%d\n", rc);
378 return -EINVAL;
379 }
380
381 if (machine_is_apq8064_liquid()) {
382 reg_ext_3p3v = regulator_get(&msm_mipi_dsi1_device.dev,
383 "dsi1_vccs_3p3v");
384 if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
385 pr_err("could not get reg_ext_3p3v, rc = %ld\n",
386 PTR_ERR(reg_ext_3p3v));
387 reg_ext_3p3v = NULL;
388 return -ENODEV;
389 }
390 mpp3 = PM8921_MPP_PM_TO_SYS(3);
391 rc = gpio_request(mpp3, "backlight_en");
392 if (rc) {
393 pr_err("request mpp3 failed, rc=%d\n", rc);
394 return -ENODEV;
395 }
396 }
397
398 gpio25 = PM8921_GPIO_PM_TO_SYS(25);
399 rc = gpio_request(gpio25, "disp_rst_n");
400 if (rc) {
401 pr_err("request gpio 25 failed, rc=%d\n", rc);
402 return -ENODEV;
403 }
404
405 gpio26 = PM8921_GPIO_PM_TO_SYS(26);
406 rc = gpio_request(gpio26, "pwm_backlight_ctrl");
407 if (rc) {
408 pr_err("request gpio 26 failed, rc=%d\n", rc);
409 return -ENODEV;
410 }
411
412 gpio36 = PM8921_GPIO_PM_TO_SYS(36); /* lcd1_pwr_en_n */
413 rc = gpio_request(gpio36, "lcd1_pwr_en_n");
414 if (rc) {
415 pr_err("request gpio 36 failed, rc=%d\n", rc);
416 return -ENODEV;
417 }
418
419 dsi_power_on = true;
420 }
421
422 if (on) {
423 rc = regulator_enable(reg_lvs7);
424 if (rc) {
425 pr_err("enable lvs7 failed, rc=%d\n", rc);
426 return -ENODEV;
427 }
428
429 rc = regulator_set_optimum_mode(reg_l11, 110000);
430 if (rc < 0) {
431 pr_err("set_optimum_mode l11 failed, rc=%d\n", rc);
432 return -EINVAL;
433 }
434 rc = regulator_enable(reg_l11);
435 if (rc) {
436 pr_err("enable l11 failed, rc=%d\n", rc);
437 return -ENODEV;
438 }
439
440 rc = regulator_set_optimum_mode(reg_l2, 100000);
441 if (rc < 0) {
442 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
443 return -EINVAL;
444 }
445 rc = regulator_enable(reg_l2);
446 if (rc) {
447 pr_err("enable l2 failed, rc=%d\n", rc);
448 return -ENODEV;
449 }
450
451 if (machine_is_apq8064_liquid()) {
452 rc = regulator_enable(reg_ext_3p3v);
453 if (rc) {
454 pr_err("enable reg_ext_3p3v failed, rc=%d\n",
455 rc);
456 return -ENODEV;
457 }
458 gpio_set_value_cansleep(mpp3, 1);
459 }
460
461 gpio_set_value_cansleep(gpio36, 0);
462 gpio_set_value_cansleep(gpio25, 1);
463 } else {
464 gpio_set_value_cansleep(gpio25, 0);
465 gpio_set_value_cansleep(gpio36, 1);
466
467 if (machine_is_apq8064_liquid()) {
468 gpio_set_value_cansleep(mpp3, 0);
469
470 rc = regulator_disable(reg_ext_3p3v);
471 if (rc) {
472 pr_err("disable reg_ext_3p3v failed, rc=%d\n",
473 rc);
474 return -ENODEV;
475 }
476 }
477
Nagamalleswararao Ganji15ad5ac2012-06-20 20:50:01 -0700478 rc = regulator_disable(reg_l11);
479 if (rc) {
480 pr_err("disable reg_l1 failed, rc=%d\n", rc);
481 return -ENODEV;
482 }
483
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800484 rc = regulator_disable(reg_lvs7);
485 if (rc) {
486 pr_err("disable reg_lvs7 failed, rc=%d\n", rc);
487 return -ENODEV;
488 }
Nagamalleswararao Ganji15ad5ac2012-06-20 20:50:01 -0700489
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800490 rc = regulator_disable(reg_l2);
491 if (rc) {
492 pr_err("disable reg_l2 failed, rc=%d\n", rc);
493 return -ENODEV;
494 }
495 }
496
497 return 0;
498}
499
500static struct mipi_dsi_platform_data mipi_dsi_pdata = {
501 .dsi_power_save = mipi_dsi_panel_power,
502};
503
504static bool lvds_power_on;
505static int lvds_panel_power(int on)
506{
507 static struct regulator *reg_lvs7, *reg_l2, *reg_ext_3p3v;
508 static int gpio36, gpio26, mpp3;
509 int rc;
510
511 pr_debug("%s: on=%d\n", __func__, on);
512
513 if (!lvds_power_on) {
514 reg_lvs7 = regulator_get(&msm_lvds_device.dev,
515 "lvds_vdda");
516 if (IS_ERR_OR_NULL(reg_lvs7)) {
517 pr_err("could not get 8921_lvs7, rc = %ld\n",
518 PTR_ERR(reg_lvs7));
519 return -ENODEV;
520 }
521
522 reg_l2 = regulator_get(&msm_lvds_device.dev,
523 "lvds_pll_vdda");
524 if (IS_ERR_OR_NULL(reg_l2)) {
525 pr_err("could not get 8921_l2, rc = %ld\n",
526 PTR_ERR(reg_l2));
527 return -ENODEV;
528 }
529
530 rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
531 if (rc) {
532 pr_err("set_voltage l2 failed, rc=%d\n", rc);
533 return -EINVAL;
534 }
535
536 reg_ext_3p3v = regulator_get(&msm_lvds_device.dev,
537 "lvds_vccs_3p3v");
538 if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
539 pr_err("could not get reg_ext_3p3v, rc = %ld\n",
540 PTR_ERR(reg_ext_3p3v));
541 return -ENODEV;
542 }
543
544 gpio26 = PM8921_GPIO_PM_TO_SYS(26);
545 rc = gpio_request(gpio26, "pwm_backlight_ctrl");
546 if (rc) {
547 pr_err("request gpio 26 failed, rc=%d\n", rc);
548 return -ENODEV;
549 }
550
551 gpio36 = PM8921_GPIO_PM_TO_SYS(36); /* lcd1_pwr_en_n */
552 rc = gpio_request(gpio36, "lcd1_pwr_en_n");
553 if (rc) {
554 pr_err("request gpio 36 failed, rc=%d\n", rc);
555 return -ENODEV;
556 }
557
558 mpp3 = PM8921_MPP_PM_TO_SYS(3);
559 rc = gpio_request(mpp3, "backlight_en");
560 if (rc) {
561 pr_err("request mpp3 failed, rc=%d\n", rc);
562 return -ENODEV;
563 }
564
565 lvds_power_on = true;
566 }
567
568 if (on) {
569 rc = regulator_enable(reg_lvs7);
570 if (rc) {
571 pr_err("enable lvs7 failed, rc=%d\n", rc);
572 return -ENODEV;
573 }
574
575 rc = regulator_set_optimum_mode(reg_l2, 100000);
576 if (rc < 0) {
577 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
578 return -EINVAL;
579 }
580 rc = regulator_enable(reg_l2);
581 if (rc) {
582 pr_err("enable l2 failed, rc=%d\n", rc);
583 return -ENODEV;
584 }
585
586 rc = regulator_enable(reg_ext_3p3v);
587 if (rc) {
588 pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
589 return -ENODEV;
590 }
591
592 gpio_set_value_cansleep(gpio36, 0);
593 gpio_set_value_cansleep(mpp3, 1);
594 } else {
595 gpio_set_value_cansleep(mpp3, 0);
596 gpio_set_value_cansleep(gpio36, 1);
597
598 rc = regulator_disable(reg_lvs7);
599 if (rc) {
600 pr_err("disable reg_lvs7 failed, rc=%d\n", rc);
601 return -ENODEV;
602 }
603 rc = regulator_disable(reg_l2);
604 if (rc) {
605 pr_err("disable reg_l2 failed, rc=%d\n", rc);
606 return -ENODEV;
607 }
608 rc = regulator_disable(reg_ext_3p3v);
609 if (rc) {
610 pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
611 return -ENODEV;
612 }
613 }
614
615 return 0;
616}
617
Huaibin Yang02f981c2012-02-27 16:58:41 -0800618static int lvds_pixel_remap(void)
619{
Lei Zhou34e216d2012-07-25 12:52:13 -0400620 u32 ver = socinfo_get_version();
621
Huaibin Yang02f981c2012-02-27 16:58:41 -0800622 if (machine_is_apq8064_cdp() ||
623 machine_is_apq8064_liquid()) {
Huaibin Yang02f981c2012-02-27 16:58:41 -0800624 if ((SOCINFO_VERSION_MAJOR(ver) == 1) &&
625 (SOCINFO_VERSION_MINOR(ver) == 0))
Zhang Chang Ken4a07fcb2012-06-03 11:24:51 -0400626 return LVDS_PIXEL_MAP_PATTERN_1;
627 } else if (machine_is_mpq8064_dtv()) {
Lei Zhou34e216d2012-07-25 12:52:13 -0400628 if ((SOCINFO_VERSION_MAJOR(ver) == 1) &&
629 (SOCINFO_VERSION_MINOR(ver) == 0))
630 return LVDS_PIXEL_MAP_PATTERN_2;
Huaibin Yang02f981c2012-02-27 16:58:41 -0800631 }
632 return 0;
633}
634
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800635static struct lcdc_platform_data lvds_pdata = {
636 .lcdc_power_save = lvds_panel_power,
Huaibin Yang02f981c2012-02-27 16:58:41 -0800637 .lvds_pixel_remap = lvds_pixel_remap
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800638};
639
640#define LPM_CHANNEL 2
641static int lvds_chimei_gpio[] = {LPM_CHANNEL};
642
643static struct lvds_panel_platform_data lvds_chimei_pdata = {
644 .gpio = lvds_chimei_gpio,
645};
646
647static struct platform_device lvds_chimei_panel_device = {
648 .name = "lvds_chimei_wxga",
649 .id = 0,
650 .dev = {
651 .platform_data = &lvds_chimei_pdata,
652 }
653};
654
Zhang Chang Ken4a07fcb2012-06-03 11:24:51 -0400655#define FRC_GPIO_UPDATE (SX150X_EXP4_GPIO_BASE + 8)
656#define FRC_GPIO_RESET (SX150X_EXP4_GPIO_BASE + 9)
657#define FRC_GPIO_PWR (SX150X_EXP4_GPIO_BASE + 10)
658
659static int lvds_frc_gpio[] = {FRC_GPIO_UPDATE, FRC_GPIO_RESET, FRC_GPIO_PWR};
660static struct lvds_panel_platform_data lvds_frc_pdata = {
661 .gpio = lvds_frc_gpio,
662};
663
664static struct platform_device lvds_frc_panel_device = {
665 .name = "lvds_frc_fhd",
666 .id = 0,
667 .dev = {
668 .platform_data = &lvds_frc_pdata,
669 }
670};
671
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800672static int dsi2lvds_gpio[2] = {
673 LPM_CHANNEL,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
674 0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
675};
676static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
677 .gpio_num = dsi2lvds_gpio,
678};
679
680static struct platform_device mipi_dsi2lvds_bridge_device = {
681 .name = "mipi_tc358764",
682 .id = 0,
683 .dev.platform_data = &mipi_dsi2lvds_pdata,
684};
685
686static int toshiba_gpio[] = {LPM_CHANNEL};
687static struct mipi_dsi_panel_platform_data toshiba_pdata = {
688 .gpio = toshiba_gpio,
689};
690
691static struct platform_device mipi_dsi_toshiba_panel_device = {
692 .name = "mipi_toshiba",
693 .id = 0,
694 .dev = {
695 .platform_data = &toshiba_pdata,
696 }
697};
698
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800699static struct msm_bus_vectors dtv_bus_init_vectors[] = {
700 {
701 .src = MSM_BUS_MASTER_MDP_PORT0,
702 .dst = MSM_BUS_SLAVE_EBI_CH0,
703 .ab = 0,
704 .ib = 0,
705 },
706};
707
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800708static struct msm_bus_vectors dtv_bus_def_vectors[] = {
709 {
710 .src = MSM_BUS_MASTER_MDP_PORT0,
711 .dst = MSM_BUS_SLAVE_EBI_CH0,
712 .ab = 566092800 * 2,
713 .ib = 707616000 * 2,
714 },
715};
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800716
717static struct msm_bus_paths dtv_bus_scale_usecases[] = {
718 {
719 ARRAY_SIZE(dtv_bus_init_vectors),
720 dtv_bus_init_vectors,
721 },
722 {
723 ARRAY_SIZE(dtv_bus_def_vectors),
724 dtv_bus_def_vectors,
725 },
726};
727static struct msm_bus_scale_pdata dtv_bus_scale_pdata = {
728 dtv_bus_scale_usecases,
729 ARRAY_SIZE(dtv_bus_scale_usecases),
730 .name = "dtv",
731};
732
733static struct lcdc_platform_data dtv_pdata = {
734 .bus_scale_table = &dtv_bus_scale_pdata,
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530735 .lcdc_power_save = hdmi_panel_power,
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800736};
737
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530738static int hdmi_panel_power(int on)
739{
740 int rc;
741
742 pr_debug("%s: HDMI Core: %s\n", __func__, (on ? "ON" : "OFF"));
743 rc = hdmi_core_power(on, 1);
744 if (rc)
745 rc = hdmi_cec_power(on);
746
747 pr_debug("%s: HDMI Core: %s Success\n", __func__, (on ? "ON" : "OFF"));
748 return rc;
749}
750
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800751static int hdmi_enable_5v(int on)
752{
753 /* TBD: PM8921 regulator instead of 8901 */
754 static struct regulator *reg_8921_hdmi_mvs; /* HDMI_5V */
755 static int prev_on;
756 int rc;
757
758 if (on == prev_on)
759 return 0;
760
761 if (!reg_8921_hdmi_mvs) {
762 reg_8921_hdmi_mvs = regulator_get(&hdmi_msm_device.dev,
763 "hdmi_mvs");
764 if (IS_ERR(reg_8921_hdmi_mvs)) {
765 pr_err("could not get reg_8921_hdmi_mvs, rc = %ld\n",
766 PTR_ERR(reg_8921_hdmi_mvs));
767 reg_8921_hdmi_mvs = NULL;
768 return -ENODEV;
769 }
770 }
771
772 if (on) {
773 rc = regulator_enable(reg_8921_hdmi_mvs);
774 if (rc) {
775 pr_err("'%s' regulator enable failed, rc=%d\n",
776 "8921_hdmi_mvs", rc);
777 return rc;
778 }
779 pr_debug("%s(on): success\n", __func__);
780 } else {
781 rc = regulator_disable(reg_8921_hdmi_mvs);
782 if (rc)
783 pr_warning("'%s' regulator disable failed, rc=%d\n",
784 "8921_hdmi_mvs", rc);
785 pr_debug("%s(off): success\n", __func__);
786 }
787
788 prev_on = on;
789
790 return 0;
791}
792
793static int hdmi_core_power(int on, int show)
794{
795 static struct regulator *reg_8921_lvs7, *reg_8921_s4, *reg_ext_3p3v;
796 static int prev_on;
797 int rc;
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800798
799 if (on == prev_on)
800 return 0;
801
802 /* TBD: PM8921 regulator instead of 8901 */
803 if (!reg_ext_3p3v) {
804 reg_ext_3p3v = regulator_get(&hdmi_msm_device.dev,
805 "hdmi_mux_vdd");
806 if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
807 pr_err("could not get reg_ext_3p3v, rc = %ld\n",
808 PTR_ERR(reg_ext_3p3v));
809 reg_ext_3p3v = NULL;
810 return -ENODEV;
811 }
812 }
813
814 if (!reg_8921_lvs7) {
815 reg_8921_lvs7 = regulator_get(&hdmi_msm_device.dev,
816 "hdmi_vdda");
817 if (IS_ERR(reg_8921_lvs7)) {
818 pr_err("could not get reg_8921_lvs7, rc = %ld\n",
819 PTR_ERR(reg_8921_lvs7));
820 reg_8921_lvs7 = NULL;
821 return -ENODEV;
822 }
823 }
824 if (!reg_8921_s4) {
825 reg_8921_s4 = regulator_get(&hdmi_msm_device.dev,
826 "hdmi_lvl_tsl");
827 if (IS_ERR(reg_8921_s4)) {
828 pr_err("could not get reg_8921_s4, rc = %ld\n",
829 PTR_ERR(reg_8921_s4));
830 reg_8921_s4 = NULL;
831 return -ENODEV;
832 }
833 rc = regulator_set_voltage(reg_8921_s4, 1800000, 1800000);
834 if (rc) {
835 pr_err("set_voltage failed for 8921_s4, rc=%d\n", rc);
836 return -EINVAL;
837 }
838 }
839
840 if (on) {
841 /*
842 * Configure 3P3V_BOOST_EN as GPIO, 8mA drive strength,
843 * pull none, out-high
844 */
845 rc = regulator_set_optimum_mode(reg_ext_3p3v, 290000);
846 if (rc < 0) {
847 pr_err("set_optimum_mode ext_3p3v failed, rc=%d\n", rc);
848 return -EINVAL;
849 }
850
851 rc = regulator_enable(reg_ext_3p3v);
852 if (rc) {
853 pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530854 return rc;
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800855 }
856 rc = regulator_enable(reg_8921_lvs7);
857 if (rc) {
858 pr_err("'%s' regulator enable failed, rc=%d\n",
859 "hdmi_vdda", rc);
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530860 goto error1;
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800861 }
862 rc = regulator_enable(reg_8921_s4);
863 if (rc) {
864 pr_err("'%s' regulator enable failed, rc=%d\n",
865 "hdmi_lvl_tsl", rc);
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530866 goto error2;
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800867 }
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530868 pr_debug("%s(on): success\n", __func__);
869 } else {
870 rc = regulator_disable(reg_ext_3p3v);
871 if (rc) {
872 pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
873 return -ENODEV;
874 }
875 rc = regulator_disable(reg_8921_lvs7);
876 if (rc) {
877 pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
878 return -ENODEV;
879 }
880 rc = regulator_disable(reg_8921_s4);
881 if (rc) {
882 pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
883 return -ENODEV;
884 }
885 pr_debug("%s(off): success\n", __func__);
886 }
887
888 prev_on = on;
889
890 return 0;
891
892error2:
893 regulator_disable(reg_8921_lvs7);
894error1:
895 regulator_disable(reg_ext_3p3v);
896 return rc;
897}
898
899static int hdmi_gpio_config(int on)
900{
901 int rc = 0;
902 static int prev_on;
903 int pmic_gpio14 = PM8921_GPIO_PM_TO_SYS(14);
904
905 if (on == prev_on)
906 return 0;
907
908 if (on) {
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800909 rc = gpio_request(HDMI_DDC_CLK_GPIO, "HDMI_DDC_CLK");
910 if (rc) {
911 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
912 "HDMI_DDC_CLK", HDMI_DDC_CLK_GPIO, rc);
913 goto error1;
914 }
915 rc = gpio_request(HDMI_DDC_DATA_GPIO, "HDMI_DDC_DATA");
916 if (rc) {
917 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
918 "HDMI_DDC_DATA", HDMI_DDC_DATA_GPIO, rc);
919 goto error2;
920 }
921 rc = gpio_request(HDMI_HPD_GPIO, "HDMI_HPD");
922 if (rc) {
923 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
924 "HDMI_HPD", HDMI_HPD_GPIO, rc);
925 goto error3;
926 }
927 if (machine_is_apq8064_liquid()) {
928 rc = gpio_request(pmic_gpio14, "PMIC_HDMI_MUX_SEL");
929 if (rc) {
930 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
931 "PMIC_HDMI_MUX_SEL", 14, rc);
932 goto error4;
933 }
934 gpio_set_value_cansleep(pmic_gpio14, 0);
935 }
936 pr_debug("%s(on): success\n", __func__);
937 } else {
938 gpio_free(HDMI_DDC_CLK_GPIO);
939 gpio_free(HDMI_DDC_DATA_GPIO);
940 gpio_free(HDMI_HPD_GPIO);
941
942 if (machine_is_apq8064_liquid()) {
943 gpio_set_value_cansleep(pmic_gpio14, 1);
944 gpio_free(pmic_gpio14);
945 }
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800946 pr_debug("%s(off): success\n", __func__);
947 }
948
949 prev_on = on;
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800950 return 0;
951
952error4:
953 gpio_free(HDMI_HPD_GPIO);
954error3:
955 gpio_free(HDMI_DDC_DATA_GPIO);
956error2:
957 gpio_free(HDMI_DDC_CLK_GPIO);
958error1:
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -0800959 return rc;
960}
961
962static int hdmi_cec_power(int on)
963{
964 static int prev_on;
965 int rc;
966
967 if (on == prev_on)
968 return 0;
969
970 if (on) {
971 rc = gpio_request(HDMI_CEC_VAR_GPIO, "HDMI_CEC_VAR");
972 if (rc) {
973 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
974 "HDMI_CEC_VAR", HDMI_CEC_VAR_GPIO, rc);
975 goto error;
976 }
977 pr_debug("%s(on): success\n", __func__);
978 } else {
979 gpio_free(HDMI_CEC_VAR_GPIO);
980 pr_debug("%s(off): success\n", __func__);
981 }
982
983 prev_on = on;
984
985 return 0;
986error:
987 return rc;
988}
989
Huaibin Yang4a084e32011-12-15 15:25:52 -0800990void __init apq8064_init_fb(void)
991{
992 platform_device_register(&msm_fb_device);
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800993 platform_device_register(&lvds_chimei_panel_device);
994
Mohan Kumar Gubbihalli Lachma Naikcb7d4e72012-03-23 18:17:30 -0700995#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
996 platform_device_register(&wfd_panel_device);
997 platform_device_register(&wfd_device);
998#endif
999
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -08001000 if (machine_is_apq8064_liquid())
1001 platform_device_register(&mipi_dsi2lvds_bridge_device);
1002 if (machine_is_apq8064_mtp())
1003 platform_device_register(&mipi_dsi_toshiba_panel_device);
Zhang Chang Ken4a07fcb2012-06-03 11:24:51 -04001004 if (machine_is_mpq8064_dtv())
1005 platform_device_register(&lvds_frc_panel_device);
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -08001006
Huaibin Yang4a084e32011-12-15 15:25:52 -08001007 msm_fb_register_device("mdp", &mdp_pdata);
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -08001008 msm_fb_register_device("lvds", &lvds_pdata);
1009 msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
Aravind Venkateswaran0507c8c2012-02-16 17:16:05 -08001010 platform_device_register(&hdmi_msm_device);
1011 msm_fb_register_device("dtv", &dtv_pdata);
Huaibin Yang4a084e32011-12-15 15:25:52 -08001012}
Aravind Venkateswaran8ac7f412012-03-16 17:57:30 -07001013
1014/**
1015 * Set MDP clocks to high frequency to avoid DSI underflow
1016 * when using high resolution 1200x1920 WUXGA panels
1017 */
1018static void set_mdp_clocks_for_wuxga(void)
1019{
Aravind Venkateswaran8ac7f412012-03-16 17:57:30 -07001020 mdp_ui_vectors[0].ab = 2000000000;
1021 mdp_ui_vectors[0].ib = 2000000000;
1022 mdp_vga_vectors[0].ab = 2000000000;
1023 mdp_vga_vectors[0].ib = 2000000000;
1024 mdp_720p_vectors[0].ab = 2000000000;
1025 mdp_720p_vectors[0].ib = 2000000000;
1026 mdp_1080p_vectors[0].ab = 2000000000;
1027 mdp_1080p_vectors[0].ib = 2000000000;
1028
Ravishangar Kalyanamfda36c42012-03-26 16:28:19 -07001029 if (apq8064_hdmi_as_primary_selected()) {
Aravind Venkateswaran8ac7f412012-03-16 17:57:30 -07001030 dtv_bus_def_vectors[0].ab = 2000000000;
1031 dtv_bus_def_vectors[0].ib = 2000000000;
1032 }
1033}
1034
Ajay Singh Parmar6b82d2b2012-07-19 17:23:26 +05301035void __init apq8064_set_display_params(char *prim_panel, char *ext_panel,
1036 unsigned char resolution)
Aravind Venkateswaran8ac7f412012-03-16 17:57:30 -07001037{
Aravind Venkateswarand98bc432012-04-04 16:19:06 -07001038 /*
1039 * For certain MPQ boards, HDMI should be set as primary display
1040 * by default, with the flexibility to specify any other panel
1041 * as a primary panel through boot parameters.
1042 */
1043 if (machine_is_mpq8064_hrd() || machine_is_mpq8064_cdp()) {
1044 pr_debug("HDMI is the primary display by default for MPQ\n");
1045 if (!strnlen(prim_panel, PANEL_NAME_MAX_LEN))
1046 strlcpy(msm_fb_pdata.prim_panel_name, HDMI_PANEL_NAME,
1047 PANEL_NAME_MAX_LEN);
1048 }
1049
Aravind Venkateswaran8ac7f412012-03-16 17:57:30 -07001050 if (strnlen(prim_panel, PANEL_NAME_MAX_LEN)) {
1051 strlcpy(msm_fb_pdata.prim_panel_name, prim_panel,
1052 PANEL_NAME_MAX_LEN);
1053 pr_debug("msm_fb_pdata.prim_panel_name %s\n",
1054 msm_fb_pdata.prim_panel_name);
1055
1056 if (!strncmp((char *)msm_fb_pdata.prim_panel_name,
1057 HDMI_PANEL_NAME, strnlen(HDMI_PANEL_NAME,
1058 PANEL_NAME_MAX_LEN))) {
1059 pr_debug("HDMI is the primary display by"
1060 " boot parameter\n");
1061 hdmi_is_primary = 1;
1062 set_mdp_clocks_for_wuxga();
1063 }
1064 }
1065 if (strnlen(ext_panel, PANEL_NAME_MAX_LEN)) {
1066 strlcpy(msm_fb_pdata.ext_panel_name, ext_panel,
1067 PANEL_NAME_MAX_LEN);
1068 pr_debug("msm_fb_pdata.ext_panel_name %s\n",
1069 msm_fb_pdata.ext_panel_name);
1070 }
Ajay Singh Parmar6b82d2b2012-07-19 17:23:26 +05301071
1072 msm_fb_pdata.ext_resolution = resolution;
Aravind Venkateswaran8ac7f412012-03-16 17:57:30 -07001073}