]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/video/exynos_fb.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / drivers / video / exynos_fb.c
1 /*
2  * Copyright (C) 2012 Samsung Electronics
3  *
4  * Author: InKi Dae <inki.dae@samsung.com>
5  * Author: Donghwa Lee <dh09.lee@samsung.com>
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <config.h>
11 #include <common.h>
12 #include <lcd.h>
13 #include <fdtdec.h>
14 #include <libfdt.h>
15 #include <asm/io.h>
16 #include <asm/arch/cpu.h>
17 #include <asm/arch/clock.h>
18 #include <asm/arch/clk.h>
19 #include <asm/arch/mipi_dsim.h>
20 #include <asm/arch/dp_info.h>
21 #include <asm/arch/system.h>
22 #include <asm-generic/errno.h>
23
24 #include "exynos_fb.h"
25
26 DECLARE_GLOBAL_DATA_PTR;
27
28 static unsigned int panel_width, panel_height;
29
30 #ifdef CONFIG_OF_CONTROL
31 vidinfo_t panel_info  = {
32         /*
33          * Insert a value here so that we don't end up in the BSS
34          * Reference: drivers/video/tegra.c
35          */
36         .vl_col = -1,
37 };
38 #endif
39
40 static void exynos_lcd_init_mem(void *lcdbase, vidinfo_t *vid)
41 {
42         unsigned long palette_size;
43         unsigned int fb_size;
44
45         fb_size = vid->vl_row * vid->vl_col * (NBITS(vid->vl_bpix) >> 3);
46
47         palette_size = NBITS(vid->vl_bpix) == 8 ? 256 : 16;
48
49         exynos_fimd_lcd_init_mem((unsigned long)lcdbase,
50                         (unsigned long)fb_size, palette_size);
51 }
52
53 static void exynos_lcd_init(vidinfo_t *vid)
54 {
55         exynos_fimd_lcd_init(vid);
56
57         /* Enable flushing after LCD writes if requested */
58         lcd_set_flush_dcache(1);
59 }
60
61 void __exynos_cfg_lcd_gpio(void)
62 {
63 }
64 void exynos_cfg_lcd_gpio(void)
65         __attribute__((weak, alias("__exynos_cfg_lcd_gpio")));
66
67 void __exynos_backlight_on(unsigned int onoff)
68 {
69 }
70 void exynos_backlight_on(unsigned int onoff)
71         __attribute__((weak, alias("__exynos_cfg_lcd_gpio")));
72
73 void __exynos_reset_lcd(void)
74 {
75 }
76 void exynos_reset_lcd(void)
77         __attribute__((weak, alias("__exynos_reset_lcd")));
78
79 void __exynos_lcd_power_on(void)
80 {
81 }
82 void exynos_lcd_power_on(void)
83         __attribute__((weak, alias("__exynos_lcd_power_on")));
84
85 void __exynos_cfg_ldo(void)
86 {
87 }
88 void exynos_cfg_ldo(void)
89         __attribute__((weak, alias("__exynos_cfg_ldo")));
90
91 void __exynos_enable_ldo(unsigned int onoff)
92 {
93 }
94 void exynos_enable_ldo(unsigned int onoff)
95         __attribute__((weak, alias("__exynos_enable_ldo")));
96
97 void __exynos_backlight_reset(void)
98 {
99 }
100 void exynos_backlight_reset(void)
101         __attribute__((weak, alias("__exynos_backlight_reset")));
102
103 int __exynos_lcd_misc_init(vidinfo_t *vid)
104 {
105         return 0;
106 }
107 int exynos_lcd_misc_init(vidinfo_t *vid)
108         __attribute__((weak, alias("__exynos_lcd_misc_init")));
109
110 static void lcd_panel_on(vidinfo_t *vid)
111 {
112         udelay(vid->init_delay);
113
114         exynos_backlight_reset();
115
116         exynos_cfg_lcd_gpio();
117
118         exynos_lcd_power_on();
119
120         udelay(vid->power_on_delay);
121
122         if (vid->dp_enabled)
123                 exynos_init_dp();
124
125         exynos_reset_lcd();
126
127         udelay(vid->reset_delay);
128
129         exynos_backlight_on(1);
130
131         exynos_cfg_ldo();
132
133         exynos_enable_ldo(1);
134
135         if (vid->mipi_enabled)
136                 exynos_mipi_dsi_init();
137 }
138
139 #ifdef CONFIG_OF_CONTROL
140 int exynos_lcd_early_init(const void *blob)
141 {
142         unsigned int node;
143         node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_FIMD);
144         if (node <= 0) {
145                 debug("exynos_fb: Can't get device node for fimd\n");
146                 return -ENODEV;
147         }
148
149         panel_info.vl_col = fdtdec_get_int(blob, node, "samsung,vl-col", 0);
150         if (panel_info.vl_col == 0) {
151                 debug("Can't get XRES\n");
152                 return -ENXIO;
153         }
154
155         panel_info.vl_row = fdtdec_get_int(blob, node, "samsung,vl-row", 0);
156         if (panel_info.vl_row == 0) {
157                 debug("Can't get YRES\n");
158                 return -ENXIO;
159         }
160
161         panel_info.vl_width = fdtdec_get_int(blob, node,
162                                                 "samsung,vl-width", 0);
163
164         panel_info.vl_height = fdtdec_get_int(blob, node,
165                                                 "samsung,vl-height", 0);
166
167         panel_info.vl_freq = fdtdec_get_int(blob, node, "samsung,vl-freq", 0);
168         if (panel_info.vl_freq == 0) {
169                 debug("Can't get refresh rate\n");
170                 return -ENXIO;
171         }
172
173         if (fdtdec_get_bool(blob, node, "samsung,vl-clkp"))
174                 panel_info.vl_clkp = CONFIG_SYS_LOW;
175
176         if (fdtdec_get_bool(blob, node, "samsung,vl-oep"))
177                 panel_info.vl_oep = CONFIG_SYS_LOW;
178
179         if (fdtdec_get_bool(blob, node, "samsung,vl-hsp"))
180                 panel_info.vl_hsp = CONFIG_SYS_LOW;
181
182         if (fdtdec_get_bool(blob, node, "samsung,vl-vsp"))
183                 panel_info.vl_vsp = CONFIG_SYS_LOW;
184
185         if (fdtdec_get_bool(blob, node, "samsung,vl-dp"))
186                 panel_info.vl_dp = CONFIG_SYS_LOW;
187
188         panel_info.vl_bpix = fdtdec_get_int(blob, node, "samsung,vl-bpix", 0);
189         if (panel_info.vl_bpix == 0) {
190                 debug("Can't get bits per pixel\n");
191                 return -ENXIO;
192         }
193
194         panel_info.vl_hspw = fdtdec_get_int(blob, node, "samsung,vl-hspw", 0);
195         if (panel_info.vl_hspw == 0) {
196                 debug("Can't get hsync width\n");
197                 return -ENXIO;
198         }
199
200         panel_info.vl_hfpd = fdtdec_get_int(blob, node, "samsung,vl-hfpd", 0);
201         if (panel_info.vl_hfpd == 0) {
202                 debug("Can't get right margin\n");
203                 return -ENXIO;
204         }
205
206         panel_info.vl_hbpd = (u_char)fdtdec_get_int(blob, node,
207                                                         "samsung,vl-hbpd", 0);
208         if (panel_info.vl_hbpd == 0) {
209                 debug("Can't get left margin\n");
210                 return -ENXIO;
211         }
212
213         panel_info.vl_vspw = (u_char)fdtdec_get_int(blob, node,
214                                                         "samsung,vl-vspw", 0);
215         if (panel_info.vl_vspw == 0) {
216                 debug("Can't get vsync width\n");
217                 return -ENXIO;
218         }
219
220         panel_info.vl_vfpd = fdtdec_get_int(blob, node,
221                                                         "samsung,vl-vfpd", 0);
222         if (panel_info.vl_vfpd == 0) {
223                 debug("Can't get lower margin\n");
224                 return -ENXIO;
225         }
226
227         panel_info.vl_vbpd = fdtdec_get_int(blob, node, "samsung,vl-vbpd", 0);
228         if (panel_info.vl_vbpd == 0) {
229                 debug("Can't get upper margin\n");
230                 return -ENXIO;
231         }
232
233         panel_info.vl_cmd_allow_len = fdtdec_get_int(blob, node,
234                                                 "samsung,vl-cmd-allow-len", 0);
235
236         panel_info.win_id = fdtdec_get_int(blob, node, "samsung,winid", 0);
237         panel_info.init_delay = fdtdec_get_int(blob, node,
238                                                 "samsung,init-delay", 0);
239         panel_info.power_on_delay = fdtdec_get_int(blob, node,
240                                                 "samsung,power-on-delay", 0);
241         panel_info.reset_delay = fdtdec_get_int(blob, node,
242                                                 "samsung,reset-delay", 0);
243         panel_info.interface_mode = fdtdec_get_int(blob, node,
244                                                 "samsung,interface-mode", 0);
245         panel_info.mipi_enabled = fdtdec_get_int(blob, node,
246                                                 "samsung,mipi-enabled", 0);
247         panel_info.dp_enabled = fdtdec_get_int(blob, node,
248                                                 "samsung,dp-enabled", 0);
249         panel_info.cs_setup = fdtdec_get_int(blob, node,
250                                                 "samsung,cs-setup", 0);
251         panel_info.wr_setup = fdtdec_get_int(blob, node,
252                                                 "samsung,wr-setup", 0);
253         panel_info.wr_act = fdtdec_get_int(blob, node, "samsung,wr-act", 0);
254         panel_info.wr_hold = fdtdec_get_int(blob, node, "samsung,wr-hold", 0);
255
256         panel_info.logo_on = fdtdec_get_int(blob, node, "samsung,logo-on", 0);
257         if (panel_info.logo_on) {
258                 panel_info.logo_width = fdtdec_get_int(blob, node,
259                                                 "samsung,logo-width", 0);
260                 panel_info.logo_height = fdtdec_get_int(blob, node,
261                                                 "samsung,logo-height", 0);
262                 panel_info.logo_addr = fdtdec_get_int(blob, node,
263                                                 "samsung,logo-addr", 0);
264         }
265
266         panel_info.rgb_mode = fdtdec_get_int(blob, node,
267                                                 "samsung,rgb-mode", 0);
268         panel_info.pclk_name = fdtdec_get_int(blob, node,
269                                                 "samsung,pclk-name", 0);
270         panel_info.sclk_div = fdtdec_get_int(blob, node,
271                                                 "samsung,sclk-div", 0);
272         panel_info.dual_lcd_enabled = fdtdec_get_int(blob, node,
273                                                 "samsung,dual-lcd-enabled", 0);
274
275         return 0;
276 }
277 #endif
278
279 void lcd_ctrl_init(void *lcdbase)
280 {
281         set_system_display_ctrl();
282         set_lcd_clk();
283
284 #ifdef CONFIG_OF_CONTROL
285 #ifdef CONFIG_EXYNOS_MIPI_DSIM
286         exynos_init_dsim_platform_data(&panel_info);
287 #endif
288         exynos_lcd_misc_init(&panel_info);
289 #else
290         /* initialize parameters which is specific to panel. */
291         init_panel_info(&panel_info);
292 #endif
293
294         panel_width = panel_info.vl_width;
295         panel_height = panel_info.vl_height;
296
297         exynos_lcd_init_mem(lcdbase, &panel_info);
298
299         exynos_lcd_init(&panel_info);
300 }
301
302 void lcd_enable(void)
303 {
304         if (panel_info.logo_on) {
305                 memset((void *) gd->fb_base, 0, panel_width * panel_height *
306                                 (NBITS(panel_info.vl_bpix) >> 3));
307         }
308
309         lcd_panel_on(&panel_info);
310 }
311
312 /* dummy function */
313 void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
314 {
315         return;
316 }