blob: 5ead88c807e8261d961092f0455d5ca25a9b2a82 [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>
18#include <asm/mach-types.h>
19#include <mach/msm_memtypes.h>
20#include <mach/board.h>
21#include <mach/gpio.h>
22#include <mach/gpiomux.h>
23#include <linux/ion.h>
24#include <mach/ion.h>
25
26#include "devices.h"
27#include "board-8064.h"
28
29#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
30/* prim = 1366 x 768 x 3(bpp) x 3(pages) */
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -080031#define MSM_FB_PRIM_BUF_SIZE roundup(1376 * 768 * 4 * 3, 0x10000)
Huaibin Yang4a084e32011-12-15 15:25:52 -080032#else
33/* prim = 1366 x 768 x 3(bpp) x 2(pages) */
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -080034#define MSM_FB_PRIM_BUF_SIZE roundup(1376 * 768 * 4 * 2, 0x10000)
Huaibin Yang4a084e32011-12-15 15:25:52 -080035#endif
36
37#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
38/* hdmi = 1920 x 1088 x 2(bpp) x 1(page) */
39#define MSM_FB_EXT_BUF_SIZE 0x3FC000
40#elif defined(CONFIG_FB_MSM_TVOUT)
41/* tvout = 720 x 576 x 2(bpp) x 2(pages) */
42#define MSM_FB_EXT_BUF_SIZE 0x195000
43#else /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
44#define MSM_FB_EXT_BUF_SIZE 0
45#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
46
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
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -080068#define PANEL_NAME_MAX_LEN 30
Huaibin Yang4a084e32011-12-15 15:25:52 -080069#define LVDS_CHIMEI_PANEL_NAME "lvds_chimei_wxga"
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -080070#define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
71#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
72#define HDMI_PANEL_NAME "hdmi_msm"
73#define TVOUT_PANEL_NAME "tvout_msm"
Huaibin Yang4a084e32011-12-15 15:25:52 -080074
75static int msm_fb_detect_panel(const char *name)
76{
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -080077 if (machine_is_apq8064_liquid()) {
78 if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
79 strnlen(LVDS_CHIMEI_PANEL_NAME,
80 PANEL_NAME_MAX_LEN)))
81 return 0;
82
83#if !defined(CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT) && \
84 !defined(CONFIG_FB_MSM_MIPI_PANEL_DETECT)
85 if (!strncmp(name, MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
86 strnlen(MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
87 PANEL_NAME_MAX_LEN)))
88 return 0;
89#endif
90 } else if (machine_is_apq8064_mtp()) {
91 if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
92 strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
93 PANEL_NAME_MAX_LEN)))
94 return 0;
95 } else if (machine_is_apq8064_cdp()) {
96 if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
97 strnlen(LVDS_CHIMEI_PANEL_NAME,
98 PANEL_NAME_MAX_LEN)))
99 return 0;
100 }
101
102 if (!strncmp(name, HDMI_PANEL_NAME,
103 strnlen(HDMI_PANEL_NAME,
104 PANEL_NAME_MAX_LEN)))
Huaibin Yang4a084e32011-12-15 15:25:52 -0800105 return 0;
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800106
Huaibin Yang4a084e32011-12-15 15:25:52 -0800107 return -ENODEV;
108}
109
110static struct msm_fb_platform_data msm_fb_pdata = {
111 .detect_client = msm_fb_detect_panel,
112};
113
114static struct platform_device msm_fb_device = {
115 .name = "msm_fb",
116 .id = 0,
117 .num_resources = ARRAY_SIZE(msm_fb_resources),
118 .resource = msm_fb_resources,
119 .dev.platform_data = &msm_fb_pdata,
120};
121
122void __init apq8064_allocate_fb_region(void)
123{
124 void *addr;
125 unsigned long size;
126
127 size = MSM_FB_SIZE;
128 addr = alloc_bootmem_align(size, 0x1000);
129 msm_fb_resources[0].start = __pa(addr);
130 msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
131 pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
132 size, addr, __pa(addr));
133}
134
135#define MDP_VSYNC_GPIO 0
136
137static int mdp_core_clk_rate_table[] = {
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800138 200000000,
139 200000000,
140 200000000,
141 200000000,
Huaibin Yang4a084e32011-12-15 15:25:52 -0800142};
143
144static struct msm_panel_common_pdata mdp_pdata = {
145 .gpio = MDP_VSYNC_GPIO,
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800146 .mdp_core_clk_rate = 200000000,
Huaibin Yang4a084e32011-12-15 15:25:52 -0800147 .mdp_core_clk_table = mdp_core_clk_rate_table,
148 .num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
149 .mdp_rev = MDP_REV_44,
150#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
151 .mem_hid = ION_CP_MM_HEAP_ID,
152#else
153 .mem_hid = MEMTYPE_EBI1,
154#endif
155};
156
157void __init apq8064_mdp_writeback(struct memtype_reserve* reserve_table)
158{
159 mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
160 mdp_pdata.ov1_wb_size = MSM_FB_OVERLAY1_WRITEBACK_SIZE;
161#if defined(CONFIG_ANDROID_PMEM) && !defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
162 reserve_table[mdp_pdata.mem_hid].size +=
163 mdp_pdata.ov0_wb_size;
164 reserve_table[mdp_pdata.mem_hid].size +=
165 mdp_pdata.ov1_wb_size;
166#endif
167}
168
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800169static bool dsi_power_on;
170static int mipi_dsi_panel_power(int on)
171{
172 static struct regulator *reg_lvs7, *reg_l2, *reg_l11, *reg_ext_3p3v;
173 static int gpio36, gpio25, gpio26, mpp3;
174 int rc;
175
176 pr_debug("%s: on=%d\n", __func__, on);
177
178 if (!dsi_power_on) {
179 reg_lvs7 = regulator_get(&msm_mipi_dsi1_device.dev,
180 "dsi1_vddio");
181 if (IS_ERR_OR_NULL(reg_lvs7)) {
182 pr_err("could not get 8921_lvs7, rc = %ld\n",
183 PTR_ERR(reg_lvs7));
184 return -ENODEV;
185 }
186
187 reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
188 "dsi1_pll_vdda");
189 if (IS_ERR_OR_NULL(reg_l2)) {
190 pr_err("could not get 8921_l2, rc = %ld\n",
191 PTR_ERR(reg_l2));
192 return -ENODEV;
193 }
194
195 rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
196 if (rc) {
197 pr_err("set_voltage l2 failed, rc=%d\n", rc);
198 return -EINVAL;
199 }
200 reg_l11 = regulator_get(&msm_mipi_dsi1_device.dev,
201 "dsi1_avdd");
202 if (IS_ERR(reg_l11)) {
203 pr_err("could not get 8921_l11, rc = %ld\n",
204 PTR_ERR(reg_l11));
205 return -ENODEV;
206 }
207 rc = regulator_set_voltage(reg_l11, 3000000, 3000000);
208 if (rc) {
209 pr_err("set_voltage l11 failed, rc=%d\n", rc);
210 return -EINVAL;
211 }
212
213 if (machine_is_apq8064_liquid()) {
214 reg_ext_3p3v = regulator_get(&msm_mipi_dsi1_device.dev,
215 "dsi1_vccs_3p3v");
216 if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
217 pr_err("could not get reg_ext_3p3v, rc = %ld\n",
218 PTR_ERR(reg_ext_3p3v));
219 reg_ext_3p3v = NULL;
220 return -ENODEV;
221 }
222 mpp3 = PM8921_MPP_PM_TO_SYS(3);
223 rc = gpio_request(mpp3, "backlight_en");
224 if (rc) {
225 pr_err("request mpp3 failed, rc=%d\n", rc);
226 return -ENODEV;
227 }
228 }
229
230 gpio25 = PM8921_GPIO_PM_TO_SYS(25);
231 rc = gpio_request(gpio25, "disp_rst_n");
232 if (rc) {
233 pr_err("request gpio 25 failed, rc=%d\n", rc);
234 return -ENODEV;
235 }
236
237 gpio26 = PM8921_GPIO_PM_TO_SYS(26);
238 rc = gpio_request(gpio26, "pwm_backlight_ctrl");
239 if (rc) {
240 pr_err("request gpio 26 failed, rc=%d\n", rc);
241 return -ENODEV;
242 }
243
244 gpio36 = PM8921_GPIO_PM_TO_SYS(36); /* lcd1_pwr_en_n */
245 rc = gpio_request(gpio36, "lcd1_pwr_en_n");
246 if (rc) {
247 pr_err("request gpio 36 failed, rc=%d\n", rc);
248 return -ENODEV;
249 }
250
251 dsi_power_on = true;
252 }
253
254 if (on) {
255 rc = regulator_enable(reg_lvs7);
256 if (rc) {
257 pr_err("enable lvs7 failed, rc=%d\n", rc);
258 return -ENODEV;
259 }
260
261 rc = regulator_set_optimum_mode(reg_l11, 110000);
262 if (rc < 0) {
263 pr_err("set_optimum_mode l11 failed, rc=%d\n", rc);
264 return -EINVAL;
265 }
266 rc = regulator_enable(reg_l11);
267 if (rc) {
268 pr_err("enable l11 failed, rc=%d\n", rc);
269 return -ENODEV;
270 }
271
272 rc = regulator_set_optimum_mode(reg_l2, 100000);
273 if (rc < 0) {
274 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
275 return -EINVAL;
276 }
277 rc = regulator_enable(reg_l2);
278 if (rc) {
279 pr_err("enable l2 failed, rc=%d\n", rc);
280 return -ENODEV;
281 }
282
283 if (machine_is_apq8064_liquid()) {
284 rc = regulator_enable(reg_ext_3p3v);
285 if (rc) {
286 pr_err("enable reg_ext_3p3v failed, rc=%d\n",
287 rc);
288 return -ENODEV;
289 }
290 gpio_set_value_cansleep(mpp3, 1);
291 }
292
293 gpio_set_value_cansleep(gpio36, 0);
294 gpio_set_value_cansleep(gpio25, 1);
295 } else {
296 gpio_set_value_cansleep(gpio25, 0);
297 gpio_set_value_cansleep(gpio36, 1);
298
299 if (machine_is_apq8064_liquid()) {
300 gpio_set_value_cansleep(mpp3, 0);
301
302 rc = regulator_disable(reg_ext_3p3v);
303 if (rc) {
304 pr_err("disable reg_ext_3p3v failed, rc=%d\n",
305 rc);
306 return -ENODEV;
307 }
308 }
309
310 rc = regulator_disable(reg_lvs7);
311 if (rc) {
312 pr_err("disable reg_lvs7 failed, rc=%d\n", rc);
313 return -ENODEV;
314 }
315 rc = regulator_disable(reg_l2);
316 if (rc) {
317 pr_err("disable reg_l2 failed, rc=%d\n", rc);
318 return -ENODEV;
319 }
320 }
321
322 return 0;
323}
324
325static struct mipi_dsi_platform_data mipi_dsi_pdata = {
326 .dsi_power_save = mipi_dsi_panel_power,
327};
328
329static bool lvds_power_on;
330static int lvds_panel_power(int on)
331{
332 static struct regulator *reg_lvs7, *reg_l2, *reg_ext_3p3v;
333 static int gpio36, gpio26, mpp3;
334 int rc;
335
336 pr_debug("%s: on=%d\n", __func__, on);
337
338 if (!lvds_power_on) {
339 reg_lvs7 = regulator_get(&msm_lvds_device.dev,
340 "lvds_vdda");
341 if (IS_ERR_OR_NULL(reg_lvs7)) {
342 pr_err("could not get 8921_lvs7, rc = %ld\n",
343 PTR_ERR(reg_lvs7));
344 return -ENODEV;
345 }
346
347 reg_l2 = regulator_get(&msm_lvds_device.dev,
348 "lvds_pll_vdda");
349 if (IS_ERR_OR_NULL(reg_l2)) {
350 pr_err("could not get 8921_l2, rc = %ld\n",
351 PTR_ERR(reg_l2));
352 return -ENODEV;
353 }
354
355 rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
356 if (rc) {
357 pr_err("set_voltage l2 failed, rc=%d\n", rc);
358 return -EINVAL;
359 }
360
361 reg_ext_3p3v = regulator_get(&msm_lvds_device.dev,
362 "lvds_vccs_3p3v");
363 if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
364 pr_err("could not get reg_ext_3p3v, rc = %ld\n",
365 PTR_ERR(reg_ext_3p3v));
366 return -ENODEV;
367 }
368
369 gpio26 = PM8921_GPIO_PM_TO_SYS(26);
370 rc = gpio_request(gpio26, "pwm_backlight_ctrl");
371 if (rc) {
372 pr_err("request gpio 26 failed, rc=%d\n", rc);
373 return -ENODEV;
374 }
375
376 gpio36 = PM8921_GPIO_PM_TO_SYS(36); /* lcd1_pwr_en_n */
377 rc = gpio_request(gpio36, "lcd1_pwr_en_n");
378 if (rc) {
379 pr_err("request gpio 36 failed, rc=%d\n", rc);
380 return -ENODEV;
381 }
382
383 mpp3 = PM8921_MPP_PM_TO_SYS(3);
384 rc = gpio_request(mpp3, "backlight_en");
385 if (rc) {
386 pr_err("request mpp3 failed, rc=%d\n", rc);
387 return -ENODEV;
388 }
389
390 lvds_power_on = true;
391 }
392
393 if (on) {
394 rc = regulator_enable(reg_lvs7);
395 if (rc) {
396 pr_err("enable lvs7 failed, rc=%d\n", rc);
397 return -ENODEV;
398 }
399
400 rc = regulator_set_optimum_mode(reg_l2, 100000);
401 if (rc < 0) {
402 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
403 return -EINVAL;
404 }
405 rc = regulator_enable(reg_l2);
406 if (rc) {
407 pr_err("enable l2 failed, rc=%d\n", rc);
408 return -ENODEV;
409 }
410
411 rc = regulator_enable(reg_ext_3p3v);
412 if (rc) {
413 pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
414 return -ENODEV;
415 }
416
417 gpio_set_value_cansleep(gpio36, 0);
418 gpio_set_value_cansleep(mpp3, 1);
419 } else {
420 gpio_set_value_cansleep(mpp3, 0);
421 gpio_set_value_cansleep(gpio36, 1);
422
423 rc = regulator_disable(reg_lvs7);
424 if (rc) {
425 pr_err("disable reg_lvs7 failed, rc=%d\n", rc);
426 return -ENODEV;
427 }
428 rc = regulator_disable(reg_l2);
429 if (rc) {
430 pr_err("disable reg_l2 failed, rc=%d\n", rc);
431 return -ENODEV;
432 }
433 rc = regulator_disable(reg_ext_3p3v);
434 if (rc) {
435 pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
436 return -ENODEV;
437 }
438 }
439
440 return 0;
441}
442
443static struct lcdc_platform_data lvds_pdata = {
444 .lcdc_power_save = lvds_panel_power,
445};
446
447#define LPM_CHANNEL 2
448static int lvds_chimei_gpio[] = {LPM_CHANNEL};
449
450static struct lvds_panel_platform_data lvds_chimei_pdata = {
451 .gpio = lvds_chimei_gpio,
452};
453
454static struct platform_device lvds_chimei_panel_device = {
455 .name = "lvds_chimei_wxga",
456 .id = 0,
457 .dev = {
458 .platform_data = &lvds_chimei_pdata,
459 }
460};
461
462static int dsi2lvds_gpio[2] = {
463 LPM_CHANNEL,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
464 0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
465};
466static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
467 .gpio_num = dsi2lvds_gpio,
468};
469
470static struct platform_device mipi_dsi2lvds_bridge_device = {
471 .name = "mipi_tc358764",
472 .id = 0,
473 .dev.platform_data = &mipi_dsi2lvds_pdata,
474};
475
476static int toshiba_gpio[] = {LPM_CHANNEL};
477static struct mipi_dsi_panel_platform_data toshiba_pdata = {
478 .gpio = toshiba_gpio,
479};
480
481static struct platform_device mipi_dsi_toshiba_panel_device = {
482 .name = "mipi_toshiba",
483 .id = 0,
484 .dev = {
485 .platform_data = &toshiba_pdata,
486 }
487};
488
Huaibin Yang4a084e32011-12-15 15:25:52 -0800489void __init apq8064_init_fb(void)
490{
491 platform_device_register(&msm_fb_device);
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800492 platform_device_register(&lvds_chimei_panel_device);
493
494 if (machine_is_apq8064_liquid())
495 platform_device_register(&mipi_dsi2lvds_bridge_device);
496 if (machine_is_apq8064_mtp())
497 platform_device_register(&mipi_dsi_toshiba_panel_device);
498
Huaibin Yang4a084e32011-12-15 15:25:52 -0800499 msm_fb_register_device("mdp", &mdp_pdata);
Ravishangar Kalyanamc2fee312012-02-09 19:11:22 -0800500 msm_fb_register_device("lvds", &lvds_pdata);
501 msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
Huaibin Yang4a084e32011-12-15 15:25:52 -0800502}