108a7aa1eSSimon Glass /* 208a7aa1eSSimon Glass * Copyright (C) 2012 Samsung Electronics 308a7aa1eSSimon Glass * 408a7aa1eSSimon Glass * Author: InKi Dae <inki.dae@samsung.com> 508a7aa1eSSimon Glass * Author: Donghwa Lee <dh09.lee@samsung.com> 608a7aa1eSSimon Glass * 708a7aa1eSSimon Glass * SPDX-License-Identifier: GPL-2.0+ 808a7aa1eSSimon Glass */ 908a7aa1eSSimon Glass 1008a7aa1eSSimon Glass #include <config.h> 1108a7aa1eSSimon Glass #include <common.h> 12*bb5930d5SSimon Glass #include <display.h> 130c84358cSSimon Glass #include <div64.h> 14*bb5930d5SSimon Glass #include <dm.h> 1508a7aa1eSSimon Glass #include <fdtdec.h> 1608a7aa1eSSimon Glass #include <libfdt.h> 17*bb5930d5SSimon Glass #include <panel.h> 18*bb5930d5SSimon Glass #include <video.h> 19*bb5930d5SSimon Glass #include <video_bridge.h> 2008a7aa1eSSimon Glass #include <asm/io.h> 2108a7aa1eSSimon Glass #include <asm/arch/cpu.h> 2208a7aa1eSSimon Glass #include <asm/arch/clock.h> 2308a7aa1eSSimon Glass #include <asm/arch/clk.h> 2408a7aa1eSSimon Glass #include <asm/arch/mipi_dsim.h> 2508a7aa1eSSimon Glass #include <asm/arch/dp_info.h> 26*bb5930d5SSimon Glass #include <asm/arch/fb.h> 27*bb5930d5SSimon Glass #include <asm/arch/pinmux.h> 2808a7aa1eSSimon Glass #include <asm/arch/system.h> 2908a7aa1eSSimon Glass #include <asm/gpio.h> 3008a7aa1eSSimon Glass #include <asm-generic/errno.h> 3108a7aa1eSSimon Glass 3208a7aa1eSSimon Glass DECLARE_GLOBAL_DATA_PTR; 3308a7aa1eSSimon Glass 34*bb5930d5SSimon Glass enum { 35*bb5930d5SSimon Glass FIMD_RGB_INTERFACE = 1, 36*bb5930d5SSimon Glass FIMD_CPU_INTERFACE = 2, 3708a7aa1eSSimon Glass }; 3808a7aa1eSSimon Glass 39*bb5930d5SSimon Glass enum exynos_fb_rgb_mode_t { 40*bb5930d5SSimon Glass MODE_RGB_P = 0, 41*bb5930d5SSimon Glass MODE_BGR_P = 1, 42*bb5930d5SSimon Glass MODE_RGB_S = 2, 43*bb5930d5SSimon Glass MODE_BGR_S = 3, 44*bb5930d5SSimon Glass }; 45*bb5930d5SSimon Glass 46*bb5930d5SSimon Glass struct exynos_fb_priv { 47*bb5930d5SSimon Glass ushort vl_col; /* Number of columns (i.e. 640) */ 48*bb5930d5SSimon Glass ushort vl_row; /* Number of rows (i.e. 480) */ 49*bb5930d5SSimon Glass ushort vl_rot; /* Rotation of Display (0, 1, 2, 3) */ 50*bb5930d5SSimon Glass ushort vl_width; /* Width of display area in millimeters */ 51*bb5930d5SSimon Glass ushort vl_height; /* Height of display area in millimeters */ 52*bb5930d5SSimon Glass 53*bb5930d5SSimon Glass /* LCD configuration register */ 54*bb5930d5SSimon Glass u_char vl_freq; /* Frequency */ 55*bb5930d5SSimon Glass u_char vl_clkp; /* Clock polarity */ 56*bb5930d5SSimon Glass u_char vl_oep; /* Output Enable polarity */ 57*bb5930d5SSimon Glass u_char vl_hsp; /* Horizontal Sync polarity */ 58*bb5930d5SSimon Glass u_char vl_vsp; /* Vertical Sync polarity */ 59*bb5930d5SSimon Glass u_char vl_dp; /* Data polarity */ 60*bb5930d5SSimon Glass u_char vl_bpix; /* Bits per pixel */ 61*bb5930d5SSimon Glass 62*bb5930d5SSimon Glass /* Horizontal control register. Timing from data sheet */ 63*bb5930d5SSimon Glass u_char vl_hspw; /* Horz sync pulse width */ 64*bb5930d5SSimon Glass u_char vl_hfpd; /* Wait before of line */ 65*bb5930d5SSimon Glass u_char vl_hbpd; /* Wait end of line */ 66*bb5930d5SSimon Glass 67*bb5930d5SSimon Glass /* Vertical control register. */ 68*bb5930d5SSimon Glass u_char vl_vspw; /* Vertical sync pulse width */ 69*bb5930d5SSimon Glass u_char vl_vfpd; /* Wait before of frame */ 70*bb5930d5SSimon Glass u_char vl_vbpd; /* Wait end of frame */ 71*bb5930d5SSimon Glass u_char vl_cmd_allow_len; /* Wait end of frame */ 72*bb5930d5SSimon Glass 73*bb5930d5SSimon Glass unsigned int win_id; 74*bb5930d5SSimon Glass unsigned int init_delay; 75*bb5930d5SSimon Glass unsigned int power_on_delay; 76*bb5930d5SSimon Glass unsigned int reset_delay; 77*bb5930d5SSimon Glass unsigned int interface_mode; 78*bb5930d5SSimon Glass unsigned int mipi_enabled; 79*bb5930d5SSimon Glass unsigned int dp_enabled; 80*bb5930d5SSimon Glass unsigned int cs_setup; 81*bb5930d5SSimon Glass unsigned int wr_setup; 82*bb5930d5SSimon Glass unsigned int wr_act; 83*bb5930d5SSimon Glass unsigned int wr_hold; 84*bb5930d5SSimon Glass unsigned int logo_on; 85*bb5930d5SSimon Glass unsigned int logo_width; 86*bb5930d5SSimon Glass unsigned int logo_height; 87*bb5930d5SSimon Glass int logo_x_offset; 88*bb5930d5SSimon Glass int logo_y_offset; 89*bb5930d5SSimon Glass unsigned long logo_addr; 90*bb5930d5SSimon Glass unsigned int rgb_mode; 91*bb5930d5SSimon Glass unsigned int resolution; 92*bb5930d5SSimon Glass 93*bb5930d5SSimon Glass /* parent clock name(MPLL, EPLL or VPLL) */ 94*bb5930d5SSimon Glass unsigned int pclk_name; 95*bb5930d5SSimon Glass /* ratio value for source clock from parent clock. */ 96*bb5930d5SSimon Glass unsigned int sclk_div; 97*bb5930d5SSimon Glass 98*bb5930d5SSimon Glass unsigned int dual_lcd_enabled; 99*bb5930d5SSimon Glass struct exynos_fb *reg; 100*bb5930d5SSimon Glass struct exynos_platform_mipi_dsim *dsim_platform_data_dt; 101*bb5930d5SSimon Glass }; 102*bb5930d5SSimon Glass 103*bb5930d5SSimon Glass static void exynos_fimd_set_dualrgb(struct exynos_fb_priv *priv, bool enabled) 1040c84358cSSimon Glass { 1058b449a66SSimon Glass struct exynos_fb *reg = priv->reg; 1060c84358cSSimon Glass unsigned int cfg = 0; 1070c84358cSSimon Glass 1080c84358cSSimon Glass if (enabled) { 1090c84358cSSimon Glass cfg = EXYNOS_DUALRGB_BYPASS_DUAL | EXYNOS_DUALRGB_LINESPLIT | 1100c84358cSSimon Glass EXYNOS_DUALRGB_VDEN_EN_ENABLE; 1110c84358cSSimon Glass 1120c84358cSSimon Glass /* in case of Line Split mode, MAIN_CNT doesn't neet to set. */ 1138b449a66SSimon Glass cfg |= EXYNOS_DUALRGB_SUB_CNT(priv->vl_col / 2) | 1140c84358cSSimon Glass EXYNOS_DUALRGB_MAIN_CNT(0); 1150c84358cSSimon Glass } 1160c84358cSSimon Glass 1178b449a66SSimon Glass writel(cfg, ®->dualrgb); 1180c84358cSSimon Glass } 1190c84358cSSimon Glass 120*bb5930d5SSimon Glass static void exynos_fimd_set_dp_clkcon(struct exynos_fb_priv *priv, 1210c84358cSSimon Glass unsigned int enabled) 1220c84358cSSimon Glass { 1238b449a66SSimon Glass struct exynos_fb *reg = priv->reg; 1240c84358cSSimon Glass unsigned int cfg = 0; 1250c84358cSSimon Glass 1260c84358cSSimon Glass if (enabled) 1270c84358cSSimon Glass cfg = EXYNOS_DP_CLK_ENABLE; 1280c84358cSSimon Glass 1298b449a66SSimon Glass writel(cfg, ®->dp_mie_clkcon); 1300c84358cSSimon Glass } 1310c84358cSSimon Glass 132*bb5930d5SSimon Glass static void exynos_fimd_set_par(struct exynos_fb_priv *priv, 133*bb5930d5SSimon Glass unsigned int win_id) 1340c84358cSSimon Glass { 1358b449a66SSimon Glass struct exynos_fb *reg = priv->reg; 1360c84358cSSimon Glass unsigned int cfg = 0; 1370c84358cSSimon Glass 1380c84358cSSimon Glass /* set window control */ 1398b449a66SSimon Glass cfg = readl((unsigned int)®->wincon0 + 1400c84358cSSimon Glass EXYNOS_WINCON(win_id)); 1410c84358cSSimon Glass 1420c84358cSSimon Glass cfg &= ~(EXYNOS_WINCON_BITSWP_ENABLE | EXYNOS_WINCON_BYTESWP_ENABLE | 1430c84358cSSimon Glass EXYNOS_WINCON_HAWSWP_ENABLE | EXYNOS_WINCON_WSWP_ENABLE | 1440c84358cSSimon Glass EXYNOS_WINCON_BURSTLEN_MASK | EXYNOS_WINCON_BPPMODE_MASK | 1450c84358cSSimon Glass EXYNOS_WINCON_INRGB_MASK | EXYNOS_WINCON_DATAPATH_MASK); 1460c84358cSSimon Glass 1470c84358cSSimon Glass /* DATAPATH is DMA */ 1480c84358cSSimon Glass cfg |= EXYNOS_WINCON_DATAPATH_DMA; 1490c84358cSSimon Glass 1500c84358cSSimon Glass cfg |= EXYNOS_WINCON_HAWSWP_ENABLE; 1510c84358cSSimon Glass 1520c84358cSSimon Glass /* dma burst is 16 */ 1530c84358cSSimon Glass cfg |= EXYNOS_WINCON_BURSTLEN_16WORD; 1540c84358cSSimon Glass 1558b449a66SSimon Glass switch (priv->vl_bpix) { 1560c84358cSSimon Glass case 4: 1570c84358cSSimon Glass cfg |= EXYNOS_WINCON_BPPMODE_16BPP_565; 1580c84358cSSimon Glass break; 1590c84358cSSimon Glass default: 1600c84358cSSimon Glass cfg |= EXYNOS_WINCON_BPPMODE_24BPP_888; 1610c84358cSSimon Glass break; 1620c84358cSSimon Glass } 1630c84358cSSimon Glass 1648b449a66SSimon Glass writel(cfg, (unsigned int)®->wincon0 + 1650c84358cSSimon Glass EXYNOS_WINCON(win_id)); 1660c84358cSSimon Glass 1670c84358cSSimon Glass /* set window position to x=0, y=0*/ 1680c84358cSSimon Glass cfg = EXYNOS_VIDOSD_LEFT_X(0) | EXYNOS_VIDOSD_TOP_Y(0); 1698b449a66SSimon Glass writel(cfg, (unsigned int)®->vidosd0a + 1700c84358cSSimon Glass EXYNOS_VIDOSD(win_id)); 1710c84358cSSimon Glass 1728b449a66SSimon Glass cfg = EXYNOS_VIDOSD_RIGHT_X(priv->vl_col - 1) | 1738b449a66SSimon Glass EXYNOS_VIDOSD_BOTTOM_Y(priv->vl_row - 1) | 1740c84358cSSimon Glass EXYNOS_VIDOSD_RIGHT_X_E(1) | 1750c84358cSSimon Glass EXYNOS_VIDOSD_BOTTOM_Y_E(0); 1760c84358cSSimon Glass 1778b449a66SSimon Glass writel(cfg, (unsigned int)®->vidosd0b + 1780c84358cSSimon Glass EXYNOS_VIDOSD(win_id)); 1790c84358cSSimon Glass 1800c84358cSSimon Glass /* set window size for window0*/ 1818b449a66SSimon Glass cfg = EXYNOS_VIDOSD_SIZE(priv->vl_col * priv->vl_row); 1828b449a66SSimon Glass writel(cfg, (unsigned int)®->vidosd0c + 1830c84358cSSimon Glass EXYNOS_VIDOSD(win_id)); 1840c84358cSSimon Glass } 1850c84358cSSimon Glass 186*bb5930d5SSimon Glass static void exynos_fimd_set_buffer_address(struct exynos_fb_priv *priv, 1870c84358cSSimon Glass unsigned int win_id, 1880c84358cSSimon Glass ulong lcd_base_addr) 1890c84358cSSimon Glass { 1908b449a66SSimon Glass struct exynos_fb *reg = priv->reg; 1910c84358cSSimon Glass unsigned long start_addr, end_addr; 1920c84358cSSimon Glass 1930c84358cSSimon Glass start_addr = lcd_base_addr; 194*bb5930d5SSimon Glass end_addr = start_addr + ((priv->vl_col * (VNBITS(priv->vl_bpix) / 8)) * 1958b449a66SSimon Glass priv->vl_row); 1960c84358cSSimon Glass 1978b449a66SSimon Glass writel(start_addr, (unsigned int)®->vidw00add0b0 + 1980c84358cSSimon Glass EXYNOS_BUFFER_OFFSET(win_id)); 1998b449a66SSimon Glass writel(end_addr, (unsigned int)®->vidw00add1b0 + 2000c84358cSSimon Glass EXYNOS_BUFFER_OFFSET(win_id)); 2010c84358cSSimon Glass } 2020c84358cSSimon Glass 203*bb5930d5SSimon Glass static void exynos_fimd_set_clock(struct exynos_fb_priv *priv) 2040c84358cSSimon Glass { 2058b449a66SSimon Glass struct exynos_fb *reg = priv->reg; 2060c84358cSSimon Glass unsigned int cfg = 0, div = 0, remainder, remainder_div; 2070c84358cSSimon Glass unsigned long pixel_clock; 2080c84358cSSimon Glass unsigned long long src_clock; 2090c84358cSSimon Glass 2108b449a66SSimon Glass if (priv->dual_lcd_enabled) { 2118b449a66SSimon Glass pixel_clock = priv->vl_freq * 2128b449a66SSimon Glass (priv->vl_hspw + priv->vl_hfpd + 2138b449a66SSimon Glass priv->vl_hbpd + priv->vl_col / 2) * 2148b449a66SSimon Glass (priv->vl_vspw + priv->vl_vfpd + 2158b449a66SSimon Glass priv->vl_vbpd + priv->vl_row); 2168b449a66SSimon Glass } else if (priv->interface_mode == FIMD_CPU_INTERFACE) { 2178b449a66SSimon Glass pixel_clock = priv->vl_freq * 2188b449a66SSimon Glass priv->vl_width * priv->vl_height * 2198b449a66SSimon Glass (priv->cs_setup + priv->wr_setup + 2208b449a66SSimon Glass priv->wr_act + priv->wr_hold + 1); 2210c84358cSSimon Glass } else { 2228b449a66SSimon Glass pixel_clock = priv->vl_freq * 2238b449a66SSimon Glass (priv->vl_hspw + priv->vl_hfpd + 2248b449a66SSimon Glass priv->vl_hbpd + priv->vl_col) * 2258b449a66SSimon Glass (priv->vl_vspw + priv->vl_vfpd + 2268b449a66SSimon Glass priv->vl_vbpd + priv->vl_row); 2270c84358cSSimon Glass } 2280c84358cSSimon Glass 2298b449a66SSimon Glass cfg = readl(®->vidcon0); 2300c84358cSSimon Glass cfg &= ~(EXYNOS_VIDCON0_CLKSEL_MASK | EXYNOS_VIDCON0_CLKVALUP_MASK | 2310c84358cSSimon Glass EXYNOS_VIDCON0_CLKVAL_F(0xFF) | EXYNOS_VIDCON0_VCLKEN_MASK | 2320c84358cSSimon Glass EXYNOS_VIDCON0_CLKDIR_MASK); 2330c84358cSSimon Glass cfg |= (EXYNOS_VIDCON0_CLKSEL_SCLK | EXYNOS_VIDCON0_CLKVALUP_ALWAYS | 2340c84358cSSimon Glass EXYNOS_VIDCON0_VCLKEN_NORMAL | EXYNOS_VIDCON0_CLKDIR_DIVIDED); 2350c84358cSSimon Glass 2360c84358cSSimon Glass src_clock = (unsigned long long) get_lcd_clk(); 2370c84358cSSimon Glass 2380c84358cSSimon Glass /* get quotient and remainder. */ 2390c84358cSSimon Glass remainder = do_div(src_clock, pixel_clock); 2400c84358cSSimon Glass div = src_clock; 2410c84358cSSimon Glass 2420c84358cSSimon Glass remainder *= 10; 2430c84358cSSimon Glass remainder_div = remainder / pixel_clock; 2440c84358cSSimon Glass 2450c84358cSSimon Glass /* round about one places of decimals. */ 2460c84358cSSimon Glass if (remainder_div >= 5) 2470c84358cSSimon Glass div++; 2480c84358cSSimon Glass 2490c84358cSSimon Glass /* in case of dual lcd mode. */ 2508b449a66SSimon Glass if (priv->dual_lcd_enabled) 2510c84358cSSimon Glass div--; 2520c84358cSSimon Glass 2530c84358cSSimon Glass cfg |= EXYNOS_VIDCON0_CLKVAL_F(div - 1); 2548b449a66SSimon Glass writel(cfg, ®->vidcon0); 2550c84358cSSimon Glass } 2560c84358cSSimon Glass 257*bb5930d5SSimon Glass void exynos_set_trigger(struct exynos_fb_priv *priv) 2580c84358cSSimon Glass { 2598b449a66SSimon Glass struct exynos_fb *reg = priv->reg; 2600c84358cSSimon Glass unsigned int cfg = 0; 2610c84358cSSimon Glass 2628b449a66SSimon Glass cfg = readl(®->trigcon); 2630c84358cSSimon Glass 2640c84358cSSimon Glass cfg |= (EXYNOS_I80SOFT_TRIG_EN | EXYNOS_I80START_TRIG); 2650c84358cSSimon Glass 2668b449a66SSimon Glass writel(cfg, ®->trigcon); 2670c84358cSSimon Glass } 2680c84358cSSimon Glass 269*bb5930d5SSimon Glass int exynos_is_i80_frame_done(struct exynos_fb_priv *priv) 2700c84358cSSimon Glass { 2718b449a66SSimon Glass struct exynos_fb *reg = priv->reg; 2720c84358cSSimon Glass unsigned int cfg = 0; 2730c84358cSSimon Glass int status; 2740c84358cSSimon Glass 2758b449a66SSimon Glass cfg = readl(®->trigcon); 2760c84358cSSimon Glass 2770c84358cSSimon Glass /* frame done func is valid only when TRIMODE[0] is set to 1. */ 2780c84358cSSimon Glass status = (cfg & EXYNOS_I80STATUS_TRIG_DONE) == 2790c84358cSSimon Glass EXYNOS_I80STATUS_TRIG_DONE; 2800c84358cSSimon Glass 2810c84358cSSimon Glass return status; 2820c84358cSSimon Glass } 2830c84358cSSimon Glass 284*bb5930d5SSimon Glass static void exynos_fimd_lcd_on(struct exynos_fb_priv *priv) 2850c84358cSSimon Glass { 2868b449a66SSimon Glass struct exynos_fb *reg = priv->reg; 2870c84358cSSimon Glass unsigned int cfg = 0; 2880c84358cSSimon Glass 2890c84358cSSimon Glass /* display on */ 2908b449a66SSimon Glass cfg = readl(®->vidcon0); 2910c84358cSSimon Glass cfg |= (EXYNOS_VIDCON0_ENVID_ENABLE | EXYNOS_VIDCON0_ENVID_F_ENABLE); 2928b449a66SSimon Glass writel(cfg, ®->vidcon0); 2930c84358cSSimon Glass } 2940c84358cSSimon Glass 295*bb5930d5SSimon Glass static void exynos_fimd_window_on(struct exynos_fb_priv *priv, 296*bb5930d5SSimon Glass unsigned int win_id) 2970c84358cSSimon Glass { 2988b449a66SSimon Glass struct exynos_fb *reg = priv->reg; 2990c84358cSSimon Glass unsigned int cfg = 0; 3000c84358cSSimon Glass 3010c84358cSSimon Glass /* enable window */ 3028b449a66SSimon Glass cfg = readl((unsigned int)®->wincon0 + 3030c84358cSSimon Glass EXYNOS_WINCON(win_id)); 3040c84358cSSimon Glass cfg |= EXYNOS_WINCON_ENWIN_ENABLE; 3058b449a66SSimon Glass writel(cfg, (unsigned int)®->wincon0 + 3060c84358cSSimon Glass EXYNOS_WINCON(win_id)); 3070c84358cSSimon Glass 3088b449a66SSimon Glass cfg = readl(®->winshmap); 3090c84358cSSimon Glass cfg |= EXYNOS_WINSHMAP_CH_ENABLE(win_id); 3108b449a66SSimon Glass writel(cfg, ®->winshmap); 3110c84358cSSimon Glass } 3120c84358cSSimon Glass 313*bb5930d5SSimon Glass void exynos_fimd_lcd_off(struct exynos_fb_priv *priv) 3140c84358cSSimon Glass { 3158b449a66SSimon Glass struct exynos_fb *reg = priv->reg; 3160c84358cSSimon Glass unsigned int cfg = 0; 3170c84358cSSimon Glass 3188b449a66SSimon Glass cfg = readl(®->vidcon0); 3190c84358cSSimon Glass cfg &= (EXYNOS_VIDCON0_ENVID_DISABLE | EXYNOS_VIDCON0_ENVID_F_DISABLE); 3208b449a66SSimon Glass writel(cfg, ®->vidcon0); 3210c84358cSSimon Glass } 3220c84358cSSimon Glass 323*bb5930d5SSimon Glass void exynos_fimd_window_off(struct exynos_fb_priv *priv, unsigned int win_id) 3240c84358cSSimon Glass { 3258b449a66SSimon Glass struct exynos_fb *reg = priv->reg; 3260c84358cSSimon Glass unsigned int cfg = 0; 3270c84358cSSimon Glass 3288b449a66SSimon Glass cfg = readl((unsigned int)®->wincon0 + 3290c84358cSSimon Glass EXYNOS_WINCON(win_id)); 3300c84358cSSimon Glass cfg &= EXYNOS_WINCON_ENWIN_DISABLE; 3318b449a66SSimon Glass writel(cfg, (unsigned int)®->wincon0 + 3320c84358cSSimon Glass EXYNOS_WINCON(win_id)); 3330c84358cSSimon Glass 3348b449a66SSimon Glass cfg = readl(®->winshmap); 3350c84358cSSimon Glass cfg &= ~EXYNOS_WINSHMAP_CH_DISABLE(win_id); 3368b449a66SSimon Glass writel(cfg, ®->winshmap); 3370c84358cSSimon Glass } 3380c84358cSSimon Glass 3390c84358cSSimon Glass /* 3400c84358cSSimon Glass * The reset value for FIMD SYSMMU register MMU_CTRL is 3 3410c84358cSSimon Glass * on Exynos5420 and newer versions. 3420c84358cSSimon Glass * This means FIMD SYSMMU is on by default on Exynos5420 3430c84358cSSimon Glass * and newer versions. 3440c84358cSSimon Glass * Since in u-boot we don't use SYSMMU, we should disable 3450c84358cSSimon Glass * those FIMD SYSMMU. 3460c84358cSSimon Glass * Note that there are 2 SYSMMU for FIMD: m0 and m1. 3470c84358cSSimon Glass * m0 handles windows 0 and 4, and m1 handles windows 1, 2 and 3. 3480c84358cSSimon Glass * We disable both of them here. 3490c84358cSSimon Glass */ 3500c84358cSSimon Glass void exynos_fimd_disable_sysmmu(void) 3510c84358cSSimon Glass { 3520c84358cSSimon Glass u32 *sysmmufimd; 3530c84358cSSimon Glass unsigned int node; 3540c84358cSSimon Glass int node_list[2]; 3550c84358cSSimon Glass int count; 3560c84358cSSimon Glass int i; 3570c84358cSSimon Glass 3580c84358cSSimon Glass count = fdtdec_find_aliases_for_id(gd->fdt_blob, "fimd", 3590c84358cSSimon Glass COMPAT_SAMSUNG_EXYNOS_SYSMMU, node_list, 2); 3600c84358cSSimon Glass for (i = 0; i < count; i++) { 3610c84358cSSimon Glass node = node_list[i]; 3620c84358cSSimon Glass if (node <= 0) { 3630c84358cSSimon Glass debug("Can't get device node for fimd sysmmu\n"); 3640c84358cSSimon Glass return; 3650c84358cSSimon Glass } 3660c84358cSSimon Glass 3670c84358cSSimon Glass sysmmufimd = (u32 *)fdtdec_get_addr(gd->fdt_blob, node, "reg"); 3680c84358cSSimon Glass if (!sysmmufimd) { 3690c84358cSSimon Glass debug("Can't get base address for sysmmu fimdm0"); 3700c84358cSSimon Glass return; 3710c84358cSSimon Glass } 3720c84358cSSimon Glass 3730c84358cSSimon Glass writel(0x0, sysmmufimd); 3740c84358cSSimon Glass } 3750c84358cSSimon Glass } 3760c84358cSSimon Glass 377*bb5930d5SSimon Glass void exynos_fimd_lcd_init(struct udevice *dev) 3780c84358cSSimon Glass { 379*bb5930d5SSimon Glass struct exynos_fb_priv *priv = dev_get_priv(dev); 380*bb5930d5SSimon Glass struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); 381*bb5930d5SSimon Glass struct exynos_fb *reg = priv->reg; 3820c84358cSSimon Glass unsigned int cfg = 0, rgb_mode; 3830c84358cSSimon Glass unsigned int offset; 3840c84358cSSimon Glass unsigned int node; 3850c84358cSSimon Glass 386*bb5930d5SSimon Glass node = dev->of_offset; 3870c84358cSSimon Glass if (fdtdec_get_bool(gd->fdt_blob, node, "samsung,disable-sysmmu")) 3880c84358cSSimon Glass exynos_fimd_disable_sysmmu(); 3890c84358cSSimon Glass 3900c84358cSSimon Glass offset = exynos_fimd_get_base_offset(); 3910c84358cSSimon Glass 3928b449a66SSimon Glass rgb_mode = priv->rgb_mode; 3930c84358cSSimon Glass 3948b449a66SSimon Glass if (priv->interface_mode == FIMD_RGB_INTERFACE) { 3950c84358cSSimon Glass cfg |= EXYNOS_VIDCON0_VIDOUT_RGB; 3968b449a66SSimon Glass writel(cfg, ®->vidcon0); 3970c84358cSSimon Glass 3988b449a66SSimon Glass cfg = readl(®->vidcon2); 3990c84358cSSimon Glass cfg &= ~(EXYNOS_VIDCON2_WB_MASK | 4000c84358cSSimon Glass EXYNOS_VIDCON2_TVFORMATSEL_MASK | 4010c84358cSSimon Glass EXYNOS_VIDCON2_TVFORMATSEL_YUV_MASK); 4020c84358cSSimon Glass cfg |= EXYNOS_VIDCON2_WB_DISABLE; 4038b449a66SSimon Glass writel(cfg, ®->vidcon2); 4040c84358cSSimon Glass 4050c84358cSSimon Glass /* set polarity */ 4060c84358cSSimon Glass cfg = 0; 4078b449a66SSimon Glass if (!priv->vl_clkp) 4080c84358cSSimon Glass cfg |= EXYNOS_VIDCON1_IVCLK_RISING_EDGE; 4098b449a66SSimon Glass if (!priv->vl_hsp) 4100c84358cSSimon Glass cfg |= EXYNOS_VIDCON1_IHSYNC_INVERT; 4118b449a66SSimon Glass if (!priv->vl_vsp) 4120c84358cSSimon Glass cfg |= EXYNOS_VIDCON1_IVSYNC_INVERT; 4138b449a66SSimon Glass if (!priv->vl_dp) 4140c84358cSSimon Glass cfg |= EXYNOS_VIDCON1_IVDEN_INVERT; 4150c84358cSSimon Glass 4168b449a66SSimon Glass writel(cfg, (unsigned int)®->vidcon1 + offset); 4170c84358cSSimon Glass 4180c84358cSSimon Glass /* set timing */ 4198b449a66SSimon Glass cfg = EXYNOS_VIDTCON0_VFPD(priv->vl_vfpd - 1); 4208b449a66SSimon Glass cfg |= EXYNOS_VIDTCON0_VBPD(priv->vl_vbpd - 1); 4218b449a66SSimon Glass cfg |= EXYNOS_VIDTCON0_VSPW(priv->vl_vspw - 1); 4228b449a66SSimon Glass writel(cfg, (unsigned int)®->vidtcon0 + offset); 4230c84358cSSimon Glass 4248b449a66SSimon Glass cfg = EXYNOS_VIDTCON1_HFPD(priv->vl_hfpd - 1); 4258b449a66SSimon Glass cfg |= EXYNOS_VIDTCON1_HBPD(priv->vl_hbpd - 1); 4268b449a66SSimon Glass cfg |= EXYNOS_VIDTCON1_HSPW(priv->vl_hspw - 1); 4270c84358cSSimon Glass 4288b449a66SSimon Glass writel(cfg, (unsigned int)®->vidtcon1 + offset); 4290c84358cSSimon Glass 4300c84358cSSimon Glass /* set lcd size */ 4318b449a66SSimon Glass cfg = EXYNOS_VIDTCON2_HOZVAL(priv->vl_col - 1) | 4328b449a66SSimon Glass EXYNOS_VIDTCON2_LINEVAL(priv->vl_row - 1) | 4338b449a66SSimon Glass EXYNOS_VIDTCON2_HOZVAL_E(priv->vl_col - 1) | 4348b449a66SSimon Glass EXYNOS_VIDTCON2_LINEVAL_E(priv->vl_row - 1); 4350c84358cSSimon Glass 4368b449a66SSimon Glass writel(cfg, (unsigned int)®->vidtcon2 + offset); 4370c84358cSSimon Glass } 4380c84358cSSimon Glass 4390c84358cSSimon Glass /* set display mode */ 4408b449a66SSimon Glass cfg = readl(®->vidcon0); 4410c84358cSSimon Glass cfg &= ~EXYNOS_VIDCON0_PNRMODE_MASK; 4420c84358cSSimon Glass cfg |= (rgb_mode << EXYNOS_VIDCON0_PNRMODE_SHIFT); 4438b449a66SSimon Glass writel(cfg, ®->vidcon0); 4440c84358cSSimon Glass 4450c84358cSSimon Glass /* set par */ 4468b449a66SSimon Glass exynos_fimd_set_par(priv, priv->win_id); 4470c84358cSSimon Glass 4480c84358cSSimon Glass /* set memory address */ 449*bb5930d5SSimon Glass exynos_fimd_set_buffer_address(priv, priv->win_id, plat->base); 4500c84358cSSimon Glass 4510c84358cSSimon Glass /* set buffer size */ 4528b449a66SSimon Glass cfg = EXYNOS_VIDADDR_PAGEWIDTH(priv->vl_col * 453*bb5930d5SSimon Glass VNBITS(priv->vl_bpix) / 8) | 4548b449a66SSimon Glass EXYNOS_VIDADDR_PAGEWIDTH_E(priv->vl_col * 455*bb5930d5SSimon Glass VNBITS(priv->vl_bpix) / 8) | 4560c84358cSSimon Glass EXYNOS_VIDADDR_OFFSIZE(0) | 4570c84358cSSimon Glass EXYNOS_VIDADDR_OFFSIZE_E(0); 4580c84358cSSimon Glass 4598b449a66SSimon Glass writel(cfg, (unsigned int)®->vidw00add2 + 4608b449a66SSimon Glass EXYNOS_BUFFER_SIZE(priv->win_id)); 4610c84358cSSimon Glass 4620c84358cSSimon Glass /* set clock */ 4638b449a66SSimon Glass exynos_fimd_set_clock(priv); 4640c84358cSSimon Glass 4650c84358cSSimon Glass /* set rgb mode to dual lcd. */ 4668b449a66SSimon Glass exynos_fimd_set_dualrgb(priv, priv->dual_lcd_enabled); 4670c84358cSSimon Glass 4680c84358cSSimon Glass /* display on */ 4698b449a66SSimon Glass exynos_fimd_lcd_on(priv); 4700c84358cSSimon Glass 4710c84358cSSimon Glass /* window on */ 4728b449a66SSimon Glass exynos_fimd_window_on(priv, priv->win_id); 4730c84358cSSimon Glass 4748b449a66SSimon Glass exynos_fimd_set_dp_clkcon(priv, priv->dp_enabled); 4750c84358cSSimon Glass } 4760c84358cSSimon Glass 477*bb5930d5SSimon Glass unsigned long exynos_fimd_calc_fbsize(struct exynos_fb_priv *priv) 4780c84358cSSimon Glass { 479*bb5930d5SSimon Glass return priv->vl_col * priv->vl_row * (VNBITS(priv->vl_bpix) / 8); 48008a7aa1eSSimon Glass } 48108a7aa1eSSimon Glass 48208a7aa1eSSimon Glass __weak void exynos_cfg_lcd_gpio(void) 48308a7aa1eSSimon Glass { 48408a7aa1eSSimon Glass } 48508a7aa1eSSimon Glass 48608a7aa1eSSimon Glass __weak void exynos_backlight_on(unsigned int onoff) 48708a7aa1eSSimon Glass { 48808a7aa1eSSimon Glass } 48908a7aa1eSSimon Glass 49008a7aa1eSSimon Glass __weak void exynos_reset_lcd(void) 49108a7aa1eSSimon Glass { 49208a7aa1eSSimon Glass } 49308a7aa1eSSimon Glass 49408a7aa1eSSimon Glass __weak void exynos_lcd_power_on(void) 49508a7aa1eSSimon Glass { 49608a7aa1eSSimon Glass } 49708a7aa1eSSimon Glass 49808a7aa1eSSimon Glass __weak void exynos_cfg_ldo(void) 49908a7aa1eSSimon Glass { 50008a7aa1eSSimon Glass } 50108a7aa1eSSimon Glass 50208a7aa1eSSimon Glass __weak void exynos_enable_ldo(unsigned int onoff) 50308a7aa1eSSimon Glass { 50408a7aa1eSSimon Glass } 50508a7aa1eSSimon Glass 50608a7aa1eSSimon Glass __weak void exynos_backlight_reset(void) 50708a7aa1eSSimon Glass { 50808a7aa1eSSimon Glass } 50908a7aa1eSSimon Glass 510aaca5b19SSimon Glass __weak int exynos_lcd_misc_init(struct vidinfo *vid) 51108a7aa1eSSimon Glass { 51208a7aa1eSSimon Glass return 0; 51308a7aa1eSSimon Glass } 51408a7aa1eSSimon Glass 515*bb5930d5SSimon Glass int exynos_fb_ofdata_to_platdata(struct udevice *dev) 51608a7aa1eSSimon Glass { 517*bb5930d5SSimon Glass struct exynos_fb_priv *priv = dev_get_priv(dev); 518*bb5930d5SSimon Glass unsigned int node = dev->of_offset; 519*bb5930d5SSimon Glass const void *blob = gd->fdt_blob; 520*bb5930d5SSimon Glass fdt_addr_t addr; 52108a7aa1eSSimon Glass 522*bb5930d5SSimon Glass addr = dev_get_addr(dev); 523*bb5930d5SSimon Glass if (addr == FDT_ADDR_T_NONE) { 524*bb5930d5SSimon Glass debug("Can't get the FIMD base address\n"); 525*bb5930d5SSimon Glass return -EINVAL; 52608a7aa1eSSimon Glass } 527*bb5930d5SSimon Glass priv->reg = (struct exynos_fb *)addr; 52808a7aa1eSSimon Glass 529*bb5930d5SSimon Glass priv->vl_col = fdtdec_get_int(blob, node, "samsung,vl-col", 0); 530*bb5930d5SSimon Glass if (priv->vl_col == 0) { 53108a7aa1eSSimon Glass debug("Can't get XRES\n"); 53208a7aa1eSSimon Glass return -ENXIO; 53308a7aa1eSSimon Glass } 53408a7aa1eSSimon Glass 535*bb5930d5SSimon Glass priv->vl_row = fdtdec_get_int(blob, node, "samsung,vl-row", 0); 536*bb5930d5SSimon Glass if (priv->vl_row == 0) { 53708a7aa1eSSimon Glass debug("Can't get YRES\n"); 53808a7aa1eSSimon Glass return -ENXIO; 53908a7aa1eSSimon Glass } 54008a7aa1eSSimon Glass 541*bb5930d5SSimon Glass priv->vl_width = fdtdec_get_int(blob, node, 54208a7aa1eSSimon Glass "samsung,vl-width", 0); 54308a7aa1eSSimon Glass 544*bb5930d5SSimon Glass priv->vl_height = fdtdec_get_int(blob, node, 54508a7aa1eSSimon Glass "samsung,vl-height", 0); 54608a7aa1eSSimon Glass 547*bb5930d5SSimon Glass priv->vl_freq = fdtdec_get_int(blob, node, "samsung,vl-freq", 0); 548*bb5930d5SSimon Glass if (priv->vl_freq == 0) { 54908a7aa1eSSimon Glass debug("Can't get refresh rate\n"); 55008a7aa1eSSimon Glass return -ENXIO; 55108a7aa1eSSimon Glass } 55208a7aa1eSSimon Glass 55308a7aa1eSSimon Glass if (fdtdec_get_bool(blob, node, "samsung,vl-clkp")) 554*bb5930d5SSimon Glass priv->vl_clkp = VIDEO_ACTIVE_LOW; 55508a7aa1eSSimon Glass 55608a7aa1eSSimon Glass if (fdtdec_get_bool(blob, node, "samsung,vl-oep")) 557*bb5930d5SSimon Glass priv->vl_oep = VIDEO_ACTIVE_LOW; 55808a7aa1eSSimon Glass 55908a7aa1eSSimon Glass if (fdtdec_get_bool(blob, node, "samsung,vl-hsp")) 560*bb5930d5SSimon Glass priv->vl_hsp = VIDEO_ACTIVE_LOW; 56108a7aa1eSSimon Glass 56208a7aa1eSSimon Glass if (fdtdec_get_bool(blob, node, "samsung,vl-vsp")) 563*bb5930d5SSimon Glass priv->vl_vsp = VIDEO_ACTIVE_LOW; 56408a7aa1eSSimon Glass 56508a7aa1eSSimon Glass if (fdtdec_get_bool(blob, node, "samsung,vl-dp")) 566*bb5930d5SSimon Glass priv->vl_dp = VIDEO_ACTIVE_LOW; 56708a7aa1eSSimon Glass 568*bb5930d5SSimon Glass priv->vl_bpix = fdtdec_get_int(blob, node, "samsung,vl-bpix", 0); 569*bb5930d5SSimon Glass if (priv->vl_bpix == 0) { 57008a7aa1eSSimon Glass debug("Can't get bits per pixel\n"); 57108a7aa1eSSimon Glass return -ENXIO; 57208a7aa1eSSimon Glass } 57308a7aa1eSSimon Glass 574*bb5930d5SSimon Glass priv->vl_hspw = fdtdec_get_int(blob, node, "samsung,vl-hspw", 0); 575*bb5930d5SSimon Glass if (priv->vl_hspw == 0) { 57608a7aa1eSSimon Glass debug("Can't get hsync width\n"); 57708a7aa1eSSimon Glass return -ENXIO; 57808a7aa1eSSimon Glass } 57908a7aa1eSSimon Glass 580*bb5930d5SSimon Glass priv->vl_hfpd = fdtdec_get_int(blob, node, "samsung,vl-hfpd", 0); 581*bb5930d5SSimon Glass if (priv->vl_hfpd == 0) { 58208a7aa1eSSimon Glass debug("Can't get right margin\n"); 58308a7aa1eSSimon Glass return -ENXIO; 58408a7aa1eSSimon Glass } 58508a7aa1eSSimon Glass 586*bb5930d5SSimon Glass priv->vl_hbpd = (u_char)fdtdec_get_int(blob, node, 58708a7aa1eSSimon Glass "samsung,vl-hbpd", 0); 588*bb5930d5SSimon Glass if (priv->vl_hbpd == 0) { 58908a7aa1eSSimon Glass debug("Can't get left margin\n"); 59008a7aa1eSSimon Glass return -ENXIO; 59108a7aa1eSSimon Glass } 59208a7aa1eSSimon Glass 593*bb5930d5SSimon Glass priv->vl_vspw = (u_char)fdtdec_get_int(blob, node, 59408a7aa1eSSimon Glass "samsung,vl-vspw", 0); 595*bb5930d5SSimon Glass if (priv->vl_vspw == 0) { 59608a7aa1eSSimon Glass debug("Can't get vsync width\n"); 59708a7aa1eSSimon Glass return -ENXIO; 59808a7aa1eSSimon Glass } 59908a7aa1eSSimon Glass 600*bb5930d5SSimon Glass priv->vl_vfpd = fdtdec_get_int(blob, node, 60108a7aa1eSSimon Glass "samsung,vl-vfpd", 0); 602*bb5930d5SSimon Glass if (priv->vl_vfpd == 0) { 60308a7aa1eSSimon Glass debug("Can't get lower margin\n"); 60408a7aa1eSSimon Glass return -ENXIO; 60508a7aa1eSSimon Glass } 60608a7aa1eSSimon Glass 607*bb5930d5SSimon Glass priv->vl_vbpd = fdtdec_get_int(blob, node, "samsung,vl-vbpd", 0); 608*bb5930d5SSimon Glass if (priv->vl_vbpd == 0) { 60908a7aa1eSSimon Glass debug("Can't get upper margin\n"); 61008a7aa1eSSimon Glass return -ENXIO; 61108a7aa1eSSimon Glass } 61208a7aa1eSSimon Glass 613*bb5930d5SSimon Glass priv->vl_cmd_allow_len = fdtdec_get_int(blob, node, 61408a7aa1eSSimon Glass "samsung,vl-cmd-allow-len", 0); 61508a7aa1eSSimon Glass 616*bb5930d5SSimon Glass priv->win_id = fdtdec_get_int(blob, node, "samsung,winid", 0); 617*bb5930d5SSimon Glass priv->init_delay = fdtdec_get_int(blob, node, 61808a7aa1eSSimon Glass "samsung,init-delay", 0); 619*bb5930d5SSimon Glass priv->power_on_delay = fdtdec_get_int(blob, node, 62008a7aa1eSSimon Glass "samsung,power-on-delay", 0); 621*bb5930d5SSimon Glass priv->reset_delay = fdtdec_get_int(blob, node, 62208a7aa1eSSimon Glass "samsung,reset-delay", 0); 623*bb5930d5SSimon Glass priv->interface_mode = fdtdec_get_int(blob, node, 62408a7aa1eSSimon Glass "samsung,interface-mode", 0); 625*bb5930d5SSimon Glass priv->mipi_enabled = fdtdec_get_int(blob, node, 62608a7aa1eSSimon Glass "samsung,mipi-enabled", 0); 627*bb5930d5SSimon Glass priv->dp_enabled = fdtdec_get_int(blob, node, 62808a7aa1eSSimon Glass "samsung,dp-enabled", 0); 629*bb5930d5SSimon Glass priv->cs_setup = fdtdec_get_int(blob, node, 63008a7aa1eSSimon Glass "samsung,cs-setup", 0); 631*bb5930d5SSimon Glass priv->wr_setup = fdtdec_get_int(blob, node, 63208a7aa1eSSimon Glass "samsung,wr-setup", 0); 633*bb5930d5SSimon Glass priv->wr_act = fdtdec_get_int(blob, node, "samsung,wr-act", 0); 634*bb5930d5SSimon Glass priv->wr_hold = fdtdec_get_int(blob, node, "samsung,wr-hold", 0); 63508a7aa1eSSimon Glass 636*bb5930d5SSimon Glass priv->logo_on = fdtdec_get_int(blob, node, "samsung,logo-on", 0); 637*bb5930d5SSimon Glass if (priv->logo_on) { 638*bb5930d5SSimon Glass priv->logo_width = fdtdec_get_int(blob, node, 63908a7aa1eSSimon Glass "samsung,logo-width", 0); 640*bb5930d5SSimon Glass priv->logo_height = fdtdec_get_int(blob, node, 64108a7aa1eSSimon Glass "samsung,logo-height", 0); 642*bb5930d5SSimon Glass priv->logo_addr = fdtdec_get_int(blob, node, 64308a7aa1eSSimon Glass "samsung,logo-addr", 0); 64408a7aa1eSSimon Glass } 64508a7aa1eSSimon Glass 646*bb5930d5SSimon Glass priv->rgb_mode = fdtdec_get_int(blob, node, 64708a7aa1eSSimon Glass "samsung,rgb-mode", 0); 648*bb5930d5SSimon Glass priv->pclk_name = fdtdec_get_int(blob, node, 64908a7aa1eSSimon Glass "samsung,pclk-name", 0); 650*bb5930d5SSimon Glass priv->sclk_div = fdtdec_get_int(blob, node, 65108a7aa1eSSimon Glass "samsung,sclk-div", 0); 652*bb5930d5SSimon Glass priv->dual_lcd_enabled = fdtdec_get_int(blob, node, 65308a7aa1eSSimon Glass "samsung,dual-lcd-enabled", 0); 65408a7aa1eSSimon Glass 65508a7aa1eSSimon Glass return 0; 65608a7aa1eSSimon Glass } 65708a7aa1eSSimon Glass 658*bb5930d5SSimon Glass static int exynos_fb_probe(struct udevice *dev) 65908a7aa1eSSimon Glass { 660*bb5930d5SSimon Glass struct video_priv *uc_priv = dev_get_uclass_priv(dev); 661*bb5930d5SSimon Glass struct exynos_fb_priv *priv = dev_get_priv(dev); 662*bb5930d5SSimon Glass struct udevice *panel, *bridge; 663*bb5930d5SSimon Glass struct udevice *dp; 664*bb5930d5SSimon Glass int ret; 665*bb5930d5SSimon Glass 666*bb5930d5SSimon Glass debug("%s: start\n", __func__); 66708a7aa1eSSimon Glass set_system_display_ctrl(); 66808a7aa1eSSimon Glass set_lcd_clk(); 66908a7aa1eSSimon Glass 67008a7aa1eSSimon Glass #ifdef CONFIG_EXYNOS_MIPI_DSIM 67108a7aa1eSSimon Glass exynos_init_dsim_platform_data(&panel_info); 67208a7aa1eSSimon Glass #endif 673*bb5930d5SSimon Glass exynos_fimd_lcd_init(dev); 67408a7aa1eSSimon Glass 675*bb5930d5SSimon Glass ret = uclass_first_device(UCLASS_PANEL, &panel); 676*bb5930d5SSimon Glass if (ret) { 677*bb5930d5SSimon Glass printf("LCD panel failed to probe\n"); 678*bb5930d5SSimon Glass return ret; 679*bb5930d5SSimon Glass } 680*bb5930d5SSimon Glass if (!panel) { 681*bb5930d5SSimon Glass printf("LCD panel not found\n"); 682*bb5930d5SSimon Glass return -ENODEV; 68308a7aa1eSSimon Glass } 68408a7aa1eSSimon Glass 685*bb5930d5SSimon Glass ret = uclass_first_device(UCLASS_DISPLAY, &dp); 686*bb5930d5SSimon Glass if (ret) { 687*bb5930d5SSimon Glass debug("%s: Display device error %d\n", __func__, ret); 688*bb5930d5SSimon Glass return ret; 689*bb5930d5SSimon Glass } 690*bb5930d5SSimon Glass if (!dev) { 691*bb5930d5SSimon Glass debug("%s: Display device missing\n", __func__); 692*bb5930d5SSimon Glass return -ENODEV; 693*bb5930d5SSimon Glass } 694*bb5930d5SSimon Glass ret = display_enable(dp, 18, NULL); 695*bb5930d5SSimon Glass if (ret) { 696*bb5930d5SSimon Glass debug("%s: Display enable error %d\n", __func__, ret); 697*bb5930d5SSimon Glass return ret; 698*bb5930d5SSimon Glass } 699*bb5930d5SSimon Glass 700*bb5930d5SSimon Glass /* backlight / pwm */ 701*bb5930d5SSimon Glass ret = panel_enable_backlight(panel); 702*bb5930d5SSimon Glass if (ret) { 703*bb5930d5SSimon Glass debug("%s: backlight error: %d\n", __func__, ret); 704*bb5930d5SSimon Glass return ret; 705*bb5930d5SSimon Glass } 706*bb5930d5SSimon Glass 707*bb5930d5SSimon Glass ret = uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &bridge); 708*bb5930d5SSimon Glass if (!ret) 709*bb5930d5SSimon Glass ret = video_bridge_set_backlight(bridge, 80); 710*bb5930d5SSimon Glass if (ret) { 711*bb5930d5SSimon Glass debug("%s: No video bridge, or no backlight on bridge\n", 712*bb5930d5SSimon Glass __func__); 713*bb5930d5SSimon Glass exynos_pinmux_config(PERIPH_ID_PWM0, 0); 714*bb5930d5SSimon Glass } 715*bb5930d5SSimon Glass 716*bb5930d5SSimon Glass uc_priv->xsize = priv->vl_col; 717*bb5930d5SSimon Glass uc_priv->ysize = priv->vl_row; 718*bb5930d5SSimon Glass uc_priv->bpix = priv->vl_bpix; 719*bb5930d5SSimon Glass 720*bb5930d5SSimon Glass /* Enable flushing after LCD writes if requested */ 721*bb5930d5SSimon Glass video_set_flush_dcache(dev, true); 722*bb5930d5SSimon Glass 723*bb5930d5SSimon Glass return 0; 724*bb5930d5SSimon Glass } 725*bb5930d5SSimon Glass 726*bb5930d5SSimon Glass static int exynos_fb_bind(struct udevice *dev) 72708a7aa1eSSimon Glass { 728*bb5930d5SSimon Glass struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); 729*bb5930d5SSimon Glass 730*bb5930d5SSimon Glass /* This is the maximum panel size we expect to see */ 731*bb5930d5SSimon Glass plat->size = 1920 * 1080 * 2; 732*bb5930d5SSimon Glass 733*bb5930d5SSimon Glass return 0; 73408a7aa1eSSimon Glass } 73508a7aa1eSSimon Glass 736*bb5930d5SSimon Glass static const struct video_ops exynos_fb_ops = { 737*bb5930d5SSimon Glass }; 73808a7aa1eSSimon Glass 739*bb5930d5SSimon Glass static const struct udevice_id exynos_fb_ids[] = { 740*bb5930d5SSimon Glass { .compatible = "samsung,exynos-fimd" }, 741*bb5930d5SSimon Glass { } 742*bb5930d5SSimon Glass }; 743*bb5930d5SSimon Glass 744*bb5930d5SSimon Glass U_BOOT_DRIVER(exynos_fb) = { 745*bb5930d5SSimon Glass .name = "exynos_fb", 746*bb5930d5SSimon Glass .id = UCLASS_VIDEO, 747*bb5930d5SSimon Glass .of_match = exynos_fb_ids, 748*bb5930d5SSimon Glass .ops = &exynos_fb_ops, 749*bb5930d5SSimon Glass .bind = exynos_fb_bind, 750*bb5930d5SSimon Glass .probe = exynos_fb_probe, 751*bb5930d5SSimon Glass .ofdata_to_platdata = exynos_fb_ofdata_to_platdata, 752*bb5930d5SSimon Glass .priv_auto_alloc_size = sizeof(struct exynos_fb_priv), 753*bb5930d5SSimon Glass }; 754