blob: 1f6d04f2a37706654a916f6841c123a9df5b33c2 [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"
Ravishangar Kalyanam8e784252012-02-10 16:27:51 -080071#define MIPI_VIDEO_ASUS_WUXGA_PANEL_NAME "mipi_video_asus_wuxga"
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080072#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
Amir Samuelov6f1e5002012-02-01 17:42:43 +020073#define MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME "mipi_video_chimei_wuxga"
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080074#define MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME "mipi_video_simulator_vga"
75#define MIPI_CMD_RENESAS_FWVGA_PANEL_NAME "mipi_cmd_renesas_fwvga"
76#define HDMI_PANEL_NAME "hdmi_msm"
77#define TVOUT_PANEL_NAME "tvout_msm"
78
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080079static struct resource msm_fb_resources[] = {
80 {
81 .flags = IORESOURCE_DMA,
82 }
83};
84
Ravishangar Kalyanam8e784252012-02-10 16:27:51 -080085static void set_mdp_clocks_for_wuxga(void);
Amir Samuelovf0d1f542012-02-06 12:50:42 +020086
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -080087static int msm_fb_detect_panel(const char *name)
88{
89 if (machine_is_msm8960_liquid()) {
Amir Samuelov6f1e5002012-02-01 17:42:43 +020090 u32 ver = socinfo_get_platform_version();
91 if (SOCINFO_VERSION_MAJOR(ver) == 3) {
92 if (!strncmp(name, MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
93 strnlen(MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
Amir Samuelovf0d1f542012-02-06 12:50:42 +020094 PANEL_NAME_MAX_LEN))) {
Ravishangar Kalyanam8e784252012-02-10 16:27:51 -080095 set_mdp_clocks_for_wuxga();
Amir Samuelov6f1e5002012-02-01 17:42:43 +020096 return 0;
Amir Samuelovf0d1f542012-02-06 12:50:42 +020097 }
Amir Samuelov6f1e5002012-02-01 17:42:43 +020098 } else {
99 if (!strncmp(name, MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
100 strnlen(MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
101 PANEL_NAME_MAX_LEN)))
102 return 0;
103 }
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800104 } else {
105 if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
106 strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
107 PANEL_NAME_MAX_LEN)))
108 return 0;
109
110#ifndef CONFIG_FB_MSM_MIPI_PANEL_DETECT
111 if (!strncmp(name, MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
112 strnlen(MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
113 PANEL_NAME_MAX_LEN)))
114 return 0;
115
116 if (!strncmp(name, MIPI_CMD_NOVATEK_QHD_PANEL_NAME,
117 strnlen(MIPI_CMD_NOVATEK_QHD_PANEL_NAME,
118 PANEL_NAME_MAX_LEN)))
119 return 0;
120
121 if (!strncmp(name, MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME,
122 strnlen(MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME,
123 PANEL_NAME_MAX_LEN)))
124 return 0;
125
126 if (!strncmp(name, MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
127 strnlen(MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
128 PANEL_NAME_MAX_LEN)))
129 return 0;
Ravishangar Kalyanam8e784252012-02-10 16:27:51 -0800130
131 if (!strncmp(name, MIPI_VIDEO_ASUS_WUXGA_PANEL_NAME,
132 strnlen(MIPI_VIDEO_ASUS_WUXGA_PANEL_NAME,
133 PANEL_NAME_MAX_LEN))) {
134 set_mdp_clocks_for_wuxga();
135 return 0;
136 }
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800137#endif
138 }
139
140 if (!strncmp(name, HDMI_PANEL_NAME,
141 strnlen(HDMI_PANEL_NAME,
142 PANEL_NAME_MAX_LEN)))
143 return 0;
144
145 if (!strncmp(name, TVOUT_PANEL_NAME,
146 strnlen(TVOUT_PANEL_NAME,
147 PANEL_NAME_MAX_LEN)))
148 return 0;
149
150 pr_warning("%s: not supported '%s'", __func__, name);
151 return -ENODEV;
152}
153
154static struct msm_fb_platform_data msm_fb_pdata = {
155 .detect_client = msm_fb_detect_panel,
156};
157
158static struct platform_device msm_fb_device = {
159 .name = "msm_fb",
160 .id = 0,
161 .num_resources = ARRAY_SIZE(msm_fb_resources),
162 .resource = msm_fb_resources,
163 .dev.platform_data = &msm_fb_pdata,
164};
165
166static bool dsi_power_on;
167
168/**
169 * LiQUID panel on/off
170 *
171 * @param on
172 *
173 * @return int
174 */
175static int mipi_dsi_liquid_panel_power(int on)
176{
177 static struct regulator *reg_l2, *reg_ext_3p3v;
178 static int gpio21, gpio24, gpio43;
179 int rc;
180
Jeff Ohlstein2cbe5ba2011-12-16 13:32:56 -0800181 pr_debug("%s: on=%d\n", __func__, on);
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800182
183 gpio21 = PM8921_GPIO_PM_TO_SYS(21); /* disp power enable_n */
184 gpio43 = PM8921_GPIO_PM_TO_SYS(43); /* Displays Enable (rst_n)*/
185 gpio24 = PM8921_GPIO_PM_TO_SYS(24); /* Backlight PWM */
186
187 if (!dsi_power_on) {
188
189 reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
190 "dsi_vdda");
191 if (IS_ERR(reg_l2)) {
192 pr_err("could not get 8921_l2, rc = %ld\n",
193 PTR_ERR(reg_l2));
194 return -ENODEV;
195 }
196
197 rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
198 if (rc) {
199 pr_err("set_voltage l2 failed, rc=%d\n", rc);
200 return -EINVAL;
201 }
202
203 reg_ext_3p3v = regulator_get(&msm_mipi_dsi1_device.dev,
204 "vdd_lvds_3p3v");
205 if (IS_ERR(reg_ext_3p3v)) {
206 pr_err("could not get reg_ext_3p3v, rc = %ld\n",
207 PTR_ERR(reg_ext_3p3v));
208 return -ENODEV;
209 }
210
211 rc = gpio_request(gpio21, "disp_pwr_en_n");
212 if (rc) {
213 pr_err("request gpio 21 failed, rc=%d\n", rc);
214 return -ENODEV;
215 }
216
217 rc = gpio_request(gpio43, "disp_rst_n");
218 if (rc) {
219 pr_err("request gpio 43 failed, rc=%d\n", rc);
220 return -ENODEV;
221 }
222
223 rc = gpio_request(gpio24, "disp_backlight_pwm");
224 if (rc) {
225 pr_err("request gpio 24 failed, rc=%d\n", rc);
226 return -ENODEV;
227 }
228
229 dsi_power_on = true;
230 }
231
232 if (on) {
233 rc = regulator_set_optimum_mode(reg_l2, 100000);
234 if (rc < 0) {
235 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
236 return -EINVAL;
237 }
238 rc = regulator_enable(reg_l2);
239 if (rc) {
240 pr_err("enable l2 failed, rc=%d\n", rc);
241 return -ENODEV;
242 }
243
244 rc = regulator_enable(reg_ext_3p3v);
245 if (rc) {
246 pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
247 return -ENODEV;
248 }
249
250 /* set reset pin before power enable */
251 gpio_set_value_cansleep(gpio43, 0); /* disp disable (resx=0) */
252
253 gpio_set_value_cansleep(gpio21, 0); /* disp power enable_n */
254 msleep(20);
255 gpio_set_value_cansleep(gpio43, 1); /* disp enable */
256 msleep(20);
257 gpio_set_value_cansleep(gpio43, 0); /* disp enable */
258 msleep(20);
259 gpio_set_value_cansleep(gpio43, 1); /* disp enable */
260 msleep(20);
261 } else {
262 gpio_set_value_cansleep(gpio43, 0);
263 gpio_set_value_cansleep(gpio21, 1);
264
265 rc = regulator_disable(reg_l2);
266 if (rc) {
267 pr_err("disable reg_l2 failed, rc=%d\n", rc);
268 return -ENODEV;
269 }
270 rc = regulator_disable(reg_ext_3p3v);
271 if (rc) {
272 pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
273 return -ENODEV;
274 }
275 rc = regulator_set_optimum_mode(reg_l2, 100);
276 if (rc < 0) {
277 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
278 return -EINVAL;
279 }
280 }
281
282 return 0;
283}
284
285static int mipi_dsi_cdp_panel_power(int on)
286{
287 static struct regulator *reg_l8, *reg_l23, *reg_l2;
288 static int gpio43;
289 int rc;
290
Jeff Ohlstein2cbe5ba2011-12-16 13:32:56 -0800291 pr_debug("%s: state : %d\n", __func__, on);
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800292
293 if (!dsi_power_on) {
294
295 reg_l8 = regulator_get(&msm_mipi_dsi1_device.dev,
296 "dsi_vdc");
297 if (IS_ERR(reg_l8)) {
298 pr_err("could not get 8921_l8, rc = %ld\n",
299 PTR_ERR(reg_l8));
300 return -ENODEV;
301 }
302 reg_l23 = regulator_get(&msm_mipi_dsi1_device.dev,
303 "dsi_vddio");
304 if (IS_ERR(reg_l23)) {
305 pr_err("could not get 8921_l23, rc = %ld\n",
306 PTR_ERR(reg_l23));
307 return -ENODEV;
308 }
309 reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
310 "dsi_vdda");
311 if (IS_ERR(reg_l2)) {
312 pr_err("could not get 8921_l2, rc = %ld\n",
313 PTR_ERR(reg_l2));
314 return -ENODEV;
315 }
316 rc = regulator_set_voltage(reg_l8, 2800000, 3000000);
317 if (rc) {
318 pr_err("set_voltage l8 failed, rc=%d\n", rc);
319 return -EINVAL;
320 }
321 rc = regulator_set_voltage(reg_l23, 1800000, 1800000);
322 if (rc) {
323 pr_err("set_voltage l23 failed, rc=%d\n", rc);
324 return -EINVAL;
325 }
326 rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
327 if (rc) {
328 pr_err("set_voltage l2 failed, rc=%d\n", rc);
329 return -EINVAL;
330 }
331 gpio43 = PM8921_GPIO_PM_TO_SYS(43);
332 rc = gpio_request(gpio43, "disp_rst_n");
333 if (rc) {
334 pr_err("request gpio 43 failed, rc=%d\n", rc);
335 return -ENODEV;
336 }
337 dsi_power_on = true;
338 }
339 if (on) {
340 rc = regulator_set_optimum_mode(reg_l8, 100000);
341 if (rc < 0) {
342 pr_err("set_optimum_mode l8 failed, rc=%d\n", rc);
343 return -EINVAL;
344 }
345 rc = regulator_set_optimum_mode(reg_l23, 100000);
346 if (rc < 0) {
347 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
348 return -EINVAL;
349 }
350 rc = regulator_set_optimum_mode(reg_l2, 100000);
351 if (rc < 0) {
352 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
353 return -EINVAL;
354 }
355 rc = regulator_enable(reg_l8);
356 if (rc) {
357 pr_err("enable l8 failed, rc=%d\n", rc);
358 return -ENODEV;
359 }
360 rc = regulator_enable(reg_l23);
361 if (rc) {
362 pr_err("enable l8 failed, rc=%d\n", rc);
363 return -ENODEV;
364 }
365 rc = regulator_enable(reg_l2);
366 if (rc) {
367 pr_err("enable l2 failed, rc=%d\n", rc);
368 return -ENODEV;
369 }
370 gpio_set_value_cansleep(gpio43, 1);
371 } else {
372 rc = regulator_disable(reg_l2);
373 if (rc) {
374 pr_err("disable reg_l2 failed, rc=%d\n", rc);
375 return -ENODEV;
376 }
377 rc = regulator_disable(reg_l8);
378 if (rc) {
379 pr_err("disable reg_l8 failed, rc=%d\n", rc);
380 return -ENODEV;
381 }
382 rc = regulator_disable(reg_l23);
383 if (rc) {
384 pr_err("disable reg_l23 failed, rc=%d\n", rc);
385 return -ENODEV;
386 }
387 rc = regulator_set_optimum_mode(reg_l8, 100);
388 if (rc < 0) {
389 pr_err("set_optimum_mode l8 failed, rc=%d\n", rc);
390 return -EINVAL;
391 }
392 rc = regulator_set_optimum_mode(reg_l23, 100);
393 if (rc < 0) {
394 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
395 return -EINVAL;
396 }
397 rc = regulator_set_optimum_mode(reg_l2, 100);
398 if (rc < 0) {
399 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
400 return -EINVAL;
401 }
402 gpio_set_value_cansleep(gpio43, 0);
403 }
404 return 0;
405}
406
407static int mipi_dsi_panel_power(int on)
408{
409 int ret;
410
Jeff Ohlstein2cbe5ba2011-12-16 13:32:56 -0800411 pr_debug("%s: on=%d\n", __func__, on);
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800412
413 if (machine_is_msm8960_liquid())
414 ret = mipi_dsi_liquid_panel_power(on);
415 else
416 ret = mipi_dsi_cdp_panel_power(on);
417
418 return ret;
419}
420
421static struct mipi_dsi_platform_data mipi_dsi_pdata = {
422 .vsync_gpio = MDP_VSYNC_GPIO,
423 .dsi_power_save = mipi_dsi_panel_power,
424};
425
426#ifdef CONFIG_MSM_BUS_SCALING
427
Nagamalleswararao Ganji5fabbd62011-11-06 23:10:43 -0800428static struct msm_bus_vectors rotator_init_vectors[] = {
429 {
430 .src = MSM_BUS_MASTER_ROTATOR,
431 .dst = MSM_BUS_SLAVE_EBI_CH0,
432 .ab = 0,
433 .ib = 0,
434 },
435};
436
437static struct msm_bus_vectors rotator_ui_vectors[] = {
438 {
439 .src = MSM_BUS_MASTER_ROTATOR,
440 .dst = MSM_BUS_SLAVE_EBI_CH0,
441 .ab = (1024 * 600 * 4 * 2 * 60),
442 .ib = (1024 * 600 * 4 * 2 * 60 * 1.5),
443 },
444};
445
446static struct msm_bus_vectors rotator_vga_vectors[] = {
447 {
448 .src = MSM_BUS_MASTER_ROTATOR,
449 .dst = MSM_BUS_SLAVE_EBI_CH0,
450 .ab = (640 * 480 * 2 * 2 * 30),
451 .ib = (640 * 480 * 2 * 2 * 30 * 1.5),
452 },
453};
454static struct msm_bus_vectors rotator_720p_vectors[] = {
455 {
456 .src = MSM_BUS_MASTER_ROTATOR,
457 .dst = MSM_BUS_SLAVE_EBI_CH0,
458 .ab = (1280 * 736 * 2 * 2 * 30),
459 .ib = (1280 * 736 * 2 * 2 * 30 * 1.5),
460 },
461};
462
463static struct msm_bus_vectors rotator_1080p_vectors[] = {
464 {
465 .src = MSM_BUS_MASTER_ROTATOR,
466 .dst = MSM_BUS_SLAVE_EBI_CH0,
467 .ab = (1920 * 1088 * 2 * 2 * 30),
468 .ib = (1920 * 1088 * 2 * 2 * 30 * 1.5),
469 },
470};
471
472static struct msm_bus_paths rotator_bus_scale_usecases[] = {
473 {
474 ARRAY_SIZE(rotator_init_vectors),
475 rotator_init_vectors,
476 },
477 {
478 ARRAY_SIZE(rotator_ui_vectors),
479 rotator_ui_vectors,
480 },
481 {
482 ARRAY_SIZE(rotator_vga_vectors),
483 rotator_vga_vectors,
484 },
485 {
486 ARRAY_SIZE(rotator_720p_vectors),
487 rotator_720p_vectors,
488 },
489 {
490 ARRAY_SIZE(rotator_1080p_vectors),
491 rotator_1080p_vectors,
492 },
493};
494
495struct msm_bus_scale_pdata rotator_bus_scale_pdata = {
496 rotator_bus_scale_usecases,
497 ARRAY_SIZE(rotator_bus_scale_usecases),
498 .name = "rotator",
499};
500
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800501static struct msm_bus_vectors mdp_init_vectors[] = {
502 {
503 .src = MSM_BUS_MASTER_MDP_PORT0,
504 .dst = MSM_BUS_SLAVE_EBI_CH0,
505 .ab = 0,
506 .ib = 0,
507 },
508};
509
510#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
511static struct msm_bus_vectors hdmi_as_primary_vectors[] = {
512 /* If HDMI is used as primary */
513 {
514 .src = MSM_BUS_MASTER_MDP_PORT0,
515 .dst = MSM_BUS_SLAVE_EBI_CH0,
516 .ab = 2000000000,
517 .ib = 2000000000,
518 },
519};
520static struct msm_bus_paths mdp_bus_scale_usecases[] = {
521 {
522 ARRAY_SIZE(mdp_init_vectors),
523 mdp_init_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 ARRAY_SIZE(hdmi_as_primary_vectors),
535 hdmi_as_primary_vectors,
536 },
537 {
538 ARRAY_SIZE(hdmi_as_primary_vectors),
539 hdmi_as_primary_vectors,
540 },
541 {
542 ARRAY_SIZE(hdmi_as_primary_vectors),
543 hdmi_as_primary_vectors,
544 },
545};
546#else
547static struct msm_bus_vectors mdp_ui_vectors[] = {
548 {
549 .src = MSM_BUS_MASTER_MDP_PORT0,
550 .dst = MSM_BUS_SLAVE_EBI_CH0,
551 .ab = 216000000 * 2,
552 .ib = 270000000 * 2,
553 },
554};
555
556static struct msm_bus_vectors mdp_vga_vectors[] = {
557 /* VGA and less video */
558 {
559 .src = MSM_BUS_MASTER_MDP_PORT0,
560 .dst = MSM_BUS_SLAVE_EBI_CH0,
561 .ab = 216000000 * 2,
562 .ib = 270000000 * 2,
563 },
564};
565
566static struct msm_bus_vectors mdp_720p_vectors[] = {
567 /* 720p and less video */
568 {
569 .src = MSM_BUS_MASTER_MDP_PORT0,
570 .dst = MSM_BUS_SLAVE_EBI_CH0,
571 .ab = 230400000 * 2,
572 .ib = 288000000 * 2,
573 },
574};
575
576static struct msm_bus_vectors mdp_1080p_vectors[] = {
577 /* 1080p and less video */
578 {
579 .src = MSM_BUS_MASTER_MDP_PORT0,
580 .dst = MSM_BUS_SLAVE_EBI_CH0,
581 .ab = 334080000 * 2,
582 .ib = 417600000 * 2,
583 },
584};
585
586static struct msm_bus_paths mdp_bus_scale_usecases[] = {
587 {
588 ARRAY_SIZE(mdp_init_vectors),
589 mdp_init_vectors,
590 },
591 {
592 ARRAY_SIZE(mdp_ui_vectors),
593 mdp_ui_vectors,
594 },
595 {
596 ARRAY_SIZE(mdp_ui_vectors),
597 mdp_ui_vectors,
598 },
599 {
600 ARRAY_SIZE(mdp_vga_vectors),
601 mdp_vga_vectors,
602 },
603 {
604 ARRAY_SIZE(mdp_720p_vectors),
605 mdp_720p_vectors,
606 },
607 {
608 ARRAY_SIZE(mdp_1080p_vectors),
609 mdp_1080p_vectors,
610 },
611};
612#endif
613
614static struct msm_bus_scale_pdata mdp_bus_scale_pdata = {
615 mdp_bus_scale_usecases,
616 ARRAY_SIZE(mdp_bus_scale_usecases),
617 .name = "mdp",
618};
619
620#endif
621
622#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
Stepan Moskovchenkofc70d902011-11-30 12:39:36 -0800623static int mdp_core_clk_rate_table[] = {
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800624 200000000,
625 200000000,
626 200000000,
627 200000000,
628};
629#else
Stepan Moskovchenkofc70d902011-11-30 12:39:36 -0800630static int mdp_core_clk_rate_table[] = {
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800631 85330000,
Huaibin Yang1f180ee2012-01-30 16:23:06 -0800632 128000000,
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800633 160000000,
634 200000000,
635};
636#endif
637
638static struct msm_panel_common_pdata mdp_pdata = {
639 .gpio = MDP_VSYNC_GPIO,
640#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
641 .mdp_core_clk_rate = 200000000,
642#else
643 .mdp_core_clk_rate = 85330000,
644#endif
645 .mdp_core_clk_table = mdp_core_clk_rate_table,
646 .num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
647#ifdef CONFIG_MSM_BUS_SCALING
648 .mdp_bus_scale_table = &mdp_bus_scale_pdata,
649#endif
650 .mdp_rev = MDP_REV_42,
Nagamalleswararao Ganji937a1192011-12-07 19:00:52 -0800651#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
652 .mem_hid = ION_CP_MM_HEAP_ID,
653#else
654 .mem_hid = MEMTYPE_EBI1,
655#endif
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800656};
657
Amir Samuelovf0d1f542012-02-06 12:50:42 +0200658/**
659 * Set MDP clocks to high frequency to avoid DSI underflow
Ravishangar Kalyanam8e784252012-02-10 16:27:51 -0800660 * when using high resolution 1200x1920 WUXGA panels
Amir Samuelovf0d1f542012-02-06 12:50:42 +0200661 */
Ravishangar Kalyanam8e784252012-02-10 16:27:51 -0800662static void set_mdp_clocks_for_wuxga(void)
Amir Samuelovf0d1f542012-02-06 12:50:42 +0200663{
664 int i;
665
666 mdp_ui_vectors[0].ab = 2000000000;
667 mdp_ui_vectors[0].ib = 2000000000;
668
669 mdp_pdata.mdp_core_clk_rate = 200000000;
670
671 for (i = 0; i < ARRAY_SIZE(mdp_core_clk_rate_table); i++)
672 mdp_core_clk_rate_table[i] = 200000000;
673
674}
675
Huaibin Yanga5419422011-12-08 23:52:10 -0800676void __init msm8960_mdp_writeback(struct memtype_reserve* reserve_table)
677{
Nagamalleswararao Ganji937a1192011-12-07 19:00:52 -0800678 mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
679 mdp_pdata.ov1_wb_size = MSM_FB_OVERLAY1_WRITEBACK_SIZE;
680#if defined(CONFIG_ANDROID_PMEM) && !defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
681 reserve_table[mdp_pdata.mem_hid].size +=
682 mdp_pdata.ov0_wb_size;
683 reserve_table[mdp_pdata.mem_hid].size +=
684 mdp_pdata.ov1_wb_size;
685#endif
Huaibin Yanga5419422011-12-08 23:52:10 -0800686}
687
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800688static struct platform_device mipi_dsi_renesas_panel_device = {
689 .name = "mipi_renesas",
690 .id = 0,
691};
692
693static struct platform_device mipi_dsi_simulator_panel_device = {
694 .name = "mipi_simulator",
695 .id = 0,
696};
697
698#define LPM_CHANNEL0 0
699static int toshiba_gpio[] = {LPM_CHANNEL0};
700
701static struct mipi_dsi_panel_platform_data toshiba_pdata = {
702 .gpio = toshiba_gpio,
703};
704
705static struct platform_device mipi_dsi_toshiba_panel_device = {
706 .name = "mipi_toshiba",
707 .id = 0,
708 .dev = {
709 .platform_data = &toshiba_pdata,
710 }
711};
712
713#define FPGA_3D_GPIO_CONFIG_ADDR 0xB5
Amir Samuelovca199b92012-01-31 14:50:04 +0200714static int dsi2lvds_gpio[4] = {
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800715 0,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
Amir Samuelovca199b92012-01-31 14:50:04 +0200716 0x1F08, /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
717 GPIO_LIQUID_EXPANDER_BASE+6, /* TN Enable */
718 GPIO_LIQUID_EXPANDER_BASE+7, /* TN Mode */
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800719 };
720
721static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
722 .gpio_num = dsi2lvds_gpio,
723};
724
725static struct mipi_dsi_phy_ctrl dsi_novatek_cmd_mode_phy_db = {
726
727/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
728 {0x0F, 0x0a, 0x04, 0x00, 0x20}, /* regulator */
729 /* timing */
730 {0xab, 0x8a, 0x18, 0x00, 0x92, 0x97, 0x1b, 0x8c,
731 0x0c, 0x03, 0x04, 0xa0},
732 {0x5f, 0x00, 0x00, 0x10}, /* phy ctrl */
733 {0xff, 0x00, 0x06, 0x00}, /* strength */
734 /* pll control */
735 {0x40, 0xf9, 0x30, 0xda, 0x00, 0x40, 0x03, 0x62,
736 0x40, 0x07, 0x03,
737 0x00, 0x1a, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01},
738};
739
740static struct mipi_dsi_panel_platform_data novatek_pdata = {
741 .fpga_3d_config_addr = FPGA_3D_GPIO_CONFIG_ADDR,
742 .fpga_ctrl_mode = FPGA_SPI_INTF,
743 .phy_ctrl_settings = &dsi_novatek_cmd_mode_phy_db,
744};
745
746static struct platform_device mipi_dsi_novatek_panel_device = {
747 .name = "mipi_novatek",
748 .id = 0,
749 .dev = {
750 .platform_data = &novatek_pdata,
751 }
752};
753
754static struct platform_device mipi_dsi2lvds_bridge_device = {
755 .name = "mipi_tc358764",
756 .id = 0,
757 .dev.platform_data = &mipi_dsi2lvds_pdata,
758};
759
760#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
761static struct resource hdmi_msm_resources[] = {
762 {
763 .name = "hdmi_msm_qfprom_addr",
764 .start = 0x00700000,
765 .end = 0x007060FF,
766 .flags = IORESOURCE_MEM,
767 },
768 {
769 .name = "hdmi_msm_hdmi_addr",
770 .start = 0x04A00000,
771 .end = 0x04A00FFF,
772 .flags = IORESOURCE_MEM,
773 },
774 {
775 .name = "hdmi_msm_irq",
776 .start = HDMI_IRQ,
777 .end = HDMI_IRQ,
778 .flags = IORESOURCE_IRQ,
779 },
780};
781
782static int hdmi_enable_5v(int on);
783static int hdmi_core_power(int on, int show);
784static int hdmi_cec_power(int on);
785
786static struct msm_hdmi_platform_data hdmi_msm_data = {
787 .irq = HDMI_IRQ,
788 .enable_5v = hdmi_enable_5v,
789 .core_power = hdmi_core_power,
790 .cec_power = hdmi_cec_power,
791};
792
793static struct platform_device hdmi_msm_device = {
794 .name = "hdmi_msm",
795 .id = 0,
796 .num_resources = ARRAY_SIZE(hdmi_msm_resources),
797 .resource = hdmi_msm_resources,
798 .dev.platform_data = &hdmi_msm_data,
799};
800#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
801
802#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
803static struct platform_device wfd_panel_device = {
804 .name = "wfd_panel",
805 .id = 0,
806 .dev.platform_data = NULL,
807};
Stepan Moskovchenko270888d2011-11-30 12:19:11 -0800808
809static struct platform_device wfd_device = {
810 .name = "msm_wfd",
811 .id = -1,
812};
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800813#endif
814
815#ifdef CONFIG_MSM_BUS_SCALING
816static struct msm_bus_vectors dtv_bus_init_vectors[] = {
817 {
818 .src = MSM_BUS_MASTER_MDP_PORT0,
819 .dst = MSM_BUS_SLAVE_EBI_CH0,
820 .ab = 0,
821 .ib = 0,
822 },
823};
824
825#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
826static struct msm_bus_vectors dtv_bus_def_vectors[] = {
827 {
828 .src = MSM_BUS_MASTER_MDP_PORT0,
829 .dst = MSM_BUS_SLAVE_EBI_CH0,
830 .ab = 2000000000,
831 .ib = 2000000000,
832 },
833};
834#else
835static struct msm_bus_vectors dtv_bus_def_vectors[] = {
836 {
837 .src = MSM_BUS_MASTER_MDP_PORT0,
838 .dst = MSM_BUS_SLAVE_EBI_CH0,
839 .ab = 566092800 * 2,
840 .ib = 707616000 * 2,
841 },
842};
843#endif
844
845static struct msm_bus_paths dtv_bus_scale_usecases[] = {
846 {
847 ARRAY_SIZE(dtv_bus_init_vectors),
848 dtv_bus_init_vectors,
849 },
850 {
851 ARRAY_SIZE(dtv_bus_def_vectors),
852 dtv_bus_def_vectors,
853 },
854};
855static struct msm_bus_scale_pdata dtv_bus_scale_pdata = {
856 dtv_bus_scale_usecases,
857 ARRAY_SIZE(dtv_bus_scale_usecases),
858 .name = "dtv",
859};
860
861static struct lcdc_platform_data dtv_pdata = {
862 .bus_scale_table = &dtv_bus_scale_pdata,
863};
864#endif
865
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800866#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -0800867static int hdmi_enable_5v(int on)
868{
869 /* TBD: PM8921 regulator instead of 8901 */
870 static struct regulator *reg_8921_hdmi_mvs; /* HDMI_5V */
871 static int prev_on;
872 int rc;
873
874 if (on == prev_on)
875 return 0;
876
877 if (!reg_8921_hdmi_mvs)
878 reg_8921_hdmi_mvs = regulator_get(&hdmi_msm_device.dev,
879 "hdmi_mvs");
880
881 if (on) {
882 rc = regulator_enable(reg_8921_hdmi_mvs);
883 if (rc) {
884 pr_err("'%s' regulator enable failed, rc=%d\n",
885 "8921_hdmi_mvs", rc);
886 return rc;
887 }
888 pr_debug("%s(on): success\n", __func__);
889 } else {
890 rc = regulator_disable(reg_8921_hdmi_mvs);
891 if (rc)
892 pr_warning("'%s' regulator disable failed, rc=%d\n",
893 "8921_hdmi_mvs", rc);
894 pr_debug("%s(off): success\n", __func__);
895 }
896
897 prev_on = on;
898
899 return 0;
900}
901
902static int hdmi_core_power(int on, int show)
903{
904 static struct regulator *reg_8921_l23, *reg_8921_s4;
905 static int prev_on;
906 int rc;
907
908 if (on == prev_on)
909 return 0;
910
911 /* TBD: PM8921 regulator instead of 8901 */
912 if (!reg_8921_l23) {
913 reg_8921_l23 = regulator_get(&hdmi_msm_device.dev, "hdmi_avdd");
914 if (IS_ERR(reg_8921_l23)) {
915 pr_err("could not get reg_8921_l23, rc = %ld\n",
916 PTR_ERR(reg_8921_l23));
917 return -ENODEV;
918 }
919 rc = regulator_set_voltage(reg_8921_l23, 1800000, 1800000);
920 if (rc) {
921 pr_err("set_voltage failed for 8921_l23, rc=%d\n", rc);
922 return -EINVAL;
923 }
924 }
925 if (!reg_8921_s4) {
926 reg_8921_s4 = regulator_get(&hdmi_msm_device.dev, "hdmi_vcc");
927 if (IS_ERR(reg_8921_s4)) {
928 pr_err("could not get reg_8921_s4, rc = %ld\n",
929 PTR_ERR(reg_8921_s4));
930 return -ENODEV;
931 }
932 rc = regulator_set_voltage(reg_8921_s4, 1800000, 1800000);
933 if (rc) {
934 pr_err("set_voltage failed for 8921_s4, rc=%d\n", rc);
935 return -EINVAL;
936 }
937 }
938
939 if (on) {
940 rc = regulator_set_optimum_mode(reg_8921_l23, 100000);
941 if (rc < 0) {
942 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
943 return -EINVAL;
944 }
945 rc = regulator_enable(reg_8921_l23);
946 if (rc) {
947 pr_err("'%s' regulator enable failed, rc=%d\n",
948 "hdmi_avdd", rc);
949 return rc;
950 }
951 rc = regulator_enable(reg_8921_s4);
952 if (rc) {
953 pr_err("'%s' regulator enable failed, rc=%d\n",
954 "hdmi_vcc", rc);
955 return rc;
956 }
957 rc = gpio_request(100, "HDMI_DDC_CLK");
958 if (rc) {
959 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
960 "HDMI_DDC_CLK", 100, rc);
961 goto error1;
962 }
963 rc = gpio_request(101, "HDMI_DDC_DATA");
964 if (rc) {
965 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
966 "HDMI_DDC_DATA", 101, rc);
967 goto error2;
968 }
969 rc = gpio_request(102, "HDMI_HPD");
970 if (rc) {
971 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
972 "HDMI_HPD", 102, rc);
973 goto error3;
974 }
975 pr_debug("%s(on): success\n", __func__);
976 } else {
977 gpio_free(100);
978 gpio_free(101);
979 gpio_free(102);
980
981 rc = regulator_disable(reg_8921_l23);
982 if (rc) {
983 pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
984 return -ENODEV;
985 }
986 rc = regulator_disable(reg_8921_s4);
987 if (rc) {
988 pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
989 return -ENODEV;
990 }
991 rc = regulator_set_optimum_mode(reg_8921_l23, 100);
992 if (rc < 0) {
993 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
994 return -EINVAL;
995 }
996 pr_debug("%s(off): success\n", __func__);
997 }
998
999 prev_on = on;
1000
1001 return 0;
1002
1003error3:
1004 gpio_free(101);
1005error2:
1006 gpio_free(100);
1007error1:
1008 regulator_disable(reg_8921_l23);
1009 regulator_disable(reg_8921_s4);
1010 return rc;
1011}
1012
1013static int hdmi_cec_power(int on)
1014{
1015 static int prev_on;
1016 int rc;
1017
1018 if (on == prev_on)
1019 return 0;
1020
1021 if (on) {
1022 rc = gpio_request(99, "HDMI_CEC_VAR");
1023 if (rc) {
1024 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
1025 "HDMI_CEC_VAR", 99, rc);
1026 goto error;
1027 }
1028 pr_debug("%s(on): success\n", __func__);
1029 } else {
1030 gpio_free(99);
1031 pr_debug("%s(off): success\n", __func__);
1032 }
1033
1034 prev_on = on;
1035
1036 return 0;
1037error:
1038 return rc;
1039}
1040#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
1041
1042void __init msm8960_init_fb(void)
1043{
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -08001044 platform_device_register(&msm_fb_device);
1045
Stepan Moskovchenko270888d2011-11-30 12:19:11 -08001046#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
1047 platform_device_register(&wfd_panel_device);
1048 platform_device_register(&wfd_device);
1049#endif
1050
Stepan Moskovchenko24cd8642011-11-29 13:07:53 -08001051 if (machine_is_msm8960_sim())
1052 platform_device_register(&mipi_dsi_simulator_panel_device);
1053
1054 if (machine_is_msm8960_rumi3())
1055 platform_device_register(&mipi_dsi_renesas_panel_device);
1056
1057 if (!machine_is_msm8960_sim() && !machine_is_msm8960_rumi3()) {
1058 platform_device_register(&mipi_dsi_novatek_panel_device);
1059
1060#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
1061 platform_device_register(&hdmi_msm_device);
1062#endif
1063 }
1064
1065 if (machine_is_msm8960_liquid())
1066 platform_device_register(&mipi_dsi2lvds_bridge_device);
1067 else
1068 platform_device_register(&mipi_dsi_toshiba_panel_device);
1069
1070 if (machine_is_msm8x60_rumi3()) {
1071 msm_fb_register_device("mdp", NULL);
1072 mipi_dsi_pdata.target_type = 1;
1073 } else
1074 msm_fb_register_device("mdp", &mdp_pdata);
1075 msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
1076#ifdef CONFIG_MSM_BUS_SCALING
1077 msm_fb_register_device("dtv", &dtv_pdata);
1078#endif
1079}
1080
1081void __init msm8960_allocate_fb_region(void)
1082{
1083 void *addr;
1084 unsigned long size;
1085
1086 size = MSM_FB_SIZE;
1087 addr = alloc_bootmem_align(size, 0x1000);
1088 msm_fb_resources[0].start = __pa(addr);
1089 msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
1090 pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
1091 size, addr, __pa(addr));
1092}