blob: f9bc8fcb3c6dbe68f31e09b8e8d53f5bdecb22f4 [file] [log] [blame]
Nagamalleswararao Ganji70fac1e2011-12-29 19:06:37 -08001/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -08002 *
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>
Huaibin Yang4a084e32011-12-15 15:25:52 -080018#include <linux/ion.h>
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080019#include <asm/mach-types.h>
20#include <mach/msm_bus_board.h>
Huaibin Yanga5419422011-12-08 23:52:10 -080021#include <mach/msm_memtypes.h>
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080022#include <mach/board.h>
23#include <mach/gpio.h>
24#include <mach/gpiomux.h>
Nagamalleswararao Ganji937a1192011-12-07 19:00:52 -080025#include <mach/ion.h>
Amir Samuelov6f1e5002012-02-01 17:42:43 +020026#include <mach/socinfo.h>
Nagamalleswararao Ganji937a1192011-12-07 19:00:52 -080027
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080028#include "devices.h"
Stepan Moskovchenko5a83dba2011-12-05 17:30:17 -080029#include "board-8960.h"
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080030
31#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
Amir Samuelovd7621032011-12-25 12:24:04 +020032#define MSM_FB_PRIM_BUF_SIZE (1920 * 1200 * 4 * 3) /* 4 bpp x 3 pages */
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080033#else
Amir Samuelovd7621032011-12-25 12:24:04 +020034#define MSM_FB_PRIM_BUF_SIZE (1920 * 1200 * 4 * 2) /* 4 bpp x 2 pages */
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080035#endif
36
37#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
38#define MSM_FB_EXT_BUF_SIZE (1920 * 1088 * 2 * 1) /* 2 bpp x 1 page */
39#elif defined(CONFIG_FB_MSM_TVOUT)
40#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
41#else
42#define MSM_FB_EXT_BUF_SIZE 0
43#endif
44
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080045#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
46/* 4 bpp x 2 page HDMI case */
47#define MSM_FB_SIZE roundup((1920 * 1088 * 4 * 2), 4096)
48#else
49/* Note: must be multiple of 4096 */
Huaibin Yang27634b82011-12-09 00:16:25 -080050#define MSM_FB_SIZE roundup(MSM_FB_PRIM_BUF_SIZE + MSM_FB_EXT_BUF_SIZE, 4096)
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080051#endif
52
Huaibin Yanga5419422011-12-08 23:52:10 -080053#ifdef CONFIG_FB_MSM_OVERLAY0_WRITEBACK
Amir Samuelovd7621032011-12-25 12:24:04 +020054#define MSM_FB_OVERLAY0_WRITEBACK_SIZE roundup((1920 * 1200 * 3 * 2), 4096)
Huaibin Yanga5419422011-12-08 23:52:10 -080055#else
56#define MSM_FB_OVERLAY0_WRITEBACK_SIZE (0)
57#endif /* CONFIG_FB_MSM_OVERLAY0_WRITEBACK */
58
59#ifdef CONFIG_FB_MSM_OVERLAY1_WRITEBACK
60#define MSM_FB_OVERLAY1_WRITEBACK_SIZE roundup((1920 * 1088 * 3 * 2), 4096)
61#else
62#define MSM_FB_OVERLAY1_WRITEBACK_SIZE (0)
63#endif /* CONFIG_FB_MSM_OVERLAY1_WRITEBACK */
64
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080065#define MDP_VSYNC_GPIO 0
66
67#define PANEL_NAME_MAX_LEN 30
68#define MIPI_CMD_NOVATEK_QHD_PANEL_NAME "mipi_cmd_novatek_qhd"
69#define MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME "mipi_video_novatek_qhd"
70#define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
71#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
Amir Samuelov6f1e5002012-02-01 17:42:43 +020072#define MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME "mipi_video_chimei_wuxga"
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080073#define MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME "mipi_video_simulator_vga"
74#define MIPI_CMD_RENESAS_FWVGA_PANEL_NAME "mipi_cmd_renesas_fwvga"
75#define HDMI_PANEL_NAME "hdmi_msm"
76#define TVOUT_PANEL_NAME "tvout_msm"
77
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080078static struct resource msm_fb_resources[] = {
79 {
80 .flags = IORESOURCE_DMA,
81 }
82};
83
84static int msm_fb_detect_panel(const char *name)
85{
86 if (machine_is_msm8960_liquid()) {
Amir Samuelov6f1e5002012-02-01 17:42:43 +020087 u32 ver = socinfo_get_platform_version();
88 if (SOCINFO_VERSION_MAJOR(ver) == 3) {
89 if (!strncmp(name, MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
90 strnlen(MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
91 PANEL_NAME_MAX_LEN)))
92 return 0;
93 } else {
94 if (!strncmp(name, MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
95 strnlen(MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
96 PANEL_NAME_MAX_LEN)))
97 return 0;
98 }
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080099 } else {
100 if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
101 strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
102 PANEL_NAME_MAX_LEN)))
103 return 0;
104
105#ifndef CONFIG_FB_MSM_MIPI_PANEL_DETECT
106 if (!strncmp(name, MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
107 strnlen(MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
108 PANEL_NAME_MAX_LEN)))
109 return 0;
110
111 if (!strncmp(name, MIPI_CMD_NOVATEK_QHD_PANEL_NAME,
112 strnlen(MIPI_CMD_NOVATEK_QHD_PANEL_NAME,
113 PANEL_NAME_MAX_LEN)))
114 return 0;
115
116 if (!strncmp(name, MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME,
117 strnlen(MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME,
118 PANEL_NAME_MAX_LEN)))
119 return 0;
120
121 if (!strncmp(name, MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
122 strnlen(MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
123 PANEL_NAME_MAX_LEN)))
124 return 0;
125#endif
126 }
127
128 if (!strncmp(name, HDMI_PANEL_NAME,
129 strnlen(HDMI_PANEL_NAME,
130 PANEL_NAME_MAX_LEN)))
131 return 0;
132
133 if (!strncmp(name, TVOUT_PANEL_NAME,
134 strnlen(TVOUT_PANEL_NAME,
135 PANEL_NAME_MAX_LEN)))
136 return 0;
137
138 pr_warning("%s: not supported '%s'", __func__, name);
139 return -ENODEV;
140}
141
142static struct msm_fb_platform_data msm_fb_pdata = {
143 .detect_client = msm_fb_detect_panel,
144};
145
146static struct platform_device msm_fb_device = {
147 .name = "msm_fb",
148 .id = 0,
149 .num_resources = ARRAY_SIZE(msm_fb_resources),
150 .resource = msm_fb_resources,
151 .dev.platform_data = &msm_fb_pdata,
152};
153
154static bool dsi_power_on;
155
156/**
157 * LiQUID panel on/off
158 *
159 * @param on
160 *
161 * @return int
162 */
163static int mipi_dsi_liquid_panel_power(int on)
164{
165 static struct regulator *reg_l2, *reg_ext_3p3v;
166 static int gpio21, gpio24, gpio43;
167 int rc;
168
Jeff Ohlstein2cbe5ba2011-12-16 13:32:56 -0800169 pr_debug("%s: on=%d\n", __func__, on);
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800170
171 gpio21 = PM8921_GPIO_PM_TO_SYS(21); /* disp power enable_n */
172 gpio43 = PM8921_GPIO_PM_TO_SYS(43); /* Displays Enable (rst_n)*/
173 gpio24 = PM8921_GPIO_PM_TO_SYS(24); /* Backlight PWM */
174
175 if (!dsi_power_on) {
176
177 reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
178 "dsi_vdda");
179 if (IS_ERR(reg_l2)) {
180 pr_err("could not get 8921_l2, rc = %ld\n",
181 PTR_ERR(reg_l2));
182 return -ENODEV;
183 }
184
185 rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
186 if (rc) {
187 pr_err("set_voltage l2 failed, rc=%d\n", rc);
188 return -EINVAL;
189 }
190
191 reg_ext_3p3v = regulator_get(&msm_mipi_dsi1_device.dev,
192 "vdd_lvds_3p3v");
193 if (IS_ERR(reg_ext_3p3v)) {
194 pr_err("could not get reg_ext_3p3v, rc = %ld\n",
195 PTR_ERR(reg_ext_3p3v));
196 return -ENODEV;
197 }
198
199 rc = gpio_request(gpio21, "disp_pwr_en_n");
200 if (rc) {
201 pr_err("request gpio 21 failed, rc=%d\n", rc);
202 return -ENODEV;
203 }
204
205 rc = gpio_request(gpio43, "disp_rst_n");
206 if (rc) {
207 pr_err("request gpio 43 failed, rc=%d\n", rc);
208 return -ENODEV;
209 }
210
211 rc = gpio_request(gpio24, "disp_backlight_pwm");
212 if (rc) {
213 pr_err("request gpio 24 failed, rc=%d\n", rc);
214 return -ENODEV;
215 }
216
217 dsi_power_on = true;
218 }
219
220 if (on) {
221 rc = regulator_set_optimum_mode(reg_l2, 100000);
222 if (rc < 0) {
223 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
224 return -EINVAL;
225 }
226 rc = regulator_enable(reg_l2);
227 if (rc) {
228 pr_err("enable l2 failed, rc=%d\n", rc);
229 return -ENODEV;
230 }
231
232 rc = regulator_enable(reg_ext_3p3v);
233 if (rc) {
234 pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
235 return -ENODEV;
236 }
237
238 /* set reset pin before power enable */
239 gpio_set_value_cansleep(gpio43, 0); /* disp disable (resx=0) */
240
241 gpio_set_value_cansleep(gpio21, 0); /* disp power enable_n */
242 msleep(20);
243 gpio_set_value_cansleep(gpio43, 1); /* disp enable */
244 msleep(20);
245 gpio_set_value_cansleep(gpio43, 0); /* disp enable */
246 msleep(20);
247 gpio_set_value_cansleep(gpio43, 1); /* disp enable */
248 msleep(20);
249 } else {
250 gpio_set_value_cansleep(gpio43, 0);
251 gpio_set_value_cansleep(gpio21, 1);
252
253 rc = regulator_disable(reg_l2);
254 if (rc) {
255 pr_err("disable reg_l2 failed, rc=%d\n", rc);
256 return -ENODEV;
257 }
258 rc = regulator_disable(reg_ext_3p3v);
259 if (rc) {
260 pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
261 return -ENODEV;
262 }
263 rc = regulator_set_optimum_mode(reg_l2, 100);
264 if (rc < 0) {
265 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
266 return -EINVAL;
267 }
268 }
269
270 return 0;
271}
272
273static int mipi_dsi_cdp_panel_power(int on)
274{
275 static struct regulator *reg_l8, *reg_l23, *reg_l2;
276 static int gpio43;
277 int rc;
278
Jeff Ohlstein2cbe5ba2011-12-16 13:32:56 -0800279 pr_debug("%s: state : %d\n", __func__, on);
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800280
281 if (!dsi_power_on) {
282
283 reg_l8 = regulator_get(&msm_mipi_dsi1_device.dev,
284 "dsi_vdc");
285 if (IS_ERR(reg_l8)) {
286 pr_err("could not get 8921_l8, rc = %ld\n",
287 PTR_ERR(reg_l8));
288 return -ENODEV;
289 }
290 reg_l23 = regulator_get(&msm_mipi_dsi1_device.dev,
291 "dsi_vddio");
292 if (IS_ERR(reg_l23)) {
293 pr_err("could not get 8921_l23, rc = %ld\n",
294 PTR_ERR(reg_l23));
295 return -ENODEV;
296 }
297 reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
298 "dsi_vdda");
299 if (IS_ERR(reg_l2)) {
300 pr_err("could not get 8921_l2, rc = %ld\n",
301 PTR_ERR(reg_l2));
302 return -ENODEV;
303 }
304 rc = regulator_set_voltage(reg_l8, 2800000, 3000000);
305 if (rc) {
306 pr_err("set_voltage l8 failed, rc=%d\n", rc);
307 return -EINVAL;
308 }
309 rc = regulator_set_voltage(reg_l23, 1800000, 1800000);
310 if (rc) {
311 pr_err("set_voltage l23 failed, rc=%d\n", rc);
312 return -EINVAL;
313 }
314 rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
315 if (rc) {
316 pr_err("set_voltage l2 failed, rc=%d\n", rc);
317 return -EINVAL;
318 }
319 gpio43 = PM8921_GPIO_PM_TO_SYS(43);
320 rc = gpio_request(gpio43, "disp_rst_n");
321 if (rc) {
322 pr_err("request gpio 43 failed, rc=%d\n", rc);
323 return -ENODEV;
324 }
325 dsi_power_on = true;
326 }
327 if (on) {
328 rc = regulator_set_optimum_mode(reg_l8, 100000);
329 if (rc < 0) {
330 pr_err("set_optimum_mode l8 failed, rc=%d\n", rc);
331 return -EINVAL;
332 }
333 rc = regulator_set_optimum_mode(reg_l23, 100000);
334 if (rc < 0) {
335 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
336 return -EINVAL;
337 }
338 rc = regulator_set_optimum_mode(reg_l2, 100000);
339 if (rc < 0) {
340 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
341 return -EINVAL;
342 }
343 rc = regulator_enable(reg_l8);
344 if (rc) {
345 pr_err("enable l8 failed, rc=%d\n", rc);
346 return -ENODEV;
347 }
348 rc = regulator_enable(reg_l23);
349 if (rc) {
350 pr_err("enable l8 failed, rc=%d\n", rc);
351 return -ENODEV;
352 }
353 rc = regulator_enable(reg_l2);
354 if (rc) {
355 pr_err("enable l2 failed, rc=%d\n", rc);
356 return -ENODEV;
357 }
358 gpio_set_value_cansleep(gpio43, 1);
359 } else {
360 rc = regulator_disable(reg_l2);
361 if (rc) {
362 pr_err("disable reg_l2 failed, rc=%d\n", rc);
363 return -ENODEV;
364 }
365 rc = regulator_disable(reg_l8);
366 if (rc) {
367 pr_err("disable reg_l8 failed, rc=%d\n", rc);
368 return -ENODEV;
369 }
370 rc = regulator_disable(reg_l23);
371 if (rc) {
372 pr_err("disable reg_l23 failed, rc=%d\n", rc);
373 return -ENODEV;
374 }
375 rc = regulator_set_optimum_mode(reg_l8, 100);
376 if (rc < 0) {
377 pr_err("set_optimum_mode l8 failed, rc=%d\n", rc);
378 return -EINVAL;
379 }
380 rc = regulator_set_optimum_mode(reg_l23, 100);
381 if (rc < 0) {
382 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
383 return -EINVAL;
384 }
385 rc = regulator_set_optimum_mode(reg_l2, 100);
386 if (rc < 0) {
387 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
388 return -EINVAL;
389 }
390 gpio_set_value_cansleep(gpio43, 0);
391 }
392 return 0;
393}
394
395static int mipi_dsi_panel_power(int on)
396{
397 int ret;
398
Jeff Ohlstein2cbe5ba2011-12-16 13:32:56 -0800399 pr_debug("%s: on=%d\n", __func__, on);
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800400
401 if (machine_is_msm8960_liquid())
402 ret = mipi_dsi_liquid_panel_power(on);
403 else
404 ret = mipi_dsi_cdp_panel_power(on);
405
406 return ret;
407}
408
409static struct mipi_dsi_platform_data mipi_dsi_pdata = {
410 .vsync_gpio = MDP_VSYNC_GPIO,
411 .dsi_power_save = mipi_dsi_panel_power,
412};
413
414#ifdef CONFIG_MSM_BUS_SCALING
415
Nagamalleswararao Ganji5fabbd62011-11-06 23:10:43 -0800416static struct msm_bus_vectors rotator_init_vectors[] = {
417 {
418 .src = MSM_BUS_MASTER_ROTATOR,
419 .dst = MSM_BUS_SLAVE_EBI_CH0,
420 .ab = 0,
421 .ib = 0,
422 },
423};
424
425static struct msm_bus_vectors rotator_ui_vectors[] = {
426 {
427 .src = MSM_BUS_MASTER_ROTATOR,
428 .dst = MSM_BUS_SLAVE_EBI_CH0,
429 .ab = (1024 * 600 * 4 * 2 * 60),
430 .ib = (1024 * 600 * 4 * 2 * 60 * 1.5),
431 },
432};
433
434static struct msm_bus_vectors rotator_vga_vectors[] = {
435 {
436 .src = MSM_BUS_MASTER_ROTATOR,
437 .dst = MSM_BUS_SLAVE_EBI_CH0,
438 .ab = (640 * 480 * 2 * 2 * 30),
439 .ib = (640 * 480 * 2 * 2 * 30 * 1.5),
440 },
441};
442static struct msm_bus_vectors rotator_720p_vectors[] = {
443 {
444 .src = MSM_BUS_MASTER_ROTATOR,
445 .dst = MSM_BUS_SLAVE_EBI_CH0,
446 .ab = (1280 * 736 * 2 * 2 * 30),
447 .ib = (1280 * 736 * 2 * 2 * 30 * 1.5),
448 },
449};
450
451static struct msm_bus_vectors rotator_1080p_vectors[] = {
452 {
453 .src = MSM_BUS_MASTER_ROTATOR,
454 .dst = MSM_BUS_SLAVE_EBI_CH0,
455 .ab = (1920 * 1088 * 2 * 2 * 30),
456 .ib = (1920 * 1088 * 2 * 2 * 30 * 1.5),
457 },
458};
459
460static struct msm_bus_paths rotator_bus_scale_usecases[] = {
461 {
462 ARRAY_SIZE(rotator_init_vectors),
463 rotator_init_vectors,
464 },
465 {
466 ARRAY_SIZE(rotator_ui_vectors),
467 rotator_ui_vectors,
468 },
469 {
470 ARRAY_SIZE(rotator_vga_vectors),
471 rotator_vga_vectors,
472 },
473 {
474 ARRAY_SIZE(rotator_720p_vectors),
475 rotator_720p_vectors,
476 },
477 {
478 ARRAY_SIZE(rotator_1080p_vectors),
479 rotator_1080p_vectors,
480 },
481};
482
483struct msm_bus_scale_pdata rotator_bus_scale_pdata = {
484 rotator_bus_scale_usecases,
485 ARRAY_SIZE(rotator_bus_scale_usecases),
486 .name = "rotator",
487};
488
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800489static struct msm_bus_vectors mdp_init_vectors[] = {
490 {
491 .src = MSM_BUS_MASTER_MDP_PORT0,
492 .dst = MSM_BUS_SLAVE_EBI_CH0,
493 .ab = 0,
494 .ib = 0,
495 },
496};
497
498#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
499static struct msm_bus_vectors hdmi_as_primary_vectors[] = {
500 /* If HDMI is used as primary */
501 {
502 .src = MSM_BUS_MASTER_MDP_PORT0,
503 .dst = MSM_BUS_SLAVE_EBI_CH0,
504 .ab = 2000000000,
505 .ib = 2000000000,
506 },
507};
508static struct msm_bus_paths mdp_bus_scale_usecases[] = {
509 {
510 ARRAY_SIZE(mdp_init_vectors),
511 mdp_init_vectors,
512 },
513 {
514 ARRAY_SIZE(hdmi_as_primary_vectors),
515 hdmi_as_primary_vectors,
516 },
517 {
518 ARRAY_SIZE(hdmi_as_primary_vectors),
519 hdmi_as_primary_vectors,
520 },
521 {
522 ARRAY_SIZE(hdmi_as_primary_vectors),
523 hdmi_as_primary_vectors,
524 },
525 {
526 ARRAY_SIZE(hdmi_as_primary_vectors),
527 hdmi_as_primary_vectors,
528 },
529 {
530 ARRAY_SIZE(hdmi_as_primary_vectors),
531 hdmi_as_primary_vectors,
532 },
533};
534#else
535static struct msm_bus_vectors mdp_ui_vectors[] = {
536 {
537 .src = MSM_BUS_MASTER_MDP_PORT0,
538 .dst = MSM_BUS_SLAVE_EBI_CH0,
539 .ab = 216000000 * 2,
540 .ib = 270000000 * 2,
541 },
542};
543
544static struct msm_bus_vectors mdp_vga_vectors[] = {
545 /* VGA and less video */
546 {
547 .src = MSM_BUS_MASTER_MDP_PORT0,
548 .dst = MSM_BUS_SLAVE_EBI_CH0,
549 .ab = 216000000 * 2,
550 .ib = 270000000 * 2,
551 },
552};
553
554static struct msm_bus_vectors mdp_720p_vectors[] = {
555 /* 720p and less video */
556 {
557 .src = MSM_BUS_MASTER_MDP_PORT0,
558 .dst = MSM_BUS_SLAVE_EBI_CH0,
559 .ab = 230400000 * 2,
560 .ib = 288000000 * 2,
561 },
562};
563
564static struct msm_bus_vectors mdp_1080p_vectors[] = {
565 /* 1080p and less video */
566 {
567 .src = MSM_BUS_MASTER_MDP_PORT0,
568 .dst = MSM_BUS_SLAVE_EBI_CH0,
569 .ab = 334080000 * 2,
570 .ib = 417600000 * 2,
571 },
572};
573
574static struct msm_bus_paths mdp_bus_scale_usecases[] = {
575 {
576 ARRAY_SIZE(mdp_init_vectors),
577 mdp_init_vectors,
578 },
579 {
580 ARRAY_SIZE(mdp_ui_vectors),
581 mdp_ui_vectors,
582 },
583 {
584 ARRAY_SIZE(mdp_ui_vectors),
585 mdp_ui_vectors,
586 },
587 {
588 ARRAY_SIZE(mdp_vga_vectors),
589 mdp_vga_vectors,
590 },
591 {
592 ARRAY_SIZE(mdp_720p_vectors),
593 mdp_720p_vectors,
594 },
595 {
596 ARRAY_SIZE(mdp_1080p_vectors),
597 mdp_1080p_vectors,
598 },
599};
600#endif
601
602static struct msm_bus_scale_pdata mdp_bus_scale_pdata = {
603 mdp_bus_scale_usecases,
604 ARRAY_SIZE(mdp_bus_scale_usecases),
605 .name = "mdp",
606};
607
608#endif
609
610#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
Stepan Moskovchenkofc70d902011-11-30 12:39:36 -0800611static int mdp_core_clk_rate_table[] = {
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800612 200000000,
613 200000000,
614 200000000,
615 200000000,
616};
617#else
Stepan Moskovchenkofc70d902011-11-30 12:39:36 -0800618static int mdp_core_clk_rate_table[] = {
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800619 85330000,
620 85330000,
621 160000000,
622 200000000,
623};
624#endif
625
626static struct msm_panel_common_pdata mdp_pdata = {
627 .gpio = MDP_VSYNC_GPIO,
628#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
629 .mdp_core_clk_rate = 200000000,
630#else
631 .mdp_core_clk_rate = 85330000,
632#endif
633 .mdp_core_clk_table = mdp_core_clk_rate_table,
634 .num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
635#ifdef CONFIG_MSM_BUS_SCALING
636 .mdp_bus_scale_table = &mdp_bus_scale_pdata,
637#endif
638 .mdp_rev = MDP_REV_42,
Nagamalleswararao Ganji937a1192011-12-07 19:00:52 -0800639#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
640 .mem_hid = ION_CP_MM_HEAP_ID,
641#else
642 .mem_hid = MEMTYPE_EBI1,
643#endif
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800644};
645
Huaibin Yanga5419422011-12-08 23:52:10 -0800646void __init msm8960_mdp_writeback(struct memtype_reserve* reserve_table)
647{
Nagamalleswararao Ganji937a1192011-12-07 19:00:52 -0800648 mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
649 mdp_pdata.ov1_wb_size = MSM_FB_OVERLAY1_WRITEBACK_SIZE;
650#if defined(CONFIG_ANDROID_PMEM) && !defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
651 reserve_table[mdp_pdata.mem_hid].size +=
652 mdp_pdata.ov0_wb_size;
653 reserve_table[mdp_pdata.mem_hid].size +=
654 mdp_pdata.ov1_wb_size;
655#endif
Huaibin Yanga5419422011-12-08 23:52:10 -0800656}
657
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800658static struct platform_device mipi_dsi_renesas_panel_device = {
659 .name = "mipi_renesas",
660 .id = 0,
661};
662
663static struct platform_device mipi_dsi_simulator_panel_device = {
664 .name = "mipi_simulator",
665 .id = 0,
666};
667
668#define LPM_CHANNEL0 0
669static int toshiba_gpio[] = {LPM_CHANNEL0};
670
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
683#define FPGA_3D_GPIO_CONFIG_ADDR 0xB5
684static int dsi2lvds_gpio[2] = {
685 0,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
686 0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
687 };
688
689static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
690 .gpio_num = dsi2lvds_gpio,
691};
692
693static struct mipi_dsi_phy_ctrl dsi_novatek_cmd_mode_phy_db = {
694
695/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
696 {0x0F, 0x0a, 0x04, 0x00, 0x20}, /* regulator */
697 /* timing */
698 {0xab, 0x8a, 0x18, 0x00, 0x92, 0x97, 0x1b, 0x8c,
699 0x0c, 0x03, 0x04, 0xa0},
700 {0x5f, 0x00, 0x00, 0x10}, /* phy ctrl */
701 {0xff, 0x00, 0x06, 0x00}, /* strength */
702 /* pll control */
703 {0x40, 0xf9, 0x30, 0xda, 0x00, 0x40, 0x03, 0x62,
704 0x40, 0x07, 0x03,
705 0x00, 0x1a, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01},
706};
707
708static struct mipi_dsi_panel_platform_data novatek_pdata = {
709 .fpga_3d_config_addr = FPGA_3D_GPIO_CONFIG_ADDR,
710 .fpga_ctrl_mode = FPGA_SPI_INTF,
711 .phy_ctrl_settings = &dsi_novatek_cmd_mode_phy_db,
712};
713
714static struct platform_device mipi_dsi_novatek_panel_device = {
715 .name = "mipi_novatek",
716 .id = 0,
717 .dev = {
718 .platform_data = &novatek_pdata,
719 }
720};
721
722static struct platform_device mipi_dsi2lvds_bridge_device = {
723 .name = "mipi_tc358764",
724 .id = 0,
725 .dev.platform_data = &mipi_dsi2lvds_pdata,
726};
727
728#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
729static struct resource hdmi_msm_resources[] = {
730 {
731 .name = "hdmi_msm_qfprom_addr",
732 .start = 0x00700000,
733 .end = 0x007060FF,
734 .flags = IORESOURCE_MEM,
735 },
736 {
737 .name = "hdmi_msm_hdmi_addr",
738 .start = 0x04A00000,
739 .end = 0x04A00FFF,
740 .flags = IORESOURCE_MEM,
741 },
742 {
743 .name = "hdmi_msm_irq",
744 .start = HDMI_IRQ,
745 .end = HDMI_IRQ,
746 .flags = IORESOURCE_IRQ,
747 },
748};
749
750static int hdmi_enable_5v(int on);
751static int hdmi_core_power(int on, int show);
752static int hdmi_cec_power(int on);
753
754static struct msm_hdmi_platform_data hdmi_msm_data = {
755 .irq = HDMI_IRQ,
756 .enable_5v = hdmi_enable_5v,
757 .core_power = hdmi_core_power,
758 .cec_power = hdmi_cec_power,
759};
760
761static struct platform_device hdmi_msm_device = {
762 .name = "hdmi_msm",
763 .id = 0,
764 .num_resources = ARRAY_SIZE(hdmi_msm_resources),
765 .resource = hdmi_msm_resources,
766 .dev.platform_data = &hdmi_msm_data,
767};
768#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
769
770#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
771static struct platform_device wfd_panel_device = {
772 .name = "wfd_panel",
773 .id = 0,
774 .dev.platform_data = NULL,
775};
Stepan Moskovchenko270888d2011-11-30 12:19:11 -0800776
777static struct platform_device wfd_device = {
778 .name = "msm_wfd",
779 .id = -1,
780};
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800781#endif
782
783#ifdef CONFIG_MSM_BUS_SCALING
784static struct msm_bus_vectors dtv_bus_init_vectors[] = {
785 {
786 .src = MSM_BUS_MASTER_MDP_PORT0,
787 .dst = MSM_BUS_SLAVE_EBI_CH0,
788 .ab = 0,
789 .ib = 0,
790 },
791};
792
793#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
794static struct msm_bus_vectors dtv_bus_def_vectors[] = {
795 {
796 .src = MSM_BUS_MASTER_MDP_PORT0,
797 .dst = MSM_BUS_SLAVE_EBI_CH0,
798 .ab = 2000000000,
799 .ib = 2000000000,
800 },
801};
802#else
803static struct msm_bus_vectors dtv_bus_def_vectors[] = {
804 {
805 .src = MSM_BUS_MASTER_MDP_PORT0,
806 .dst = MSM_BUS_SLAVE_EBI_CH0,
807 .ab = 566092800 * 2,
808 .ib = 707616000 * 2,
809 },
810};
811#endif
812
813static struct msm_bus_paths dtv_bus_scale_usecases[] = {
814 {
815 ARRAY_SIZE(dtv_bus_init_vectors),
816 dtv_bus_init_vectors,
817 },
818 {
819 ARRAY_SIZE(dtv_bus_def_vectors),
820 dtv_bus_def_vectors,
821 },
822};
823static struct msm_bus_scale_pdata dtv_bus_scale_pdata = {
824 dtv_bus_scale_usecases,
825 ARRAY_SIZE(dtv_bus_scale_usecases),
826 .name = "dtv",
827};
828
829static struct lcdc_platform_data dtv_pdata = {
830 .bus_scale_table = &dtv_bus_scale_pdata,
831};
832#endif
833
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800834#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800835static int hdmi_enable_5v(int on)
836{
837 /* TBD: PM8921 regulator instead of 8901 */
838 static struct regulator *reg_8921_hdmi_mvs; /* HDMI_5V */
839 static int prev_on;
840 int rc;
841
842 if (on == prev_on)
843 return 0;
844
845 if (!reg_8921_hdmi_mvs)
846 reg_8921_hdmi_mvs = regulator_get(&hdmi_msm_device.dev,
847 "hdmi_mvs");
848
849 if (on) {
850 rc = regulator_enable(reg_8921_hdmi_mvs);
851 if (rc) {
852 pr_err("'%s' regulator enable failed, rc=%d\n",
853 "8921_hdmi_mvs", rc);
854 return rc;
855 }
856 pr_debug("%s(on): success\n", __func__);
857 } else {
858 rc = regulator_disable(reg_8921_hdmi_mvs);
859 if (rc)
860 pr_warning("'%s' regulator disable failed, rc=%d\n",
861 "8921_hdmi_mvs", rc);
862 pr_debug("%s(off): success\n", __func__);
863 }
864
865 prev_on = on;
866
867 return 0;
868}
869
870static int hdmi_core_power(int on, int show)
871{
872 static struct regulator *reg_8921_l23, *reg_8921_s4;
873 static int prev_on;
874 int rc;
875
876 if (on == prev_on)
877 return 0;
878
879 /* TBD: PM8921 regulator instead of 8901 */
880 if (!reg_8921_l23) {
881 reg_8921_l23 = regulator_get(&hdmi_msm_device.dev, "hdmi_avdd");
882 if (IS_ERR(reg_8921_l23)) {
883 pr_err("could not get reg_8921_l23, rc = %ld\n",
884 PTR_ERR(reg_8921_l23));
885 return -ENODEV;
886 }
887 rc = regulator_set_voltage(reg_8921_l23, 1800000, 1800000);
888 if (rc) {
889 pr_err("set_voltage failed for 8921_l23, rc=%d\n", rc);
890 return -EINVAL;
891 }
892 }
893 if (!reg_8921_s4) {
894 reg_8921_s4 = regulator_get(&hdmi_msm_device.dev, "hdmi_vcc");
895 if (IS_ERR(reg_8921_s4)) {
896 pr_err("could not get reg_8921_s4, rc = %ld\n",
897 PTR_ERR(reg_8921_s4));
898 return -ENODEV;
899 }
900 rc = regulator_set_voltage(reg_8921_s4, 1800000, 1800000);
901 if (rc) {
902 pr_err("set_voltage failed for 8921_s4, rc=%d\n", rc);
903 return -EINVAL;
904 }
905 }
906
907 if (on) {
908 rc = regulator_set_optimum_mode(reg_8921_l23, 100000);
909 if (rc < 0) {
910 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
911 return -EINVAL;
912 }
913 rc = regulator_enable(reg_8921_l23);
914 if (rc) {
915 pr_err("'%s' regulator enable failed, rc=%d\n",
916 "hdmi_avdd", rc);
917 return rc;
918 }
919 rc = regulator_enable(reg_8921_s4);
920 if (rc) {
921 pr_err("'%s' regulator enable failed, rc=%d\n",
922 "hdmi_vcc", rc);
923 return rc;
924 }
925 rc = gpio_request(100, "HDMI_DDC_CLK");
926 if (rc) {
927 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
928 "HDMI_DDC_CLK", 100, rc);
929 goto error1;
930 }
931 rc = gpio_request(101, "HDMI_DDC_DATA");
932 if (rc) {
933 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
934 "HDMI_DDC_DATA", 101, rc);
935 goto error2;
936 }
937 rc = gpio_request(102, "HDMI_HPD");
938 if (rc) {
939 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
940 "HDMI_HPD", 102, rc);
941 goto error3;
942 }
943 pr_debug("%s(on): success\n", __func__);
944 } else {
945 gpio_free(100);
946 gpio_free(101);
947 gpio_free(102);
948
949 rc = regulator_disable(reg_8921_l23);
950 if (rc) {
951 pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
952 return -ENODEV;
953 }
954 rc = regulator_disable(reg_8921_s4);
955 if (rc) {
956 pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
957 return -ENODEV;
958 }
959 rc = regulator_set_optimum_mode(reg_8921_l23, 100);
960 if (rc < 0) {
961 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
962 return -EINVAL;
963 }
964 pr_debug("%s(off): success\n", __func__);
965 }
966
967 prev_on = on;
968
969 return 0;
970
971error3:
972 gpio_free(101);
973error2:
974 gpio_free(100);
975error1:
976 regulator_disable(reg_8921_l23);
977 regulator_disable(reg_8921_s4);
978 return rc;
979}
980
981static int hdmi_cec_power(int on)
982{
983 static int prev_on;
984 int rc;
985
986 if (on == prev_on)
987 return 0;
988
989 if (on) {
990 rc = gpio_request(99, "HDMI_CEC_VAR");
991 if (rc) {
992 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
993 "HDMI_CEC_VAR", 99, rc);
994 goto error;
995 }
996 pr_debug("%s(on): success\n", __func__);
997 } else {
998 gpio_free(99);
999 pr_debug("%s(off): success\n", __func__);
1000 }
1001
1002 prev_on = on;
1003
1004 return 0;
1005error:
1006 return rc;
1007}
1008#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
1009
1010void __init msm8960_init_fb(void)
1011{
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -08001012 platform_device_register(&msm_fb_device);
1013
Stepan Moskovchenko270888d2011-11-30 12:19:11 -08001014#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
1015 platform_device_register(&wfd_panel_device);
1016 platform_device_register(&wfd_device);
1017#endif
1018
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -08001019 if (machine_is_msm8960_sim())
1020 platform_device_register(&mipi_dsi_simulator_panel_device);
1021
1022 if (machine_is_msm8960_rumi3())
1023 platform_device_register(&mipi_dsi_renesas_panel_device);
1024
1025 if (!machine_is_msm8960_sim() && !machine_is_msm8960_rumi3()) {
1026 platform_device_register(&mipi_dsi_novatek_panel_device);
1027
1028#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
1029 platform_device_register(&hdmi_msm_device);
1030#endif
1031 }
1032
1033 if (machine_is_msm8960_liquid())
1034 platform_device_register(&mipi_dsi2lvds_bridge_device);
1035 else
1036 platform_device_register(&mipi_dsi_toshiba_panel_device);
1037
1038 if (machine_is_msm8x60_rumi3()) {
1039 msm_fb_register_device("mdp", NULL);
1040 mipi_dsi_pdata.target_type = 1;
1041 } else
1042 msm_fb_register_device("mdp", &mdp_pdata);
1043 msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
1044#ifdef CONFIG_MSM_BUS_SCALING
1045 msm_fb_register_device("dtv", &dtv_pdata);
1046#endif
1047}
1048
1049void __init msm8960_allocate_fb_region(void)
1050{
1051 void *addr;
1052 unsigned long size;
1053
1054 size = MSM_FB_SIZE;
1055 addr = alloc_bootmem_align(size, 0x1000);
1056 msm_fb_resources[0].start = __pa(addr);
1057 msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
1058 pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
1059 size, addr, __pa(addr));
1060}