diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /arch/arm/mach-tegra/board-enterprise-panel.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'arch/arm/mach-tegra/board-enterprise-panel.c')
-rw-r--r-- | arch/arm/mach-tegra/board-enterprise-panel.c | 905 |
1 files changed, 905 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/board-enterprise-panel.c b/arch/arm/mach-tegra/board-enterprise-panel.c new file mode 100644 index 00000000000..9dc5da1f28d --- /dev/null +++ b/arch/arm/mach-tegra/board-enterprise-panel.c | |||
@@ -0,0 +1,905 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/board-enterprise-panel.c | ||
3 | * | ||
4 | * Copyright (c) 2011-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/gpio.h> | ||
23 | #include <linux/regulator/consumer.h> | ||
24 | #include <linux/resource.h> | ||
25 | #include <asm/mach-types.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/earlysuspend.h> | ||
28 | #include <linux/tegra_pwm_bl.h> | ||
29 | #include <asm/atomic.h> | ||
30 | #include <linux/nvhost.h> | ||
31 | #include <mach/nvmap.h> | ||
32 | #include <mach/irqs.h> | ||
33 | #include <mach/iomap.h> | ||
34 | #include <mach/dc.h> | ||
35 | #include <mach/fb.h> | ||
36 | #include <mach/hardware.h> | ||
37 | |||
38 | #include "board.h" | ||
39 | #include "board-enterprise.h" | ||
40 | #include "devices.h" | ||
41 | #include "gpio-names.h" | ||
42 | |||
43 | #define DC_CTRL_MODE TEGRA_DC_OUT_ONE_SHOT_MODE | ||
44 | |||
45 | /* Select panel to be used. */ | ||
46 | #define AVDD_LCD PMU_TCA6416_GPIO_PORT17 | ||
47 | #define DSI_PANEL_RESET 1 | ||
48 | |||
49 | #define enterprise_lvds_shutdown TEGRA_GPIO_PL2 | ||
50 | #define enterprise_hdmi_hpd TEGRA_GPIO_PN7 | ||
51 | |||
52 | #define enterprise_dsi_panel_reset TEGRA_GPIO_PW0 | ||
53 | |||
54 | #define enterprise_lcd_2d_3d TEGRA_GPIO_PH1 | ||
55 | #define ENTERPRISE_STEREO_3D 0 | ||
56 | #define ENTERPRISE_STEREO_2D 1 | ||
57 | |||
58 | #define enterprise_lcd_swp_pl TEGRA_GPIO_PH2 | ||
59 | #define ENTERPRISE_STEREO_LANDSCAPE 0 | ||
60 | #define ENTERPRISE_STEREO_PORTRAIT 1 | ||
61 | |||
62 | #define enterprise_lcd_te TEGRA_GPIO_PJ1 | ||
63 | |||
64 | #ifdef CONFIG_TEGRA_DC | ||
65 | static struct regulator *enterprise_dsi_reg; | ||
66 | static struct regulator *enterprise_lcd_reg; | ||
67 | |||
68 | static struct regulator *enterprise_hdmi_reg; | ||
69 | static struct regulator *enterprise_hdmi_pll; | ||
70 | static struct regulator *enterprise_hdmi_vddio; | ||
71 | #endif | ||
72 | |||
73 | static atomic_t sd_brightness = ATOMIC_INIT(255); | ||
74 | |||
75 | static tegra_dc_bl_output enterprise_bl_output_measured_a02 = { | ||
76 | 1, 5, 9, 10, 11, 12, 12, 13, | ||
77 | 13, 14, 14, 15, 15, 16, 16, 17, | ||
78 | 17, 18, 18, 19, 19, 20, 21, 21, | ||
79 | 22, 22, 23, 24, 24, 25, 26, 26, | ||
80 | 27, 27, 28, 29, 29, 31, 31, 32, | ||
81 | 32, 33, 34, 35, 36, 36, 37, 38, | ||
82 | 39, 39, 40, 41, 41, 42, 43, 43, | ||
83 | 44, 45, 45, 46, 47, 47, 48, 49, | ||
84 | 49, 50, 51, 51, 52, 53, 53, 54, | ||
85 | 55, 56, 56, 57, 58, 59, 60, 61, | ||
86 | 61, 62, 63, 64, 65, 65, 66, 67, | ||
87 | 67, 68, 69, 69, 70, 71, 71, 72, | ||
88 | 73, 73, 74, 74, 75, 76, 76, 77, | ||
89 | 77, 78, 79, 79, 80, 81, 82, 83, | ||
90 | 83, 84, 85, 85, 86, 86, 88, 89, | ||
91 | 90, 91, 91, 92, 93, 93, 94, 95, | ||
92 | 95, 96, 97, 97, 98, 99, 99, 100, | ||
93 | 101, 101, 102, 103, 103, 104, 105, 105, | ||
94 | 107, 107, 108, 109, 110, 111, 111, 112, | ||
95 | 113, 113, 114, 115, 115, 116, 117, 117, | ||
96 | 118, 119, 119, 120, 121, 122, 123, 124, | ||
97 | 124, 125, 126, 126, 127, 128, 129, 129, | ||
98 | 130, 131, 131, 132, 133, 133, 134, 135, | ||
99 | 135, 136, 137, 137, 138, 139, 139, 140, | ||
100 | 142, 142, 143, 144, 145, 146, 147, 147, | ||
101 | 148, 149, 149, 150, 151, 152, 153, 153, | ||
102 | 153, 154, 155, 156, 157, 158, 158, 159, | ||
103 | 160, 161, 162, 163, 163, 164, 165, 165, | ||
104 | 166, 166, 167, 168, 169, 169, 170, 170, | ||
105 | 171, 172, 173, 173, 174, 175, 175, 176, | ||
106 | 176, 178, 178, 179, 180, 181, 182, 182, | ||
107 | 183, 184, 185, 186, 186, 187, 188, 188 | ||
108 | }; | ||
109 | |||
110 | /* TODO: Measure BL response for this table */ | ||
111 | static tegra_dc_bl_output enterprise_bl_output_measured_a03 = { | ||
112 | 0, 1, 2, 3, 4, 5, 6, 7, | ||
113 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
114 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
115 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
116 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
117 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
118 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
119 | 56, 57, 58, 59, 60, 61, 62, 63, | ||
120 | 64, 65, 66, 67, 68, 69, 70, 71, | ||
121 | 72, 73, 74, 75, 76, 77, 78, 79, | ||
122 | 80, 81, 82, 83, 84, 85, 86, 87, | ||
123 | 88, 89, 90, 91, 92, 93, 94, 95, | ||
124 | 96, 97, 98, 99, 100, 101, 102, 103, | ||
125 | 104, 105, 106, 107, 108, 109, 110, 111, | ||
126 | 112, 113, 114, 115, 116, 117, 118, 119, | ||
127 | 120, 121, 122, 123, 124, 125, 126, 127, | ||
128 | 128, 129, 130, 131, 132, 133, 134, 135, | ||
129 | 136, 137, 138, 139, 140, 141, 142, 143, | ||
130 | 144, 145, 146, 147, 148, 149, 150, 151, | ||
131 | 152, 153, 154, 155, 156, 157, 158, 159, | ||
132 | 160, 161, 162, 163, 164, 165, 166, 167, | ||
133 | 168, 169, 170, 171, 172, 173, 174, 175, | ||
134 | 176, 177, 178, 179, 180, 181, 182, 183, | ||
135 | 184, 185, 186, 187, 188, 189, 190, 191, | ||
136 | 192, 193, 194, 195, 196, 197, 198, 199, | ||
137 | 200, 201, 202, 203, 204, 205, 206, 207, | ||
138 | 208, 209, 210, 211, 212, 213, 214, 215, | ||
139 | 216, 217, 218, 219, 220, 221, 222, 223, | ||
140 | 224, 225, 226, 227, 228, 229, 230, 231, | ||
141 | 232, 233, 234, 235, 236, 237, 238, 239, | ||
142 | 240, 241, 242, 243, 244, 245, 246, 247, | ||
143 | 248, 249, 250, 251, 252, 253, 254, 255, | ||
144 | }; | ||
145 | |||
146 | static p_tegra_dc_bl_output bl_output; | ||
147 | |||
148 | static bool kernel_1st_panel_init = true; | ||
149 | |||
150 | static int enterprise_backlight_notify(struct device *unused, int brightness) | ||
151 | { | ||
152 | int cur_sd_brightness = atomic_read(&sd_brightness); | ||
153 | int orig_brightness = brightness; | ||
154 | |||
155 | /* SD brightness is a percentage, 8-bit value. */ | ||
156 | brightness = (brightness * cur_sd_brightness) / 255; | ||
157 | |||
158 | /* Apply any backlight response curve */ | ||
159 | if (brightness > 255) | ||
160 | pr_info("Error: Brightness > 255!\n"); | ||
161 | else | ||
162 | brightness = bl_output[brightness]; | ||
163 | |||
164 | return brightness; | ||
165 | } | ||
166 | |||
167 | static int enterprise_disp1_check_fb(struct device *dev, struct fb_info *info); | ||
168 | |||
169 | /* | ||
170 | * In case which_pwm is TEGRA_PWM_PM0, | ||
171 | * gpio_conf_to_sfio should be TEGRA_GPIO_PW0: set LCD_CS1_N pin to SFIO | ||
172 | * In case which_pwm is TEGRA_PWM_PM1, | ||
173 | * gpio_conf_to_sfio should be TEGRA_GPIO_PW1: set LCD_M1 pin to SFIO | ||
174 | */ | ||
175 | static struct platform_tegra_pwm_backlight_data enterprise_disp1_backlight_data = { | ||
176 | .which_dc = 0, | ||
177 | .which_pwm = TEGRA_PWM_PM1, | ||
178 | .gpio_conf_to_sfio = TEGRA_GPIO_PW1, | ||
179 | .switch_to_sfio = &tegra_gpio_disable, | ||
180 | .max_brightness = 255, | ||
181 | .dft_brightness = 224, | ||
182 | .notify = enterprise_backlight_notify, | ||
183 | .period = 0xFF, | ||
184 | .clk_div = 0x3FF, | ||
185 | .clk_select = 0, | ||
186 | /* Only toggle backlight on fb blank notifications for disp1 */ | ||
187 | .check_fb = enterprise_disp1_check_fb, | ||
188 | }; | ||
189 | |||
190 | static struct platform_device enterprise_disp1_backlight_device = { | ||
191 | .name = "tegra-pwm-bl", | ||
192 | .id = -1, | ||
193 | .dev = { | ||
194 | .platform_data = &enterprise_disp1_backlight_data, | ||
195 | }, | ||
196 | }; | ||
197 | |||
198 | #ifdef CONFIG_TEGRA_DC | ||
199 | static int enterprise_hdmi_vddio_enable(void) | ||
200 | { | ||
201 | int ret; | ||
202 | if (!enterprise_hdmi_vddio) { | ||
203 | enterprise_hdmi_vddio = regulator_get(NULL, "hdmi_5v0"); | ||
204 | if (IS_ERR_OR_NULL(enterprise_hdmi_vddio)) { | ||
205 | ret = PTR_ERR(enterprise_hdmi_vddio); | ||
206 | pr_err("hdmi: couldn't get regulator hdmi_5v0\n"); | ||
207 | enterprise_hdmi_vddio = NULL; | ||
208 | return ret; | ||
209 | } | ||
210 | } | ||
211 | ret = regulator_enable(enterprise_hdmi_vddio); | ||
212 | if (ret < 0) { | ||
213 | pr_err("hdmi: couldn't enable regulator hdmi_5v0\n"); | ||
214 | regulator_put(enterprise_hdmi_vddio); | ||
215 | enterprise_hdmi_vddio = NULL; | ||
216 | return ret; | ||
217 | } | ||
218 | return ret; | ||
219 | } | ||
220 | |||
221 | static int enterprise_hdmi_vddio_disable(void) | ||
222 | { | ||
223 | if (enterprise_hdmi_vddio) { | ||
224 | regulator_disable(enterprise_hdmi_vddio); | ||
225 | regulator_put(enterprise_hdmi_vddio); | ||
226 | enterprise_hdmi_vddio = NULL; | ||
227 | } | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int enterprise_hdmi_enable(void) | ||
232 | { | ||
233 | int ret; | ||
234 | if (!enterprise_hdmi_reg) { | ||
235 | enterprise_hdmi_reg = regulator_get(NULL, "avdd_hdmi"); | ||
236 | if (IS_ERR_OR_NULL(enterprise_hdmi_reg)) { | ||
237 | pr_err("hdmi: couldn't get regulator avdd_hdmi\n"); | ||
238 | enterprise_hdmi_reg = NULL; | ||
239 | return PTR_ERR(enterprise_hdmi_reg); | ||
240 | } | ||
241 | } | ||
242 | ret = regulator_enable(enterprise_hdmi_reg); | ||
243 | if (ret < 0) { | ||
244 | pr_err("hdmi: couldn't enable regulator avdd_hdmi\n"); | ||
245 | return ret; | ||
246 | } | ||
247 | if (!enterprise_hdmi_pll) { | ||
248 | enterprise_hdmi_pll = regulator_get(NULL, "avdd_hdmi_pll"); | ||
249 | if (IS_ERR_OR_NULL(enterprise_hdmi_pll)) { | ||
250 | pr_err("hdmi: couldn't get regulator avdd_hdmi_pll\n"); | ||
251 | enterprise_hdmi_pll = NULL; | ||
252 | regulator_put(enterprise_hdmi_reg); | ||
253 | enterprise_hdmi_reg = NULL; | ||
254 | return PTR_ERR(enterprise_hdmi_pll); | ||
255 | } | ||
256 | } | ||
257 | ret = regulator_enable(enterprise_hdmi_pll); | ||
258 | if (ret < 0) { | ||
259 | pr_err("hdmi: couldn't enable regulator avdd_hdmi_pll\n"); | ||
260 | return ret; | ||
261 | } | ||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static int enterprise_hdmi_disable(void) | ||
266 | { | ||
267 | |||
268 | regulator_disable(enterprise_hdmi_reg); | ||
269 | regulator_put(enterprise_hdmi_reg); | ||
270 | enterprise_hdmi_reg = NULL; | ||
271 | |||
272 | regulator_disable(enterprise_hdmi_pll); | ||
273 | regulator_put(enterprise_hdmi_pll); | ||
274 | enterprise_hdmi_pll = NULL; | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | static struct resource enterprise_disp1_resources[] = { | ||
279 | { | ||
280 | .name = "irq", | ||
281 | .start = INT_DISPLAY_GENERAL, | ||
282 | .end = INT_DISPLAY_GENERAL, | ||
283 | .flags = IORESOURCE_IRQ, | ||
284 | }, | ||
285 | { | ||
286 | .name = "regs", | ||
287 | .start = TEGRA_DISPLAY_BASE, | ||
288 | .end = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE-1, | ||
289 | .flags = IORESOURCE_MEM, | ||
290 | }, | ||
291 | { | ||
292 | .name = "fbmem", | ||
293 | .start = 0, /* Filled in by enterprise_panel_init() */ | ||
294 | .end = 0, /* Filled in by enterprise_panel_init() */ | ||
295 | .flags = IORESOURCE_MEM, | ||
296 | }, | ||
297 | { | ||
298 | .name = "dsi_regs", | ||
299 | .start = TEGRA_DSI_BASE, | ||
300 | .end = TEGRA_DSI_BASE + TEGRA_DSI_SIZE - 1, | ||
301 | .flags = IORESOURCE_MEM, | ||
302 | }, | ||
303 | }; | ||
304 | |||
305 | static struct resource enterprise_disp2_resources[] = { | ||
306 | { | ||
307 | .name = "irq", | ||
308 | .start = INT_DISPLAY_B_GENERAL, | ||
309 | .end = INT_DISPLAY_B_GENERAL, | ||
310 | .flags = IORESOURCE_IRQ, | ||
311 | }, | ||
312 | { | ||
313 | .name = "regs", | ||
314 | .start = TEGRA_DISPLAY2_BASE, | ||
315 | .end = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1, | ||
316 | .flags = IORESOURCE_MEM, | ||
317 | }, | ||
318 | { | ||
319 | .name = "fbmem", | ||
320 | .flags = IORESOURCE_MEM, | ||
321 | .start = 0, | ||
322 | .end = 0, | ||
323 | }, | ||
324 | { | ||
325 | .name = "hdmi_regs", | ||
326 | .start = TEGRA_HDMI_BASE, | ||
327 | .end = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1, | ||
328 | .flags = IORESOURCE_MEM, | ||
329 | }, | ||
330 | }; | ||
331 | |||
332 | static struct tegra_dc_sd_settings enterprise_sd_settings = { | ||
333 | .enable = 1, /* Normal mode operation */ | ||
334 | .use_auto_pwm = false, | ||
335 | .hw_update_delay = 0, | ||
336 | .bin_width = -1, | ||
337 | .aggressiveness = 1, | ||
338 | .phase_in_adjustments = true, | ||
339 | .use_vid_luma = false, | ||
340 | /* Default video coefficients */ | ||
341 | .coeff = {5, 9, 2}, | ||
342 | .fc = {0, 0}, | ||
343 | /* Immediate backlight changes */ | ||
344 | .blp = {1024, 255}, | ||
345 | /* Gammas: R: 2.2 G: 2.2 B: 2.2 */ | ||
346 | /* Default BL TF */ | ||
347 | .bltf = { | ||
348 | { | ||
349 | {57, 65, 74, 83}, | ||
350 | {93, 103, 114, 126}, | ||
351 | {138, 151, 165, 179}, | ||
352 | {194, 209, 225, 242}, | ||
353 | }, | ||
354 | { | ||
355 | {58, 66, 75, 84}, | ||
356 | {94, 105, 116, 127}, | ||
357 | {140, 153, 166, 181}, | ||
358 | {196, 211, 227, 244}, | ||
359 | }, | ||
360 | { | ||
361 | {60, 68, 77, 87}, | ||
362 | {97, 107, 119, 130}, | ||
363 | {143, 156, 170, 184}, | ||
364 | {199, 215, 231, 248}, | ||
365 | }, | ||
366 | { | ||
367 | {64, 73, 82, 91}, | ||
368 | {102, 113, 124, 137}, | ||
369 | {149, 163, 177, 192}, | ||
370 | {207, 223, 240, 255}, | ||
371 | }, | ||
372 | }, | ||
373 | /* Default LUT */ | ||
374 | .lut = { | ||
375 | { | ||
376 | {250, 250, 250}, | ||
377 | {194, 194, 194}, | ||
378 | {149, 149, 149}, | ||
379 | {113, 113, 113}, | ||
380 | {82, 82, 82}, | ||
381 | {56, 56, 56}, | ||
382 | {34, 34, 34}, | ||
383 | {15, 15, 15}, | ||
384 | {0, 0, 0}, | ||
385 | }, | ||
386 | { | ||
387 | {246, 246, 246}, | ||
388 | {191, 191, 191}, | ||
389 | {147, 147, 147}, | ||
390 | {111, 111, 111}, | ||
391 | {80, 80, 80}, | ||
392 | {55, 55, 55}, | ||
393 | {33, 33, 33}, | ||
394 | {14, 14, 14}, | ||
395 | {0, 0, 0}, | ||
396 | }, | ||
397 | { | ||
398 | {239, 239, 239}, | ||
399 | {185, 185, 185}, | ||
400 | {142, 142, 142}, | ||
401 | {107, 107, 107}, | ||
402 | {77, 77, 77}, | ||
403 | {52, 52, 52}, | ||
404 | {30, 30, 30}, | ||
405 | {12, 12, 12}, | ||
406 | {0, 0, 0}, | ||
407 | }, | ||
408 | { | ||
409 | {224, 224, 224}, | ||
410 | {173, 173, 173}, | ||
411 | {133, 133, 133}, | ||
412 | {99, 99, 99}, | ||
413 | {70, 70, 70}, | ||
414 | {46, 46, 46}, | ||
415 | {25, 25, 25}, | ||
416 | {7, 7, 7}, | ||
417 | {0, 0, 0}, | ||
418 | }, | ||
419 | }, | ||
420 | .sd_brightness = &sd_brightness, | ||
421 | .bl_device = &enterprise_disp1_backlight_device, | ||
422 | }; | ||
423 | |||
424 | static struct tegra_fb_data enterprise_hdmi_fb_data = { | ||
425 | .win = 0, | ||
426 | .xres = 1366, | ||
427 | .yres = 768, | ||
428 | .bits_per_pixel = 32, | ||
429 | .flags = TEGRA_FB_FLIP_ON_PROBE, | ||
430 | }; | ||
431 | |||
432 | static struct tegra_dc_out enterprise_disp2_out = { | ||
433 | .type = TEGRA_DC_OUT_HDMI, | ||
434 | .flags = TEGRA_DC_OUT_HOTPLUG_HIGH, | ||
435 | .parent_clk = "pll_d2_out0", | ||
436 | |||
437 | .dcc_bus = 3, | ||
438 | .hotplug_gpio = enterprise_hdmi_hpd, | ||
439 | |||
440 | .max_pixclock = KHZ2PICOS(148500), | ||
441 | |||
442 | .align = TEGRA_DC_ALIGN_MSB, | ||
443 | .order = TEGRA_DC_ORDER_RED_BLUE, | ||
444 | |||
445 | .enable = enterprise_hdmi_enable, | ||
446 | .disable = enterprise_hdmi_disable, | ||
447 | .postsuspend = enterprise_hdmi_vddio_disable, | ||
448 | .hotplug_init = enterprise_hdmi_vddio_enable, | ||
449 | }; | ||
450 | |||
451 | static struct tegra_dc_platform_data enterprise_disp2_pdata = { | ||
452 | .flags = 0, | ||
453 | .default_out = &enterprise_disp2_out, | ||
454 | .fb = &enterprise_hdmi_fb_data, | ||
455 | .emc_clk_rate = 300000000, | ||
456 | }; | ||
457 | |||
458 | static int enterprise_dsi_panel_enable(void) | ||
459 | { | ||
460 | int ret; | ||
461 | struct board_info board_info; | ||
462 | |||
463 | tegra_get_board_info(&board_info); | ||
464 | |||
465 | if (enterprise_dsi_reg == NULL) { | ||
466 | enterprise_dsi_reg = regulator_get(NULL, "avdd_dsi_csi"); | ||
467 | if (IS_ERR_OR_NULL(enterprise_dsi_reg)) { | ||
468 | pr_err("dsi: Could not get regulator avdd_dsi_csi\n"); | ||
469 | enterprise_dsi_reg = NULL; | ||
470 | return PTR_ERR(enterprise_dsi_reg); | ||
471 | } | ||
472 | } | ||
473 | ret = regulator_enable(enterprise_dsi_reg); | ||
474 | if (ret < 0) { | ||
475 | printk(KERN_ERR | ||
476 | "DSI regulator avdd_dsi_csi could not be enabled\n"); | ||
477 | return ret; | ||
478 | } | ||
479 | |||
480 | #if DSI_PANEL_RESET | ||
481 | |||
482 | if (board_info.fab >= BOARD_FAB_A03) { | ||
483 | if (enterprise_lcd_reg == NULL) { | ||
484 | enterprise_lcd_reg = regulator_get(NULL, "lcd_vddio_en"); | ||
485 | if (IS_ERR_OR_NULL(enterprise_lcd_reg)) { | ||
486 | pr_err("Could not get regulator lcd_vddio_en\n"); | ||
487 | ret = PTR_ERR(enterprise_lcd_reg); | ||
488 | enterprise_lcd_reg = NULL; | ||
489 | return ret; | ||
490 | } | ||
491 | } | ||
492 | if (enterprise_lcd_reg != NULL) { | ||
493 | ret = regulator_enable(enterprise_lcd_reg); | ||
494 | if (ret < 0) { | ||
495 | pr_err("Could not enable lcd_vddio_en\n"); | ||
496 | return ret; | ||
497 | } | ||
498 | } | ||
499 | } | ||
500 | |||
501 | if (kernel_1st_panel_init != true) { | ||
502 | ret = gpio_request(enterprise_dsi_panel_reset, "panel reset"); | ||
503 | if (ret < 0) | ||
504 | return ret; | ||
505 | |||
506 | ret = gpio_direction_output(enterprise_dsi_panel_reset, 0); | ||
507 | if (ret < 0) { | ||
508 | gpio_free(enterprise_dsi_panel_reset); | ||
509 | return ret; | ||
510 | } | ||
511 | tegra_gpio_enable(enterprise_dsi_panel_reset); | ||
512 | |||
513 | gpio_set_value(enterprise_dsi_panel_reset, 0); | ||
514 | udelay(2000); | ||
515 | gpio_set_value(enterprise_dsi_panel_reset, 1); | ||
516 | mdelay(20); | ||
517 | } | ||
518 | #endif | ||
519 | |||
520 | return ret; | ||
521 | } | ||
522 | |||
523 | static int enterprise_dsi_panel_disable(void) | ||
524 | { | ||
525 | if (enterprise_lcd_reg != NULL) | ||
526 | regulator_disable(enterprise_lcd_reg); | ||
527 | |||
528 | #if DSI_PANEL_RESET | ||
529 | if (kernel_1st_panel_init != true) { | ||
530 | tegra_gpio_disable(enterprise_dsi_panel_reset); | ||
531 | gpio_free(enterprise_dsi_panel_reset); | ||
532 | } else | ||
533 | kernel_1st_panel_init = false; | ||
534 | #endif | ||
535 | return 0; | ||
536 | } | ||
537 | #endif | ||
538 | |||
539 | static void enterprise_stereo_set_mode(int mode) | ||
540 | { | ||
541 | switch (mode) { | ||
542 | case TEGRA_DC_STEREO_MODE_2D: | ||
543 | gpio_set_value(TEGRA_GPIO_PH1, ENTERPRISE_STEREO_2D); | ||
544 | break; | ||
545 | case TEGRA_DC_STEREO_MODE_3D: | ||
546 | gpio_set_value(TEGRA_GPIO_PH1, ENTERPRISE_STEREO_3D); | ||
547 | break; | ||
548 | } | ||
549 | } | ||
550 | |||
551 | static void enterprise_stereo_set_orientation(int mode) | ||
552 | { | ||
553 | switch (mode) { | ||
554 | case TEGRA_DC_STEREO_LANDSCAPE: | ||
555 | gpio_set_value(TEGRA_GPIO_PH2, ENTERPRISE_STEREO_LANDSCAPE); | ||
556 | break; | ||
557 | case TEGRA_DC_STEREO_PORTRAIT: | ||
558 | gpio_set_value(TEGRA_GPIO_PH2, ENTERPRISE_STEREO_PORTRAIT); | ||
559 | break; | ||
560 | } | ||
561 | } | ||
562 | |||
563 | #ifdef CONFIG_TEGRA_DC | ||
564 | static int enterprise_dsi_panel_postsuspend(void) | ||
565 | { | ||
566 | /* Do nothing for enterprise dsi panel */ | ||
567 | return 0; | ||
568 | } | ||
569 | #endif | ||
570 | |||
571 | static struct tegra_dsi_cmd dsi_init_cmd[]= { | ||
572 | DSI_CMD_SHORT(0x05, 0x11, 0x00), | ||
573 | DSI_DLY_MS(20), | ||
574 | #if(DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE) | ||
575 | DSI_CMD_SHORT(0x15, 0x35, 0x00), | ||
576 | #endif | ||
577 | DSI_CMD_SHORT(0x05, 0x29, 0x00), | ||
578 | DSI_DLY_MS(20), | ||
579 | }; | ||
580 | |||
581 | static struct tegra_dsi_cmd dsi_early_suspend_cmd[] = { | ||
582 | DSI_CMD_SHORT(0x05, 0x28, 0x00), | ||
583 | DSI_DLY_MS(20), | ||
584 | #if(DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE) | ||
585 | DSI_CMD_SHORT(0x05, 0x34, 0x00), | ||
586 | #endif | ||
587 | }; | ||
588 | |||
589 | static struct tegra_dsi_cmd dsi_late_resume_cmd[] = { | ||
590 | #if(DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE) | ||
591 | DSI_CMD_SHORT(0x15, 0x35, 0x00), | ||
592 | #endif | ||
593 | DSI_CMD_SHORT(0x05, 0x29, 0x00), | ||
594 | DSI_DLY_MS(20), | ||
595 | }; | ||
596 | |||
597 | static struct tegra_dsi_cmd dsi_suspend_cmd[] = { | ||
598 | DSI_CMD_SHORT(0x05, 0x28, 0x00), | ||
599 | DSI_DLY_MS(20), | ||
600 | #if(DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE) | ||
601 | DSI_CMD_SHORT(0x05, 0x34, 0x00), | ||
602 | #endif | ||
603 | DSI_CMD_SHORT(0x05, 0x10, 0x00), | ||
604 | DSI_DLY_MS(5), | ||
605 | }; | ||
606 | |||
607 | struct tegra_dsi_out enterprise_dsi = { | ||
608 | .n_data_lanes = 2, | ||
609 | .pixel_format = TEGRA_DSI_PIXEL_FORMAT_24BIT_P, | ||
610 | #if(DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE) | ||
611 | /* For one-shot mode, actual refresh rate is decided by the | ||
612 | * frequency of TE signal. Although the frequency of TE is | ||
613 | * expected running at rated_refresh_rate (typically 60Hz), | ||
614 | * it may vary. Mismatch between freq of DC and TE signal | ||
615 | * would cause frame drop. We increase refresh_rate to the | ||
616 | * value larger than maximum TE frequency to avoid missing | ||
617 | * any TE signal. The value of refresh_rate is also used to | ||
618 | * calculate the pixel clock. | ||
619 | */ | ||
620 | .refresh_rate = 66, | ||
621 | .rated_refresh_rate = 60, | ||
622 | #else | ||
623 | .refresh_rate = 60, | ||
624 | #endif | ||
625 | .virtual_channel = TEGRA_DSI_VIRTUAL_CHANNEL_0, | ||
626 | |||
627 | .panel_has_frame_buffer = true, | ||
628 | .dsi_instance = 0, | ||
629 | |||
630 | .panel_reset = DSI_PANEL_RESET, | ||
631 | .power_saving_suspend = true, | ||
632 | .n_init_cmd = ARRAY_SIZE(dsi_init_cmd), | ||
633 | .dsi_init_cmd = dsi_init_cmd, | ||
634 | |||
635 | .n_early_suspend_cmd = ARRAY_SIZE(dsi_early_suspend_cmd), | ||
636 | .dsi_early_suspend_cmd = dsi_early_suspend_cmd, | ||
637 | |||
638 | .n_late_resume_cmd = ARRAY_SIZE(dsi_late_resume_cmd), | ||
639 | .dsi_late_resume_cmd = dsi_late_resume_cmd, | ||
640 | |||
641 | .n_suspend_cmd = ARRAY_SIZE(dsi_suspend_cmd), | ||
642 | .dsi_suspend_cmd = dsi_suspend_cmd, | ||
643 | |||
644 | .video_data_type = TEGRA_DSI_VIDEO_TYPE_COMMAND_MODE, | ||
645 | .lp_cmd_mode_freq_khz = 20000, | ||
646 | |||
647 | /* TODO: Get the vender recommended freq */ | ||
648 | .lp_read_cmd_mode_freq_khz = 200000, | ||
649 | }; | ||
650 | |||
651 | static struct tegra_stereo_out enterprise_stereo = { | ||
652 | .set_mode = &enterprise_stereo_set_mode, | ||
653 | .set_orientation = &enterprise_stereo_set_orientation, | ||
654 | }; | ||
655 | |||
656 | #ifdef CONFIG_TEGRA_DC | ||
657 | static struct tegra_dc_mode enterprise_dsi_modes[] = { | ||
658 | { | ||
659 | .pclk = 10000000, | ||
660 | .h_ref_to_sync = 4, | ||
661 | .v_ref_to_sync = 1, | ||
662 | .h_sync_width = 16, | ||
663 | .v_sync_width = 1, | ||
664 | .h_back_porch = 32, | ||
665 | .v_back_porch = 1, | ||
666 | .h_active = 540, | ||
667 | .v_active = 960, | ||
668 | .h_front_porch = 32, | ||
669 | .v_front_porch = 2, | ||
670 | }, | ||
671 | }; | ||
672 | |||
673 | static struct tegra_fb_data enterprise_dsi_fb_data = { | ||
674 | .win = 0, | ||
675 | .xres = 540, | ||
676 | .yres = 960, | ||
677 | .bits_per_pixel = 32, | ||
678 | .flags = TEGRA_FB_FLIP_ON_PROBE, | ||
679 | }; | ||
680 | |||
681 | static struct tegra_dc_out enterprise_disp1_out = { | ||
682 | .align = TEGRA_DC_ALIGN_MSB, | ||
683 | .order = TEGRA_DC_ORDER_RED_BLUE, | ||
684 | .sd_settings = &enterprise_sd_settings, | ||
685 | |||
686 | .flags = DC_CTRL_MODE, | ||
687 | |||
688 | .type = TEGRA_DC_OUT_DSI, | ||
689 | |||
690 | .modes = enterprise_dsi_modes, | ||
691 | .n_modes = ARRAY_SIZE(enterprise_dsi_modes), | ||
692 | |||
693 | .dsi = &enterprise_dsi, | ||
694 | .stereo = &enterprise_stereo, | ||
695 | |||
696 | .enable = enterprise_dsi_panel_enable, | ||
697 | .disable = enterprise_dsi_panel_disable, | ||
698 | .postsuspend = enterprise_dsi_panel_postsuspend, | ||
699 | |||
700 | .width = 53, | ||
701 | .height = 95, | ||
702 | }; | ||
703 | static struct tegra_dc_platform_data enterprise_disp1_pdata = { | ||
704 | .flags = TEGRA_DC_FLAG_ENABLED, | ||
705 | .default_out = &enterprise_disp1_out, | ||
706 | .emc_clk_rate = 204000000, | ||
707 | .fb = &enterprise_dsi_fb_data, | ||
708 | }; | ||
709 | |||
710 | static struct nvhost_device enterprise_disp1_device = { | ||
711 | .name = "tegradc", | ||
712 | .id = 0, | ||
713 | .resource = enterprise_disp1_resources, | ||
714 | .num_resources = ARRAY_SIZE(enterprise_disp1_resources), | ||
715 | .dev = { | ||
716 | .platform_data = &enterprise_disp1_pdata, | ||
717 | }, | ||
718 | }; | ||
719 | |||
720 | static int enterprise_disp1_check_fb(struct device *dev, struct fb_info *info) | ||
721 | { | ||
722 | return info->device == &enterprise_disp1_device.dev; | ||
723 | } | ||
724 | |||
725 | static struct nvhost_device enterprise_disp2_device = { | ||
726 | .name = "tegradc", | ||
727 | .id = 1, | ||
728 | .resource = enterprise_disp2_resources, | ||
729 | .num_resources = ARRAY_SIZE(enterprise_disp2_resources), | ||
730 | .dev = { | ||
731 | .platform_data = &enterprise_disp2_pdata, | ||
732 | }, | ||
733 | }; | ||
734 | #endif | ||
735 | |||
736 | #if defined(CONFIG_TEGRA_NVMAP) | ||
737 | static struct nvmap_platform_carveout enterprise_carveouts[] = { | ||
738 | [0] = NVMAP_HEAP_CARVEOUT_IRAM_INIT, | ||
739 | [1] = { | ||
740 | .name = "generic-0", | ||
741 | .usage_mask = NVMAP_HEAP_CARVEOUT_GENERIC, | ||
742 | .base = 0, /* Filled in by enterprise_panel_init() */ | ||
743 | .size = 0, /* Filled in by enterprise_panel_init() */ | ||
744 | .buddy_size = SZ_32K, | ||
745 | }, | ||
746 | }; | ||
747 | |||
748 | static struct nvmap_platform_data enterprise_nvmap_data = { | ||
749 | .carveouts = enterprise_carveouts, | ||
750 | .nr_carveouts = ARRAY_SIZE(enterprise_carveouts), | ||
751 | }; | ||
752 | |||
753 | static struct platform_device enterprise_nvmap_device = { | ||
754 | .name = "tegra-nvmap", | ||
755 | .id = -1, | ||
756 | .dev = { | ||
757 | .platform_data = &enterprise_nvmap_data, | ||
758 | }, | ||
759 | }; | ||
760 | #endif | ||
761 | |||
762 | static struct platform_device *enterprise_gfx_devices[] __initdata = { | ||
763 | #if defined(CONFIG_TEGRA_NVMAP) | ||
764 | &enterprise_nvmap_device, | ||
765 | #endif | ||
766 | &tegra_pwfm0_device, | ||
767 | }; | ||
768 | |||
769 | static struct platform_device *enterprise_bl_devices[] = { | ||
770 | &enterprise_disp1_backlight_device, | ||
771 | }; | ||
772 | |||
773 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
774 | /* put early_suspend/late_resume handlers here for the display in order | ||
775 | * to keep the code out of the display driver, keeping it closer to upstream | ||
776 | */ | ||
777 | struct early_suspend enterprise_panel_early_suspender; | ||
778 | |||
779 | static void enterprise_panel_early_suspend(struct early_suspend *h) | ||
780 | { | ||
781 | /* power down LCD, add use a black screen for HDMI */ | ||
782 | if (num_registered_fb > 0) | ||
783 | fb_blank(registered_fb[0], FB_BLANK_POWERDOWN); | ||
784 | if (num_registered_fb > 1) | ||
785 | fb_blank(registered_fb[1], FB_BLANK_NORMAL); | ||
786 | #ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND | ||
787 | cpufreq_save_default_governor(); | ||
788 | cpufreq_set_conservative_governor(); | ||
789 | cpufreq_set_conservative_governor_param("up_threshold", | ||
790 | SET_CONSERVATIVE_GOVERNOR_UP_THRESHOLD); | ||
791 | |||
792 | cpufreq_set_conservative_governor_param("down_threshold", | ||
793 | SET_CONSERVATIVE_GOVERNOR_DOWN_THRESHOLD); | ||
794 | |||
795 | cpufreq_set_conservative_governor_param("freq_step", | ||
796 | SET_CONSERVATIVE_GOVERNOR_FREQ_STEP); | ||
797 | #endif | ||
798 | } | ||
799 | |||
800 | static void enterprise_panel_late_resume(struct early_suspend *h) | ||
801 | { | ||
802 | unsigned i; | ||
803 | |||
804 | #ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND | ||
805 | cpufreq_restore_default_governor(); | ||
806 | #endif | ||
807 | for (i = 0; i < num_registered_fb; i++) | ||
808 | fb_blank(registered_fb[i], FB_BLANK_UNBLANK); | ||
809 | } | ||
810 | #endif | ||
811 | |||
812 | int __init enterprise_panel_init(void) | ||
813 | { | ||
814 | int err; | ||
815 | struct resource __maybe_unused *res; | ||
816 | struct board_info board_info; | ||
817 | |||
818 | tegra_get_board_info(&board_info); | ||
819 | |||
820 | BUILD_BUG_ON(ARRAY_SIZE(enterprise_bl_output_measured_a03) != 256); | ||
821 | BUILD_BUG_ON(ARRAY_SIZE(enterprise_bl_output_measured_a02) != 256); | ||
822 | |||
823 | if (board_info.fab >= BOARD_FAB_A03) { | ||
824 | enterprise_disp1_backlight_data.clk_div = 0x1D; | ||
825 | bl_output = enterprise_bl_output_measured_a03; | ||
826 | } else | ||
827 | bl_output = enterprise_bl_output_measured_a02; | ||
828 | |||
829 | enterprise_dsi.chip_id = tegra_get_chipid(); | ||
830 | enterprise_dsi.chip_rev = tegra_get_revision(); | ||
831 | |||
832 | #if defined(CONFIG_TEGRA_NVMAP) | ||
833 | enterprise_carveouts[1].base = tegra_carveout_start; | ||
834 | enterprise_carveouts[1].size = tegra_carveout_size; | ||
835 | #endif | ||
836 | |||
837 | tegra_gpio_enable(enterprise_hdmi_hpd); | ||
838 | gpio_request(enterprise_hdmi_hpd, "hdmi_hpd"); | ||
839 | gpio_direction_input(enterprise_hdmi_hpd); | ||
840 | |||
841 | tegra_gpio_enable(enterprise_lcd_2d_3d); | ||
842 | gpio_request(enterprise_lcd_2d_3d, "lcd_2d_3d"); | ||
843 | gpio_direction_output(enterprise_lcd_2d_3d, 0); | ||
844 | enterprise_stereo_set_mode(enterprise_stereo.mode_2d_3d); | ||
845 | |||
846 | tegra_gpio_enable(enterprise_lcd_swp_pl); | ||
847 | gpio_request(enterprise_lcd_swp_pl, "lcd_swp_pl"); | ||
848 | gpio_direction_output(enterprise_lcd_swp_pl, 0); | ||
849 | enterprise_stereo_set_orientation(enterprise_stereo.orientation); | ||
850 | |||
851 | #if !(DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE) | ||
852 | tegra_gpio_enable(enterprise_lcd_te); | ||
853 | gpio_request(enterprise_lcd_swp_pl, "lcd_te"); | ||
854 | gpio_direction_input(enterprise_lcd_te); | ||
855 | #endif | ||
856 | |||
857 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
858 | enterprise_panel_early_suspender.suspend = enterprise_panel_early_suspend; | ||
859 | enterprise_panel_early_suspender.resume = enterprise_panel_late_resume; | ||
860 | enterprise_panel_early_suspender.level = EARLY_SUSPEND_LEVEL_DISABLE_FB; | ||
861 | register_early_suspend(&enterprise_panel_early_suspender); | ||
862 | #endif | ||
863 | |||
864 | #ifdef CONFIG_TEGRA_GRHOST | ||
865 | err = nvhost_device_register(&tegra_grhost_device); | ||
866 | if (err) | ||
867 | return err; | ||
868 | #endif | ||
869 | |||
870 | err = platform_add_devices(enterprise_gfx_devices, | ||
871 | ARRAY_SIZE(enterprise_gfx_devices)); | ||
872 | |||
873 | #if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC) | ||
874 | res = nvhost_get_resource_byname(&enterprise_disp1_device, | ||
875 | IORESOURCE_MEM, "fbmem"); | ||
876 | res->start = tegra_fb_start; | ||
877 | res->end = tegra_fb_start + tegra_fb_size - 1; | ||
878 | #endif | ||
879 | |||
880 | /* Copy the bootloader fb to the fb. */ | ||
881 | tegra_move_framebuffer(tegra_fb_start, tegra_bootloader_fb_start, | ||
882 | min(tegra_fb_size, tegra_bootloader_fb_size)); | ||
883 | |||
884 | #if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC) | ||
885 | if (!err) | ||
886 | err = nvhost_device_register(&enterprise_disp1_device); | ||
887 | |||
888 | res = nvhost_get_resource_byname(&enterprise_disp2_device, | ||
889 | IORESOURCE_MEM, "fbmem"); | ||
890 | res->start = tegra_fb2_start; | ||
891 | res->end = tegra_fb2_start + tegra_fb2_size - 1; | ||
892 | if (!err) | ||
893 | err = nvhost_device_register(&enterprise_disp2_device); | ||
894 | #endif | ||
895 | |||
896 | #if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_NVAVP) | ||
897 | if (!err) | ||
898 | err = nvhost_device_register(&nvavp_device); | ||
899 | #endif | ||
900 | |||
901 | if (!err) | ||
902 | err = platform_add_devices(enterprise_bl_devices, | ||
903 | ARRAY_SIZE(enterprise_bl_devices)); | ||
904 | return err; | ||
905 | } | ||