blob: 2e6718d2c25c54f323ee0e9d573461005295c921 [file] [log] [blame]
Stepan Moskovchenko39236d72011-11-30 17:42:23 -08001/* Copyright (c) 2011, 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_bus_board.h>
Huaibin Yanga5419422011-12-08 23:52:10 -080020#include <mach/msm_memtypes.h>
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080021#include <mach/board.h>
22#include <mach/gpio.h>
23#include <mach/gpiomux.h>
Ajay Dudani9114be72011-12-03 07:46:35 -080024#include <mach/socinfo.h>
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080025#include "devices.h"
Jay Chokshi06fa7542011-12-07 13:09:17 -080026
27/* TODO: Remove this once PM8038 physically becomes
28 * available.
29 */
30#ifndef MSM8930_PHASE_2
31#include "board-8960.h"
32#else
Stepan Moskovchenko5a83dba2011-12-05 17:30:17 -080033#include "board-8930.h"
Jay Chokshi06fa7542011-12-07 13:09:17 -080034#endif
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080035
36#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
37#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 3) /* 4 bpp x 3 pages */
38#else
39#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 2) /* 4 bpp x 2 pages */
40#endif
41
42#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
43#define MSM_FB_EXT_BUF_SIZE (1920 * 1088 * 2 * 1) /* 2 bpp x 1 page */
44#elif defined(CONFIG_FB_MSM_TVOUT)
45#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
46#else
47#define MSM_FB_EXT_BUF_SIZE 0
48#endif
49
50#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
51/* width x height x 3 bpp x 2 frame buffer */
52#define MSM_FB_WRITEBACK_SIZE (1376 * 768 * 3 * 2)
53#define MSM_FB_WRITEBACK_OFFSET \
54 (MSM_FB_PRIM_BUF_SIZE + MSM_FB_EXT_BUF_SIZE)
55#else
56#define MSM_FB_WRITEBACK_SIZE 0
57#define MSM_FB_WRITEBACK_OFFSET 0
58#endif
59
60#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
61/* 4 bpp x 2 page HDMI case */
62#define MSM_FB_SIZE roundup((1920 * 1088 * 4 * 2), 4096)
63#else
64/* Note: must be multiple of 4096 */
65#define MSM_FB_SIZE roundup(MSM_FB_PRIM_BUF_SIZE + MSM_FB_EXT_BUF_SIZE + \
66 MSM_FB_WRITEBACK_SIZE, 4096)
67#endif
68
Huaibin Yanga5419422011-12-08 23:52:10 -080069#ifdef CONFIG_FB_MSM_OVERLAY0_WRITEBACK
70#define MSM_FB_OVERLAY0_WRITEBACK_SIZE roundup((1376 * 768 * 3 * 2), 4096)
71#else
72#define MSM_FB_OVERLAY0_WRITEBACK_SIZE (0)
73#endif /* CONFIG_FB_MSM_OVERLAY0_WRITEBACK */
74
75#ifdef CONFIG_FB_MSM_OVERLAY1_WRITEBACK
76#define MSM_FB_OVERLAY1_WRITEBACK_SIZE roundup((1920 * 1088 * 3 * 2), 4096)
77#else
78#define MSM_FB_OVERLAY1_WRITEBACK_SIZE (0)
79#endif /* CONFIG_FB_MSM_OVERLAY1_WRITEBACK */
80
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080081#define MDP_VSYNC_GPIO 0
82
83#define PANEL_NAME_MAX_LEN 30
84#define MIPI_CMD_NOVATEK_QHD_PANEL_NAME "mipi_cmd_novatek_qhd"
85#define MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME "mipi_video_novatek_qhd"
86#define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
87#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
88#define MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME "mipi_video_simulator_vga"
89#define MIPI_CMD_RENESAS_FWVGA_PANEL_NAME "mipi_cmd_renesas_fwvga"
90#define HDMI_PANEL_NAME "hdmi_msm"
91#define TVOUT_PANEL_NAME "tvout_msm"
92
93static int writeback_offset(void)
94{
95 return MSM_FB_WRITEBACK_OFFSET;
96}
97
98static struct resource msm_fb_resources[] = {
99 {
100 .flags = IORESOURCE_DMA,
101 }
102};
103
104static int msm_fb_detect_panel(const char *name)
105{
106 if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
107 strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
108 PANEL_NAME_MAX_LEN)))
109 return 0;
110
111#ifndef CONFIG_FB_MSM_MIPI_PANEL_DETECT
112 if (!strncmp(name, MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
113 strnlen(MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
114 PANEL_NAME_MAX_LEN)))
115 return 0;
116
117 if (!strncmp(name, MIPI_CMD_NOVATEK_QHD_PANEL_NAME,
118 strnlen(MIPI_CMD_NOVATEK_QHD_PANEL_NAME,
119 PANEL_NAME_MAX_LEN)))
120 return 0;
121
122 if (!strncmp(name, MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME,
123 strnlen(MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME,
124 PANEL_NAME_MAX_LEN)))
125 return 0;
126
127 if (!strncmp(name, MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
128 strnlen(MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
129 PANEL_NAME_MAX_LEN)))
130 return 0;
131#endif
132
133 if (!strncmp(name, HDMI_PANEL_NAME,
134 strnlen(HDMI_PANEL_NAME,
135 PANEL_NAME_MAX_LEN)))
136 return 0;
137
138 if (!strncmp(name, TVOUT_PANEL_NAME,
139 strnlen(TVOUT_PANEL_NAME,
140 PANEL_NAME_MAX_LEN)))
141 return 0;
142
143 pr_warning("%s: not supported '%s'", __func__, name);
144 return -ENODEV;
145}
146
147static struct msm_fb_platform_data msm_fb_pdata = {
148 .detect_client = msm_fb_detect_panel,
149};
150
151static struct platform_device msm_fb_device = {
152 .name = "msm_fb",
153 .id = 0,
154 .num_resources = ARRAY_SIZE(msm_fb_resources),
155 .resource = msm_fb_resources,
156 .dev.platform_data = &msm_fb_pdata,
157};
158
159static bool dsi_power_on;
160
Jay Chokshi06fa7542011-12-07 13:09:17 -0800161/*
162 * TODO: When physical 8930/PM8038 hardware becomes
163 * available, replace mipi_dsi_cdp_panel_power with
164 * appropriate function.
165 */
166#ifndef MSM8930_PHASE_2
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800167static int mipi_dsi_cdp_panel_power(int on)
168{
169 static struct regulator *reg_l8, *reg_l23, *reg_l2;
170 static int gpio43;
171 int rc;
172
173 pr_info("%s: state : %d\n", __func__, on);
174
175 if (!dsi_power_on) {
176
177 reg_l8 = regulator_get(&msm_mipi_dsi1_device.dev,
178 "dsi_vdc");
179 if (IS_ERR(reg_l8)) {
180 pr_err("could not get 8921_l8, rc = %ld\n",
181 PTR_ERR(reg_l8));
182 return -ENODEV;
183 }
184 reg_l23 = regulator_get(&msm_mipi_dsi1_device.dev,
185 "dsi_vddio");
186 if (IS_ERR(reg_l23)) {
187 pr_err("could not get 8921_l23, rc = %ld\n",
188 PTR_ERR(reg_l23));
189 return -ENODEV;
190 }
191 reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
192 "dsi_vdda");
193 if (IS_ERR(reg_l2)) {
194 pr_err("could not get 8921_l2, rc = %ld\n",
195 PTR_ERR(reg_l2));
196 return -ENODEV;
197 }
198 rc = regulator_set_voltage(reg_l8, 2800000, 3000000);
199 if (rc) {
200 pr_err("set_voltage l8 failed, rc=%d\n", rc);
201 return -EINVAL;
202 }
203 rc = regulator_set_voltage(reg_l23, 1800000, 1800000);
204 if (rc) {
205 pr_err("set_voltage l23 failed, rc=%d\n", rc);
206 return -EINVAL;
207 }
208 rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
209 if (rc) {
210 pr_err("set_voltage l2 failed, rc=%d\n", rc);
211 return -EINVAL;
212 }
213 gpio43 = PM8921_GPIO_PM_TO_SYS(43);
214 rc = gpio_request(gpio43, "disp_rst_n");
215 if (rc) {
216 pr_err("request gpio 43 failed, rc=%d\n", rc);
217 return -ENODEV;
218 }
219 dsi_power_on = true;
220 }
221 if (on) {
222 rc = regulator_set_optimum_mode(reg_l8, 100000);
223 if (rc < 0) {
224 pr_err("set_optimum_mode l8 failed, rc=%d\n", rc);
225 return -EINVAL;
226 }
227 rc = regulator_set_optimum_mode(reg_l23, 100000);
228 if (rc < 0) {
229 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
230 return -EINVAL;
231 }
232 rc = regulator_set_optimum_mode(reg_l2, 100000);
233 if (rc < 0) {
234 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
235 return -EINVAL;
236 }
237 rc = regulator_enable(reg_l8);
238 if (rc) {
239 pr_err("enable l8 failed, rc=%d\n", rc);
240 return -ENODEV;
241 }
242 rc = regulator_enable(reg_l23);
243 if (rc) {
244 pr_err("enable l8 failed, rc=%d\n", rc);
245 return -ENODEV;
246 }
247 rc = regulator_enable(reg_l2);
248 if (rc) {
249 pr_err("enable l2 failed, rc=%d\n", rc);
250 return -ENODEV;
251 }
252 gpio_set_value_cansleep(gpio43, 1);
253 } else {
254 rc = regulator_disable(reg_l2);
255 if (rc) {
256 pr_err("disable reg_l2 failed, rc=%d\n", rc);
257 return -ENODEV;
258 }
259 rc = regulator_disable(reg_l8);
260 if (rc) {
261 pr_err("disable reg_l8 failed, rc=%d\n", rc);
262 return -ENODEV;
263 }
264 rc = regulator_disable(reg_l23);
265 if (rc) {
266 pr_err("disable reg_l23 failed, rc=%d\n", rc);
267 return -ENODEV;
268 }
269 rc = regulator_set_optimum_mode(reg_l8, 100);
270 if (rc < 0) {
271 pr_err("set_optimum_mode l8 failed, rc=%d\n", rc);
272 return -EINVAL;
273 }
274 rc = regulator_set_optimum_mode(reg_l23, 100);
275 if (rc < 0) {
276 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
277 return -EINVAL;
278 }
279 rc = regulator_set_optimum_mode(reg_l2, 100);
280 if (rc < 0) {
281 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
282 return -EINVAL;
283 }
284 gpio_set_value_cansleep(gpio43, 0);
285 }
286 return 0;
287}
Jay Chokshi06fa7542011-12-07 13:09:17 -0800288#endif
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800289
290static int mipi_dsi_panel_power(int on)
291{
292 pr_info("%s: on=%d\n", __func__, on);
293
294 return mipi_dsi_cdp_panel_power(on);
295}
296
297static struct mipi_dsi_platform_data mipi_dsi_pdata = {
298 .vsync_gpio = MDP_VSYNC_GPIO,
299 .dsi_power_save = mipi_dsi_panel_power,
300};
301
302#ifdef CONFIG_MSM_BUS_SCALING
303
304static struct msm_bus_vectors mdp_init_vectors[] = {
305 {
306 .src = MSM_BUS_MASTER_MDP_PORT0,
307 .dst = MSM_BUS_SLAVE_EBI_CH0,
308 .ab = 0,
309 .ib = 0,
310 },
311};
312
313#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
314static struct msm_bus_vectors hdmi_as_primary_vectors[] = {
315 /* If HDMI is used as primary */
316 {
317 .src = MSM_BUS_MASTER_MDP_PORT0,
318 .dst = MSM_BUS_SLAVE_EBI_CH0,
319 .ab = 2000000000,
320 .ib = 2000000000,
321 },
322};
323static struct msm_bus_paths mdp_bus_scale_usecases[] = {
324 {
325 ARRAY_SIZE(mdp_init_vectors),
326 mdp_init_vectors,
327 },
328 {
329 ARRAY_SIZE(hdmi_as_primary_vectors),
330 hdmi_as_primary_vectors,
331 },
332 {
333 ARRAY_SIZE(hdmi_as_primary_vectors),
334 hdmi_as_primary_vectors,
335 },
336 {
337 ARRAY_SIZE(hdmi_as_primary_vectors),
338 hdmi_as_primary_vectors,
339 },
340 {
341 ARRAY_SIZE(hdmi_as_primary_vectors),
342 hdmi_as_primary_vectors,
343 },
344 {
345 ARRAY_SIZE(hdmi_as_primary_vectors),
346 hdmi_as_primary_vectors,
347 },
348};
349#else
350static struct msm_bus_vectors mdp_ui_vectors[] = {
351 {
352 .src = MSM_BUS_MASTER_MDP_PORT0,
353 .dst = MSM_BUS_SLAVE_EBI_CH0,
354 .ab = 216000000 * 2,
355 .ib = 270000000 * 2,
356 },
357};
358
359static struct msm_bus_vectors mdp_vga_vectors[] = {
360 /* VGA and less video */
361 {
362 .src = MSM_BUS_MASTER_MDP_PORT0,
363 .dst = MSM_BUS_SLAVE_EBI_CH0,
364 .ab = 216000000 * 2,
365 .ib = 270000000 * 2,
366 },
367};
368
369static struct msm_bus_vectors mdp_720p_vectors[] = {
370 /* 720p and less video */
371 {
372 .src = MSM_BUS_MASTER_MDP_PORT0,
373 .dst = MSM_BUS_SLAVE_EBI_CH0,
374 .ab = 230400000 * 2,
375 .ib = 288000000 * 2,
376 },
377};
378
379static struct msm_bus_vectors mdp_1080p_vectors[] = {
380 /* 1080p and less video */
381 {
382 .src = MSM_BUS_MASTER_MDP_PORT0,
383 .dst = MSM_BUS_SLAVE_EBI_CH0,
384 .ab = 334080000 * 2,
385 .ib = 417600000 * 2,
386 },
387};
388
389static struct msm_bus_paths mdp_bus_scale_usecases[] = {
390 {
391 ARRAY_SIZE(mdp_init_vectors),
392 mdp_init_vectors,
393 },
394 {
395 ARRAY_SIZE(mdp_ui_vectors),
396 mdp_ui_vectors,
397 },
398 {
399 ARRAY_SIZE(mdp_ui_vectors),
400 mdp_ui_vectors,
401 },
402 {
403 ARRAY_SIZE(mdp_vga_vectors),
404 mdp_vga_vectors,
405 },
406 {
407 ARRAY_SIZE(mdp_720p_vectors),
408 mdp_720p_vectors,
409 },
410 {
411 ARRAY_SIZE(mdp_1080p_vectors),
412 mdp_1080p_vectors,
413 },
414};
415#endif
416
417static struct msm_bus_scale_pdata mdp_bus_scale_pdata = {
418 mdp_bus_scale_usecases,
419 ARRAY_SIZE(mdp_bus_scale_usecases),
420 .name = "mdp",
421};
422
423#endif
424
425#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
426static int mdp_core_clk_rate_table[] = {
427 200000000,
428 200000000,
429 200000000,
430 200000000,
431};
432#else
433static int mdp_core_clk_rate_table[] = {
434 85330000,
435 85330000,
436 160000000,
437 200000000,
438};
439#endif
440
441static struct msm_panel_common_pdata mdp_pdata = {
442 .gpio = MDP_VSYNC_GPIO,
443#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
444 .mdp_core_clk_rate = 200000000,
445#else
446 .mdp_core_clk_rate = 85330000,
447#endif
448 .mdp_core_clk_table = mdp_core_clk_rate_table,
449 .num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
450#ifdef CONFIG_MSM_BUS_SCALING
451 .mdp_bus_scale_table = &mdp_bus_scale_pdata,
452#endif
453 .mdp_rev = MDP_REV_42,
454 .writeback_offset = writeback_offset,
Huaibin Yanga5419422011-12-08 23:52:10 -0800455 .mdp_writeback_memtype = MEMTYPE_EBI1,
456 .mdp_writeback_phys = NULL,
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800457};
458
Huaibin Yanga5419422011-12-08 23:52:10 -0800459void __init msm8930_mdp_writeback(struct memtype_reserve* reserve_table)
460{
461 mdp_pdata.mdp_writeback_size_ov0 = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
462 mdp_pdata.mdp_writeback_size_ov1 = MSM_FB_OVERLAY1_WRITEBACK_SIZE;
463
464 reserve_table[mdp_pdata.mdp_writeback_memtype].size +=
465 mdp_pdata.mdp_writeback_size_ov0;
466 reserve_table[mdp_pdata.mdp_writeback_memtype].size +=
467 mdp_pdata.mdp_writeback_size_ov1;
468}
469
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800470#define LPM_CHANNEL0 0
471static int toshiba_gpio[] = {LPM_CHANNEL0};
472
473static struct mipi_dsi_panel_platform_data toshiba_pdata = {
474 .gpio = toshiba_gpio,
475};
476
477static struct platform_device mipi_dsi_toshiba_panel_device = {
478 .name = "mipi_toshiba",
479 .id = 0,
480 .dev = {
481 .platform_data = &toshiba_pdata,
482 }
483};
484
485#define FPGA_3D_GPIO_CONFIG_ADDR 0xB5
486
487static struct mipi_dsi_phy_ctrl dsi_novatek_cmd_mode_phy_db = {
488
489/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
490 {0x0F, 0x0a, 0x04, 0x00, 0x20}, /* regulator */
491 /* timing */
492 {0xab, 0x8a, 0x18, 0x00, 0x92, 0x97, 0x1b, 0x8c,
493 0x0c, 0x03, 0x04, 0xa0},
494 {0x5f, 0x00, 0x00, 0x10}, /* phy ctrl */
495 {0xff, 0x00, 0x06, 0x00}, /* strength */
496 /* pll control */
497 {0x40, 0xf9, 0x30, 0xda, 0x00, 0x40, 0x03, 0x62,
498 0x40, 0x07, 0x03,
499 0x00, 0x1a, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01},
500};
501
502static struct mipi_dsi_panel_platform_data novatek_pdata = {
503 .fpga_3d_config_addr = FPGA_3D_GPIO_CONFIG_ADDR,
504 .fpga_ctrl_mode = FPGA_SPI_INTF,
505 .phy_ctrl_settings = &dsi_novatek_cmd_mode_phy_db,
506};
507
508static struct platform_device mipi_dsi_novatek_panel_device = {
509 .name = "mipi_novatek",
510 .id = 0,
511 .dev = {
512 .platform_data = &novatek_pdata,
513 }
514};
515
516#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
517static struct resource hdmi_msm_resources[] = {
518 {
519 .name = "hdmi_msm_qfprom_addr",
520 .start = 0x00700000,
521 .end = 0x007060FF,
522 .flags = IORESOURCE_MEM,
523 },
524 {
525 .name = "hdmi_msm_hdmi_addr",
526 .start = 0x04A00000,
527 .end = 0x04A00FFF,
528 .flags = IORESOURCE_MEM,
529 },
530 {
531 .name = "hdmi_msm_irq",
532 .start = HDMI_IRQ,
533 .end = HDMI_IRQ,
534 .flags = IORESOURCE_IRQ,
535 },
536};
537
538static int hdmi_enable_5v(int on);
539static int hdmi_core_power(int on, int show);
540static int hdmi_cec_power(int on);
541
542static struct msm_hdmi_platform_data hdmi_msm_data = {
543 .irq = HDMI_IRQ,
544 .enable_5v = hdmi_enable_5v,
545 .core_power = hdmi_core_power,
546 .cec_power = hdmi_cec_power,
547};
548
549static struct platform_device hdmi_msm_device = {
550 .name = "hdmi_msm",
551 .id = 0,
552 .num_resources = ARRAY_SIZE(hdmi_msm_resources),
553 .resource = hdmi_msm_resources,
554 .dev.platform_data = &hdmi_msm_data,
555};
556#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
557
558#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
559static struct platform_device wfd_panel_device = {
560 .name = "wfd_panel",
561 .id = 0,
562 .dev.platform_data = NULL,
563};
564
565static struct platform_device wfd_device = {
566 .name = "msm_wfd",
567 .id = -1,
568};
569#endif
570
571#ifdef CONFIG_MSM_BUS_SCALING
572static struct msm_bus_vectors dtv_bus_init_vectors[] = {
573 {
574 .src = MSM_BUS_MASTER_MDP_PORT0,
575 .dst = MSM_BUS_SLAVE_EBI_CH0,
576 .ab = 0,
577 .ib = 0,
578 },
579};
580
581#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
582static struct msm_bus_vectors dtv_bus_def_vectors[] = {
583 {
584 .src = MSM_BUS_MASTER_MDP_PORT0,
585 .dst = MSM_BUS_SLAVE_EBI_CH0,
586 .ab = 2000000000,
587 .ib = 2000000000,
588 },
589};
590#else
591static struct msm_bus_vectors dtv_bus_def_vectors[] = {
592 {
593 .src = MSM_BUS_MASTER_MDP_PORT0,
594 .dst = MSM_BUS_SLAVE_EBI_CH0,
595 .ab = 566092800 * 2,
596 .ib = 707616000 * 2,
597 },
598};
599#endif
600
601static struct msm_bus_paths dtv_bus_scale_usecases[] = {
602 {
603 ARRAY_SIZE(dtv_bus_init_vectors),
604 dtv_bus_init_vectors,
605 },
606 {
607 ARRAY_SIZE(dtv_bus_def_vectors),
608 dtv_bus_def_vectors,
609 },
610};
611static struct msm_bus_scale_pdata dtv_bus_scale_pdata = {
612 dtv_bus_scale_usecases,
613 ARRAY_SIZE(dtv_bus_scale_usecases),
614 .name = "dtv",
615};
616
617static struct lcdc_platform_data dtv_pdata = {
618 .bus_scale_table = &dtv_bus_scale_pdata,
619};
620#endif
621
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800622#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800623static int hdmi_enable_5v(int on)
624{
625 /* TBD: PM8921 regulator instead of 8901 */
626 static struct regulator *reg_8921_hdmi_mvs; /* HDMI_5V */
627 static int prev_on;
628 int rc;
629
630 if (on == prev_on)
631 return 0;
632
633 if (!reg_8921_hdmi_mvs)
634 reg_8921_hdmi_mvs = regulator_get(&hdmi_msm_device.dev,
635 "hdmi_mvs");
636
637 if (on) {
638 rc = regulator_enable(reg_8921_hdmi_mvs);
639 if (rc) {
640 pr_err("'%s' regulator enable failed, rc=%d\n",
641 "8921_hdmi_mvs", rc);
642 return rc;
643 }
644 pr_debug("%s(on): success\n", __func__);
645 } else {
646 rc = regulator_disable(reg_8921_hdmi_mvs);
647 if (rc)
648 pr_warning("'%s' regulator disable failed, rc=%d\n",
649 "8921_hdmi_mvs", rc);
650 pr_debug("%s(off): success\n", __func__);
651 }
652
653 prev_on = on;
654
655 return 0;
656}
657
658static int hdmi_core_power(int on, int show)
659{
660 static struct regulator *reg_8921_l23, *reg_8921_s4;
661 static int prev_on;
662 int rc;
663
664 if (on == prev_on)
665 return 0;
666
667 /* TBD: PM8921 regulator instead of 8901 */
668 if (!reg_8921_l23) {
669 reg_8921_l23 = regulator_get(&hdmi_msm_device.dev, "hdmi_avdd");
670 if (IS_ERR(reg_8921_l23)) {
671 pr_err("could not get reg_8921_l23, rc = %ld\n",
672 PTR_ERR(reg_8921_l23));
673 return -ENODEV;
674 }
675 rc = regulator_set_voltage(reg_8921_l23, 1800000, 1800000);
676 if (rc) {
677 pr_err("set_voltage failed for 8921_l23, rc=%d\n", rc);
678 return -EINVAL;
679 }
680 }
681 if (!reg_8921_s4) {
682 reg_8921_s4 = regulator_get(&hdmi_msm_device.dev, "hdmi_vcc");
683 if (IS_ERR(reg_8921_s4)) {
684 pr_err("could not get reg_8921_s4, rc = %ld\n",
685 PTR_ERR(reg_8921_s4));
686 return -ENODEV;
687 }
688 rc = regulator_set_voltage(reg_8921_s4, 1800000, 1800000);
689 if (rc) {
690 pr_err("set_voltage failed for 8921_s4, rc=%d\n", rc);
691 return -EINVAL;
692 }
693 }
694
695 if (on) {
696 rc = regulator_set_optimum_mode(reg_8921_l23, 100000);
697 if (rc < 0) {
698 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
699 return -EINVAL;
700 }
701 rc = regulator_enable(reg_8921_l23);
702 if (rc) {
703 pr_err("'%s' regulator enable failed, rc=%d\n",
704 "hdmi_avdd", rc);
705 return rc;
706 }
707 rc = regulator_enable(reg_8921_s4);
708 if (rc) {
709 pr_err("'%s' regulator enable failed, rc=%d\n",
710 "hdmi_vcc", rc);
711 return rc;
712 }
713 rc = gpio_request(100, "HDMI_DDC_CLK");
714 if (rc) {
715 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
716 "HDMI_DDC_CLK", 100, rc);
717 goto error1;
718 }
719 rc = gpio_request(101, "HDMI_DDC_DATA");
720 if (rc) {
721 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
722 "HDMI_DDC_DATA", 101, rc);
723 goto error2;
724 }
725 rc = gpio_request(102, "HDMI_HPD");
726 if (rc) {
727 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
728 "HDMI_HPD", 102, rc);
729 goto error3;
730 }
731 pr_debug("%s(on): success\n", __func__);
732 } else {
733 gpio_free(100);
734 gpio_free(101);
735 gpio_free(102);
736
737 rc = regulator_disable(reg_8921_l23);
738 if (rc) {
739 pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
740 return -ENODEV;
741 }
742 rc = regulator_disable(reg_8921_s4);
743 if (rc) {
744 pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
745 return -ENODEV;
746 }
747 rc = regulator_set_optimum_mode(reg_8921_l23, 100);
748 if (rc < 0) {
749 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
750 return -EINVAL;
751 }
752 pr_debug("%s(off): success\n", __func__);
753 }
754
755 prev_on = on;
756
757 return 0;
758
759error3:
760 gpio_free(101);
761error2:
762 gpio_free(100);
763error1:
764 regulator_disable(reg_8921_l23);
765 regulator_disable(reg_8921_s4);
766 return rc;
767}
768
769static int hdmi_cec_power(int on)
770{
771 static int prev_on;
772 int rc;
773
774 if (on == prev_on)
775 return 0;
776
777 if (on) {
778 rc = gpio_request(99, "HDMI_CEC_VAR");
779 if (rc) {
780 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
781 "HDMI_CEC_VAR", 99, rc);
782 goto error;
783 }
784 pr_debug("%s(on): success\n", __func__);
785 } else {
786 gpio_free(99);
787 pr_debug("%s(off): success\n", __func__);
788 }
789
790 prev_on = on;
791
792 return 0;
793error:
794 return rc;
795}
796#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
797
798void __init msm8930_init_fb(void)
799{
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800800 platform_device_register(&msm_fb_device);
801
802#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
803 platform_device_register(&wfd_panel_device);
804 platform_device_register(&wfd_device);
805#endif
806
807 platform_device_register(&mipi_dsi_novatek_panel_device);
808
809#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
Ajay Dudani52e88232011-12-13 13:33:10 -0800810 if (!cpu_is_msm8930())
Ajay Dudani9114be72011-12-03 07:46:35 -0800811 platform_device_register(&hdmi_msm_device);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800812#endif
813
814 platform_device_register(&mipi_dsi_toshiba_panel_device);
815
816 msm_fb_register_device("mdp", &mdp_pdata);
817 msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
818#ifdef CONFIG_MSM_BUS_SCALING
819 msm_fb_register_device("dtv", &dtv_pdata);
820#endif
821}
822
823void __init msm8930_allocate_fb_region(void)
824{
825 void *addr;
826 unsigned long size;
827
828 size = MSM_FB_SIZE;
829 addr = alloc_bootmem_align(size, 0x1000);
830 msm_fb_resources[0].start = __pa(addr);
831 msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
832 pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
833 size, addr, __pa(addr));
834}