diff options
Diffstat (limited to 'arch/arm/mach-tegra/board-cardhu-panel.c')
-rw-r--r-- | arch/arm/mach-tegra/board-cardhu-panel.c | 1288 |
1 files changed, 1288 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/board-cardhu-panel.c b/arch/arm/mach-tegra/board-cardhu-panel.c new file mode 100644 index 00000000000..8636a4d6743 --- /dev/null +++ b/arch/arm/mach-tegra/board-cardhu-panel.c | |||
@@ -0,0 +1,1288 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/board-cardhu-panel.c | ||
3 | * | ||
4 | * Copyright (c) 2010-2012, NVIDIA Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/delay.h> | ||
22 | #include <linux/ion.h> | ||
23 | #include <linux/tegra_ion.h> | ||
24 | #include <linux/gpio.h> | ||
25 | #include <linux/regulator/consumer.h> | ||
26 | #include <linux/resource.h> | ||
27 | #include <asm/mach-types.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/earlysuspend.h> | ||
30 | #include <linux/pwm_backlight.h> | ||
31 | #include <asm/atomic.h> | ||
32 | #include <linux/nvhost.h> | ||
33 | #include <mach/nvmap.h> | ||
34 | #include <mach/irqs.h> | ||
35 | #include <mach/iomap.h> | ||
36 | #include <mach/dc.h> | ||
37 | #include <mach/fb.h> | ||
38 | #include <mach/smmu.h> | ||
39 | |||
40 | #include "board.h" | ||
41 | #include "board-cardhu.h" | ||
42 | #include "devices.h" | ||
43 | #include "gpio-names.h" | ||
44 | |||
45 | /* Select panel to be used. */ | ||
46 | #define DSI_PANEL_219 1 | ||
47 | #define DSI_PANEL_218 0 | ||
48 | #define AVDD_LCD PMU_TCA6416_GPIO_PORT17 | ||
49 | #define DSI_PANEL_RESET 1 | ||
50 | |||
51 | /* Select LVDS panel resolution. 13X7 is default */ | ||
52 | #define PM313_LVDS_PANEL_19X12 1 | ||
53 | #define PM313_LVDS_PANEL_BPP 0 /* 0:24bpp, 1:18bpp */ | ||
54 | |||
55 | /* PM313 display board specific pins */ | ||
56 | #define pm313_R_FDE TEGRA_GPIO_PW0 | ||
57 | #define pm313_R_FB TEGRA_GPIO_PN4 | ||
58 | #define pm313_MODE0 TEGRA_GPIO_PZ4 | ||
59 | #define pm313_MODE1 TEGRA_GPIO_PW1 | ||
60 | #define pm313_BPP TEGRA_GPIO_PN6 /* 0:24bpp, 1:18bpp */ | ||
61 | #define pm313_lvds_shutdown TEGRA_GPIO_PH1 | ||
62 | |||
63 | /* E1247 reworked for pm269 pins */ | ||
64 | #define e1247_pm269_lvds_shutdown TEGRA_GPIO_PN6 | ||
65 | |||
66 | /* E1247 cardhu default display board pins */ | ||
67 | #define cardhu_lvds_shutdown TEGRA_GPIO_PL2 | ||
68 | |||
69 | /* common pins( backlight ) for all display boards */ | ||
70 | #define cardhu_bl_enb TEGRA_GPIO_PH2 | ||
71 | #define cardhu_bl_pwm TEGRA_GPIO_PH0 | ||
72 | #define cardhu_hdmi_hpd TEGRA_GPIO_PN7 | ||
73 | |||
74 | #if defined(DSI_PANEL_219) || defined(DSI_PANEL_218) | ||
75 | #define cardhu_dsia_bl_enb TEGRA_GPIO_PW1 | ||
76 | #define cardhu_dsib_bl_enb TEGRA_GPIO_PW0 | ||
77 | #define cardhu_dsi_218_panel_reset TEGRA_GPIO_PD2 | ||
78 | #define cardhu_dsi_219_panel_reset TEGRA_GPIO_PW0 | ||
79 | #endif | ||
80 | |||
81 | #ifdef CONFIG_TEGRA_DC | ||
82 | static struct regulator *cardhu_hdmi_reg = NULL; | ||
83 | static struct regulator *cardhu_hdmi_pll = NULL; | ||
84 | static struct regulator *cardhu_hdmi_vddio = NULL; | ||
85 | #endif | ||
86 | |||
87 | static atomic_t sd_brightness = ATOMIC_INIT(255); | ||
88 | |||
89 | #ifdef CONFIG_TEGRA_CARDHU_DSI | ||
90 | static struct regulator *cardhu_dsi_reg = NULL; | ||
91 | #else | ||
92 | static struct regulator *cardhu_lvds_reg = NULL; | ||
93 | static struct regulator *cardhu_lvds_vdd_bl = NULL; | ||
94 | static struct regulator *cardhu_lvds_vdd_panel = NULL; | ||
95 | #endif | ||
96 | |||
97 | static struct board_info board_info; | ||
98 | static struct board_info display_board_info; | ||
99 | |||
100 | static tegra_dc_bl_output cardhu_bl_output_measured = { | ||
101 | 0, 1, 2, 3, 4, 5, 6, 7, | ||
102 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
103 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
104 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
105 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
106 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
107 | 48, 49, 49, 50, 51, 52, 53, 54, | ||
108 | 55, 56, 57, 58, 59, 60, 61, 62, | ||
109 | 63, 64, 65, 66, 67, 68, 69, 70, | ||
110 | 70, 72, 73, 74, 75, 76, 77, 78, | ||
111 | 79, 80, 81, 82, 83, 84, 85, 86, | ||
112 | 87, 88, 89, 90, 91, 92, 93, 94, | ||
113 | 95, 96, 97, 98, 99, 100, 101, 102, | ||
114 | 103, 104, 105, 106, 107, 108, 110, 111, | ||
115 | 112, 113, 114, 115, 116, 117, 118, 119, | ||
116 | 120, 121, 122, 123, 124, 124, 125, 126, | ||
117 | 127, 128, 129, 130, 131, 132, 133, 133, | ||
118 | 134, 135, 136, 137, 138, 139, 140, 141, | ||
119 | 142, 143, 144, 145, 146, 147, 148, 148, | ||
120 | 149, 150, 151, 152, 153, 154, 155, 156, | ||
121 | 157, 158, 159, 160, 161, 162, 163, 164, | ||
122 | 165, 166, 167, 168, 169, 170, 171, 172, | ||
123 | 173, 174, 175, 176, 177, 179, 180, 181, | ||
124 | 182, 184, 185, 186, 187, 188, 189, 190, | ||
125 | 191, 192, 193, 194, 195, 196, 197, 198, | ||
126 | 199, 200, 201, 202, 203, 204, 205, 206, | ||
127 | 207, 208, 209, 211, 212, 213, 214, 215, | ||
128 | 216, 217, 218, 219, 220, 221, 222, 223, | ||
129 | 224, 225, 226, 227, 228, 229, 230, 231, | ||
130 | 232, 233, 234, 235, 236, 237, 238, 239, | ||
131 | 240, 241, 242, 243, 244, 245, 246, 247, | ||
132 | 248, 249, 250, 251, 252, 253, 254, 255 | ||
133 | }; | ||
134 | |||
135 | static p_tegra_dc_bl_output bl_output; | ||
136 | |||
137 | static int cardhu_backlight_init(struct device *dev) | ||
138 | { | ||
139 | int ret; | ||
140 | |||
141 | bl_output = cardhu_bl_output_measured; | ||
142 | |||
143 | if (WARN_ON(ARRAY_SIZE(cardhu_bl_output_measured) != 256)) | ||
144 | pr_err("bl_output array does not have 256 elements\n"); | ||
145 | |||
146 | #ifndef CONFIG_TEGRA_CARDHU_DSI | ||
147 | tegra_gpio_disable(cardhu_bl_pwm); | ||
148 | |||
149 | ret = gpio_request(cardhu_bl_enb, "backlight_enb"); | ||
150 | if (ret < 0) | ||
151 | return ret; | ||
152 | |||
153 | ret = gpio_direction_output(cardhu_bl_enb, 1); | ||
154 | if (ret < 0) | ||
155 | gpio_free(cardhu_bl_enb); | ||
156 | else | ||
157 | tegra_gpio_enable(cardhu_bl_enb); | ||
158 | |||
159 | return ret; | ||
160 | #endif | ||
161 | |||
162 | #if DSI_PANEL_218 | ||
163 | /* Enable back light for DSIa panel */ | ||
164 | ret = gpio_request(cardhu_dsia_bl_enb, "dsia_bl_enable"); | ||
165 | if (ret < 0) | ||
166 | return ret; | ||
167 | |||
168 | ret = gpio_direction_output(cardhu_dsia_bl_enb, 1); | ||
169 | if (ret < 0) | ||
170 | gpio_free(cardhu_dsia_bl_enb); | ||
171 | else | ||
172 | tegra_gpio_enable(cardhu_dsia_bl_enb); | ||
173 | |||
174 | /* Enable back light for DSIb panel */ | ||
175 | ret = gpio_request(cardhu_dsib_bl_enb, "dsib_bl_enable"); | ||
176 | if (ret < 0) | ||
177 | return ret; | ||
178 | |||
179 | ret = gpio_direction_output(cardhu_dsib_bl_enb, 1); | ||
180 | if (ret < 0) | ||
181 | gpio_free(cardhu_dsib_bl_enb); | ||
182 | else | ||
183 | tegra_gpio_enable(cardhu_dsib_bl_enb); | ||
184 | #endif | ||
185 | |||
186 | #if DSI_PANEL_219 | ||
187 | /* Enable back light for DSIa panel */ | ||
188 | ret = gpio_request(cardhu_dsia_bl_enb, "dsia_bl_enable"); | ||
189 | if (ret < 0) | ||
190 | return ret; | ||
191 | |||
192 | ret = gpio_direction_output(cardhu_dsia_bl_enb, 1); | ||
193 | if (ret < 0) | ||
194 | gpio_free(cardhu_dsia_bl_enb); | ||
195 | else | ||
196 | tegra_gpio_enable(cardhu_dsia_bl_enb); | ||
197 | #endif | ||
198 | |||
199 | return ret; | ||
200 | }; | ||
201 | |||
202 | static void cardhu_backlight_exit(struct device *dev) | ||
203 | { | ||
204 | #ifndef CONFIG_TEGRA_CARDHU_DSI | ||
205 | /* int ret; */ | ||
206 | /*ret = gpio_request(cardhu_bl_enb, "backlight_enb");*/ | ||
207 | gpio_set_value(cardhu_bl_enb, 0); | ||
208 | gpio_free(cardhu_bl_enb); | ||
209 | tegra_gpio_disable(cardhu_bl_enb); | ||
210 | return; | ||
211 | #endif | ||
212 | |||
213 | #if DSI_PANEL_218 | ||
214 | /* Disable back light for DSIa panel */ | ||
215 | gpio_set_value(cardhu_dsia_bl_enb, 0); | ||
216 | gpio_free(cardhu_dsia_bl_enb); | ||
217 | tegra_gpio_disable(cardhu_dsia_bl_enb); | ||
218 | |||
219 | /* Disable back light for DSIb panel */ | ||
220 | gpio_set_value(cardhu_dsib_bl_enb, 0); | ||
221 | gpio_free(cardhu_dsib_bl_enb); | ||
222 | tegra_gpio_disable(cardhu_dsib_bl_enb); | ||
223 | |||
224 | gpio_set_value(cardhu_lvds_shutdown, 1); | ||
225 | mdelay(20); | ||
226 | #endif | ||
227 | |||
228 | #if DSI_PANEL_219 | ||
229 | /* Disable back light for DSIa panel */ | ||
230 | gpio_set_value(cardhu_dsia_bl_enb, 0); | ||
231 | gpio_free(cardhu_dsia_bl_enb); | ||
232 | tegra_gpio_disable(cardhu_dsia_bl_enb); | ||
233 | |||
234 | gpio_set_value(cardhu_lvds_shutdown, 1); | ||
235 | mdelay(20); | ||
236 | #endif | ||
237 | } | ||
238 | |||
239 | static int cardhu_backlight_notify(struct device *unused, int brightness) | ||
240 | { | ||
241 | int cur_sd_brightness = atomic_read(&sd_brightness); | ||
242 | |||
243 | #ifndef CONFIG_TEGRA_CARDHU_DSI | ||
244 | /* Set the backlight GPIO pin mode to 'backlight_enable' */ | ||
245 | gpio_set_value(cardhu_bl_enb, !!brightness); | ||
246 | #elif DSI_PANEL_218 | ||
247 | /* DSIa */ | ||
248 | gpio_set_value(cardhu_dsia_bl_enb, !!brightness); | ||
249 | |||
250 | /* DSIb */ | ||
251 | gpio_set_value(cardhu_dsib_bl_enb, !!brightness); | ||
252 | #elif DSI_PANEL_219 | ||
253 | /* DSIa */ | ||
254 | gpio_set_value(cardhu_dsia_bl_enb, !!brightness); | ||
255 | #endif | ||
256 | |||
257 | /* SD brightness is a percentage, 8-bit value. */ | ||
258 | brightness = (brightness * cur_sd_brightness) / 255; | ||
259 | |||
260 | /* Apply any backlight response curve */ | ||
261 | if (brightness > 255) { | ||
262 | pr_info("Error: Brightness > 255!\n"); | ||
263 | } else { | ||
264 | /* This value depends on the panel. | ||
265 | Current 19X12 panel with PM313 gets | ||
266 | full brightness when the output is 0. */ | ||
267 | if (display_board_info.board_id == BOARD_DISPLAY_PM313) | ||
268 | brightness = 255 - bl_output[brightness]; | ||
269 | else | ||
270 | brightness = bl_output[brightness]; | ||
271 | } | ||
272 | |||
273 | return brightness; | ||
274 | } | ||
275 | |||
276 | static int cardhu_disp1_check_fb(struct device *dev, struct fb_info *info); | ||
277 | |||
278 | static struct platform_pwm_backlight_data cardhu_backlight_data = { | ||
279 | .pwm_id = 0, | ||
280 | .max_brightness = 255, | ||
281 | .dft_brightness = 224, | ||
282 | .pwm_period_ns = 1000000, | ||
283 | .init = cardhu_backlight_init, | ||
284 | .exit = cardhu_backlight_exit, | ||
285 | .notify = cardhu_backlight_notify, | ||
286 | /* Only toggle backlight on fb blank notifications for disp1 */ | ||
287 | .check_fb = cardhu_disp1_check_fb, | ||
288 | }; | ||
289 | |||
290 | static struct platform_device cardhu_backlight_device = { | ||
291 | .name = "pwm-backlight", | ||
292 | .id = -1, | ||
293 | .dev = { | ||
294 | .platform_data = &cardhu_backlight_data, | ||
295 | }, | ||
296 | }; | ||
297 | |||
298 | #ifndef CONFIG_TEGRA_CARDHU_DSI | ||
299 | static int cardhu_panel_enable(void) | ||
300 | { | ||
301 | if (cardhu_lvds_reg == NULL) { | ||
302 | cardhu_lvds_reg = regulator_get(NULL, "vdd_lvds"); | ||
303 | if (WARN_ON(IS_ERR(cardhu_lvds_reg))) | ||
304 | pr_err("%s: couldn't get regulator vdd_lvds: %ld\n", | ||
305 | __func__, PTR_ERR(cardhu_lvds_reg)); | ||
306 | else | ||
307 | regulator_enable(cardhu_lvds_reg); | ||
308 | } | ||
309 | |||
310 | if (cardhu_lvds_vdd_bl == NULL) { | ||
311 | cardhu_lvds_vdd_bl = regulator_get(NULL, "vdd_backlight"); | ||
312 | if (WARN_ON(IS_ERR(cardhu_lvds_vdd_bl))) | ||
313 | pr_err("%s: couldn't get regulator vdd_backlight: %ld\n", | ||
314 | __func__, PTR_ERR(cardhu_lvds_vdd_bl)); | ||
315 | else | ||
316 | regulator_enable(cardhu_lvds_vdd_bl); | ||
317 | } | ||
318 | |||
319 | if (cardhu_lvds_vdd_panel == NULL) { | ||
320 | cardhu_lvds_vdd_panel = regulator_get(NULL, "vdd_lcd_panel"); | ||
321 | if (WARN_ON(IS_ERR(cardhu_lvds_vdd_panel))) | ||
322 | pr_err("%s: couldn't get regulator vdd_lcd_panel: %ld\n", | ||
323 | __func__, PTR_ERR(cardhu_lvds_vdd_panel)); | ||
324 | else | ||
325 | regulator_enable(cardhu_lvds_vdd_panel); | ||
326 | } | ||
327 | |||
328 | if (display_board_info.board_id == BOARD_DISPLAY_PM313) { | ||
329 | /* lvds configuration */ | ||
330 | gpio_set_value(pm313_R_FDE, 1); | ||
331 | gpio_set_value(pm313_R_FB, 1); | ||
332 | gpio_set_value(pm313_MODE0, 1); | ||
333 | gpio_set_value(pm313_MODE1, 0); | ||
334 | gpio_set_value(pm313_BPP, PM313_LVDS_PANEL_BPP); | ||
335 | |||
336 | /* FIXME : it may require more or less delay for latching | ||
337 | values correctly before enabling RGB2LVDS */ | ||
338 | mdelay(100); | ||
339 | gpio_set_value(pm313_lvds_shutdown, 1); | ||
340 | } else if ((display_board_info.board_id == BOARD_DISPLAY_E1247 && | ||
341 | board_info.board_id == BOARD_PM269) || | ||
342 | (board_info.board_id == BOARD_E1257) || | ||
343 | (board_info.board_id == BOARD_PM305) || | ||
344 | (board_info.board_id == BOARD_PM311)) | ||
345 | gpio_set_value(e1247_pm269_lvds_shutdown, 1); | ||
346 | else | ||
347 | gpio_set_value(cardhu_lvds_shutdown, 1); | ||
348 | |||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | static int cardhu_panel_disable(void) | ||
353 | { | ||
354 | regulator_disable(cardhu_lvds_reg); | ||
355 | regulator_put(cardhu_lvds_reg); | ||
356 | cardhu_lvds_reg = NULL; | ||
357 | |||
358 | regulator_disable(cardhu_lvds_vdd_bl); | ||
359 | regulator_put(cardhu_lvds_vdd_bl); | ||
360 | cardhu_lvds_vdd_bl = NULL; | ||
361 | |||
362 | regulator_disable(cardhu_lvds_vdd_panel); | ||
363 | regulator_put(cardhu_lvds_vdd_panel); | ||
364 | |||
365 | cardhu_lvds_vdd_panel= NULL; | ||
366 | |||
367 | if (display_board_info.board_id == BOARD_DISPLAY_PM313) { | ||
368 | gpio_set_value(pm313_lvds_shutdown, 0); | ||
369 | } else if ((display_board_info.board_id == BOARD_DISPLAY_E1247 && | ||
370 | board_info.board_id == BOARD_PM269) || | ||
371 | (board_info.board_id == BOARD_E1257) || | ||
372 | (board_info.board_id == BOARD_PM305) || | ||
373 | (board_info.board_id == BOARD_PM311)) { | ||
374 | gpio_set_value(e1247_pm269_lvds_shutdown, 0); | ||
375 | } else { | ||
376 | gpio_set_value(cardhu_lvds_shutdown, 0); | ||
377 | } | ||
378 | return 0; | ||
379 | } | ||
380 | #endif | ||
381 | |||
382 | #ifdef CONFIG_TEGRA_DC | ||
383 | static int cardhu_hdmi_vddio_enable(void) | ||
384 | { | ||
385 | int ret; | ||
386 | if (!cardhu_hdmi_vddio) { | ||
387 | cardhu_hdmi_vddio = regulator_get(NULL, "vdd_hdmi_con"); | ||
388 | if (IS_ERR_OR_NULL(cardhu_hdmi_vddio)) { | ||
389 | ret = PTR_ERR(cardhu_hdmi_vddio); | ||
390 | pr_err("hdmi: couldn't get regulator vdd_hdmi_con\n"); | ||
391 | cardhu_hdmi_vddio = NULL; | ||
392 | return ret; | ||
393 | } | ||
394 | } | ||
395 | ret = regulator_enable(cardhu_hdmi_vddio); | ||
396 | if (ret < 0) { | ||
397 | pr_err("hdmi: couldn't enable regulator vdd_hdmi_con\n"); | ||
398 | regulator_put(cardhu_hdmi_vddio); | ||
399 | cardhu_hdmi_vddio = NULL; | ||
400 | return ret; | ||
401 | } | ||
402 | return ret; | ||
403 | } | ||
404 | |||
405 | static int cardhu_hdmi_vddio_disable(void) | ||
406 | { | ||
407 | if (cardhu_hdmi_vddio) { | ||
408 | regulator_disable(cardhu_hdmi_vddio); | ||
409 | regulator_put(cardhu_hdmi_vddio); | ||
410 | cardhu_hdmi_vddio = NULL; | ||
411 | } | ||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static int cardhu_hdmi_enable(void) | ||
416 | { | ||
417 | int ret; | ||
418 | if (!cardhu_hdmi_reg) { | ||
419 | cardhu_hdmi_reg = regulator_get(NULL, "avdd_hdmi"); | ||
420 | if (IS_ERR_OR_NULL(cardhu_hdmi_reg)) { | ||
421 | pr_err("hdmi: couldn't get regulator avdd_hdmi\n"); | ||
422 | cardhu_hdmi_reg = NULL; | ||
423 | return PTR_ERR(cardhu_hdmi_reg); | ||
424 | } | ||
425 | } | ||
426 | ret = regulator_enable(cardhu_hdmi_reg); | ||
427 | if (ret < 0) { | ||
428 | pr_err("hdmi: couldn't enable regulator avdd_hdmi\n"); | ||
429 | return ret; | ||
430 | } | ||
431 | if (!cardhu_hdmi_pll) { | ||
432 | cardhu_hdmi_pll = regulator_get(NULL, "avdd_hdmi_pll"); | ||
433 | if (IS_ERR_OR_NULL(cardhu_hdmi_pll)) { | ||
434 | pr_err("hdmi: couldn't get regulator avdd_hdmi_pll\n"); | ||
435 | cardhu_hdmi_pll = NULL; | ||
436 | regulator_put(cardhu_hdmi_reg); | ||
437 | cardhu_hdmi_reg = NULL; | ||
438 | return PTR_ERR(cardhu_hdmi_pll); | ||
439 | } | ||
440 | } | ||
441 | ret = regulator_enable(cardhu_hdmi_pll); | ||
442 | if (ret < 0) { | ||
443 | pr_err("hdmi: couldn't enable regulator avdd_hdmi_pll\n"); | ||
444 | return ret; | ||
445 | } | ||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | static int cardhu_hdmi_disable(void) | ||
450 | { | ||
451 | regulator_disable(cardhu_hdmi_reg); | ||
452 | regulator_put(cardhu_hdmi_reg); | ||
453 | cardhu_hdmi_reg = NULL; | ||
454 | |||
455 | regulator_disable(cardhu_hdmi_pll); | ||
456 | regulator_put(cardhu_hdmi_pll); | ||
457 | cardhu_hdmi_pll = NULL; | ||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | static struct resource cardhu_disp1_resources[] = { | ||
462 | { | ||
463 | .name = "irq", | ||
464 | .start = INT_DISPLAY_GENERAL, | ||
465 | .end = INT_DISPLAY_GENERAL, | ||
466 | .flags = IORESOURCE_IRQ, | ||
467 | }, | ||
468 | { | ||
469 | .name = "regs", | ||
470 | .start = TEGRA_DISPLAY_BASE, | ||
471 | .end = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE-1, | ||
472 | .flags = IORESOURCE_MEM, | ||
473 | }, | ||
474 | { | ||
475 | .name = "fbmem", | ||
476 | .start = 0, /* Filled in by cardhu_panel_init() */ | ||
477 | .end = 0, /* Filled in by cardhu_panel_init() */ | ||
478 | .flags = IORESOURCE_MEM, | ||
479 | }, | ||
480 | #ifdef CONFIG_TEGRA_DSI_INSTANCE_1 | ||
481 | { | ||
482 | .name = "dsi_regs", | ||
483 | .start = TEGRA_DSIB_BASE, | ||
484 | .end = TEGRA_DSIB_BASE + TEGRA_DSIB_SIZE - 1, | ||
485 | .flags = IORESOURCE_MEM, | ||
486 | }, | ||
487 | #else | ||
488 | { | ||
489 | .name = "dsi_regs", | ||
490 | .start = TEGRA_DSI_BASE, | ||
491 | .end = TEGRA_DSI_BASE + TEGRA_DSI_SIZE - 1, | ||
492 | .flags = IORESOURCE_MEM, | ||
493 | }, | ||
494 | #endif | ||
495 | }; | ||
496 | |||
497 | static struct resource cardhu_disp2_resources[] = { | ||
498 | { | ||
499 | .name = "irq", | ||
500 | .start = INT_DISPLAY_B_GENERAL, | ||
501 | .end = INT_DISPLAY_B_GENERAL, | ||
502 | .flags = IORESOURCE_IRQ, | ||
503 | }, | ||
504 | { | ||
505 | .name = "regs", | ||
506 | .start = TEGRA_DISPLAY2_BASE, | ||
507 | .end = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1, | ||
508 | .flags = IORESOURCE_MEM, | ||
509 | }, | ||
510 | { | ||
511 | .name = "fbmem", | ||
512 | .flags = IORESOURCE_MEM, | ||
513 | .start = 0, | ||
514 | .end = 0, | ||
515 | }, | ||
516 | { | ||
517 | .name = "hdmi_regs", | ||
518 | .start = TEGRA_HDMI_BASE, | ||
519 | .end = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1, | ||
520 | .flags = IORESOURCE_MEM, | ||
521 | }, | ||
522 | }; | ||
523 | #endif | ||
524 | |||
525 | #ifndef CONFIG_TEGRA_CARDHU_DSI | ||
526 | static struct tegra_dc_mode panel_19X12_modes[] = { | ||
527 | { | ||
528 | .pclk = 154000000, | ||
529 | .h_ref_to_sync = 11, | ||
530 | .v_ref_to_sync = 1, | ||
531 | .h_sync_width = 32, | ||
532 | .v_sync_width = 6, | ||
533 | .h_back_porch = 80, | ||
534 | .v_back_porch = 26, | ||
535 | .h_active = 1920, | ||
536 | .v_active = 1200, | ||
537 | .h_front_porch = 48, | ||
538 | .v_front_porch = 3, | ||
539 | }, | ||
540 | }; | ||
541 | |||
542 | static struct tegra_dc_mode cardhu_panel_modes[] = { | ||
543 | { | ||
544 | /* 1366x768@60Hz */ | ||
545 | .pclk = 74180000, | ||
546 | .h_ref_to_sync = 1, | ||
547 | .v_ref_to_sync = 1, | ||
548 | .h_sync_width = 30, | ||
549 | .v_sync_width = 5, | ||
550 | .h_back_porch = 52, | ||
551 | .v_back_porch = 20, | ||
552 | .h_active = 1366, | ||
553 | .v_active = 768, | ||
554 | .h_front_porch = 64, | ||
555 | .v_front_porch = 25, | ||
556 | }, | ||
557 | }; | ||
558 | |||
559 | static struct tegra_dc_mode cardhu_panel_modes_55hz[] = { | ||
560 | { | ||
561 | /* 1366x768p 55Hz */ | ||
562 | .pclk = 68000000, | ||
563 | .h_ref_to_sync = 0, | ||
564 | .v_ref_to_sync = 12, | ||
565 | .h_sync_width = 30, | ||
566 | .v_sync_width = 5, | ||
567 | .h_back_porch = 52, | ||
568 | .v_back_porch = 20, | ||
569 | .h_active = 1366, | ||
570 | .v_active = 768, | ||
571 | .h_front_porch = 64, | ||
572 | .v_front_porch = 25, | ||
573 | }, | ||
574 | }; | ||
575 | #endif | ||
576 | |||
577 | static struct tegra_dc_sd_settings cardhu_sd_settings = { | ||
578 | .enable = 1, /* enabled by default. */ | ||
579 | .use_auto_pwm = false, | ||
580 | .hw_update_delay = 0, | ||
581 | .bin_width = -1, | ||
582 | .aggressiveness = 1, | ||
583 | .phase_in_adjustments = true, | ||
584 | .use_vid_luma = false, | ||
585 | /* Default video coefficients */ | ||
586 | .coeff = {5, 9, 2}, | ||
587 | .fc = {0, 0}, | ||
588 | /* Immediate backlight changes */ | ||
589 | .blp = {1024, 255}, | ||
590 | /* Gammas: R: 2.2 G: 2.2 B: 2.2 */ | ||
591 | /* Default BL TF */ | ||
592 | .bltf = { | ||
593 | { | ||
594 | {57, 65, 74, 83}, | ||
595 | {93, 103, 114, 126}, | ||
596 | {138, 151, 165, 179}, | ||
597 | {194, 209, 225, 242}, | ||
598 | }, | ||
599 | { | ||
600 | {58, 66, 75, 84}, | ||
601 | {94, 105, 116, 127}, | ||
602 | {140, 153, 166, 181}, | ||
603 | {196, 211, 227, 244}, | ||
604 | }, | ||
605 | { | ||
606 | {60, 68, 77, 87}, | ||
607 | {97, 107, 119, 130}, | ||
608 | {143, 156, 170, 184}, | ||
609 | {199, 215, 231, 248}, | ||
610 | }, | ||
611 | { | ||
612 | {64, 73, 82, 91}, | ||
613 | {102, 113, 124, 137}, | ||
614 | {149, 163, 177, 192}, | ||
615 | {207, 223, 240, 255}, | ||
616 | }, | ||
617 | }, | ||
618 | /* Default LUT */ | ||
619 | .lut = { | ||
620 | { | ||
621 | {250, 250, 250}, | ||
622 | {194, 194, 194}, | ||
623 | {149, 149, 149}, | ||
624 | {113, 113, 113}, | ||
625 | {82, 82, 82}, | ||
626 | {56, 56, 56}, | ||
627 | {34, 34, 34}, | ||
628 | {15, 15, 15}, | ||
629 | {0, 0, 0}, | ||
630 | }, | ||
631 | { | ||
632 | {246, 246, 246}, | ||
633 | {191, 191, 191}, | ||
634 | {147, 147, 147}, | ||
635 | {111, 111, 111}, | ||
636 | {80, 80, 80}, | ||
637 | {55, 55, 55}, | ||
638 | {33, 33, 33}, | ||
639 | {14, 14, 14}, | ||
640 | {0, 0, 0}, | ||
641 | }, | ||
642 | { | ||
643 | {239, 239, 239}, | ||
644 | {185, 185, 185}, | ||
645 | {142, 142, 142}, | ||
646 | {107, 107, 107}, | ||
647 | {77, 77, 77}, | ||
648 | {52, 52, 52}, | ||
649 | {30, 30, 30}, | ||
650 | {12, 12, 12}, | ||
651 | {0, 0, 0}, | ||
652 | }, | ||
653 | { | ||
654 | {224, 224, 224}, | ||
655 | {173, 173, 173}, | ||
656 | {133, 133, 133}, | ||
657 | {99, 99, 99}, | ||
658 | {70, 70, 70}, | ||
659 | {46, 46, 46}, | ||
660 | {25, 25, 25}, | ||
661 | {7, 7, 7}, | ||
662 | {0, 0, 0}, | ||
663 | }, | ||
664 | }, | ||
665 | .sd_brightness = &sd_brightness, | ||
666 | .bl_device = &cardhu_backlight_device, | ||
667 | }; | ||
668 | |||
669 | #ifdef CONFIG_TEGRA_DC | ||
670 | #ifndef CONFIG_TEGRA_CARDHU_DSI | ||
671 | static struct tegra_fb_data cardhu_fb_data = { | ||
672 | .win = 0, | ||
673 | .xres = 1366, | ||
674 | .yres = 768, | ||
675 | .bits_per_pixel = 32, | ||
676 | .flags = TEGRA_FB_FLIP_ON_PROBE, | ||
677 | }; | ||
678 | #endif | ||
679 | |||
680 | static struct tegra_fb_data cardhu_hdmi_fb_data = { | ||
681 | .win = 0, | ||
682 | .xres = 1366, | ||
683 | .yres = 768, | ||
684 | .bits_per_pixel = 32, | ||
685 | .flags = TEGRA_FB_FLIP_ON_PROBE, | ||
686 | }; | ||
687 | |||
688 | static struct tegra_dc_out cardhu_disp2_out = { | ||
689 | .type = TEGRA_DC_OUT_HDMI, | ||
690 | .flags = TEGRA_DC_OUT_HOTPLUG_HIGH, | ||
691 | |||
692 | .dcc_bus = 3, | ||
693 | .hotplug_gpio = cardhu_hdmi_hpd, | ||
694 | |||
695 | .max_pixclock = KHZ2PICOS(148500), | ||
696 | |||
697 | .align = TEGRA_DC_ALIGN_MSB, | ||
698 | .order = TEGRA_DC_ORDER_RED_BLUE, | ||
699 | |||
700 | .enable = cardhu_hdmi_enable, | ||
701 | .disable = cardhu_hdmi_disable, | ||
702 | |||
703 | .postsuspend = cardhu_hdmi_vddio_disable, | ||
704 | .hotplug_init = cardhu_hdmi_vddio_enable, | ||
705 | }; | ||
706 | |||
707 | static struct tegra_dc_platform_data cardhu_disp2_pdata = { | ||
708 | .flags = 0, | ||
709 | .default_out = &cardhu_disp2_out, | ||
710 | .fb = &cardhu_hdmi_fb_data, | ||
711 | .emc_clk_rate = 300000000, | ||
712 | }; | ||
713 | #endif | ||
714 | |||
715 | #ifdef CONFIG_TEGRA_CARDHU_DSI | ||
716 | static int cardhu_dsi_panel_enable(void) | ||
717 | { | ||
718 | int ret; | ||
719 | |||
720 | if (cardhu_dsi_reg == NULL) { | ||
721 | cardhu_dsi_reg = regulator_get(NULL, "avdd_dsi_csi"); | ||
722 | if (IS_ERR_OR_NULL(cardhu_dsi_reg)) { | ||
723 | pr_err("dsi: Could not get regulator avdd_dsi_csi\n"); | ||
724 | cardhu_dsi_reg = NULL; | ||
725 | return PTR_ERR(cardhu_dsi_reg); | ||
726 | } | ||
727 | } | ||
728 | regulator_enable(cardhu_dsi_reg); | ||
729 | |||
730 | ret = gpio_request(AVDD_LCD, "avdd_lcd"); | ||
731 | if (ret < 0) | ||
732 | gpio_free(AVDD_LCD); | ||
733 | ret = gpio_direction_output(AVDD_LCD, 1); | ||
734 | if (ret < 0) | ||
735 | gpio_free(AVDD_LCD); | ||
736 | else | ||
737 | tegra_gpio_enable(AVDD_LCD); | ||
738 | |||
739 | #if DSI_PANEL_219 | ||
740 | |||
741 | ret = gpio_request(cardhu_bl_pwm, "bl_pwm"); | ||
742 | if (ret < 0) | ||
743 | return ret; | ||
744 | ret = gpio_direction_output(cardhu_bl_pwm, 0); | ||
745 | if (ret < 0) { | ||
746 | gpio_free(cardhu_bl_pwm); | ||
747 | return ret; | ||
748 | } else | ||
749 | tegra_gpio_enable(cardhu_bl_pwm); | ||
750 | |||
751 | ret = gpio_request(cardhu_bl_enb, "bl_enb"); | ||
752 | if (ret < 0) | ||
753 | return ret; | ||
754 | ret = gpio_direction_output(cardhu_bl_enb, 0); | ||
755 | if (ret < 0) { | ||
756 | gpio_free(cardhu_bl_enb); | ||
757 | return ret; | ||
758 | } else | ||
759 | tegra_gpio_enable(cardhu_bl_enb); | ||
760 | |||
761 | gpio_set_value(cardhu_lvds_shutdown, 1); | ||
762 | mdelay(20); | ||
763 | gpio_set_value(cardhu_bl_pwm, 1); | ||
764 | mdelay(10); | ||
765 | gpio_set_value(cardhu_bl_enb, 1); | ||
766 | mdelay(15); | ||
767 | #endif | ||
768 | |||
769 | #if DSI_PANEL_RESET | ||
770 | #if DSI_PANEL_218 | ||
771 | ret = gpio_request(cardhu_dsi_218_panel_reset, "dsi_panel_reset"); | ||
772 | if (ret < 0) { | ||
773 | return ret; | ||
774 | } | ||
775 | ret = gpio_direction_output(cardhu_dsi_218_panel_reset, 0); | ||
776 | if (ret < 0) { | ||
777 | gpio_free(cardhu_dsi_218_panel_reset); | ||
778 | return ret; | ||
779 | } else | ||
780 | tegra_gpio_enable(cardhu_dsi_218_panel_reset); | ||
781 | |||
782 | gpio_set_value(cardhu_dsi_218_panel_reset, 1); | ||
783 | gpio_set_value(cardhu_dsi_218_panel_reset, 0); | ||
784 | mdelay(2); | ||
785 | gpio_set_value(cardhu_dsi_218_panel_reset, 1); | ||
786 | mdelay(2); | ||
787 | #endif | ||
788 | |||
789 | #if DSI_PANEL_219 | ||
790 | ret = gpio_request(cardhu_dsi_219_panel_reset, "dsi_panel_reset"); | ||
791 | if (ret < 0) | ||
792 | return ret; | ||
793 | ret = gpio_direction_output(cardhu_dsi_219_panel_reset, 0); | ||
794 | if (ret < 0) { | ||
795 | gpio_free(cardhu_dsi_219_panel_reset); | ||
796 | return ret; | ||
797 | } else | ||
798 | tegra_gpio_enable(cardhu_dsi_219_panel_reset); | ||
799 | |||
800 | gpio_set_value(cardhu_dsi_219_panel_reset, 0); | ||
801 | gpio_set_value(cardhu_dsi_219_panel_reset, 1); | ||
802 | mdelay(10); | ||
803 | gpio_set_value(cardhu_dsi_219_panel_reset, 0); | ||
804 | mdelay(10); | ||
805 | gpio_set_value(cardhu_dsi_219_panel_reset, 1); | ||
806 | mdelay(15); | ||
807 | #endif | ||
808 | #endif | ||
809 | |||
810 | return 0; | ||
811 | } | ||
812 | |||
813 | static int cardhu_dsi_panel_disable(void) | ||
814 | { | ||
815 | int err; | ||
816 | |||
817 | err = 0; | ||
818 | printk(KERN_INFO "DSI panel disable\n"); | ||
819 | |||
820 | #if DSI_PANEL_219 | ||
821 | tegra_gpio_disable(cardhu_dsi_219_panel_reset); | ||
822 | gpio_free(cardhu_dsi_219_panel_reset); | ||
823 | tegra_gpio_disable(cardhu_bl_enb); | ||
824 | gpio_free(cardhu_bl_enb); | ||
825 | tegra_gpio_disable(cardhu_bl_pwm); | ||
826 | gpio_free(cardhu_bl_pwm); | ||
827 | tegra_gpio_disable(cardhu_lvds_shutdown); | ||
828 | gpio_free(cardhu_lvds_shutdown); | ||
829 | #endif | ||
830 | |||
831 | #if DSI_PANEL_218 | ||
832 | tegra_gpio_disable(cardhu_dsi_218_panel_reset); | ||
833 | gpio_free(cardhu_dsi_218_panel_reset); | ||
834 | #endif | ||
835 | |||
836 | return err; | ||
837 | } | ||
838 | |||
839 | static int cardhu_dsi_panel_postsuspend(void) | ||
840 | { | ||
841 | int err; | ||
842 | |||
843 | err = 0; | ||
844 | printk(KERN_INFO "DSI panel postsuspend\n"); | ||
845 | |||
846 | if (cardhu_dsi_reg) { | ||
847 | err = regulator_disable(cardhu_dsi_reg); | ||
848 | if (err < 0) | ||
849 | printk(KERN_ERR | ||
850 | "DSI regulator avdd_dsi_csi disable failed\n"); | ||
851 | regulator_put(cardhu_dsi_reg); | ||
852 | cardhu_dsi_reg = NULL; | ||
853 | } | ||
854 | |||
855 | #if DSI_PANEL_218 | ||
856 | tegra_gpio_disable(AVDD_LCD); | ||
857 | gpio_free(AVDD_LCD); | ||
858 | #endif | ||
859 | |||
860 | return err; | ||
861 | } | ||
862 | |||
863 | static struct tegra_dsi_cmd dsi_init_cmd[] = { | ||
864 | DSI_CMD_SHORT(0x05, 0x11, 0x00), | ||
865 | DSI_DLY_MS(150), | ||
866 | DSI_CMD_SHORT(0x05, 0x29, 0x00), | ||
867 | DSI_DLY_MS(20), | ||
868 | }; | ||
869 | |||
870 | static struct tegra_dsi_cmd dsi_suspend_cmd[] = { | ||
871 | DSI_CMD_SHORT(0x05, 0x28, 0x00), | ||
872 | DSI_DLY_MS(20), | ||
873 | DSI_CMD_SHORT(0x05, 0x10, 0x00), | ||
874 | DSI_DLY_MS(5), | ||
875 | }; | ||
876 | |||
877 | struct tegra_dsi_out cardhu_dsi = { | ||
878 | .n_data_lanes = 2, | ||
879 | .pixel_format = TEGRA_DSI_PIXEL_FORMAT_24BIT_P, | ||
880 | .refresh_rate = 60, | ||
881 | .virtual_channel = TEGRA_DSI_VIRTUAL_CHANNEL_0, | ||
882 | |||
883 | .panel_has_frame_buffer = true, | ||
884 | #ifdef CONFIG_TEGRA_DSI_INSTANCE_1 | ||
885 | .dsi_instance = 1, | ||
886 | #else | ||
887 | .dsi_instance = 0, | ||
888 | #endif | ||
889 | .panel_reset = DSI_PANEL_RESET, | ||
890 | .power_saving_suspend = true, | ||
891 | |||
892 | .n_init_cmd = ARRAY_SIZE(dsi_init_cmd), | ||
893 | .dsi_init_cmd = dsi_init_cmd, | ||
894 | |||
895 | .n_suspend_cmd = ARRAY_SIZE(dsi_suspend_cmd), | ||
896 | .dsi_suspend_cmd = dsi_suspend_cmd, | ||
897 | |||
898 | .video_data_type = TEGRA_DSI_VIDEO_TYPE_COMMAND_MODE, | ||
899 | .lp_cmd_mode_freq_khz = 430000, | ||
900 | }; | ||
901 | |||
902 | static struct tegra_dc_mode cardhu_dsi_modes[] = { | ||
903 | #if DSI_PANEL_219 | ||
904 | { | ||
905 | .pclk = 10000000, | ||
906 | .h_ref_to_sync = 4, | ||
907 | .v_ref_to_sync = 1, | ||
908 | .h_sync_width = 16, | ||
909 | .v_sync_width = 1, | ||
910 | .h_back_porch = 32, | ||
911 | .v_back_porch = 1, | ||
912 | .h_active = 540, | ||
913 | .v_active = 960, | ||
914 | .h_front_porch = 32, | ||
915 | .v_front_porch = 2, | ||
916 | }, | ||
917 | #endif | ||
918 | |||
919 | #if DSI_PANEL_218 | ||
920 | { | ||
921 | .pclk = 323000000, | ||
922 | .h_ref_to_sync = 11, | ||
923 | .v_ref_to_sync = 1, | ||
924 | .h_sync_width = 16, | ||
925 | .v_sync_width = 4, | ||
926 | .h_back_porch = 16, | ||
927 | .v_back_porch = 4, | ||
928 | .h_active = 864, | ||
929 | .v_active = 480, | ||
930 | .h_front_porch = 16, | ||
931 | .v_front_porch = 4, | ||
932 | }, | ||
933 | #endif | ||
934 | |||
935 | }; | ||
936 | |||
937 | |||
938 | static struct tegra_fb_data cardhu_dsi_fb_data = { | ||
939 | #if DSI_PANEL_219 | ||
940 | .win = 0, | ||
941 | .xres = 540, | ||
942 | .yres = 960, | ||
943 | .bits_per_pixel = 32, | ||
944 | #endif | ||
945 | |||
946 | #if DSI_PANEL_218 | ||
947 | .win = 0, | ||
948 | .xres = 864, | ||
949 | .yres = 480, | ||
950 | .bits_per_pixel = 32, | ||
951 | #endif | ||
952 | .flags = TEGRA_FB_FLIP_ON_PROBE, | ||
953 | }; | ||
954 | #endif | ||
955 | |||
956 | static struct tegra_dc_out cardhu_disp1_out = { | ||
957 | .align = TEGRA_DC_ALIGN_MSB, | ||
958 | .order = TEGRA_DC_ORDER_RED_BLUE, | ||
959 | .sd_settings = &cardhu_sd_settings, | ||
960 | |||
961 | #ifndef CONFIG_TEGRA_CARDHU_DSI | ||
962 | .parent_clk = "pll_p", | ||
963 | .parent_clk_backup = "pll_d2_out0", | ||
964 | |||
965 | .type = TEGRA_DC_OUT_RGB, | ||
966 | #ifdef CONFIG_TEGRA_LVDS_18_BITS | ||
967 | .depth = 18, | ||
968 | #endif | ||
969 | #ifdef CONFIG_TEGRA_LVDS_24_BITS | ||
970 | .depth = 24, | ||
971 | #endif | ||
972 | .dither = TEGRA_DC_ORDERED_DITHER, | ||
973 | |||
974 | .modes = cardhu_panel_modes, | ||
975 | .n_modes = ARRAY_SIZE(cardhu_panel_modes), | ||
976 | |||
977 | .enable = cardhu_panel_enable, | ||
978 | .disable = cardhu_panel_disable, | ||
979 | #else | ||
980 | .type = TEGRA_DC_OUT_DSI, | ||
981 | |||
982 | .modes = cardhu_dsi_modes, | ||
983 | .n_modes = ARRAY_SIZE(cardhu_dsi_modes), | ||
984 | |||
985 | .dsi = &cardhu_dsi, | ||
986 | |||
987 | .enable = cardhu_dsi_panel_enable, | ||
988 | .disable = cardhu_dsi_panel_disable, | ||
989 | .postsuspend = cardhu_dsi_panel_postsuspend, | ||
990 | #endif | ||
991 | }; | ||
992 | |||
993 | #ifdef CONFIG_TEGRA_DC | ||
994 | static struct tegra_dc_platform_data cardhu_disp1_pdata = { | ||
995 | .flags = TEGRA_DC_FLAG_ENABLED, | ||
996 | .default_out = &cardhu_disp1_out, | ||
997 | .emc_clk_rate = 300000000, | ||
998 | #ifndef CONFIG_TEGRA_CARDHU_DSI | ||
999 | .fb = &cardhu_fb_data, | ||
1000 | #else | ||
1001 | .fb = &cardhu_dsi_fb_data, | ||
1002 | #endif | ||
1003 | }; | ||
1004 | |||
1005 | static struct nvhost_device cardhu_disp1_device = { | ||
1006 | .name = "tegradc", | ||
1007 | .id = 0, | ||
1008 | .resource = cardhu_disp1_resources, | ||
1009 | .num_resources = ARRAY_SIZE(cardhu_disp1_resources), | ||
1010 | .dev = { | ||
1011 | .platform_data = &cardhu_disp1_pdata, | ||
1012 | }, | ||
1013 | }; | ||
1014 | |||
1015 | static int cardhu_disp1_check_fb(struct device *dev, struct fb_info *info) | ||
1016 | { | ||
1017 | return info->device == &cardhu_disp1_device.dev; | ||
1018 | } | ||
1019 | |||
1020 | static struct nvhost_device cardhu_disp2_device = { | ||
1021 | .name = "tegradc", | ||
1022 | .id = 1, | ||
1023 | .resource = cardhu_disp2_resources, | ||
1024 | .num_resources = ARRAY_SIZE(cardhu_disp2_resources), | ||
1025 | .dev = { | ||
1026 | .platform_data = &cardhu_disp2_pdata, | ||
1027 | }, | ||
1028 | }; | ||
1029 | #else | ||
1030 | static int cardhu_disp1_check_fb(struct device *dev, struct fb_info *info) | ||
1031 | { | ||
1032 | return 0; | ||
1033 | } | ||
1034 | #endif | ||
1035 | |||
1036 | #if defined(CONFIG_TEGRA_NVMAP) | ||
1037 | static struct nvmap_platform_carveout cardhu_carveouts[] = { | ||
1038 | [0] = NVMAP_HEAP_CARVEOUT_IRAM_INIT, | ||
1039 | [1] = { | ||
1040 | .name = "generic-0", | ||
1041 | .usage_mask = NVMAP_HEAP_CARVEOUT_GENERIC, | ||
1042 | .base = 0, /* Filled in by cardhu_panel_init() */ | ||
1043 | .size = 0, /* Filled in by cardhu_panel_init() */ | ||
1044 | .buddy_size = SZ_32K, | ||
1045 | }, | ||
1046 | }; | ||
1047 | |||
1048 | static struct nvmap_platform_data cardhu_nvmap_data = { | ||
1049 | .carveouts = cardhu_carveouts, | ||
1050 | .nr_carveouts = ARRAY_SIZE(cardhu_carveouts), | ||
1051 | }; | ||
1052 | |||
1053 | static struct platform_device cardhu_nvmap_device = { | ||
1054 | .name = "tegra-nvmap", | ||
1055 | .id = -1, | ||
1056 | .dev = { | ||
1057 | .platform_data = &cardhu_nvmap_data, | ||
1058 | }, | ||
1059 | }; | ||
1060 | #endif | ||
1061 | |||
1062 | #if defined(CONFIG_ION_TEGRA) | ||
1063 | |||
1064 | static struct platform_device tegra_iommu_device = { | ||
1065 | .name = "tegra_iommu_device", | ||
1066 | .id = -1, | ||
1067 | .dev = { | ||
1068 | .platform_data = (void *)((1 << HWGRP_COUNT) - 1), | ||
1069 | }, | ||
1070 | }; | ||
1071 | |||
1072 | static struct ion_platform_data tegra_ion_data = { | ||
1073 | .nr = 4, | ||
1074 | .heaps = { | ||
1075 | { | ||
1076 | .type = ION_HEAP_TYPE_CARVEOUT, | ||
1077 | .id = TEGRA_ION_HEAP_CARVEOUT, | ||
1078 | .name = "carveout", | ||
1079 | .base = 0, | ||
1080 | .size = 0, | ||
1081 | }, | ||
1082 | { | ||
1083 | .type = ION_HEAP_TYPE_CARVEOUT, | ||
1084 | .id = TEGRA_ION_HEAP_IRAM, | ||
1085 | .name = "iram", | ||
1086 | .base = TEGRA_IRAM_BASE + TEGRA_RESET_HANDLER_SIZE, | ||
1087 | .size = TEGRA_IRAM_SIZE - TEGRA_RESET_HANDLER_SIZE, | ||
1088 | }, | ||
1089 | { | ||
1090 | .type = ION_HEAP_TYPE_CARVEOUT, | ||
1091 | .id = TEGRA_ION_HEAP_VPR, | ||
1092 | .name = "vpr", | ||
1093 | .base = 0, | ||
1094 | .size = 0, | ||
1095 | }, | ||
1096 | { | ||
1097 | .type = ION_HEAP_TYPE_IOMMU, | ||
1098 | .id = TEGRA_ION_HEAP_IOMMU, | ||
1099 | .name = "iommu", | ||
1100 | .base = TEGRA_SMMU_BASE, | ||
1101 | .size = TEGRA_SMMU_SIZE, | ||
1102 | .priv = &tegra_iommu_device.dev, | ||
1103 | }, | ||
1104 | }, | ||
1105 | }; | ||
1106 | |||
1107 | static struct platform_device tegra_ion_device = { | ||
1108 | .name = "ion-tegra", | ||
1109 | .id = -1, | ||
1110 | .dev = { | ||
1111 | .platform_data = &tegra_ion_data, | ||
1112 | }, | ||
1113 | }; | ||
1114 | #endif | ||
1115 | |||
1116 | static struct platform_device *cardhu_gfx_devices[] __initdata = { | ||
1117 | #if defined(CONFIG_TEGRA_NVMAP) | ||
1118 | &cardhu_nvmap_device, | ||
1119 | #endif | ||
1120 | #if defined(CONFIG_ION_TEGRA) | ||
1121 | &tegra_ion_device, | ||
1122 | #endif | ||
1123 | &tegra_pwfm0_device, | ||
1124 | &cardhu_backlight_device, | ||
1125 | }; | ||
1126 | |||
1127 | |||
1128 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
1129 | /* put early_suspend/late_resume handlers here for the display in order | ||
1130 | * to keep the code out of the display driver, keeping it closer to upstream | ||
1131 | */ | ||
1132 | struct early_suspend cardhu_panel_early_suspender; | ||
1133 | |||
1134 | static void cardhu_panel_early_suspend(struct early_suspend *h) | ||
1135 | { | ||
1136 | /* power down LCD, add use a black screen for HDMI */ | ||
1137 | if (num_registered_fb > 0) | ||
1138 | fb_blank(registered_fb[0], FB_BLANK_POWERDOWN); | ||
1139 | if (num_registered_fb > 1) | ||
1140 | fb_blank(registered_fb[1], FB_BLANK_NORMAL); | ||
1141 | } | ||
1142 | |||
1143 | static void cardhu_panel_late_resume(struct early_suspend *h) | ||
1144 | { | ||
1145 | unsigned i; | ||
1146 | for (i = 0; i < num_registered_fb; i++) | ||
1147 | fb_blank(registered_fb[i], FB_BLANK_UNBLANK); | ||
1148 | } | ||
1149 | #endif | ||
1150 | |||
1151 | int __init cardhu_panel_init(void) | ||
1152 | { | ||
1153 | int err; | ||
1154 | struct resource __maybe_unused *res; | ||
1155 | |||
1156 | tegra_get_board_info(&board_info); | ||
1157 | tegra_get_display_board_info(&display_board_info); | ||
1158 | |||
1159 | #if defined(CONFIG_TEGRA_NVMAP) | ||
1160 | cardhu_carveouts[1].base = tegra_carveout_start; | ||
1161 | cardhu_carveouts[1].size = tegra_carveout_size; | ||
1162 | #endif | ||
1163 | |||
1164 | #if defined(CONFIG_ION_TEGRA) | ||
1165 | tegra_ion_data.heaps[0].base = tegra_carveout_start; | ||
1166 | tegra_ion_data.heaps[0].size = tegra_carveout_size; | ||
1167 | #endif | ||
1168 | |||
1169 | #if defined(CONFIG_TEGRA_DC) && !defined(CONFIG_TEGRA_CARDHU_DSI) | ||
1170 | if (board_info.board_id == BOARD_E1291 && | ||
1171 | ((board_info.sku & SKU_TOUCHSCREEN_MECH_FIX) == 0)) { | ||
1172 | /* use 55Hz panel timings to reduce noise on sensitive touch */ | ||
1173 | printk("Using cardhu_panel_modes_55hz\n"); | ||
1174 | cardhu_disp1_out.modes = cardhu_panel_modes_55hz; | ||
1175 | cardhu_disp1_out.n_modes = ARRAY_SIZE(cardhu_panel_modes_55hz); | ||
1176 | } | ||
1177 | |||
1178 | if (display_board_info.board_id == BOARD_DISPLAY_PM313) { | ||
1179 | /* initialize the values */ | ||
1180 | #if defined(PM313_LVDS_PANEL_19X12) | ||
1181 | cardhu_disp1_out.modes = panel_19X12_modes; | ||
1182 | cardhu_disp1_out.n_modes = ARRAY_SIZE(panel_19X12_modes); | ||
1183 | cardhu_disp1_out.parent_clk = "pll_d_out0"; | ||
1184 | #if (PM313_LVDS_PANEL_BPP == 1) | ||
1185 | cardhu_disp1_out.depth = 18; | ||
1186 | #else | ||
1187 | cardhu_disp1_out.depth = 24; | ||
1188 | #endif | ||
1189 | cardhu_fb_data.xres = 1920; | ||
1190 | cardhu_fb_data.yres = 1200; | ||
1191 | |||
1192 | cardhu_disp2_out.parent_clk = "pll_d2_out0"; | ||
1193 | cardhu_hdmi_fb_data.xres = 1920; | ||
1194 | cardhu_hdmi_fb_data.yres = 1200; | ||
1195 | #endif | ||
1196 | |||
1197 | /* lvds configuration */ | ||
1198 | err = gpio_request(pm313_R_FDE, "R_FDE"); | ||
1199 | err |= gpio_direction_output(pm313_R_FDE, 1); | ||
1200 | tegra_gpio_enable(pm313_R_FDE); | ||
1201 | |||
1202 | err |= gpio_request(pm313_R_FB, "R_FB"); | ||
1203 | err |= gpio_direction_output(pm313_R_FB, 1); | ||
1204 | tegra_gpio_enable(pm313_R_FB); | ||
1205 | |||
1206 | err |= gpio_request(pm313_MODE0, "MODE0"); | ||
1207 | err |= gpio_direction_output(pm313_MODE0, 1); | ||
1208 | tegra_gpio_enable(pm313_MODE0); | ||
1209 | |||
1210 | err |= gpio_request(pm313_MODE1, "MODE1"); | ||
1211 | err |= gpio_direction_output(pm313_MODE1, 0); | ||
1212 | tegra_gpio_enable(pm313_MODE1); | ||
1213 | |||
1214 | err |= gpio_request(pm313_BPP, "BPP"); | ||
1215 | err |= gpio_direction_output(pm313_BPP, PM313_LVDS_PANEL_BPP); | ||
1216 | tegra_gpio_enable(pm313_BPP); | ||
1217 | |||
1218 | err = gpio_request(pm313_lvds_shutdown, "lvds_shutdown"); | ||
1219 | /* free ride provided by bootloader */ | ||
1220 | err |= gpio_direction_output(pm313_lvds_shutdown, 1); | ||
1221 | tegra_gpio_enable(pm313_lvds_shutdown); | ||
1222 | |||
1223 | if (err) | ||
1224 | printk(KERN_ERR "ERROR(s) in LVDS configuration\n"); | ||
1225 | } else if ((display_board_info.board_id == BOARD_DISPLAY_E1247 && | ||
1226 | board_info.board_id == BOARD_PM269) || | ||
1227 | (board_info.board_id == BOARD_E1257) || | ||
1228 | (board_info.board_id == BOARD_PM305) || | ||
1229 | (board_info.board_id == BOARD_PM311)) { | ||
1230 | gpio_request(e1247_pm269_lvds_shutdown, "lvds_shutdown"); | ||
1231 | gpio_direction_output(e1247_pm269_lvds_shutdown, 1); | ||
1232 | tegra_gpio_enable(e1247_pm269_lvds_shutdown); | ||
1233 | } else { | ||
1234 | gpio_request(cardhu_lvds_shutdown, "lvds_shutdown"); | ||
1235 | gpio_direction_output(cardhu_lvds_shutdown, 1); | ||
1236 | tegra_gpio_enable(cardhu_lvds_shutdown); | ||
1237 | } | ||
1238 | #endif | ||
1239 | |||
1240 | tegra_gpio_enable(cardhu_hdmi_hpd); | ||
1241 | gpio_request(cardhu_hdmi_hpd, "hdmi_hpd"); | ||
1242 | gpio_direction_input(cardhu_hdmi_hpd); | ||
1243 | |||
1244 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
1245 | cardhu_panel_early_suspender.suspend = cardhu_panel_early_suspend; | ||
1246 | cardhu_panel_early_suspender.resume = cardhu_panel_late_resume; | ||
1247 | cardhu_panel_early_suspender.level = EARLY_SUSPEND_LEVEL_DISABLE_FB; | ||
1248 | register_early_suspend(&cardhu_panel_early_suspender); | ||
1249 | #endif | ||
1250 | |||
1251 | #ifdef CONFIG_TEGRA_GRHOST | ||
1252 | err = nvhost_device_register(&tegra_grhost_device); | ||
1253 | if (err) | ||
1254 | return err; | ||
1255 | #endif | ||
1256 | |||
1257 | err = platform_add_devices(cardhu_gfx_devices, | ||
1258 | ARRAY_SIZE(cardhu_gfx_devices)); | ||
1259 | |||
1260 | #if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC) | ||
1261 | res = nvhost_get_resource_byname(&cardhu_disp1_device, | ||
1262 | IORESOURCE_MEM, "fbmem"); | ||
1263 | res->start = tegra_fb_start; | ||
1264 | res->end = tegra_fb_start + tegra_fb_size - 1; | ||
1265 | #endif | ||
1266 | |||
1267 | /* Copy the bootloader fb to the fb. */ | ||
1268 | tegra_move_framebuffer(tegra_fb_start, tegra_bootloader_fb_start, | ||
1269 | min(tegra_fb_size, tegra_bootloader_fb_size)); | ||
1270 | |||
1271 | #if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC) | ||
1272 | if (!err) | ||
1273 | err = nvhost_device_register(&cardhu_disp1_device); | ||
1274 | |||
1275 | res = nvhost_get_resource_byname(&cardhu_disp2_device, | ||
1276 | IORESOURCE_MEM, "fbmem"); | ||
1277 | res->start = tegra_fb2_start; | ||
1278 | res->end = tegra_fb2_start + tegra_fb2_size - 1; | ||
1279 | if (!err) | ||
1280 | err = nvhost_device_register(&cardhu_disp2_device); | ||
1281 | #endif | ||
1282 | |||
1283 | #if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_NVAVP) | ||
1284 | if (!err) | ||
1285 | err = nvhost_device_register(&nvavp_device); | ||
1286 | #endif | ||
1287 | return err; | ||
1288 | } | ||