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