blob: fb78ce753d12568cd43849ae903a899796a805fc [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
Amir Samuelovca199b92012-01-31 14:50:04 +0200684static int dsi2lvds_gpio[4] = {
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800685 0,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
Amir Samuelovca199b92012-01-31 14:50:04 +0200686 0x1F08, /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
687 GPIO_LIQUID_EXPANDER_BASE+6, /* TN Enable */
688 GPIO_LIQUID_EXPANDER_BASE+7, /* TN Mode */
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800689 };
690
691static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
692 .gpio_num = dsi2lvds_gpio,
693};
694
695static struct mipi_dsi_phy_ctrl dsi_novatek_cmd_mode_phy_db = {
696
697/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
698 {0x0F, 0x0a, 0x04, 0x00, 0x20}, /* regulator */
699 /* timing */
700 {0xab, 0x8a, 0x18, 0x00, 0x92, 0x97, 0x1b, 0x8c,
701 0x0c, 0x03, 0x04, 0xa0},
702 {0x5f, 0x00, 0x00, 0x10}, /* phy ctrl */
703 {0xff, 0x00, 0x06, 0x00}, /* strength */
704 /* pll control */
705 {0x40, 0xf9, 0x30, 0xda, 0x00, 0x40, 0x03, 0x62,
706 0x40, 0x07, 0x03,
707 0x00, 0x1a, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01},
708};
709
710static struct mipi_dsi_panel_platform_data novatek_pdata = {
711 .fpga_3d_config_addr = FPGA_3D_GPIO_CONFIG_ADDR,
712 .fpga_ctrl_mode = FPGA_SPI_INTF,
713 .phy_ctrl_settings = &dsi_novatek_cmd_mode_phy_db,
714};
715
716static struct platform_device mipi_dsi_novatek_panel_device = {
717 .name = "mipi_novatek",
718 .id = 0,
719 .dev = {
720 .platform_data = &novatek_pdata,
721 }
722};
723
724static struct platform_device mipi_dsi2lvds_bridge_device = {
725 .name = "mipi_tc358764",
726 .id = 0,
727 .dev.platform_data = &mipi_dsi2lvds_pdata,
728};
729
730#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
731static struct resource hdmi_msm_resources[] = {
732 {
733 .name = "hdmi_msm_qfprom_addr",
734 .start = 0x00700000,
735 .end = 0x007060FF,
736 .flags = IORESOURCE_MEM,
737 },
738 {
739 .name = "hdmi_msm_hdmi_addr",
740 .start = 0x04A00000,
741 .end = 0x04A00FFF,
742 .flags = IORESOURCE_MEM,
743 },
744 {
745 .name = "hdmi_msm_irq",
746 .start = HDMI_IRQ,
747 .end = HDMI_IRQ,
748 .flags = IORESOURCE_IRQ,
749 },
750};
751
752static int hdmi_enable_5v(int on);
753static int hdmi_core_power(int on, int show);
754static int hdmi_cec_power(int on);
755
756static struct msm_hdmi_platform_data hdmi_msm_data = {
757 .irq = HDMI_IRQ,
758 .enable_5v = hdmi_enable_5v,
759 .core_power = hdmi_core_power,
760 .cec_power = hdmi_cec_power,
761};
762
763static struct platform_device hdmi_msm_device = {
764 .name = "hdmi_msm",
765 .id = 0,
766 .num_resources = ARRAY_SIZE(hdmi_msm_resources),
767 .resource = hdmi_msm_resources,
768 .dev.platform_data = &hdmi_msm_data,
769};
770#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
771
772#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
773static struct platform_device wfd_panel_device = {
774 .name = "wfd_panel",
775 .id = 0,
776 .dev.platform_data = NULL,
777};
Stepan Moskovchenko270888d2011-11-30 12:19:11 -0800778
779static struct platform_device wfd_device = {
780 .name = "msm_wfd",
781 .id = -1,
782};
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800783#endif
784
785#ifdef CONFIG_MSM_BUS_SCALING
786static struct msm_bus_vectors dtv_bus_init_vectors[] = {
787 {
788 .src = MSM_BUS_MASTER_MDP_PORT0,
789 .dst = MSM_BUS_SLAVE_EBI_CH0,
790 .ab = 0,
791 .ib = 0,
792 },
793};
794
795#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
796static struct msm_bus_vectors dtv_bus_def_vectors[] = {
797 {
798 .src = MSM_BUS_MASTER_MDP_PORT0,
799 .dst = MSM_BUS_SLAVE_EBI_CH0,
800 .ab = 2000000000,
801 .ib = 2000000000,
802 },
803};
804#else
805static struct msm_bus_vectors dtv_bus_def_vectors[] = {
806 {
807 .src = MSM_BUS_MASTER_MDP_PORT0,
808 .dst = MSM_BUS_SLAVE_EBI_CH0,
809 .ab = 566092800 * 2,
810 .ib = 707616000 * 2,
811 },
812};
813#endif
814
815static struct msm_bus_paths dtv_bus_scale_usecases[] = {
816 {
817 ARRAY_SIZE(dtv_bus_init_vectors),
818 dtv_bus_init_vectors,
819 },
820 {
821 ARRAY_SIZE(dtv_bus_def_vectors),
822 dtv_bus_def_vectors,
823 },
824};
825static struct msm_bus_scale_pdata dtv_bus_scale_pdata = {
826 dtv_bus_scale_usecases,
827 ARRAY_SIZE(dtv_bus_scale_usecases),
828 .name = "dtv",
829};
830
831static struct lcdc_platform_data dtv_pdata = {
832 .bus_scale_table = &dtv_bus_scale_pdata,
833};
834#endif
835
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800836#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800837static int hdmi_enable_5v(int on)
838{
839 /* TBD: PM8921 regulator instead of 8901 */
840 static struct regulator *reg_8921_hdmi_mvs; /* HDMI_5V */
841 static int prev_on;
842 int rc;
843
844 if (on == prev_on)
845 return 0;
846
847 if (!reg_8921_hdmi_mvs)
848 reg_8921_hdmi_mvs = regulator_get(&hdmi_msm_device.dev,
849 "hdmi_mvs");
850
851 if (on) {
852 rc = regulator_enable(reg_8921_hdmi_mvs);
853 if (rc) {
854 pr_err("'%s' regulator enable failed, rc=%d\n",
855 "8921_hdmi_mvs", rc);
856 return rc;
857 }
858 pr_debug("%s(on): success\n", __func__);
859 } else {
860 rc = regulator_disable(reg_8921_hdmi_mvs);
861 if (rc)
862 pr_warning("'%s' regulator disable failed, rc=%d\n",
863 "8921_hdmi_mvs", rc);
864 pr_debug("%s(off): success\n", __func__);
865 }
866
867 prev_on = on;
868
869 return 0;
870}
871
872static int hdmi_core_power(int on, int show)
873{
874 static struct regulator *reg_8921_l23, *reg_8921_s4;
875 static int prev_on;
876 int rc;
877
878 if (on == prev_on)
879 return 0;
880
881 /* TBD: PM8921 regulator instead of 8901 */
882 if (!reg_8921_l23) {
883 reg_8921_l23 = regulator_get(&hdmi_msm_device.dev, "hdmi_avdd");
884 if (IS_ERR(reg_8921_l23)) {
885 pr_err("could not get reg_8921_l23, rc = %ld\n",
886 PTR_ERR(reg_8921_l23));
887 return -ENODEV;
888 }
889 rc = regulator_set_voltage(reg_8921_l23, 1800000, 1800000);
890 if (rc) {
891 pr_err("set_voltage failed for 8921_l23, rc=%d\n", rc);
892 return -EINVAL;
893 }
894 }
895 if (!reg_8921_s4) {
896 reg_8921_s4 = regulator_get(&hdmi_msm_device.dev, "hdmi_vcc");
897 if (IS_ERR(reg_8921_s4)) {
898 pr_err("could not get reg_8921_s4, rc = %ld\n",
899 PTR_ERR(reg_8921_s4));
900 return -ENODEV;
901 }
902 rc = regulator_set_voltage(reg_8921_s4, 1800000, 1800000);
903 if (rc) {
904 pr_err("set_voltage failed for 8921_s4, rc=%d\n", rc);
905 return -EINVAL;
906 }
907 }
908
909 if (on) {
910 rc = regulator_set_optimum_mode(reg_8921_l23, 100000);
911 if (rc < 0) {
912 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
913 return -EINVAL;
914 }
915 rc = regulator_enable(reg_8921_l23);
916 if (rc) {
917 pr_err("'%s' regulator enable failed, rc=%d\n",
918 "hdmi_avdd", rc);
919 return rc;
920 }
921 rc = regulator_enable(reg_8921_s4);
922 if (rc) {
923 pr_err("'%s' regulator enable failed, rc=%d\n",
924 "hdmi_vcc", rc);
925 return rc;
926 }
927 rc = gpio_request(100, "HDMI_DDC_CLK");
928 if (rc) {
929 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
930 "HDMI_DDC_CLK", 100, rc);
931 goto error1;
932 }
933 rc = gpio_request(101, "HDMI_DDC_DATA");
934 if (rc) {
935 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
936 "HDMI_DDC_DATA", 101, rc);
937 goto error2;
938 }
939 rc = gpio_request(102, "HDMI_HPD");
940 if (rc) {
941 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
942 "HDMI_HPD", 102, rc);
943 goto error3;
944 }
945 pr_debug("%s(on): success\n", __func__);
946 } else {
947 gpio_free(100);
948 gpio_free(101);
949 gpio_free(102);
950
951 rc = regulator_disable(reg_8921_l23);
952 if (rc) {
953 pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
954 return -ENODEV;
955 }
956 rc = regulator_disable(reg_8921_s4);
957 if (rc) {
958 pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
959 return -ENODEV;
960 }
961 rc = regulator_set_optimum_mode(reg_8921_l23, 100);
962 if (rc < 0) {
963 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
964 return -EINVAL;
965 }
966 pr_debug("%s(off): success\n", __func__);
967 }
968
969 prev_on = on;
970
971 return 0;
972
973error3:
974 gpio_free(101);
975error2:
976 gpio_free(100);
977error1:
978 regulator_disable(reg_8921_l23);
979 regulator_disable(reg_8921_s4);
980 return rc;
981}
982
983static int hdmi_cec_power(int on)
984{
985 static int prev_on;
986 int rc;
987
988 if (on == prev_on)
989 return 0;
990
991 if (on) {
992 rc = gpio_request(99, "HDMI_CEC_VAR");
993 if (rc) {
994 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
995 "HDMI_CEC_VAR", 99, rc);
996 goto error;
997 }
998 pr_debug("%s(on): success\n", __func__);
999 } else {
1000 gpio_free(99);
1001 pr_debug("%s(off): success\n", __func__);
1002 }
1003
1004 prev_on = on;
1005
1006 return 0;
1007error:
1008 return rc;
1009}
1010#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
1011
1012void __init msm8960_init_fb(void)
1013{
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -08001014 platform_device_register(&msm_fb_device);
1015
Stepan Moskovchenko270888d2011-11-30 12:19:11 -08001016#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
1017 platform_device_register(&wfd_panel_device);
1018 platform_device_register(&wfd_device);
1019#endif
1020
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -08001021 if (machine_is_msm8960_sim())
1022 platform_device_register(&mipi_dsi_simulator_panel_device);
1023
1024 if (machine_is_msm8960_rumi3())
1025 platform_device_register(&mipi_dsi_renesas_panel_device);
1026
1027 if (!machine_is_msm8960_sim() && !machine_is_msm8960_rumi3()) {
1028 platform_device_register(&mipi_dsi_novatek_panel_device);
1029
1030#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
1031 platform_device_register(&hdmi_msm_device);
1032#endif
1033 }
1034
1035 if (machine_is_msm8960_liquid())
1036 platform_device_register(&mipi_dsi2lvds_bridge_device);
1037 else
1038 platform_device_register(&mipi_dsi_toshiba_panel_device);
1039
1040 if (machine_is_msm8x60_rumi3()) {
1041 msm_fb_register_device("mdp", NULL);
1042 mipi_dsi_pdata.target_type = 1;
1043 } else
1044 msm_fb_register_device("mdp", &mdp_pdata);
1045 msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
1046#ifdef CONFIG_MSM_BUS_SCALING
1047 msm_fb_register_device("dtv", &dtv_pdata);
1048#endif
1049}
1050
1051void __init msm8960_allocate_fb_region(void)
1052{
1053 void *addr;
1054 unsigned long size;
1055
1056 size = MSM_FB_SIZE;
1057 addr = alloc_bootmem_align(size, 0x1000);
1058 msm_fb_resources[0].start = __pa(addr);
1059 msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
1060 pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
1061 size, addr, __pa(addr));
1062}