ARM: tegra: Add CHIMEI LVDS panel support
[linux-3.10.git] / arch / arm / mach-tegra / board-ardbeg-panel.c
1 /*
2  * arch/arm/mach-tegra/board-ardbeg-panel.c
3  *
4  * Copyright (c) 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 #include <linux/of.h>
31
32 #include <mach/irqs.h>
33 #include <mach/dc.h>
34
35 #include "board.h"
36 #include "devices.h"
37 #include "gpio-names.h"
38 #include "board-ardbeg.h"
39 #include "board-panel.h"
40 #include "common.h"
41 #include "iomap.h"
42
43 #ifdef CONFIG_ARCH_TEGRA_11x_SOC
44 #include "tegra11_host1x_devices.h"
45 #else
46 #include "tegra12_host1x_devices.h"
47 #endif
48
49
50 struct platform_device * __init ardbeg_host1x_init(void)
51 {
52         struct platform_device *pdev = NULL;
53
54 #ifdef CONFIG_TEGRA_GRHOST
55 #ifdef CONFIG_ARCH_TEGRA_11x_SOC
56         if (!of_have_populated_dt())
57                 pdev = tegra11_register_host1x_devices();
58         else
59                 pdev = to_platform_device(bus_find_device_by_name(
60                                 &platform_bus_type, NULL, "host1x"));
61 #else
62         pdev = tegra12_register_host1x_devices();
63 #endif
64
65         if (!pdev) {
66                 pr_err("host1x devices registration failed\n");
67                 return NULL;
68         }
69 #endif
70         return pdev;
71 }
72
73 #ifdef CONFIG_TEGRA_DC
74
75
76 /* hdmi related regulators */
77 static struct regulator *ardbeg_hdmi_reg;
78 static struct regulator *ardbeg_hdmi_pll;
79 static struct regulator *ardbeg_hdmi_vddio;
80
81 static struct resource ardbeg_disp1_resources[] = {
82         {
83                 .name   = "irq",
84                 .start  = INT_DISPLAY_GENERAL,
85                 .end    = INT_DISPLAY_GENERAL,
86                 .flags  = IORESOURCE_IRQ,
87         },
88         {
89                 .name   = "regs",
90                 .start  = TEGRA_DISPLAY_BASE,
91                 .end    = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE - 1,
92                 .flags  = IORESOURCE_MEM,
93         },
94         {
95                 .name   = "fbmem",
96                 .start  = 0, /* Filled in by ardbeg_panel_init() */
97                 .end    = 0, /* Filled in by ardbeg_panel_init() */
98                 .flags  = IORESOURCE_MEM,
99         },
100         {
101                 .name   = "ganged_dsia_regs",
102                 .start  = 0, /* Filled in the panel file by init_resources() */
103                 .end    = 0, /* Filled in the panel file by init_resources() */
104                 .flags  = IORESOURCE_MEM,
105         },
106         {
107                 .name   = "ganged_dsib_regs",
108                 .start  = 0, /* Filled in the panel file by init_resources() */
109                 .end    = 0, /* Filled in the panel file by init_resources() */
110                 .flags  = IORESOURCE_MEM,
111         },
112         {
113                 .name   = "dsi_regs",
114                 .start  = 0, /* Filled in the panel file by init_resources() */
115                 .end    = 0, /* Filled in the panel file by init_resources() */
116                 .flags  = IORESOURCE_MEM,
117         },
118         {
119                 .name   = "mipi_cal",
120                 .start  = TEGRA_MIPI_CAL_BASE,
121                 .end    = TEGRA_MIPI_CAL_BASE + TEGRA_MIPI_CAL_SIZE - 1,
122                 .flags  = IORESOURCE_MEM,
123         },
124 };
125
126 static struct resource ardbeg_disp1_edp_resources[] = {
127         {
128                 .name   = "irq",
129                 .start  = INT_DISPLAY_GENERAL,
130                 .end    = INT_DISPLAY_GENERAL,
131                 .flags  = IORESOURCE_IRQ,
132         },
133         {
134                 .name   = "regs",
135                 .start  = TEGRA_DISPLAY_BASE,
136                 .end    = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE - 1,
137                 .flags  = IORESOURCE_MEM,
138         },
139         {
140                 .name   = "fbmem",
141                 .start  = 0, /* Filled in by ardbeg_panel_init() */
142                 .end    = 0, /* Filled in by ardbeg_panel_init() */
143                 .flags  = IORESOURCE_MEM,
144         },
145         {
146                 .name   = "mipi_cal",
147                 .start  = TEGRA_MIPI_CAL_BASE,
148                 .end    = TEGRA_MIPI_CAL_BASE + TEGRA_MIPI_CAL_SIZE - 1,
149                 .flags  = IORESOURCE_MEM,
150         },
151         {
152                 .name   = "sor",
153                 .start  = TEGRA_SOR_BASE,
154                 .end    = TEGRA_SOR_BASE + TEGRA_SOR_SIZE - 1,
155                 .flags  = IORESOURCE_MEM,
156         },
157         {
158                 .name   = "dpaux",
159                 .start  = TEGRA_DPAUX_BASE,
160                 .end    = TEGRA_DPAUX_BASE + TEGRA_DPAUX_SIZE - 1,
161                 .flags  = IORESOURCE_MEM,
162         },
163 };
164
165 static struct resource ardbeg_disp2_resources[] = {
166         {
167                 .name   = "irq",
168                 .start  = INT_DISPLAY_B_GENERAL,
169                 .end    = INT_DISPLAY_B_GENERAL,
170                 .flags  = IORESOURCE_IRQ,
171         },
172         {
173                 .name   = "regs",
174                 .start  = TEGRA_DISPLAY2_BASE,
175                 .end    = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1,
176                 .flags  = IORESOURCE_MEM,
177         },
178         {
179                 .name   = "fbmem",
180                 .start  = 0, /* Filled in by ardbeg_panel_init() */
181                 .end    = 0, /* Filled in by ardbeg_panel_init() */
182                 .flags  = IORESOURCE_MEM,
183         },
184         {
185                 .name   = "hdmi_regs",
186                 .start  = TEGRA_HDMI_BASE,
187                 .end    = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1,
188                 .flags  = IORESOURCE_MEM,
189         },
190 };
191
192
193 static struct tegra_dc_sd_settings sd_settings;
194
195 static struct tegra_dc_out ardbeg_disp1_out = {
196         .type           = TEGRA_DC_OUT_DSI,
197         .sd_settings    = &sd_settings,
198 };
199
200 static int ardbeg_hdmi_enable(struct device *dev)
201 {
202         int ret;
203         if (!ardbeg_hdmi_reg) {
204                 ardbeg_hdmi_reg = regulator_get(dev, "avdd_hdmi");
205                 if (IS_ERR_OR_NULL(ardbeg_hdmi_reg)) {
206                         pr_err("hdmi: couldn't get regulator avdd_hdmi\n");
207                         ardbeg_hdmi_reg = NULL;
208                         return PTR_ERR(ardbeg_hdmi_reg);
209                 }
210         }
211         ret = regulator_enable(ardbeg_hdmi_reg);
212         if (ret < 0) {
213                 pr_err("hdmi: couldn't enable regulator avdd_hdmi\n");
214                 return ret;
215         }
216         if (!ardbeg_hdmi_pll) {
217                 ardbeg_hdmi_pll = regulator_get(dev, "avdd_hdmi_pll");
218                 if (IS_ERR_OR_NULL(ardbeg_hdmi_pll)) {
219                         pr_err("hdmi: couldn't get regulator avdd_hdmi_pll\n");
220                         ardbeg_hdmi_pll = NULL;
221                         regulator_put(ardbeg_hdmi_reg);
222                         ardbeg_hdmi_reg = NULL;
223                         return PTR_ERR(ardbeg_hdmi_pll);
224                 }
225         }
226         ret = regulator_enable(ardbeg_hdmi_pll);
227         if (ret < 0) {
228                 pr_err("hdmi: couldn't enable regulator avdd_hdmi_pll\n");
229                 return ret;
230         }
231         return 0;
232 }
233
234 static int ardbeg_hdmi_disable(void)
235 {
236         if (ardbeg_hdmi_reg) {
237                 regulator_disable(ardbeg_hdmi_reg);
238                 regulator_put(ardbeg_hdmi_reg);
239                 ardbeg_hdmi_reg = NULL;
240         }
241
242         if (ardbeg_hdmi_pll) {
243                 regulator_disable(ardbeg_hdmi_pll);
244                 regulator_put(ardbeg_hdmi_pll);
245                 ardbeg_hdmi_pll = NULL;
246         }
247         return 0;
248 }
249
250 static int ardbeg_hdmi_postsuspend(void)
251 {
252         if (ardbeg_hdmi_vddio) {
253                 regulator_disable(ardbeg_hdmi_vddio);
254                 regulator_put(ardbeg_hdmi_vddio);
255                 ardbeg_hdmi_vddio = NULL;
256         }
257         return 0;
258 }
259
260 static int ardbeg_hdmi_hotplug_init(struct device *dev)
261 {
262         if (!ardbeg_hdmi_vddio) {
263                 ardbeg_hdmi_vddio = regulator_get(dev, "vdd_hdmi_5v0");
264                 if (WARN_ON(IS_ERR(ardbeg_hdmi_vddio))) {
265                         pr_err("%s: couldn't get regulator vdd_hdmi_5v0: %ld\n",
266                                 __func__, PTR_ERR(ardbeg_hdmi_vddio));
267                                 ardbeg_hdmi_vddio = NULL;
268                 } else {
269                         regulator_enable(ardbeg_hdmi_vddio);
270                 }
271         }
272
273         return 0;
274 }
275
276 /* Electrical characteristics for HDMI, all modes must be declared here */
277 struct tmds_config ardbeg_tmds_config[] = {
278         { /* 480p : 27 MHz and below */
279                 .pclk = 27000000,
280                 .pll0 = 0x01003010,
281                 .pll1 = 0x00301b00,
282                 .drive_current = 0x23232323,
283                 .pe_current = 0x00000000,
284                 .peak_current = 0x00000000,
285         },
286         { /* 720p : 74.25MHz modes */
287                 .pclk = 74250000,
288                 .pll0 = 0x01003110,
289                 .pll1 = 0x00301b00,
290                 .drive_current = 0x25252525,
291                 .pe_current = 0x00000000,
292                 .peak_current = 0x03030303,
293         },
294         { /* 1080p : 148.5MHz modes */
295                 .pclk = 148500000,
296                 .pll0 = 0x01003310,
297                 .pll1 = 0x00301b00,
298                 .drive_current = 0x27272727,
299                 .pe_current = 0x00000000,
300                 .peak_current = 0x03030303,
301         },
302         { /* 4K : 297MHz modes */
303                 .pclk = INT_MAX,
304                 .pll0 = 0x01003f10,
305                 .pll1 = 0x00300f00,
306                 .drive_current = 0x303f3f3f,
307                 .pe_current = 0x00000000,
308                 .peak_current = 0x040f0f0f,
309         },
310 };
311
312 struct tegra_hdmi_out ardbeg_hdmi_out = {
313         .tmds_config = ardbeg_tmds_config,
314         .n_tmds_config = ARRAY_SIZE(ardbeg_tmds_config),
315 };
316
317
318 static struct tegra_dc_out ardbeg_disp2_out = {
319         .type           = TEGRA_DC_OUT_HDMI,
320         .flags          = TEGRA_DC_OUT_HOTPLUG_HIGH,
321         .parent_clk     = "pll_d2",
322
323         .dcc_bus        = 3,
324         .hotplug_gpio   = ardbeg_hdmi_hpd,
325         .hdmi_out       = &ardbeg_hdmi_out,
326
327         /* TODO: update max pclk to POR */
328         .max_pixclock   = KHZ2PICOS(297000),
329
330         .align          = TEGRA_DC_ALIGN_MSB,
331         .order          = TEGRA_DC_ORDER_RED_BLUE,
332
333         .enable         = ardbeg_hdmi_enable,
334         .disable        = ardbeg_hdmi_disable,
335         .postsuspend    = ardbeg_hdmi_postsuspend,
336         .hotplug_init   = ardbeg_hdmi_hotplug_init,
337 };
338
339 static struct tegra_fb_data ardbeg_disp1_fb_data = {
340         .win            = 0,
341         .bits_per_pixel = 32,
342         .flags          = TEGRA_FB_FLIP_ON_PROBE,
343 };
344
345 static struct tegra_dc_platform_data ardbeg_disp1_pdata = {
346         .flags          = TEGRA_DC_FLAG_ENABLED,
347         .default_out    = &ardbeg_disp1_out,
348         .fb             = &ardbeg_disp1_fb_data,
349         .emc_clk_rate   = 204000000,
350 #ifdef CONFIG_TEGRA_DC_CMU
351         .cmu_enable     = 1,
352 #endif
353 };
354
355 static struct tegra_fb_data ardbeg_disp2_fb_data = {
356         .win            = 0,
357         .xres           = 1280,
358         .yres           = 720,
359         .bits_per_pixel = 32,
360         .flags          = TEGRA_FB_FLIP_ON_PROBE,
361 };
362
363 static struct tegra_dc_platform_data ardbeg_disp2_pdata = {
364         .flags          = TEGRA_DC_FLAG_ENABLED,
365         .default_out    = &ardbeg_disp2_out,
366         .fb             = &ardbeg_disp2_fb_data,
367         .emc_clk_rate   = 300000000,
368 };
369
370 static struct platform_device ardbeg_disp2_device = {
371         .name           = "tegradc",
372         .id             = 1,
373         .resource       = ardbeg_disp2_resources,
374         .num_resources  = ARRAY_SIZE(ardbeg_disp2_resources),
375         .dev = {
376                 .platform_data = &ardbeg_disp2_pdata,
377         },
378 };
379
380 static struct platform_device ardbeg_disp1_device = {
381         .name           = "tegradc",
382         .id             = 0,
383         .resource       = ardbeg_disp1_resources,
384         .num_resources  = ARRAY_SIZE(ardbeg_disp1_resources),
385         .dev = {
386                 .platform_data = &ardbeg_disp1_pdata,
387         },
388 };
389
390 static struct nvmap_platform_carveout ardbeg_carveouts[] = {
391         [0] = {
392                 .name           = "iram",
393                 .usage_mask     = NVMAP_HEAP_CARVEOUT_IRAM,
394                 .base           = TEGRA_IRAM_BASE + TEGRA_RESET_HANDLER_SIZE,
395                 .size           = TEGRA_IRAM_SIZE - TEGRA_RESET_HANDLER_SIZE,
396                 .buddy_size     = 0, /* no buddy allocation for IRAM */
397         },
398         [1] = {
399                 .name           = "generic-0",
400                 .usage_mask     = NVMAP_HEAP_CARVEOUT_GENERIC,
401                 .base           = 0, /* Filled in by ardbeg_panel_init() */
402                 .size           = 0, /* Filled in by ardbeg_panel_init() */
403                 .buddy_size     = SZ_32K,
404         },
405         [2] = {
406                 .name           = "vpr",
407                 .usage_mask     = NVMAP_HEAP_CARVEOUT_VPR,
408                 .base           = 0, /* Filled in by ardbeg_panel_init() */
409                 .size           = 0, /* Filled in by ardbeg_panel_init() */
410                 .buddy_size     = SZ_32K,
411         },
412 };
413
414 static struct nvmap_platform_data ardbeg_nvmap_data = {
415         .carveouts      = ardbeg_carveouts,
416         .nr_carveouts   = ARRAY_SIZE(ardbeg_carveouts),
417 };
418 static struct platform_device ardbeg_nvmap_device  = {
419         .name   = "tegra-nvmap",
420         .id     = -1,
421         .dev    = {
422                 .platform_data = &ardbeg_nvmap_data,
423         },
424 };
425
426 static struct tegra_dc_sd_settings ardbeg_sd_settings = {
427         .enable = 1, /* enabled by default. */
428         .use_auto_pwm = false,
429         .hw_update_delay = 0,
430         .bin_width = -1,
431         .aggressiveness = 5,
432         .use_vid_luma = false,
433         .phase_in_adjustments = 0,
434         .k_limit_enable = true,
435         .k_limit = 200,
436         .sd_window_enable = false,
437         .soft_clipping_enable = true,
438         /* Low soft clipping threshold to compensate for aggressive k_limit */
439         .soft_clipping_threshold = 128,
440         .smooth_k_enable = false,
441         .smooth_k_incr = 64,
442         /* Default video coefficients */
443         .coeff = {5, 9, 2},
444         .fc = {0, 0},
445         /* Immediate backlight changes */
446         .blp = {1024, 255},
447         /* Gammas: R: 2.2 G: 2.2 B: 2.2 */
448         /* Default BL TF */
449         .bltf = {
450                         {
451                                 {57, 65, 73, 82},
452                                 {92, 103, 114, 125},
453                                 {138, 150, 164, 178},
454                                 {193, 208, 224, 241},
455                         },
456                 },
457         /* Default LUT */
458         .lut = {
459                         {
460                                 {255, 255, 255},
461                                 {199, 199, 199},
462                                 {153, 153, 153},
463                                 {116, 116, 116},
464                                 {85, 85, 85},
465                                 {59, 59, 59},
466                                 {36, 36, 36},
467                                 {17, 17, 17},
468                                 {0, 0, 0},
469                         },
470                 },
471         .sd_brightness = &sd_brightness,
472         .use_vpulse2 = true,
473 };
474
475 static void ardbeg_panel_select(void)
476 {
477         struct tegra_panel *panel = NULL;
478         struct board_info board;
479         u8 dsi_instance;
480
481         tegra_get_display_board_info(&board);
482
483         switch (board.board_id) {
484         case BOARD_E1639:
485         case BOARD_E1813:
486                 panel = &dsi_s_wqxga_10_1;
487                 dsi_instance = DSI_INSTANCE_0;
488                 break;
489         case BOARD_PM354:
490                 panel = &dsi_a_1080p_14_0;
491                 dsi_instance = DSI_INSTANCE_0;
492                 break;
493         case BOARD_E1627:
494                 panel = &dsi_p_wuxga_10_1;
495                 dsi_instance = DSI_INSTANCE_0;
496                 break;
497         case BOARD_PM363:
498         case BOARD_E1824:
499                 panel = &edp_a_1080p_14_0;
500                 ardbeg_disp1_out.type = TEGRA_DC_OUT_DP;
501                 ardbeg_disp1_device.resource = ardbeg_disp1_edp_resources;
502                 ardbeg_disp1_device.num_resources =
503                         ARRAY_SIZE(ardbeg_disp1_edp_resources);
504                 break;
505         case BOARD_PM366:
506                 panel = &lvds_c_1366_14;
507                 ardbeg_disp1_out.type = TEGRA_DC_OUT_LVDS;
508                 ardbeg_disp1_device.resource = ardbeg_disp1_edp_resources;
509                 ardbeg_disp1_device.num_resources =
510                         ARRAY_SIZE(ardbeg_disp1_edp_resources);
511                 break;
512         default:
513                 panel = &dsi_p_wuxga_10_1;
514                 dsi_instance = DSI_INSTANCE_0;
515                 break;
516         }
517
518         if (panel) {
519                 if (panel->init_sd_settings)
520                         panel->init_sd_settings(&sd_settings);
521
522                 if (panel->init_dc_out) {
523                         panel->init_dc_out(&ardbeg_disp1_out);
524                         if (ardbeg_disp1_out.type == TEGRA_DC_OUT_DSI) {
525                                 ardbeg_disp1_out.dsi->dsi_instance =
526                                         dsi_instance;
527                                 ardbeg_disp1_out.dsi->dsi_panel_rst_gpio =
528                                         DSI_PANEL_RST_GPIO;
529                                 ardbeg_disp1_out.dsi->dsi_panel_bl_pwm_gpio =
530                                         DSI_PANEL_BL_PWM_GPIO;
531                                 ardbeg_disp1_out.dsi->te_gpio = TEGRA_GPIO_PR6;
532                         }
533                 }
534
535                 if (panel->init_fb_data)
536                         panel->init_fb_data(&ardbeg_disp1_fb_data);
537
538                 if (panel->init_cmu_data)
539                         panel->init_cmu_data(&ardbeg_disp1_pdata);
540
541                 if (panel->set_disp_device)
542                         panel->set_disp_device(&ardbeg_disp1_device);
543
544                 if (ardbeg_disp1_out.type == TEGRA_DC_OUT_DSI) {
545                         tegra_dsi_resources_init(dsi_instance,
546                                 ardbeg_disp1_resources,
547                                 ARRAY_SIZE(ardbeg_disp1_resources));
548                 }
549
550                 if (panel->register_bl_dev)
551                         panel->register_bl_dev();
552
553                 if (panel->register_i2c_bridge)
554                         panel->register_i2c_bridge();
555         }
556
557 }
558 int __init ardbeg_panel_init(void)
559 {
560         int err = 0;
561         struct resource __maybe_unused *res;
562         struct platform_device *phost1x = NULL;
563
564         sd_settings = ardbeg_sd_settings;
565
566         ardbeg_panel_select();
567
568 #ifdef CONFIG_TEGRA_NVMAP
569         ardbeg_carveouts[1].base = tegra_carveout_start;
570         ardbeg_carveouts[1].size = tegra_carveout_size;
571         ardbeg_carveouts[2].base = tegra_vpr_start;
572         ardbeg_carveouts[2].size = tegra_vpr_size;
573
574         err = platform_device_register(&ardbeg_nvmap_device);
575         if (err) {
576                 pr_err("nvmap device registration failed\n");
577                 return err;
578         }
579 #endif
580
581         phost1x = ardbeg_host1x_init();
582         if (!phost1x) {
583                 pr_err("host1x devices registration failed\n");
584                 return -EINVAL;
585         }
586
587         res = platform_get_resource_byname(&ardbeg_disp1_device,
588                                          IORESOURCE_MEM, "fbmem");
589         res->start = tegra_fb_start;
590         res->end = tegra_fb_start + tegra_fb_size - 1;
591
592         /* Copy the bootloader fb to the fb. */
593         __tegra_move_framebuffer(&ardbeg_nvmap_device,
594                 tegra_fb_start, tegra_bootloader_fb_start,
595                         min(tegra_fb_size, tegra_bootloader_fb_size));
596
597         res = platform_get_resource_byname(&ardbeg_disp2_device,
598                                          IORESOURCE_MEM, "fbmem");
599
600         res->start = tegra_fb2_start;
601         res->end = tegra_fb2_start + tegra_fb2_size - 1;
602
603         ardbeg_disp1_device.dev.parent = &phost1x->dev;
604         err = platform_device_register(&ardbeg_disp1_device);
605         if (err) {
606                 pr_err("disp1 device registration failed\n");
607                 return err;
608         }
609
610         ardbeg_disp2_device.dev.parent = &phost1x->dev;
611         err = platform_device_register(&ardbeg_disp2_device);
612         if (err) {
613                 pr_err("disp2 device registration failed\n");
614                 return err;
615         }
616
617 #ifdef CONFIG_TEGRA_NVAVP
618         nvavp_device.dev.parent = &phost1x->dev;
619         err = platform_device_register(&nvavp_device);
620         if (err) {
621                 pr_err("nvavp device registration failed\n");
622                 return err;
623         }
624 #endif
625         return err;
626 }
627 #else
628 int __init ardbeg_panel_init(void)
629 {
630         if (ardbeg_host1x_init())
631                 return 0;
632         else
633                 return -EINVAL;
634 }
635 #endif