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/gpio.h> 23 #include <asm-generic/errno.h> 24 25 #include "exynos_fb.h" 26 27 DECLARE_GLOBAL_DATA_PTR; 28 29 static unsigned int panel_width, panel_height; 30 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 39 ushort *configuration_get_cmap(void) 40 { 41 #if defined(CONFIG_LCD_LOGO) 42 return bmp_logo_palette; 43 #else 44 return NULL; 45 #endif 46 } 47 48 static void exynos_lcd_init_mem(void *lcdbase, vidinfo_t *vid) 49 { 50 unsigned long palette_size; 51 unsigned int fb_size; 52 53 fb_size = vid->vl_row * vid->vl_col * (NBITS(vid->vl_bpix) >> 3); 54 55 palette_size = NBITS(vid->vl_bpix) == 8 ? 256 : 16; 56 57 exynos_fimd_lcd_init_mem((unsigned long)lcdbase, 58 (unsigned long)fb_size, palette_size); 59 } 60 61 static void exynos_lcd_init(vidinfo_t *vid) 62 { 63 exynos_fimd_lcd_init(vid); 64 65 /* Enable flushing after LCD writes if requested */ 66 lcd_set_flush_dcache(1); 67 } 68 69 __weak void exynos_cfg_lcd_gpio(void) 70 { 71 } 72 73 __weak void exynos_backlight_on(unsigned int onoff) 74 { 75 } 76 77 __weak void exynos_reset_lcd(void) 78 { 79 } 80 81 __weak void exynos_lcd_power_on(void) 82 { 83 } 84 85 __weak void exynos_cfg_ldo(void) 86 { 87 } 88 89 __weak void exynos_enable_ldo(unsigned int onoff) 90 { 91 } 92 93 __weak void exynos_backlight_reset(void) 94 { 95 } 96 97 __weak int exynos_lcd_misc_init(vidinfo_t *vid) 98 { 99 return 0; 100 } 101 102 static void lcd_panel_on(vidinfo_t *vid) 103 { 104 struct gpio_desc pwm_out_gpio; 105 struct gpio_desc bl_en_gpio; 106 unsigned int node; 107 108 udelay(vid->init_delay); 109 110 exynos_backlight_reset(); 111 112 exynos_cfg_lcd_gpio(); 113 114 exynos_lcd_power_on(); 115 116 udelay(vid->power_on_delay); 117 118 if (vid->dp_enabled) 119 exynos_init_dp(); 120 121 exynos_reset_lcd(); 122 123 udelay(vid->reset_delay); 124 125 exynos_backlight_on(1); 126 127 node = fdtdec_next_compatible(gd->fdt_blob, 0, 128 COMPAT_SAMSUNG_EXYNOS_FIMD); 129 if (node <= 0) { 130 debug("FIMD: Can't get device node for FIMD\n"); 131 return; 132 } 133 gpio_request_by_name_nodev(gd->fdt_blob, node, "samsung,pwm-out-gpio", 134 0, &pwm_out_gpio, 135 GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); 136 137 gpio_request_by_name_nodev(gd->fdt_blob, node, "samsung,bl-en-gpio", 0, 138 &bl_en_gpio, 139 GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); 140 141 exynos_cfg_ldo(); 142 143 exynos_enable_ldo(1); 144 145 if (vid->mipi_enabled) 146 exynos_mipi_dsi_init(); 147 } 148 149 int exynos_lcd_early_init(const void *blob) 150 { 151 unsigned int node; 152 node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_FIMD); 153 if (node <= 0) { 154 debug("exynos_fb: Can't get device node for fimd\n"); 155 return -ENODEV; 156 } 157 158 panel_info.vl_col = fdtdec_get_int(blob, node, "samsung,vl-col", 0); 159 if (panel_info.vl_col == 0) { 160 debug("Can't get XRES\n"); 161 return -ENXIO; 162 } 163 164 panel_info.vl_row = fdtdec_get_int(blob, node, "samsung,vl-row", 0); 165 if (panel_info.vl_row == 0) { 166 debug("Can't get YRES\n"); 167 return -ENXIO; 168 } 169 170 panel_info.vl_width = fdtdec_get_int(blob, node, 171 "samsung,vl-width", 0); 172 173 panel_info.vl_height = fdtdec_get_int(blob, node, 174 "samsung,vl-height", 0); 175 176 panel_info.vl_freq = fdtdec_get_int(blob, node, "samsung,vl-freq", 0); 177 if (panel_info.vl_freq == 0) { 178 debug("Can't get refresh rate\n"); 179 return -ENXIO; 180 } 181 182 if (fdtdec_get_bool(blob, node, "samsung,vl-clkp")) 183 panel_info.vl_clkp = CONFIG_SYS_LOW; 184 185 if (fdtdec_get_bool(blob, node, "samsung,vl-oep")) 186 panel_info.vl_oep = CONFIG_SYS_LOW; 187 188 if (fdtdec_get_bool(blob, node, "samsung,vl-hsp")) 189 panel_info.vl_hsp = CONFIG_SYS_LOW; 190 191 if (fdtdec_get_bool(blob, node, "samsung,vl-vsp")) 192 panel_info.vl_vsp = CONFIG_SYS_LOW; 193 194 if (fdtdec_get_bool(blob, node, "samsung,vl-dp")) 195 panel_info.vl_dp = CONFIG_SYS_LOW; 196 197 panel_info.vl_bpix = fdtdec_get_int(blob, node, "samsung,vl-bpix", 0); 198 if (panel_info.vl_bpix == 0) { 199 debug("Can't get bits per pixel\n"); 200 return -ENXIO; 201 } 202 203 panel_info.vl_hspw = fdtdec_get_int(blob, node, "samsung,vl-hspw", 0); 204 if (panel_info.vl_hspw == 0) { 205 debug("Can't get hsync width\n"); 206 return -ENXIO; 207 } 208 209 panel_info.vl_hfpd = fdtdec_get_int(blob, node, "samsung,vl-hfpd", 0); 210 if (panel_info.vl_hfpd == 0) { 211 debug("Can't get right margin\n"); 212 return -ENXIO; 213 } 214 215 panel_info.vl_hbpd = (u_char)fdtdec_get_int(blob, node, 216 "samsung,vl-hbpd", 0); 217 if (panel_info.vl_hbpd == 0) { 218 debug("Can't get left margin\n"); 219 return -ENXIO; 220 } 221 222 panel_info.vl_vspw = (u_char)fdtdec_get_int(blob, node, 223 "samsung,vl-vspw", 0); 224 if (panel_info.vl_vspw == 0) { 225 debug("Can't get vsync width\n"); 226 return -ENXIO; 227 } 228 229 panel_info.vl_vfpd = fdtdec_get_int(blob, node, 230 "samsung,vl-vfpd", 0); 231 if (panel_info.vl_vfpd == 0) { 232 debug("Can't get lower margin\n"); 233 return -ENXIO; 234 } 235 236 panel_info.vl_vbpd = fdtdec_get_int(blob, node, "samsung,vl-vbpd", 0); 237 if (panel_info.vl_vbpd == 0) { 238 debug("Can't get upper margin\n"); 239 return -ENXIO; 240 } 241 242 panel_info.vl_cmd_allow_len = fdtdec_get_int(blob, node, 243 "samsung,vl-cmd-allow-len", 0); 244 245 panel_info.win_id = fdtdec_get_int(blob, node, "samsung,winid", 0); 246 panel_info.init_delay = fdtdec_get_int(blob, node, 247 "samsung,init-delay", 0); 248 panel_info.power_on_delay = fdtdec_get_int(blob, node, 249 "samsung,power-on-delay", 0); 250 panel_info.reset_delay = fdtdec_get_int(blob, node, 251 "samsung,reset-delay", 0); 252 panel_info.interface_mode = fdtdec_get_int(blob, node, 253 "samsung,interface-mode", 0); 254 panel_info.mipi_enabled = fdtdec_get_int(blob, node, 255 "samsung,mipi-enabled", 0); 256 panel_info.dp_enabled = fdtdec_get_int(blob, node, 257 "samsung,dp-enabled", 0); 258 panel_info.cs_setup = fdtdec_get_int(blob, node, 259 "samsung,cs-setup", 0); 260 panel_info.wr_setup = fdtdec_get_int(blob, node, 261 "samsung,wr-setup", 0); 262 panel_info.wr_act = fdtdec_get_int(blob, node, "samsung,wr-act", 0); 263 panel_info.wr_hold = fdtdec_get_int(blob, node, "samsung,wr-hold", 0); 264 265 panel_info.logo_on = fdtdec_get_int(blob, node, "samsung,logo-on", 0); 266 if (panel_info.logo_on) { 267 panel_info.logo_width = fdtdec_get_int(blob, node, 268 "samsung,logo-width", 0); 269 panel_info.logo_height = fdtdec_get_int(blob, node, 270 "samsung,logo-height", 0); 271 panel_info.logo_addr = fdtdec_get_int(blob, node, 272 "samsung,logo-addr", 0); 273 } 274 275 panel_info.rgb_mode = fdtdec_get_int(blob, node, 276 "samsung,rgb-mode", 0); 277 panel_info.pclk_name = fdtdec_get_int(blob, node, 278 "samsung,pclk-name", 0); 279 panel_info.sclk_div = fdtdec_get_int(blob, node, 280 "samsung,sclk-div", 0); 281 panel_info.dual_lcd_enabled = fdtdec_get_int(blob, node, 282 "samsung,dual-lcd-enabled", 0); 283 284 return 0; 285 } 286 287 void lcd_ctrl_init(void *lcdbase) 288 { 289 set_system_display_ctrl(); 290 set_lcd_clk(); 291 292 #ifdef CONFIG_EXYNOS_MIPI_DSIM 293 exynos_init_dsim_platform_data(&panel_info); 294 #endif 295 exynos_lcd_misc_init(&panel_info); 296 297 panel_width = panel_info.vl_width; 298 panel_height = panel_info.vl_height; 299 300 exynos_lcd_init_mem(lcdbase, &panel_info); 301 302 exynos_lcd_init(&panel_info); 303 } 304 305 void lcd_enable(void) 306 { 307 if (panel_info.logo_on) { 308 memset((void *) gd->fb_base, 0, panel_width * panel_height * 309 (NBITS(panel_info.vl_bpix) >> 3)); 310 } 311 312 lcd_panel_on(&panel_info); 313 } 314 315 /* dummy function */ 316 void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) 317 { 318 return; 319 } 320