blob: 7e477b1b08bd99e4cc3bcac3c1dbe1e81a9f77e9 [file] [log] [blame]
Nagamalleswararao Ganji70fac1e2011-12-29 19:06:37 -08001/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Stepan Moskovchenko39236d72011-11-30 17:42:23 -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>
Steve Mucklef132c6c2012-06-06 18:30:57 -070018#include <linux/gpio.h>
Stepan Moskovchenko39236d72011-11-30 17:42:23 -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 Moskovchenko39236d72011-11-30 17:42:23 -080022#include <mach/board.h>
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080023#include <mach/gpiomux.h>
Ajay Dudani9114be72011-12-03 07:46:35 -080024#include <mach/socinfo.h>
Mitchel Humpherysd0b5da02012-09-06 11:33:09 -070025#include <linux/msm_ion.h>
Nagamalleswararao Ganji937a1192011-12-07 19:00:52 -080026#include <mach/ion.h>
27
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080028#include "devices.h"
Stepan Moskovchenko5a83dba2011-12-05 17:30:17 -080029#include "board-8930.h"
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080030
31#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
Padmanabhan Komanduruede0a632012-01-25 12:01:28 +053032#define MSM_FB_PRIM_BUF_SIZE \
Huaibin Yangc8946d42012-05-04 17:22:02 -070033 (roundup((1920 * 1088 * 4), 4096) * 3) /* 4 bpp x 3 pages */
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080034#else
Padmanabhan Komanduruede0a632012-01-25 12:01:28 +053035#define MSM_FB_PRIM_BUF_SIZE \
Huaibin Yangc8946d42012-05-04 17:22:02 -070036 (roundup((1920 * 1088 * 4), 4096) * 2) /* 4 bpp x 2 pages */
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080037#endif
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080038/* Note: must be multiple of 4096 */
Huaibin Yangc8946d42012-05-04 17:22:02 -070039#define MSM_FB_SIZE roundup(MSM_FB_PRIM_BUF_SIZE, 4096)
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080040
Huaibin Yanga5419422011-12-08 23:52:10 -080041#ifdef CONFIG_FB_MSM_OVERLAY0_WRITEBACK
42#define MSM_FB_OVERLAY0_WRITEBACK_SIZE roundup((1376 * 768 * 3 * 2), 4096)
43#else
44#define MSM_FB_OVERLAY0_WRITEBACK_SIZE (0)
45#endif /* CONFIG_FB_MSM_OVERLAY0_WRITEBACK */
46
47#ifdef CONFIG_FB_MSM_OVERLAY1_WRITEBACK
48#define MSM_FB_OVERLAY1_WRITEBACK_SIZE roundup((1920 * 1088 * 3 * 2), 4096)
49#else
50#define MSM_FB_OVERLAY1_WRITEBACK_SIZE (0)
51#endif /* CONFIG_FB_MSM_OVERLAY1_WRITEBACK */
52
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080053#define MDP_VSYNC_GPIO 0
54
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080055#define MIPI_CMD_NOVATEK_QHD_PANEL_NAME "mipi_cmd_novatek_qhd"
56#define MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME "mipi_video_novatek_qhd"
57#define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
58#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
59#define MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME "mipi_video_simulator_vga"
60#define MIPI_CMD_RENESAS_FWVGA_PANEL_NAME "mipi_cmd_renesas_fwvga"
61#define HDMI_PANEL_NAME "hdmi_msm"
Aravind Venkateswaran06a46352012-08-16 14:52:39 -070062#define MHL_PANEL_NAME "hdmi_msm,mhl_8334"
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080063#define TVOUT_PANEL_NAME "tvout_msm"
64
Aravind Venkateswaran06a46352012-08-16 14:52:39 -070065static unsigned char mhl_display_enabled;
66
67unsigned char msm8930_mhl_display_enabled(void)
68{
69 return mhl_display_enabled;
70}
71
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080072static struct resource msm_fb_resources[] = {
73 {
74 .flags = IORESOURCE_DMA,
75 }
76};
77
78static int msm_fb_detect_panel(const char *name)
79{
Chandan Uddaraju59894ca2011-12-05 17:07:02 -080080 if (!strncmp(name, MIPI_CMD_NOVATEK_QHD_PANEL_NAME,
81 strnlen(MIPI_CMD_NOVATEK_QHD_PANEL_NAME,
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080082 PANEL_NAME_MAX_LEN)))
83 return 0;
84
Ravishangar Kalyanama4286d72012-02-15 16:09:58 -080085#if !defined(CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT) && \
86 !defined(CONFIG_FB_MSM_MIPI_PANEL_DETECT)
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080087 if (!strncmp(name, MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
88 strnlen(MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
89 PANEL_NAME_MAX_LEN)))
90 return 0;
91
Chandan Uddaraju59894ca2011-12-05 17:07:02 -080092 if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
93 strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
Stepan Moskovchenko39236d72011-11-30 17:42:23 -080094 PANEL_NAME_MAX_LEN)))
95 return 0;
96
97 if (!strncmp(name, MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME,
98 strnlen(MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME,
99 PANEL_NAME_MAX_LEN)))
100 return 0;
101
102 if (!strncmp(name, MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
103 strnlen(MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
104 PANEL_NAME_MAX_LEN)))
105 return 0;
106#endif
107
108 if (!strncmp(name, HDMI_PANEL_NAME,
109 strnlen(HDMI_PANEL_NAME,
110 PANEL_NAME_MAX_LEN)))
111 return 0;
112
113 if (!strncmp(name, TVOUT_PANEL_NAME,
114 strnlen(TVOUT_PANEL_NAME,
115 PANEL_NAME_MAX_LEN)))
116 return 0;
117
118 pr_warning("%s: not supported '%s'", __func__, name);
119 return -ENODEV;
120}
121
122static struct msm_fb_platform_data msm_fb_pdata = {
123 .detect_client = msm_fb_detect_panel,
124};
125
126static struct platform_device msm_fb_device = {
127 .name = "msm_fb",
128 .id = 0,
129 .num_resources = ARRAY_SIZE(msm_fb_resources),
130 .resource = msm_fb_resources,
131 .dev.platform_data = &msm_fb_pdata,
132};
133
134static bool dsi_power_on;
135
Jay Chokshi06fa7542011-12-07 13:09:17 -0800136/*
137 * TODO: When physical 8930/PM8038 hardware becomes
138 * available, replace mipi_dsi_cdp_panel_power with
139 * appropriate function.
140 */
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800141#define DISP_RST_GPIO 58
Siddhartha Agrawalf5a8e382012-07-18 16:33:18 -0700142#define DISP_3D_2D_MODE 1
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800143static int mipi_dsi_cdp_panel_power(int on)
144{
145 static struct regulator *reg_l8, *reg_l23, *reg_l2;
David Collins9898ac32012-08-10 17:24:38 -0700146 /* Control backlight GPIO (24) directly when using PM8917 */
147 int gpio24 = PM8917_GPIO_PM_TO_SYS(24);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800148 int rc;
149
Jeff Ohlstein2cbe5ba2011-12-16 13:32:56 -0800150 pr_debug("%s: state : %d\n", __func__, on);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800151
152 if (!dsi_power_on) {
153
154 reg_l8 = regulator_get(&msm_mipi_dsi1_device.dev,
155 "dsi_vdc");
156 if (IS_ERR(reg_l8)) {
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800157 pr_err("could not get 8038_l8, rc = %ld\n",
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800158 PTR_ERR(reg_l8));
159 return -ENODEV;
160 }
161 reg_l23 = regulator_get(&msm_mipi_dsi1_device.dev,
162 "dsi_vddio");
163 if (IS_ERR(reg_l23)) {
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800164 pr_err("could not get 8038_l23, rc = %ld\n",
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800165 PTR_ERR(reg_l23));
166 return -ENODEV;
167 }
168 reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
169 "dsi_vdda");
170 if (IS_ERR(reg_l2)) {
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800171 pr_err("could not get 8038_l2, rc = %ld\n",
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800172 PTR_ERR(reg_l2));
173 return -ENODEV;
174 }
175 rc = regulator_set_voltage(reg_l8, 2800000, 3000000);
176 if (rc) {
177 pr_err("set_voltage l8 failed, rc=%d\n", rc);
178 return -EINVAL;
179 }
180 rc = regulator_set_voltage(reg_l23, 1800000, 1800000);
181 if (rc) {
182 pr_err("set_voltage l23 failed, rc=%d\n", rc);
183 return -EINVAL;
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 }
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800190 rc = gpio_request(DISP_RST_GPIO, "disp_rst_n");
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800191 if (rc) {
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800192 pr_err("request gpio DISP_RST_GPIO failed, rc=%d\n",
193 rc);
194 gpio_free(DISP_RST_GPIO);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800195 return -ENODEV;
196 }
Siddhartha Agrawalf5a8e382012-07-18 16:33:18 -0700197 rc = gpio_request(DISP_3D_2D_MODE, "disp_3d_2d");
198 if (rc) {
199 pr_err("request gpio DISP_3D_2D_MODE failed, rc=%d\n",
200 rc);
201 gpio_free(DISP_3D_2D_MODE);
202 return -ENODEV;
David Collins9898ac32012-08-10 17:24:38 -0700203 }
Siddhartha Agrawalf5a8e382012-07-18 16:33:18 -0700204 rc = gpio_direction_output(DISP_3D_2D_MODE, 0);
205 if (rc) {
206 pr_err("gpio_direction_output failed for %d gpio rc=%d\n",
207 DISP_3D_2D_MODE, rc);
208 return -ENODEV;
David Collins9898ac32012-08-10 17:24:38 -0700209 }
210 if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
211 rc = gpio_request(gpio24, "disp_bl");
212 if (rc) {
213 pr_err("request for gpio 24 failed, rc=%d\n",
214 rc);
215 return -ENODEV;
Siddhartha Agrawalf5a8e382012-07-18 16:33:18 -0700216 }
David Collins9898ac32012-08-10 17:24:38 -0700217 }
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800218 dsi_power_on = true;
219 }
220 if (on) {
221 rc = regulator_set_optimum_mode(reg_l8, 100000);
222 if (rc < 0) {
223 pr_err("set_optimum_mode l8 failed, rc=%d\n", rc);
224 return -EINVAL;
225 }
226 rc = regulator_set_optimum_mode(reg_l23, 100000);
227 if (rc < 0) {
228 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
229 return -EINVAL;
230 }
231 rc = regulator_set_optimum_mode(reg_l2, 100000);
232 if (rc < 0) {
233 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
234 return -EINVAL;
235 }
236 rc = regulator_enable(reg_l8);
237 if (rc) {
238 pr_err("enable l8 failed, rc=%d\n", rc);
239 return -ENODEV;
240 }
241 rc = regulator_enable(reg_l23);
242 if (rc) {
243 pr_err("enable l8 failed, rc=%d\n", rc);
244 return -ENODEV;
245 }
246 rc = regulator_enable(reg_l2);
247 if (rc) {
248 pr_err("enable l2 failed, rc=%d\n", rc);
249 return -ENODEV;
250 }
Ravishangar Kalyanam87c5fb62012-01-28 21:24:58 -0800251 usleep(10000);
252 gpio_set_value(DISP_RST_GPIO, 1);
253 usleep(10);
254 gpio_set_value(DISP_RST_GPIO, 0);
255 usleep(20);
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800256 gpio_set_value(DISP_RST_GPIO, 1);
Siddhartha Agrawalf5a8e382012-07-18 16:33:18 -0700257 gpio_set_value(DISP_3D_2D_MODE, 1);
258 usleep(20);
David Collins9898ac32012-08-10 17:24:38 -0700259 if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
260 gpio_set_value_cansleep(gpio24, 1);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800261 } else {
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800262
263 gpio_set_value(DISP_RST_GPIO, 0);
264
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800265 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_l8);
271 if (rc) {
272 pr_err("disable reg_l8 failed, rc=%d\n", rc);
273 return -ENODEV;
274 }
275 rc = regulator_disable(reg_l23);
276 if (rc) {
277 pr_err("disable reg_l23 failed, rc=%d\n", rc);
278 return -ENODEV;
279 }
280 rc = regulator_set_optimum_mode(reg_l8, 100);
281 if (rc < 0) {
282 pr_err("set_optimum_mode l8 failed, rc=%d\n", rc);
283 return -EINVAL;
284 }
285 rc = regulator_set_optimum_mode(reg_l23, 100);
286 if (rc < 0) {
287 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
288 return -EINVAL;
289 }
290 rc = regulator_set_optimum_mode(reg_l2, 100);
291 if (rc < 0) {
292 pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
293 return -EINVAL;
294 }
Siddhartha Agrawalf5a8e382012-07-18 16:33:18 -0700295 gpio_set_value(DISP_3D_2D_MODE, 0);
296 usleep(20);
David Collins9898ac32012-08-10 17:24:38 -0700297 if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
298 gpio_set_value_cansleep(gpio24, 0);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800299 }
300 return 0;
301}
302
303static int mipi_dsi_panel_power(int on)
304{
Jeff Ohlstein2cbe5ba2011-12-16 13:32:56 -0800305 pr_debug("%s: on=%d\n", __func__, on);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800306
307 return mipi_dsi_cdp_panel_power(on);
308}
309
310static struct mipi_dsi_platform_data mipi_dsi_pdata = {
311 .vsync_gpio = MDP_VSYNC_GPIO,
312 .dsi_power_save = mipi_dsi_panel_power,
313};
314
315#ifdef CONFIG_MSM_BUS_SCALING
316
317static struct msm_bus_vectors mdp_init_vectors[] = {
318 {
319 .src = MSM_BUS_MASTER_MDP_PORT0,
320 .dst = MSM_BUS_SLAVE_EBI_CH0,
321 .ab = 0,
322 .ib = 0,
323 },
324};
325
326#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
327static struct msm_bus_vectors hdmi_as_primary_vectors[] = {
328 /* If HDMI is used as primary */
329 {
330 .src = MSM_BUS_MASTER_MDP_PORT0,
331 .dst = MSM_BUS_SLAVE_EBI_CH0,
332 .ab = 2000000000,
333 .ib = 2000000000,
334 },
335};
336static struct msm_bus_paths mdp_bus_scale_usecases[] = {
337 {
338 ARRAY_SIZE(mdp_init_vectors),
339 mdp_init_vectors,
340 },
341 {
342 ARRAY_SIZE(hdmi_as_primary_vectors),
343 hdmi_as_primary_vectors,
344 },
345 {
346 ARRAY_SIZE(hdmi_as_primary_vectors),
347 hdmi_as_primary_vectors,
348 },
349 {
350 ARRAY_SIZE(hdmi_as_primary_vectors),
351 hdmi_as_primary_vectors,
352 },
353 {
354 ARRAY_SIZE(hdmi_as_primary_vectors),
355 hdmi_as_primary_vectors,
356 },
357 {
358 ARRAY_SIZE(hdmi_as_primary_vectors),
359 hdmi_as_primary_vectors,
360 },
361};
362#else
363static struct msm_bus_vectors mdp_ui_vectors[] = {
364 {
365 .src = MSM_BUS_MASTER_MDP_PORT0,
366 .dst = MSM_BUS_SLAVE_EBI_CH0,
367 .ab = 216000000 * 2,
368 .ib = 270000000 * 2,
369 },
370};
371
372static struct msm_bus_vectors mdp_vga_vectors[] = {
373 /* VGA and less video */
374 {
375 .src = MSM_BUS_MASTER_MDP_PORT0,
376 .dst = MSM_BUS_SLAVE_EBI_CH0,
377 .ab = 216000000 * 2,
378 .ib = 270000000 * 2,
379 },
380};
381
382static struct msm_bus_vectors mdp_720p_vectors[] = {
383 /* 720p and less video */
384 {
385 .src = MSM_BUS_MASTER_MDP_PORT0,
386 .dst = MSM_BUS_SLAVE_EBI_CH0,
387 .ab = 230400000 * 2,
388 .ib = 288000000 * 2,
389 },
390};
391
392static struct msm_bus_vectors mdp_1080p_vectors[] = {
393 /* 1080p and less video */
394 {
395 .src = MSM_BUS_MASTER_MDP_PORT0,
396 .dst = MSM_BUS_SLAVE_EBI_CH0,
397 .ab = 334080000 * 2,
398 .ib = 417600000 * 2,
399 },
400};
401
402static struct msm_bus_paths mdp_bus_scale_usecases[] = {
403 {
404 ARRAY_SIZE(mdp_init_vectors),
405 mdp_init_vectors,
406 },
407 {
408 ARRAY_SIZE(mdp_ui_vectors),
409 mdp_ui_vectors,
410 },
411 {
412 ARRAY_SIZE(mdp_ui_vectors),
413 mdp_ui_vectors,
414 },
415 {
416 ARRAY_SIZE(mdp_vga_vectors),
417 mdp_vga_vectors,
418 },
419 {
420 ARRAY_SIZE(mdp_720p_vectors),
421 mdp_720p_vectors,
422 },
423 {
424 ARRAY_SIZE(mdp_1080p_vectors),
425 mdp_1080p_vectors,
426 },
427};
428#endif
429
430static struct msm_bus_scale_pdata mdp_bus_scale_pdata = {
431 mdp_bus_scale_usecases,
432 ARRAY_SIZE(mdp_bus_scale_usecases),
433 .name = "mdp",
434};
435
436#endif
437
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800438static struct msm_panel_common_pdata mdp_pdata = {
439 .gpio = MDP_VSYNC_GPIO,
Siddhartha Agrawal496f9282012-08-15 17:41:34 -0700440 .mdp_max_clk = 200000000,
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800441#ifdef CONFIG_MSM_BUS_SCALING
442 .mdp_bus_scale_table = &mdp_bus_scale_pdata,
443#endif
444 .mdp_rev = MDP_REV_42,
Nagamalleswararao Ganji937a1192011-12-07 19:00:52 -0800445#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
Ravishangar Kalyanama3b168b2012-03-26 11:13:11 -0700446 .mem_hid = BIT(ION_CP_MM_HEAP_ID),
Nagamalleswararao Ganji937a1192011-12-07 19:00:52 -0800447#else
448 .mem_hid = MEMTYPE_EBI1,
449#endif
Olav Hauganef95ae32012-05-15 09:50:30 -0700450 .mdp_iommu_split_domain = 0,
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800451};
452
Huaibin Yanga5419422011-12-08 23:52:10 -0800453void __init msm8930_mdp_writeback(struct memtype_reserve* reserve_table)
454{
Nagamalleswararao Ganji937a1192011-12-07 19:00:52 -0800455 mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
456 mdp_pdata.ov1_wb_size = MSM_FB_OVERLAY1_WRITEBACK_SIZE;
457#if defined(CONFIG_ANDROID_PMEM) && !defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
458 reserve_table[mdp_pdata.mem_hid].size +=
459 mdp_pdata.ov0_wb_size;
460 reserve_table[mdp_pdata.mem_hid].size +=
461 mdp_pdata.ov1_wb_size;
462#endif
Huaibin Yanga5419422011-12-08 23:52:10 -0800463}
464
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800465#define LPM_CHANNEL0 0
466static int toshiba_gpio[] = {LPM_CHANNEL0};
467
468static struct mipi_dsi_panel_platform_data toshiba_pdata = {
469 .gpio = toshiba_gpio,
470};
471
472static struct platform_device mipi_dsi_toshiba_panel_device = {
473 .name = "mipi_toshiba",
474 .id = 0,
475 .dev = {
476 .platform_data = &toshiba_pdata,
477 }
478};
479
480#define FPGA_3D_GPIO_CONFIG_ADDR 0xB5
481
482static struct mipi_dsi_phy_ctrl dsi_novatek_cmd_mode_phy_db = {
483
484/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
Chandan Uddaraju58d759e2012-07-16 16:20:30 -0700485 {0x09, 0x08, 0x05, 0x00, 0x20}, /* regulator */
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800486 /* timing */
487 {0xab, 0x8a, 0x18, 0x00, 0x92, 0x97, 0x1b, 0x8c,
488 0x0c, 0x03, 0x04, 0xa0},
489 {0x5f, 0x00, 0x00, 0x10}, /* phy ctrl */
490 {0xff, 0x00, 0x06, 0x00}, /* strength */
491 /* pll control */
Chandan Uddaraju58d759e2012-07-16 16:20:30 -0700492 {0x0, 0xe, 0x30, 0xda, 0x00, 0x10, 0x0f, 0x61,
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800493 0x40, 0x07, 0x03,
Chandan Uddaraju58d759e2012-07-16 16:20:30 -0700494 0x00, 0x1a, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x02},
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800495};
496
497static struct mipi_dsi_panel_platform_data novatek_pdata = {
498 .fpga_3d_config_addr = FPGA_3D_GPIO_CONFIG_ADDR,
499 .fpga_ctrl_mode = FPGA_SPI_INTF,
500 .phy_ctrl_settings = &dsi_novatek_cmd_mode_phy_db,
Ravishangar Kalyanam903f65c2012-01-28 21:36:22 -0800501 .dlane_swap = 0x1,
Chandan Uddaraju194a4b52012-03-21 10:11:18 -0700502 .enable_wled_bl_ctrl = 0x1,
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800503};
504
505static struct platform_device mipi_dsi_novatek_panel_device = {
506 .name = "mipi_novatek",
507 .id = 0,
508 .dev = {
509 .platform_data = &novatek_pdata,
510 }
511};
512
513#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
514static struct resource hdmi_msm_resources[] = {
515 {
516 .name = "hdmi_msm_qfprom_addr",
517 .start = 0x00700000,
518 .end = 0x007060FF,
519 .flags = IORESOURCE_MEM,
520 },
521 {
522 .name = "hdmi_msm_hdmi_addr",
523 .start = 0x04A00000,
524 .end = 0x04A00FFF,
525 .flags = IORESOURCE_MEM,
526 },
527 {
528 .name = "hdmi_msm_irq",
529 .start = HDMI_IRQ,
530 .end = HDMI_IRQ,
531 .flags = IORESOURCE_IRQ,
532 },
533};
534
535static int hdmi_enable_5v(int on);
536static int hdmi_core_power(int on, int show);
537static int hdmi_cec_power(int on);
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530538static int hdmi_gpio_config(int on);
539static int hdmi_panel_power(int on);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800540
541static struct msm_hdmi_platform_data hdmi_msm_data = {
542 .irq = HDMI_IRQ,
543 .enable_5v = hdmi_enable_5v,
544 .core_power = hdmi_core_power,
545 .cec_power = hdmi_cec_power,
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530546 .panel_power = hdmi_panel_power,
547 .gpio_config = hdmi_gpio_config,
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800548};
549
550static struct platform_device hdmi_msm_device = {
551 .name = "hdmi_msm",
552 .id = 0,
553 .num_resources = ARRAY_SIZE(hdmi_msm_resources),
554 .resource = hdmi_msm_resources,
555 .dev.platform_data = &hdmi_msm_data,
556};
557#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
558
559#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
560static struct platform_device wfd_panel_device = {
561 .name = "wfd_panel",
562 .id = 0,
563 .dev.platform_data = NULL,
564};
565
566static struct platform_device wfd_device = {
567 .name = "msm_wfd",
568 .id = -1,
569};
570#endif
571
572#ifdef CONFIG_MSM_BUS_SCALING
573static struct msm_bus_vectors dtv_bus_init_vectors[] = {
574 {
575 .src = MSM_BUS_MASTER_MDP_PORT0,
576 .dst = MSM_BUS_SLAVE_EBI_CH0,
577 .ab = 0,
578 .ib = 0,
579 },
580};
581
582#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
583static struct msm_bus_vectors dtv_bus_def_vectors[] = {
584 {
585 .src = MSM_BUS_MASTER_MDP_PORT0,
586 .dst = MSM_BUS_SLAVE_EBI_CH0,
587 .ab = 2000000000,
588 .ib = 2000000000,
589 },
590};
591#else
592static struct msm_bus_vectors dtv_bus_def_vectors[] = {
593 {
594 .src = MSM_BUS_MASTER_MDP_PORT0,
595 .dst = MSM_BUS_SLAVE_EBI_CH0,
596 .ab = 566092800 * 2,
597 .ib = 707616000 * 2,
598 },
599};
600#endif
601
602static struct msm_bus_paths dtv_bus_scale_usecases[] = {
603 {
604 ARRAY_SIZE(dtv_bus_init_vectors),
605 dtv_bus_init_vectors,
606 },
607 {
608 ARRAY_SIZE(dtv_bus_def_vectors),
609 dtv_bus_def_vectors,
610 },
611};
612static struct msm_bus_scale_pdata dtv_bus_scale_pdata = {
613 dtv_bus_scale_usecases,
614 ARRAY_SIZE(dtv_bus_scale_usecases),
615 .name = "dtv",
616};
617
618static struct lcdc_platform_data dtv_pdata = {
619 .bus_scale_table = &dtv_bus_scale_pdata,
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530620 .lcdc_power_save = hdmi_panel_power,
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800621};
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530622
623static int hdmi_panel_power(int on)
624{
625 int rc;
626
627 pr_debug("%s: HDMI Core: %s\n", __func__, (on ? "ON" : "OFF"));
628 rc = hdmi_core_power(on, 1);
629 if (rc)
630 rc = hdmi_cec_power(on);
631
632 pr_debug("%s: HDMI Core: %s Success\n", __func__, (on ? "ON" : "OFF"));
633 return rc;
634}
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800635#endif
636
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800637#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800638static int hdmi_enable_5v(int on)
639{
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800640 static struct regulator *reg_ext_5v; /* HDMI_5V */
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800641 static int prev_on;
642 int rc;
643
644 if (on == prev_on)
645 return 0;
646
Ajay Singh Parmar07847642011-12-09 02:57:45 +0530647 if (!reg_ext_5v) {
648 reg_ext_5v = regulator_get(&hdmi_msm_device.dev, "hdmi_mvs");
649 if (IS_ERR(reg_ext_5v)) {
650 pr_err("'%s' regulator not found, rc=%ld\n",
651 "hdmi_mvs", IS_ERR(reg_ext_5v));
652 reg_ext_5v = NULL;
653 return -ENODEV;
654 }
655 }
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800656
657 if (on) {
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800658 rc = regulator_enable(reg_ext_5v);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800659 if (rc) {
660 pr_err("'%s' regulator enable failed, rc=%d\n",
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800661 "reg_ext_5v", rc);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800662 return rc;
663 }
664 pr_debug("%s(on): success\n", __func__);
665 } else {
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800666 rc = regulator_disable(reg_ext_5v);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800667 if (rc)
668 pr_warning("'%s' regulator disable failed, rc=%d\n",
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800669 "reg_ext_5v", rc);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800670 pr_debug("%s(off): success\n", __func__);
671 }
672
673 prev_on = on;
674
675 return 0;
676}
677
678static int hdmi_core_power(int on, int show)
679{
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800680 /* Both HDMI "avdd" and "vcc" are powered by 8038_l23 regulator */
681 static struct regulator *reg_8038_l23;
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800682 static int prev_on;
683 int rc;
684
685 if (on == prev_on)
686 return 0;
687
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800688 if (!reg_8038_l23) {
689 reg_8038_l23 = regulator_get(&hdmi_msm_device.dev, "hdmi_avdd");
690 if (IS_ERR(reg_8038_l23)) {
691 pr_err("could not get reg_8038_l23, rc = %ld\n",
692 PTR_ERR(reg_8038_l23));
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800693 return -ENODEV;
694 }
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800695 rc = regulator_set_voltage(reg_8038_l23, 1800000, 1800000);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800696 if (rc) {
697 pr_err("set_voltage failed for 8921_l23, rc=%d\n", rc);
698 return -EINVAL;
699 }
700 }
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800701
702 if (on) {
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800703 rc = regulator_set_optimum_mode(reg_8038_l23, 100000);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800704 if (rc < 0) {
705 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
706 return -EINVAL;
707 }
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800708 rc = regulator_enable(reg_8038_l23);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800709 if (rc) {
710 pr_err("'%s' regulator enable failed, rc=%d\n",
711 "hdmi_avdd", rc);
712 return rc;
713 }
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800714 pr_debug("%s(on): success\n", __func__);
715 } else {
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800716 rc = regulator_disable(reg_8038_l23);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800717 if (rc) {
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800718 pr_err("disable reg_8038_l23 failed, rc=%d\n", rc);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800719 return -ENODEV;
720 }
Chandan Uddaraju59894ca2011-12-05 17:07:02 -0800721 rc = regulator_set_optimum_mode(reg_8038_l23, 100);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800722 if (rc < 0) {
723 pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
724 return -EINVAL;
725 }
726 pr_debug("%s(off): success\n", __func__);
727 }
728
729 prev_on = on;
730
731 return 0;
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530732}
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800733
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530734static int hdmi_gpio_config(int on)
735{
736 int rc = 0;
737 static int prev_on;
738
739 if (on == prev_on)
740 return 0;
741
742 if (on) {
Manoj Rao908ad742012-08-08 15:03:39 -0700743 if (!(hdmi_msm_data.is_mhl_enabled)) {
744 rc = gpio_request(HDMI_MHL_MUX_GPIO, "MHL_HDMI_MUX");
745 if (rc < 0) {
746 pr_err("gpio hdmi_mhl mux req failed:%d\n",
747 rc);
748 return rc;
749 }
750 rc = gpio_direction_output(HDMI_MHL_MUX_GPIO, 1);
751 if (rc < 0) {
752 pr_err("set gpio hdmi_mhl dir failed:%d\n",
753 rc);
754 goto error0;
755 }
756 gpio_set_value(HDMI_MHL_MUX_GPIO, 1);
757 pr_debug("set gpio hdmi mhl mux %d to 1\n",
758 HDMI_MHL_MUX_GPIO);
759 }
760
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530761 rc = gpio_request(100, "HDMI_DDC_CLK");
762 if (rc) {
763 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
764 "HDMI_DDC_CLK", 100, rc);
Manoj Rao908ad742012-08-08 15:03:39 -0700765 goto error0;
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530766 }
767 rc = gpio_request(101, "HDMI_DDC_DATA");
768 if (rc) {
769 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
770 "HDMI_DDC_DATA", 101, rc);
771 goto error1;
772 }
773 rc = gpio_request(102, "HDMI_HPD");
774 if (rc) {
775 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
776 "HDMI_HPD", 102, rc);
777 goto error2;
778 }
779 pr_debug("%s(on): success\n", __func__);
780 } else {
Manoj Rao908ad742012-08-08 15:03:39 -0700781 if (!(hdmi_msm_data.is_mhl_enabled))
782 gpio_free(HDMI_MHL_MUX_GPIO);
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530783 gpio_free(100);
784 gpio_free(101);
785 gpio_free(102);
786 pr_debug("%s(off): success\n", __func__);
787 }
788
789 prev_on = on;
790 return 0;
791
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800792error2:
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530793 gpio_free(101);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800794error1:
Ajay Singh Parmar7d11c272012-06-07 12:25:31 +0530795 gpio_free(100);
Manoj Rao908ad742012-08-08 15:03:39 -0700796error0:
797 if (!(hdmi_msm_data.is_mhl_enabled))
798 gpio_free(HDMI_MHL_MUX_GPIO);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800799 return rc;
800}
801
802static int hdmi_cec_power(int on)
803{
804 static int prev_on;
805 int rc;
806
807 if (on == prev_on)
808 return 0;
809
810 if (on) {
811 rc = gpio_request(99, "HDMI_CEC_VAR");
812 if (rc) {
813 pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
814 "HDMI_CEC_VAR", 99, rc);
815 goto error;
816 }
817 pr_debug("%s(on): success\n", __func__);
818 } else {
819 gpio_free(99);
820 pr_debug("%s(off): success\n", __func__);
821 }
822
823 prev_on = on;
824
825 return 0;
826error:
827 return rc;
828}
829#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
830
831void __init msm8930_init_fb(void)
832{
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800833 platform_device_register(&msm_fb_device);
834
835#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
836 platform_device_register(&wfd_panel_device);
837 platform_device_register(&wfd_device);
838#endif
839
840 platform_device_register(&mipi_dsi_novatek_panel_device);
841
842#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
Aravind Venkateswaranfff132d2012-03-07 13:22:30 -0800843 platform_device_register(&hdmi_msm_device);
Stepan Moskovchenko39236d72011-11-30 17:42:23 -0800844#endif
845
846 platform_device_register(&mipi_dsi_toshiba_panel_device);
847
848 msm_fb_register_device("mdp", &mdp_pdata);
849 msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
850#ifdef CONFIG_MSM_BUS_SCALING
851 msm_fb_register_device("dtv", &dtv_pdata);
852#endif
853}
854
855void __init msm8930_allocate_fb_region(void)
856{
857 void *addr;
858 unsigned long size;
859
860 size = MSM_FB_SIZE;
861 addr = alloc_bootmem_align(size, 0x1000);
862 msm_fb_resources[0].start = __pa(addr);
863 msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
864 pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
865 size, addr, __pa(addr));
866}
Aravind Venkateswaran06a46352012-08-16 14:52:39 -0700867
868void __init msm8930_set_display_params(char *prim_panel, char *ext_panel)
869{
870 if (strnlen(prim_panel, PANEL_NAME_MAX_LEN)) {
871 strlcpy(msm_fb_pdata.prim_panel_name, prim_panel,
872 PANEL_NAME_MAX_LEN);
873 pr_debug("msm_fb_pdata.prim_panel_name %s\n",
874 msm_fb_pdata.prim_panel_name);
875 }
876 if (strnlen(ext_panel, PANEL_NAME_MAX_LEN)) {
877 strlcpy(msm_fb_pdata.ext_panel_name, ext_panel,
878 PANEL_NAME_MAX_LEN);
879 pr_debug("msm_fb_pdata.ext_panel_name %s\n",
880 msm_fb_pdata.ext_panel_name);
881
882 if (!strncmp((char *)msm_fb_pdata.ext_panel_name,
883 MHL_PANEL_NAME, strnlen(MHL_PANEL_NAME,
884 PANEL_NAME_MAX_LEN))) {
885 pr_debug("MHL is external display by boot parameter\n");
886 mhl_display_enabled = 1;
887 }
888 }
889
890 hdmi_msm_data.is_mhl_enabled = mhl_display_enabled;
891}