diff options
Diffstat (limited to 'arch/arm/mach-tegra/board-kai-panel.c')
-rw-r--r-- | arch/arm/mach-tegra/board-kai-panel.c | 740 |
1 files changed, 740 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/board-kai-panel.c b/arch/arm/mach-tegra/board-kai-panel.c new file mode 100644 index 00000000000..71e238fdcdc --- /dev/null +++ b/arch/arm/mach-tegra/board-kai-panel.c | |||
@@ -0,0 +1,740 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/board-kai-panel.c | ||
3 | * | ||
4 | * Copyright (c) 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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along | ||
16 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/delay.h> | ||
21 | #include <linux/gpio.h> | ||
22 | #include <linux/regulator/consumer.h> | ||
23 | #include <linux/resource.h> | ||
24 | #include <asm/mach-types.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/earlysuspend.h> | ||
27 | #include <linux/pwm_backlight.h> | ||
28 | #include <asm/atomic.h> | ||
29 | #include <linux/nvhost.h> | ||
30 | #include <mach/nvmap.h> | ||
31 | #include <mach/irqs.h> | ||
32 | #include <mach/iomap.h> | ||
33 | #include <mach/dc.h> | ||
34 | #include <mach/fb.h> | ||
35 | |||
36 | #include "board.h" | ||
37 | #include "board-kai.h" | ||
38 | #include "devices.h" | ||
39 | #include "gpio-names.h" | ||
40 | |||
41 | /* kai default display board pins */ | ||
42 | #define kai_lvds_avdd_en TEGRA_GPIO_PH6 | ||
43 | #define kai_lvds_stdby TEGRA_GPIO_PG5 | ||
44 | #define kai_lvds_rst TEGRA_GPIO_PG7 | ||
45 | #define kai_lvds_shutdown TEGRA_GPIO_PN6 | ||
46 | #define kai_lvds_rs TEGRA_GPIO_PV6 | ||
47 | #define kai_lvds_lr TEGRA_GPIO_PG1 | ||
48 | |||
49 | /* kai A00 display board pins */ | ||
50 | #define kai_lvds_rs_a00 TEGRA_GPIO_PH1 | ||
51 | |||
52 | /* common pins( backlight ) for all display boards */ | ||
53 | #define kai_bl_enb TEGRA_GPIO_PH3 | ||
54 | #define kai_bl_pwm TEGRA_GPIO_PH0 | ||
55 | #define kai_hdmi_hpd TEGRA_GPIO_PN7 | ||
56 | |||
57 | #ifdef CONFIG_TEGRA_DC | ||
58 | static struct regulator *kai_hdmi_reg; | ||
59 | static struct regulator *kai_hdmi_pll; | ||
60 | static struct regulator *kai_hdmi_vddio; | ||
61 | #endif | ||
62 | |||
63 | static atomic_t sd_brightness = ATOMIC_INIT(255); | ||
64 | |||
65 | static struct regulator *kai_lvds_reg; | ||
66 | static struct regulator *kai_lvds_vdd_panel; | ||
67 | |||
68 | static tegra_dc_bl_output kai_bl_output_measured = { | ||
69 | 0, 1, 2, 3, 4, 5, 6, 7, | ||
70 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
71 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
72 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
73 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
74 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
75 | 48, 49, 49, 50, 51, 52, 53, 54, | ||
76 | 55, 56, 57, 58, 59, 60, 61, 62, | ||
77 | 63, 64, 65, 66, 67, 68, 69, 70, | ||
78 | 70, 72, 73, 74, 75, 76, 77, 78, | ||
79 | 79, 80, 81, 82, 83, 84, 85, 86, | ||
80 | 87, 88, 89, 90, 91, 92, 93, 94, | ||
81 | 95, 96, 97, 98, 99, 100, 101, 102, | ||
82 | 103, 104, 105, 106, 107, 108, 110, 111, | ||
83 | 112, 113, 114, 115, 116, 117, 118, 119, | ||
84 | 120, 121, 122, 123, 124, 124, 125, 126, | ||
85 | 127, 128, 129, 130, 131, 132, 133, 133, | ||
86 | 134, 135, 136, 137, 138, 139, 140, 141, | ||
87 | 142, 143, 144, 145, 146, 147, 148, 148, | ||
88 | 149, 150, 151, 152, 153, 154, 155, 156, | ||
89 | 157, 158, 159, 160, 161, 162, 163, 164, | ||
90 | 165, 166, 167, 168, 169, 170, 171, 172, | ||
91 | 173, 174, 175, 176, 177, 179, 180, 181, | ||
92 | 182, 184, 185, 186, 187, 188, 189, 190, | ||
93 | 191, 192, 193, 194, 195, 196, 197, 198, | ||
94 | 199, 200, 201, 202, 203, 204, 205, 206, | ||
95 | 207, 208, 209, 211, 212, 213, 214, 215, | ||
96 | 216, 217, 218, 219, 220, 221, 222, 223, | ||
97 | 224, 225, 226, 227, 228, 229, 230, 231, | ||
98 | 232, 233, 234, 235, 236, 237, 238, 239, | ||
99 | 240, 241, 242, 243, 244, 245, 246, 247, | ||
100 | 248, 249, 250, 251, 252, 253, 254, 255 | ||
101 | }; | ||
102 | |||
103 | static p_tegra_dc_bl_output bl_output; | ||
104 | |||
105 | static int kai_backlight_init(struct device *dev) | ||
106 | { | ||
107 | int ret; | ||
108 | |||
109 | bl_output = kai_bl_output_measured; | ||
110 | |||
111 | if (WARN_ON(ARRAY_SIZE(kai_bl_output_measured) != 256)) | ||
112 | pr_err("bl_output array does not have 256 elements\n"); | ||
113 | |||
114 | tegra_gpio_disable(kai_bl_pwm); | ||
115 | |||
116 | ret = gpio_request(kai_bl_enb, "backlight_enb"); | ||
117 | if (ret < 0) | ||
118 | return ret; | ||
119 | |||
120 | ret = gpio_direction_output(kai_bl_enb, 1); | ||
121 | if (ret < 0) | ||
122 | gpio_free(kai_bl_enb); | ||
123 | else | ||
124 | tegra_gpio_enable(kai_bl_enb); | ||
125 | |||
126 | return ret; | ||
127 | }; | ||
128 | |||
129 | static void kai_backlight_exit(struct device *dev) | ||
130 | { | ||
131 | /* int ret; */ | ||
132 | /*ret = gpio_request(kai_bl_enb, "backlight_enb");*/ | ||
133 | gpio_set_value(kai_bl_enb, 0); | ||
134 | gpio_free(kai_bl_enb); | ||
135 | tegra_gpio_disable(kai_bl_enb); | ||
136 | return; | ||
137 | } | ||
138 | |||
139 | static int kai_backlight_notify(struct device *unused, int brightness) | ||
140 | { | ||
141 | int cur_sd_brightness = atomic_read(&sd_brightness); | ||
142 | |||
143 | /* Set the backlight GPIO pin mode to 'backlight_enable' */ | ||
144 | gpio_set_value(kai_bl_enb, !!brightness); | ||
145 | |||
146 | /* SD brightness is a percentage, 8-bit value. */ | ||
147 | brightness = (brightness * cur_sd_brightness) / 255; | ||
148 | |||
149 | /* Apply any backlight response curve */ | ||
150 | if (brightness > 255) | ||
151 | pr_info("Error: Brightness > 255!\n"); | ||
152 | else | ||
153 | brightness = bl_output[brightness]; | ||
154 | |||
155 | return brightness; | ||
156 | } | ||
157 | |||
158 | static int kai_disp1_check_fb(struct device *dev, struct fb_info *info); | ||
159 | |||
160 | static struct platform_pwm_backlight_data kai_backlight_data = { | ||
161 | .pwm_id = 0, | ||
162 | .max_brightness = 255, | ||
163 | .dft_brightness = 224, | ||
164 | .pwm_period_ns = 100000, | ||
165 | .init = kai_backlight_init, | ||
166 | .exit = kai_backlight_exit, | ||
167 | .notify = kai_backlight_notify, | ||
168 | /* Only toggle backlight on fb blank notifications for disp1 */ | ||
169 | .check_fb = kai_disp1_check_fb, | ||
170 | }; | ||
171 | |||
172 | static struct platform_device kai_backlight_device = { | ||
173 | .name = "pwm-backlight", | ||
174 | .id = -1, | ||
175 | .dev = { | ||
176 | .platform_data = &kai_backlight_data, | ||
177 | }, | ||
178 | }; | ||
179 | |||
180 | static int kai_panel_enable(void) | ||
181 | { | ||
182 | if (kai_lvds_reg == NULL) { | ||
183 | kai_lvds_reg = regulator_get(NULL, "vdd_lvds"); | ||
184 | if (WARN_ON(IS_ERR(kai_lvds_reg))) | ||
185 | pr_err("%s: couldn't get regulator vdd_lvds: %ld\n", | ||
186 | __func__, PTR_ERR(kai_lvds_reg)); | ||
187 | else | ||
188 | regulator_enable(kai_lvds_reg); | ||
189 | } | ||
190 | |||
191 | if (kai_lvds_vdd_panel == NULL) { | ||
192 | kai_lvds_vdd_panel = regulator_get(NULL, "vdd_lcd_panel"); | ||
193 | if (WARN_ON(IS_ERR(kai_lvds_vdd_panel))) | ||
194 | pr_err("%s: couldn't get regulator vdd_lcd_panel: %ld\n", | ||
195 | __func__, PTR_ERR(kai_lvds_vdd_panel)); | ||
196 | else | ||
197 | regulator_enable(kai_lvds_vdd_panel); | ||
198 | } | ||
199 | |||
200 | mdelay(5); | ||
201 | |||
202 | gpio_set_value(kai_lvds_avdd_en, 1); | ||
203 | mdelay(5); | ||
204 | |||
205 | gpio_set_value(kai_lvds_stdby, 1); | ||
206 | gpio_set_value(kai_lvds_rst, 1); | ||
207 | gpio_set_value(kai_lvds_shutdown, 1); | ||
208 | gpio_set_value(kai_lvds_lr, 1); | ||
209 | |||
210 | mdelay(10); | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static int kai_panel_disable(void) | ||
216 | { | ||
217 | gpio_set_value(kai_lvds_lr, 0); | ||
218 | gpio_set_value(kai_lvds_shutdown, 0); | ||
219 | gpio_set_value(kai_lvds_rst, 0); | ||
220 | gpio_set_value(kai_lvds_stdby, 0); | ||
221 | mdelay(5); | ||
222 | |||
223 | gpio_set_value(kai_lvds_avdd_en, 0); | ||
224 | mdelay(5); | ||
225 | |||
226 | regulator_disable(kai_lvds_reg); | ||
227 | regulator_put(kai_lvds_reg); | ||
228 | kai_lvds_reg = NULL; | ||
229 | |||
230 | regulator_disable(kai_lvds_vdd_panel); | ||
231 | regulator_put(kai_lvds_vdd_panel); | ||
232 | kai_lvds_vdd_panel = NULL; | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | #ifdef CONFIG_TEGRA_DC | ||
238 | static int kai_hdmi_vddio_enable(void) | ||
239 | { | ||
240 | int ret; | ||
241 | if (!kai_hdmi_vddio) { | ||
242 | kai_hdmi_vddio = regulator_get(NULL, "vdd_hdmi_con"); | ||
243 | if (IS_ERR_OR_NULL(kai_hdmi_vddio)) { | ||
244 | ret = PTR_ERR(kai_hdmi_vddio); | ||
245 | pr_err("hdmi: couldn't get regulator vdd_hdmi_con\n"); | ||
246 | kai_hdmi_vddio = NULL; | ||
247 | return ret; | ||
248 | } | ||
249 | } | ||
250 | ret = regulator_enable(kai_hdmi_vddio); | ||
251 | if (ret < 0) { | ||
252 | pr_err("hdmi: couldn't enable regulator vdd_hdmi_con\n"); | ||
253 | regulator_put(kai_hdmi_vddio); | ||
254 | kai_hdmi_vddio = NULL; | ||
255 | return ret; | ||
256 | } | ||
257 | return ret; | ||
258 | } | ||
259 | |||
260 | static int kai_hdmi_vddio_disable(void) | ||
261 | { | ||
262 | if (kai_hdmi_vddio) { | ||
263 | regulator_disable(kai_hdmi_vddio); | ||
264 | regulator_put(kai_hdmi_vddio); | ||
265 | kai_hdmi_vddio = NULL; | ||
266 | } | ||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static int kai_hdmi_enable(void) | ||
271 | { | ||
272 | int ret; | ||
273 | if (!kai_hdmi_reg) { | ||
274 | kai_hdmi_reg = regulator_get(NULL, "avdd_hdmi"); | ||
275 | if (IS_ERR_OR_NULL(kai_hdmi_reg)) { | ||
276 | pr_err("hdmi: couldn't get regulator avdd_hdmi\n"); | ||
277 | kai_hdmi_reg = NULL; | ||
278 | return PTR_ERR(kai_hdmi_reg); | ||
279 | } | ||
280 | } | ||
281 | ret = regulator_enable(kai_hdmi_reg); | ||
282 | if (ret < 0) { | ||
283 | pr_err("hdmi: couldn't enable regulator avdd_hdmi\n"); | ||
284 | return ret; | ||
285 | } | ||
286 | if (!kai_hdmi_pll) { | ||
287 | kai_hdmi_pll = regulator_get(NULL, "avdd_hdmi_pll"); | ||
288 | if (IS_ERR_OR_NULL(kai_hdmi_pll)) { | ||
289 | pr_err("hdmi: couldn't get regulator avdd_hdmi_pll\n"); | ||
290 | kai_hdmi_pll = NULL; | ||
291 | regulator_put(kai_hdmi_reg); | ||
292 | kai_hdmi_reg = NULL; | ||
293 | return PTR_ERR(kai_hdmi_pll); | ||
294 | } | ||
295 | } | ||
296 | ret = regulator_enable(kai_hdmi_pll); | ||
297 | if (ret < 0) { | ||
298 | pr_err("hdmi: couldn't enable regulator avdd_hdmi_pll\n"); | ||
299 | return ret; | ||
300 | } | ||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static int kai_hdmi_disable(void) | ||
305 | { | ||
306 | regulator_disable(kai_hdmi_reg); | ||
307 | regulator_put(kai_hdmi_reg); | ||
308 | kai_hdmi_reg = NULL; | ||
309 | |||
310 | regulator_disable(kai_hdmi_pll); | ||
311 | regulator_put(kai_hdmi_pll); | ||
312 | kai_hdmi_pll = NULL; | ||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static struct resource kai_disp1_resources[] = { | ||
317 | { | ||
318 | .name = "irq", | ||
319 | .start = INT_DISPLAY_GENERAL, | ||
320 | .end = INT_DISPLAY_GENERAL, | ||
321 | .flags = IORESOURCE_IRQ, | ||
322 | }, | ||
323 | { | ||
324 | .name = "regs", | ||
325 | .start = TEGRA_DISPLAY_BASE, | ||
326 | .end = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE-1, | ||
327 | .flags = IORESOURCE_MEM, | ||
328 | }, | ||
329 | { | ||
330 | .name = "fbmem", | ||
331 | .start = 0, /* Filled in by kai_panel_init() */ | ||
332 | .end = 0, /* Filled in by kai_panel_init() */ | ||
333 | .flags = IORESOURCE_MEM, | ||
334 | }, | ||
335 | }; | ||
336 | |||
337 | static struct resource kai_disp2_resources[] = { | ||
338 | { | ||
339 | .name = "irq", | ||
340 | .start = INT_DISPLAY_B_GENERAL, | ||
341 | .end = INT_DISPLAY_B_GENERAL, | ||
342 | .flags = IORESOURCE_IRQ, | ||
343 | }, | ||
344 | { | ||
345 | .name = "regs", | ||
346 | .start = TEGRA_DISPLAY2_BASE, | ||
347 | .end = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1, | ||
348 | .flags = IORESOURCE_MEM, | ||
349 | }, | ||
350 | { | ||
351 | .name = "fbmem", | ||
352 | .flags = IORESOURCE_MEM, | ||
353 | .start = 0, | ||
354 | .end = 0, | ||
355 | }, | ||
356 | { | ||
357 | .name = "hdmi_regs", | ||
358 | .start = TEGRA_HDMI_BASE, | ||
359 | .end = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1, | ||
360 | .flags = IORESOURCE_MEM, | ||
361 | }, | ||
362 | }; | ||
363 | #endif | ||
364 | |||
365 | static struct tegra_dc_mode kai_panel_modes[] = { | ||
366 | { | ||
367 | /* 1024x600@60Hz */ | ||
368 | .pclk = 51206000, | ||
369 | .h_ref_to_sync = 11, | ||
370 | .v_ref_to_sync = 1, | ||
371 | .h_sync_width = 10, | ||
372 | .v_sync_width = 5, | ||
373 | .h_back_porch = 10, | ||
374 | .v_back_porch = 15, | ||
375 | .h_active = 1024, | ||
376 | .v_active = 600, | ||
377 | .h_front_porch = 300, | ||
378 | .v_front_porch = 15, | ||
379 | }, | ||
380 | }; | ||
381 | |||
382 | static struct tegra_dc_sd_settings kai_sd_settings = { | ||
383 | .enable = 1, /* enabled by default. */ | ||
384 | .use_auto_pwm = false, | ||
385 | .hw_update_delay = 0, | ||
386 | .bin_width = -1, | ||
387 | .aggressiveness = 1, | ||
388 | .phase_in_adjustments = true, | ||
389 | .use_vid_luma = false, | ||
390 | /* Default video coefficients */ | ||
391 | .coeff = {5, 9, 2}, | ||
392 | .fc = {0, 0}, | ||
393 | /* Immediate backlight changes */ | ||
394 | .blp = {1024, 255}, | ||
395 | /* Gammas: R: 2.2 G: 2.2 B: 2.2 */ | ||
396 | /* Default BL TF */ | ||
397 | .bltf = { | ||
398 | { | ||
399 | {57, 65, 74, 83}, | ||
400 | {93, 103, 114, 126}, | ||
401 | {138, 151, 165, 179}, | ||
402 | {194, 209, 225, 242}, | ||
403 | }, | ||
404 | { | ||
405 | {58, 66, 75, 84}, | ||
406 | {94, 105, 116, 127}, | ||
407 | {140, 153, 166, 181}, | ||
408 | {196, 211, 227, 244}, | ||
409 | }, | ||
410 | { | ||
411 | {60, 68, 77, 87}, | ||
412 | {97, 107, 119, 130}, | ||
413 | {143, 156, 170, 184}, | ||
414 | {199, 215, 231, 248}, | ||
415 | }, | ||
416 | { | ||
417 | {64, 73, 82, 91}, | ||
418 | {102, 113, 124, 137}, | ||
419 | {149, 163, 177, 192}, | ||
420 | {207, 223, 240, 255}, | ||
421 | }, | ||
422 | }, | ||
423 | /* Default LUT */ | ||
424 | .lut = { | ||
425 | { | ||
426 | {250, 250, 250}, | ||
427 | {194, 194, 194}, | ||
428 | {149, 149, 149}, | ||
429 | {113, 113, 113}, | ||
430 | {82, 82, 82}, | ||
431 | {56, 56, 56}, | ||
432 | {34, 34, 34}, | ||
433 | {15, 15, 15}, | ||
434 | {0, 0, 0}, | ||
435 | }, | ||
436 | { | ||
437 | {246, 246, 246}, | ||
438 | {191, 191, 191}, | ||
439 | {147, 147, 147}, | ||
440 | {111, 111, 111}, | ||
441 | {80, 80, 80}, | ||
442 | {55, 55, 55}, | ||
443 | {33, 33, 33}, | ||
444 | {14, 14, 14}, | ||
445 | {0, 0, 0}, | ||
446 | }, | ||
447 | { | ||
448 | {239, 239, 239}, | ||
449 | {185, 185, 185}, | ||
450 | {142, 142, 142}, | ||
451 | {107, 107, 107}, | ||
452 | {77, 77, 77}, | ||
453 | {52, 52, 52}, | ||
454 | {30, 30, 30}, | ||
455 | {12, 12, 12}, | ||
456 | {0, 0, 0}, | ||
457 | }, | ||
458 | { | ||
459 | {224, 224, 224}, | ||
460 | {173, 173, 173}, | ||
461 | {133, 133, 133}, | ||
462 | {99, 99, 99}, | ||
463 | {70, 70, 70}, | ||
464 | {46, 46, 46}, | ||
465 | {25, 25, 25}, | ||
466 | {7, 7, 7}, | ||
467 | {0, 0, 0}, | ||
468 | }, | ||
469 | }, | ||
470 | .sd_brightness = &sd_brightness, | ||
471 | .bl_device = &kai_backlight_device, | ||
472 | }; | ||
473 | |||
474 | #ifdef CONFIG_TEGRA_DC | ||
475 | static struct tegra_fb_data kai_fb_data = { | ||
476 | .win = 0, | ||
477 | .xres = 1024, | ||
478 | .yres = 600, | ||
479 | .bits_per_pixel = 32, | ||
480 | .flags = TEGRA_FB_FLIP_ON_PROBE, | ||
481 | }; | ||
482 | |||
483 | static struct tegra_fb_data kai_hdmi_fb_data = { | ||
484 | .win = 0, | ||
485 | .xres = 1024, | ||
486 | .yres = 600, | ||
487 | .bits_per_pixel = 32, | ||
488 | .flags = TEGRA_FB_FLIP_ON_PROBE, | ||
489 | }; | ||
490 | |||
491 | static struct tegra_dc_out kai_disp2_out = { | ||
492 | .type = TEGRA_DC_OUT_HDMI, | ||
493 | .flags = TEGRA_DC_OUT_HOTPLUG_HIGH, | ||
494 | |||
495 | .dcc_bus = 3, | ||
496 | .hotplug_gpio = kai_hdmi_hpd, | ||
497 | |||
498 | .max_pixclock = KHZ2PICOS(148500), | ||
499 | |||
500 | .align = TEGRA_DC_ALIGN_MSB, | ||
501 | .order = TEGRA_DC_ORDER_RED_BLUE, | ||
502 | |||
503 | .enable = kai_hdmi_enable, | ||
504 | .disable = kai_hdmi_disable, | ||
505 | |||
506 | .postsuspend = kai_hdmi_vddio_disable, | ||
507 | .hotplug_init = kai_hdmi_vddio_enable, | ||
508 | }; | ||
509 | |||
510 | static struct tegra_dc_platform_data kai_disp2_pdata = { | ||
511 | .flags = 0, | ||
512 | .default_out = &kai_disp2_out, | ||
513 | .fb = &kai_hdmi_fb_data, | ||
514 | .emc_clk_rate = 300000000, | ||
515 | }; | ||
516 | #endif | ||
517 | |||
518 | static struct tegra_dc_out kai_disp1_out = { | ||
519 | .align = TEGRA_DC_ALIGN_MSB, | ||
520 | .order = TEGRA_DC_ORDER_RED_BLUE, | ||
521 | .sd_settings = &kai_sd_settings, | ||
522 | .parent_clk = "pll_p", | ||
523 | .parent_clk_backup = "pll_d2_out0", | ||
524 | |||
525 | .type = TEGRA_DC_OUT_RGB, | ||
526 | .depth = 18, | ||
527 | .dither = TEGRA_DC_ORDERED_DITHER, | ||
528 | |||
529 | .modes = kai_panel_modes, | ||
530 | .n_modes = ARRAY_SIZE(kai_panel_modes), | ||
531 | |||
532 | .enable = kai_panel_enable, | ||
533 | .disable = kai_panel_disable, | ||
534 | }; | ||
535 | |||
536 | #ifdef CONFIG_TEGRA_DC | ||
537 | static struct tegra_dc_platform_data kai_disp1_pdata = { | ||
538 | .flags = TEGRA_DC_FLAG_ENABLED, | ||
539 | .default_out = &kai_disp1_out, | ||
540 | .emc_clk_rate = 300000000, | ||
541 | .fb = &kai_fb_data, | ||
542 | }; | ||
543 | |||
544 | static struct nvhost_device kai_disp1_device = { | ||
545 | .name = "tegradc", | ||
546 | .id = 0, | ||
547 | .resource = kai_disp1_resources, | ||
548 | .num_resources = ARRAY_SIZE(kai_disp1_resources), | ||
549 | .dev = { | ||
550 | .platform_data = &kai_disp1_pdata, | ||
551 | }, | ||
552 | }; | ||
553 | |||
554 | static int kai_disp1_check_fb(struct device *dev, struct fb_info *info) | ||
555 | { | ||
556 | return info->device == &kai_disp1_device.dev; | ||
557 | } | ||
558 | |||
559 | static struct nvhost_device kai_disp2_device = { | ||
560 | .name = "tegradc", | ||
561 | .id = 1, | ||
562 | .resource = kai_disp2_resources, | ||
563 | .num_resources = ARRAY_SIZE(kai_disp2_resources), | ||
564 | .dev = { | ||
565 | .platform_data = &kai_disp2_pdata, | ||
566 | }, | ||
567 | }; | ||
568 | #else | ||
569 | static int kai_disp1_check_fb(struct device *dev, struct fb_info *info) | ||
570 | { | ||
571 | return 0; | ||
572 | } | ||
573 | #endif | ||
574 | |||
575 | #if defined(CONFIG_TEGRA_NVMAP) | ||
576 | static struct nvmap_platform_carveout kai_carveouts[] = { | ||
577 | [0] = NVMAP_HEAP_CARVEOUT_IRAM_INIT, | ||
578 | [1] = { | ||
579 | .name = "generic-0", | ||
580 | .usage_mask = NVMAP_HEAP_CARVEOUT_GENERIC, | ||
581 | .base = 0, /* Filled in by kai_panel_init() */ | ||
582 | .size = 0, /* Filled in by kai_panel_init() */ | ||
583 | .buddy_size = SZ_32K, | ||
584 | }, | ||
585 | }; | ||
586 | |||
587 | static struct nvmap_platform_data kai_nvmap_data = { | ||
588 | .carveouts = kai_carveouts, | ||
589 | .nr_carveouts = ARRAY_SIZE(kai_carveouts), | ||
590 | }; | ||
591 | |||
592 | static struct platform_device kai_nvmap_device = { | ||
593 | .name = "tegra-nvmap", | ||
594 | .id = -1, | ||
595 | .dev = { | ||
596 | .platform_data = &kai_nvmap_data, | ||
597 | }, | ||
598 | }; | ||
599 | #endif | ||
600 | |||
601 | static struct platform_device *kai_gfx_devices[] __initdata = { | ||
602 | #if defined(CONFIG_TEGRA_NVMAP) | ||
603 | &kai_nvmap_device, | ||
604 | #endif | ||
605 | &tegra_pwfm0_device, | ||
606 | &kai_backlight_device, | ||
607 | }; | ||
608 | |||
609 | |||
610 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
611 | /* put early_suspend/late_resume handlers here for the display in order | ||
612 | * to keep the code out of the display driver, keeping it closer to upstream | ||
613 | */ | ||
614 | struct early_suspend kai_panel_early_suspender; | ||
615 | |||
616 | static void kai_panel_early_suspend(struct early_suspend *h) | ||
617 | { | ||
618 | /* power down LCD, add use a black screen for HDMI */ | ||
619 | if (num_registered_fb > 0) | ||
620 | fb_blank(registered_fb[0], FB_BLANK_POWERDOWN); | ||
621 | if (num_registered_fb > 1) | ||
622 | fb_blank(registered_fb[1], FB_BLANK_NORMAL); | ||
623 | |||
624 | #ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND | ||
625 | cpufreq_save_default_governor(); | ||
626 | cpufreq_set_conservative_governor(); | ||
627 | cpufreq_set_conservative_governor_param("up_threshold", | ||
628 | SET_CONSERVATIVE_GOVERNOR_UP_THRESHOLD); | ||
629 | |||
630 | cpufreq_set_conservative_governor_param("down_threshold", | ||
631 | SET_CONSERVATIVE_GOVERNOR_DOWN_THRESHOLD); | ||
632 | |||
633 | cpufreq_set_conservative_governor_param("freq_step", | ||
634 | SET_CONSERVATIVE_GOVERNOR_FREQ_STEP); | ||
635 | #endif | ||
636 | |||
637 | } | ||
638 | |||
639 | static void kai_panel_late_resume(struct early_suspend *h) | ||
640 | { | ||
641 | unsigned i; | ||
642 | #ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND | ||
643 | cpufreq_restore_default_governor(); | ||
644 | #endif | ||
645 | for (i = 0; i < num_registered_fb; i++) | ||
646 | fb_blank(registered_fb[i], FB_BLANK_UNBLANK); | ||
647 | } | ||
648 | #endif | ||
649 | |||
650 | int __init kai_panel_init(void) | ||
651 | { | ||
652 | int err; | ||
653 | struct resource __maybe_unused *res; | ||
654 | struct board_info board_info; | ||
655 | |||
656 | tegra_get_board_info(&board_info); | ||
657 | |||
658 | #if defined(CONFIG_TEGRA_NVMAP) | ||
659 | kai_carveouts[1].base = tegra_carveout_start; | ||
660 | kai_carveouts[1].size = tegra_carveout_size; | ||
661 | #endif | ||
662 | gpio_request(kai_lvds_avdd_en, "lvds_avdd_en"); | ||
663 | gpio_direction_output(kai_lvds_avdd_en, 1); | ||
664 | tegra_gpio_enable(kai_lvds_avdd_en); | ||
665 | |||
666 | gpio_request(kai_lvds_stdby, "lvds_stdby"); | ||
667 | gpio_direction_output(kai_lvds_stdby, 1); | ||
668 | tegra_gpio_enable(kai_lvds_stdby); | ||
669 | |||
670 | gpio_request(kai_lvds_rst, "lvds_rst"); | ||
671 | gpio_direction_output(kai_lvds_rst, 1); | ||
672 | tegra_gpio_enable(kai_lvds_rst); | ||
673 | |||
674 | if (board_info.fab == BOARD_FAB_A00) { | ||
675 | gpio_request(kai_lvds_rs_a00, "lvds_rs"); | ||
676 | gpio_direction_output(kai_lvds_rs_a00, 0); | ||
677 | tegra_gpio_enable(kai_lvds_rs_a00); | ||
678 | } else { | ||
679 | gpio_request(kai_lvds_rs, "lvds_rs"); | ||
680 | gpio_direction_output(kai_lvds_rs, 0); | ||
681 | tegra_gpio_enable(kai_lvds_rs); | ||
682 | } | ||
683 | |||
684 | gpio_request(kai_lvds_lr, "lvds_lr"); | ||
685 | gpio_direction_output(kai_lvds_lr, 1); | ||
686 | tegra_gpio_enable(kai_lvds_lr); | ||
687 | |||
688 | gpio_request(kai_lvds_shutdown, "lvds_shutdown"); | ||
689 | gpio_direction_output(kai_lvds_shutdown, 1); | ||
690 | tegra_gpio_enable(kai_lvds_shutdown); | ||
691 | |||
692 | tegra_gpio_enable(kai_hdmi_hpd); | ||
693 | gpio_request(kai_hdmi_hpd, "hdmi_hpd"); | ||
694 | gpio_direction_input(kai_hdmi_hpd); | ||
695 | |||
696 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
697 | kai_panel_early_suspender.suspend = kai_panel_early_suspend; | ||
698 | kai_panel_early_suspender.resume = kai_panel_late_resume; | ||
699 | kai_panel_early_suspender.level = EARLY_SUSPEND_LEVEL_DISABLE_FB; | ||
700 | register_early_suspend(&kai_panel_early_suspender); | ||
701 | #endif | ||
702 | |||
703 | #ifdef CONFIG_TEGRA_GRHOST | ||
704 | err = nvhost_device_register(&tegra_grhost_device); | ||
705 | if (err) | ||
706 | return err; | ||
707 | #endif | ||
708 | |||
709 | err = platform_add_devices(kai_gfx_devices, | ||
710 | ARRAY_SIZE(kai_gfx_devices)); | ||
711 | |||
712 | #if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC) | ||
713 | res = nvhost_get_resource_byname(&kai_disp1_device, | ||
714 | IORESOURCE_MEM, "fbmem"); | ||
715 | res->start = tegra_fb_start; | ||
716 | res->end = tegra_fb_start + tegra_fb_size - 1; | ||
717 | #endif | ||
718 | |||
719 | /* Copy the bootloader fb to the fb. */ | ||
720 | tegra_move_framebuffer(tegra_fb_start, tegra_bootloader_fb_start, | ||
721 | min(tegra_fb_size, tegra_bootloader_fb_size)); | ||
722 | |||
723 | #if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC) | ||
724 | if (!err) | ||
725 | err = nvhost_device_register(&kai_disp1_device); | ||
726 | |||
727 | res = nvhost_get_resource_byname(&kai_disp2_device, | ||
728 | IORESOURCE_MEM, "fbmem"); | ||
729 | res->start = tegra_fb2_start; | ||
730 | res->end = tegra_fb2_start + tegra_fb2_size - 1; | ||
731 | if (!err) | ||
732 | err = nvhost_device_register(&kai_disp2_device); | ||
733 | #endif | ||
734 | |||
735 | #if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_NVAVP) | ||
736 | if (!err) | ||
737 | err = nvhost_device_register(&nvavp_device); | ||
738 | #endif | ||
739 | return err; | ||
740 | } | ||