c395be1d2b6d0d005b3fb2b1239391c1665b59c8
[linux-3.10.git] / arch / arm / mach-tegra / board-loki-panel.c
1 /*
2  * arch/arm/mach-tegra/board-loki-panel.c
3  *
4  * Copyright (c) 2011-2013, NVIDIA Corporation. All rights reserved.
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 #include <linux/ioport.h>
21 #include <linux/fb.h>
22 #include <linux/nvmap.h>
23 #include <linux/nvhost.h>
24 #include <linux/init.h>
25 #include <linux/delay.h>
26 #include <linux/gpio.h>
27 #include <linux/tegra_pwm_bl.h>
28 #include <linux/regulator/consumer.h>
29 #include <linux/pwm_backlight.h>
30
31 #include <mach/irqs.h>
32 #include <mach/dc.h>
33 #include <mach/pinmux-t12.h>
34
35 #include "board.h"
36 #include "devices.h"
37 #include "gpio-names.h"
38 #include "iomap.h"
39 #include "tegra12_host1x_devices.h"
40 #include "board-panel.h"
41
42 struct platform_device * __init loki_host1x_init(void)
43 {
44         struct platform_device *pdev = NULL;
45
46         pdev = tegra12_register_host1x_devices();
47
48         if (!pdev) {
49                 pr_err("host1x devices registration failed\n");
50                 return NULL;
51         }
52         return pdev;
53 }
54
55 #ifdef CONFIG_TEGRA_DC
56
57 #define DSI_PANEL_RST_GPIO      TEGRA_GPIO_PH3
58 #define DSI_PANEL_BL_PWM_GPIO   TEGRA_GPIO_PH1
59
60 /* HDMI Hotplug detection pin */
61 #define loki_hdmi_hpd   TEGRA_GPIO_PN7
62
63 static struct regulator *loki_hdmi_reg;
64 static struct regulator *loki_hdmi_pll;
65 static struct regulator *loki_hdmi_vddio;
66
67 static struct resource loki_disp1_resources[] = {
68         {
69                 .name   = "irq",
70                 .start  = INT_DISPLAY_GENERAL,
71                 .end    = INT_DISPLAY_GENERAL,
72                 .flags  = IORESOURCE_IRQ,
73         },
74         {
75                 .name   = "regs",
76                 .start  = TEGRA_DISPLAY_BASE,
77                 .end    = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE - 1,
78                 .flags  = IORESOURCE_MEM,
79         },
80         {
81                 .name   = "fbmem",
82                 .start  = 0, /* Filled in by loki_panel_init() */
83                 .end    = 0, /* Filled in by loki_panel_init() */
84                 .flags  = IORESOURCE_MEM,
85         },
86         {
87                 .name   = "dsi_regs",
88                 .start  = TEGRA_DSI_BASE,
89                 .end    = TEGRA_DSI_BASE + TEGRA_DSI_SIZE - 1,
90                 .flags  = IORESOURCE_MEM,
91         },
92         {
93                 .name   = "mipi_cal",
94                 .start  = TEGRA_MIPI_CAL_BASE,
95                 .end    = TEGRA_MIPI_CAL_BASE + TEGRA_MIPI_CAL_SIZE - 1,
96                 .flags  = IORESOURCE_MEM,
97         },
98 };
99
100 static struct resource loki_disp2_resources[] = {
101         {
102                 .name   = "irq",
103                 .start  = INT_DISPLAY_B_GENERAL,
104                 .end    = INT_DISPLAY_B_GENERAL,
105                 .flags  = IORESOURCE_IRQ,
106         },
107         {
108                 .name   = "regs",
109                 .start  = TEGRA_DISPLAY2_BASE,
110                 .end    = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1,
111                 .flags  = IORESOURCE_MEM,
112         },
113         {
114                 .name   = "fbmem",
115                 .start  = 0, /* Filled in by loki_panel_init() */
116                 .end    = 0, /* Filled in by loki_panel_init() */
117                 .flags  = IORESOURCE_MEM,
118         },
119         {
120                 .name   = "hdmi_regs",
121                 .start  = TEGRA_HDMI_BASE,
122                 .end    = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1,
123                 .flags  = IORESOURCE_MEM,
124         },
125 };
126
127 static struct tegra_dc_sd_settings sd_settings;
128
129 static struct tegra_dc_out loki_disp1_out = {
130         .type           = TEGRA_DC_OUT_DSI,
131         .sd_settings    = &sd_settings,
132 };
133
134 static int loki_hdmi_enable(struct device *dev)
135 {
136         int ret;
137         if (!loki_hdmi_reg) {
138                 loki_hdmi_reg = regulator_get(dev, "avdd_hdmi");
139                 if (IS_ERR_OR_NULL(loki_hdmi_reg)) {
140                         pr_err("hdmi: couldn't get regulator avdd_hdmi\n");
141                         loki_hdmi_reg = NULL;
142                         return PTR_ERR(loki_hdmi_reg);
143                 }
144         }
145         ret = regulator_enable(loki_hdmi_reg);
146         if (ret < 0) {
147                 pr_err("hdmi: couldn't enable regulator avdd_hdmi\n");
148                 return ret;
149         }
150         if (!loki_hdmi_pll) {
151                 loki_hdmi_pll = regulator_get(dev, "avdd_hdmi_pll");
152                 if (IS_ERR_OR_NULL(loki_hdmi_pll)) {
153                         pr_err("hdmi: couldn't get regulator avdd_hdmi_pll\n");
154                         loki_hdmi_pll = NULL;
155                         regulator_put(loki_hdmi_reg);
156                         loki_hdmi_reg = NULL;
157                         return PTR_ERR(loki_hdmi_pll);
158                 }
159         }
160         ret = regulator_enable(loki_hdmi_pll);
161         if (ret < 0) {
162                 pr_err("hdmi: couldn't enable regulator avdd_hdmi_pll\n");
163                 return ret;
164         }
165         return 0;
166 }
167
168 static int loki_hdmi_disable(void)
169 {
170         if (loki_hdmi_reg) {
171                 regulator_disable(loki_hdmi_reg);
172                 regulator_put(loki_hdmi_reg);
173                 loki_hdmi_reg = NULL;
174         }
175
176         if (loki_hdmi_pll) {
177                 regulator_disable(loki_hdmi_pll);
178                 regulator_put(loki_hdmi_pll);
179                 loki_hdmi_pll = NULL;
180         }
181
182         return 0;
183 }
184
185 static int loki_hdmi_postsuspend(void)
186 {
187         if (loki_hdmi_vddio) {
188                 regulator_disable(loki_hdmi_vddio);
189                 regulator_put(loki_hdmi_vddio);
190                 loki_hdmi_vddio = NULL;
191         }
192         return 0;
193 }
194
195 static int loki_hdmi_hotplug_init(struct device *dev)
196 {
197         if (!loki_hdmi_vddio) {
198                 loki_hdmi_vddio = regulator_get(dev, "vdd_hdmi_5v0");
199                 if (WARN_ON(IS_ERR(loki_hdmi_vddio))) {
200                         pr_err("%s: couldn't get regulator vdd_hdmi_5v0: %ld\n",
201                                         __func__, PTR_ERR(loki_hdmi_vddio));
202                         loki_hdmi_vddio = NULL;
203                 } else
204                         regulator_enable(loki_hdmi_vddio);
205         }
206         return 0;
207 }
208
209 /* Table of electrical characteristics for Roth HDMI.
210  * All modes must be declared here
211  */
212 struct tmds_config loki_tmds_config[] = {
213         { /* 720p / 74.25MHz modes */
214                 .pclk = 74250000,
215                 .pll0 = 0x01003f10,
216                 .pll1 = 0x10300b00,
217                 .pe_current = 0x00000000,
218                 .drive_current = 0x2e2e2e2e,
219                 .peak_current = 0x05050505,
220         },
221         { /* 1080p / 148.5MHz modes */
222                 .pclk = 148500000,
223                 .pll0 = 0x01003f10,
224                 .pll1 = 0x10300b00,
225                 .pe_current = 0x00000000,
226                 .drive_current = 0x2e2e2e2e,
227                 .peak_current = 0x05050505,
228         },
229         { /* 297MHz modes */
230                 .pclk = INT_MAX,
231                 .pll0 = 0x01003f10,
232                 .pll1 = 0x13300b00,
233                 .pe_current = 0x00000000,
234                 .drive_current = 0x34343434,
235                 .peak_current = 0x07070707,
236         },
237 };
238
239 struct tegra_hdmi_out loki_hdmi_out = {
240         .tmds_config = loki_tmds_config,
241         .n_tmds_config = 3,
242 };
243
244 static void loki_hdmi_hotplug_report(bool state)
245 {
246         if (state) {
247                 tegra_pinmux_set_pullupdown(TEGRA_PINGROUP_DDC_SDA,
248                                                 TEGRA_PUPD_PULL_DOWN);
249                 tegra_pinmux_set_pullupdown(TEGRA_PINGROUP_DDC_SCL,
250                                                 TEGRA_PUPD_PULL_DOWN);
251         } else {
252                 tegra_pinmux_set_pullupdown(TEGRA_PINGROUP_DDC_SDA,
253                                                 TEGRA_PUPD_NORMAL);
254                 tegra_pinmux_set_pullupdown(TEGRA_PINGROUP_DDC_SCL,
255                                                 TEGRA_PUPD_NORMAL);
256         }
257 }
258
259 static struct tegra_dc_out loki_disp2_out = {
260         .type           = TEGRA_DC_OUT_HDMI,
261         .flags          = TEGRA_DC_OUT_HOTPLUG_HIGH,
262         .parent_clk     = "pll_d2",
263
264         .dcc_bus        = 3,
265         .hotplug_gpio   = loki_hdmi_hpd,
266
267         .max_pixclock   = KHZ2PICOS(297000),
268
269         .align          = TEGRA_DC_ALIGN_MSB,
270         .order          = TEGRA_DC_ORDER_RED_BLUE,
271
272         .enable         = loki_hdmi_enable,
273         .disable        = loki_hdmi_disable,
274         .postsuspend    = loki_hdmi_postsuspend,
275         .hotplug_init   = loki_hdmi_hotplug_init,
276         .hotplug_report = loki_hdmi_hotplug_report,
277 };
278
279 static struct tegra_fb_data loki_disp1_fb_data = {
280         .win            = 0,
281         .bits_per_pixel = 32,
282         .flags          = TEGRA_FB_FLIP_ON_PROBE,
283 };
284
285 static struct tegra_dc_platform_data loki_disp1_pdata = {
286         .flags          = TEGRA_DC_FLAG_ENABLED,
287         .default_out    = &loki_disp1_out,
288         .fb             = &loki_disp1_fb_data,
289         .emc_clk_rate   = 204000000,
290 #ifdef CONFIG_TEGRA_DC_CMU
291         .cmu_enable     = 1,
292 #endif
293 };
294
295 static struct tegra_fb_data loki_disp2_fb_data = {
296         .win            = 0,
297         .xres           = 1024,
298         .yres           = 600,
299         .bits_per_pixel = 32,
300         .flags          = TEGRA_FB_FLIP_ON_PROBE,
301 };
302
303 static struct tegra_dc_platform_data loki_disp2_pdata = {
304         .flags          = TEGRA_DC_FLAG_ENABLED,
305         .default_out    = &loki_disp2_out,
306         .fb             = &loki_disp2_fb_data,
307         .emc_clk_rate   = 300000000,
308 #ifdef CONFIG_TEGRA_DC_CMU
309         .cmu_enable     = 1,
310 #endif
311 };
312
313 static struct platform_device loki_disp2_device = {
314         .name           = "tegradc",
315         .id             = 1,
316         .resource       = loki_disp2_resources,
317         .num_resources  = ARRAY_SIZE(loki_disp2_resources),
318         .dev = {
319                 .platform_data = &loki_disp2_pdata,
320         },
321 };
322
323 static struct platform_device loki_disp1_device = {
324         .name           = "tegradc",
325         .id             = 0,
326         .resource       = loki_disp1_resources,
327         .num_resources  = ARRAY_SIZE(loki_disp1_resources),
328         .dev = {
329                 .platform_data = &loki_disp1_pdata,
330         },
331 };
332
333 static struct nvmap_platform_carveout loki_carveouts[] = {
334         [0] = {
335                 .name           = "iram",
336                 .usage_mask     = NVMAP_HEAP_CARVEOUT_IRAM,
337                 .base           = TEGRA_IRAM_BASE + TEGRA_RESET_HANDLER_SIZE,
338                 .size           = TEGRA_IRAM_SIZE - TEGRA_RESET_HANDLER_SIZE,
339         },
340         [1] = {
341                 .name           = "generic-0",
342                 .usage_mask     = NVMAP_HEAP_CARVEOUT_GENERIC,
343                 .base           = 0, /* Filled in by loki_panel_init() */
344                 .size           = 0, /* Filled in by loki_panel_init() */
345         },
346         [2] = {
347                 .name           = "vpr",
348                 .usage_mask     = NVMAP_HEAP_CARVEOUT_VPR,
349                 .base           = 0, /* Filled in by loki_panel_init() */
350                 .size           = 0, /* Filled in by loki_panel_init() */
351         },
352 };
353
354 static struct nvmap_platform_data loki_nvmap_data = {
355         .carveouts      = loki_carveouts,
356         .nr_carveouts   = ARRAY_SIZE(loki_carveouts),
357 };
358
359 static struct platform_device loki_nvmap_device = {
360         .name   = "tegra-nvmap",
361         .id     = -1,
362         .dev    = {
363                 .platform_data = &loki_nvmap_data,
364         },
365 };
366
367 static struct tegra_dc_sd_settings loki_sd_settings = {
368         .enable = 0, /* disabled by default. */
369         .use_auto_pwm = false,
370         .hw_update_delay = 0,
371         .bin_width = -1,
372         .aggressiveness = 1,
373         .use_vid_luma = false,
374         .phase_in_adjustments = 0,
375         .k_limit_enable = true,
376         .k_limit = 180,
377         .sd_window_enable = false,
378         .soft_clipping_enable = true,
379         /* Low soft clipping threshold to compensate for aggressive k_limit */
380         .soft_clipping_threshold = 128,
381         .smooth_k_enable = true,
382         .smooth_k_incr = 128,
383         /* Default video coefficients */
384         .coeff = {5, 9, 2},
385         .fc = {0, 0},
386         /* Immediate backlight changes */
387         .blp = {1024, 255},
388         /* Gammas: R: 2.2 G: 2.2 B: 2.2 */
389         /* Default BL TF */
390         .bltf = {
391                         {
392                                 {57, 65, 73, 82},
393                                 {92, 103, 114, 125},
394                                 {138, 150, 164, 178},
395                                 {193, 208, 224, 241},
396                         },
397                 },
398         /* Default LUT */
399         .lut = {
400                         {
401                                 {255, 255, 255},
402                                 {199, 199, 199},
403                                 {153, 153, 153},
404                                 {116, 116, 116},
405                                 {85, 85, 85},
406                                 {59, 59, 59},
407                                 {36, 36, 36},
408                                 {17, 17, 17},
409                                 {0, 0, 0},
410                         },
411                 },
412         .sd_brightness = &sd_brightness,
413 };
414
415 static void loki_panel_select(void)
416 {
417         struct tegra_panel *panel;
418         struct board_info board;
419         u8 dsi_instance = DSI_INSTANCE_0;
420
421         tegra_get_display_board_info(&board);
422
423         switch (board.board_id) {
424         default:
425                 panel = &dsi_l_720p_5_loki;
426                 break;
427         }
428         if (panel) {
429                 if (panel->init_sd_settings)
430                         panel->init_sd_settings(&sd_settings);
431
432                 if (panel->init_dc_out) {
433                         panel->init_dc_out(&loki_disp1_out);
434                         loki_disp1_out.dsi->dsi_instance = dsi_instance;
435                         loki_disp1_out.dsi->dsi_panel_rst_gpio =
436                                 DSI_PANEL_RST_GPIO;
437                         loki_disp1_out.dsi->dsi_panel_bl_pwm_gpio =
438                                 DSI_PANEL_BL_PWM_GPIO;
439                         tegra_dsi_update_init_cmd_gpio_rst(&loki_disp1_out);
440                 }
441
442                 if (panel->init_fb_data)
443                         panel->init_fb_data(&loki_disp1_fb_data);
444
445                 if (panel->init_cmu_data)
446                         panel->init_cmu_data(&loki_disp1_pdata);
447
448                 if (panel->set_disp_device)
449                         panel->set_disp_device(&loki_disp1_device);
450
451                 if (panel->register_bl_dev)
452                         panel->register_bl_dev();
453         }
454 }
455
456 int __init loki_panel_init(int board_id)
457 {
458         int err = 0;
459         struct resource __maybe_unused *res;
460         struct platform_device *phost1x = NULL;
461
462         sd_settings = loki_sd_settings;
463
464         loki_panel_select();
465
466 #ifdef CONFIG_TEGRA_NVMAP
467         loki_carveouts[1].base = tegra_carveout_start;
468         loki_carveouts[1].size = tegra_carveout_size;
469         loki_carveouts[2].base = tegra_vpr_start;
470         loki_carveouts[2].size = tegra_vpr_size;
471
472         err = platform_device_register(&loki_nvmap_device);
473         if (err) {
474                 pr_err("nvmap device registration failed\n");
475                 return err;
476         }
477 #endif
478
479         phost1x = loki_host1x_init();
480         if (!phost1x) {
481                 pr_err("host1x devices registration failed\n");
482                 return -EINVAL;
483         }
484
485         res = platform_get_resource_byname(&loki_disp1_device,
486                                          IORESOURCE_MEM, "fbmem");
487         res->start = tegra_fb_start;
488         res->end = tegra_fb_start + tegra_fb_size - 1;
489
490         /* Copy the bootloader fb to the fb. */
491         __tegra_move_framebuffer(&loki_nvmap_device,
492                 tegra_fb_start, tegra_bootloader_fb_start,
493                         min(tegra_fb_size, tegra_bootloader_fb_size));
494
495         res = platform_get_resource_byname(&loki_disp2_device,
496                                          IORESOURCE_MEM, "fbmem");
497         res->start = tegra_fb2_start;
498         res->end = tegra_fb2_start + tegra_fb2_size - 1;
499
500         loki_disp1_device.dev.parent = &phost1x->dev;
501         err = platform_device_register(&loki_disp1_device);
502         if (err) {
503                 pr_err("disp1 device registration failed\n");
504                 return err;
505         }
506
507         loki_disp2_device.dev.parent = &phost1x->dev;
508         loki_disp2_out.hdmi_out = &loki_hdmi_out;
509         err = platform_device_register(&loki_disp2_device);
510         if (err) {
511                 pr_err("disp2 device registration failed\n");
512                 return err;
513         }
514
515 #ifdef CONFIG_TEGRA_NVAVP
516         nvavp_device.dev.parent = &phost1x->dev;
517         err = platform_device_register(&nvavp_device);
518         if (err) {
519                 pr_err("nvavp device registration failed\n");
520                 return err;
521         }
522 #endif
523         return err;
524 }
525 #else
526 int __init loki_panel_init(void)
527 {
528         if (loki_host1x_init())
529                 return 0;
530         else
531                 return -EINVAL;
532 }
533 #endif