Part Number: AM4378
Other Parts Discussed in Thread: SYSCONFIG
Hi,All:
Is there support of LCD in u-boot for AM437X board?
Thanks!
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi Biser Gatchev-XID,
Does the uboot in ti-processor-sdk-linux-am437x-evm-03.01.00.06 support LCD driver?
If yes, how to enable the LCD driver?
We need to display the boot logo in uboot...
Thanks!
Part Number: AM4378
Tool/software: Linux
Hi,
For AM437x EVM u-boot LCD logo display,
work finished.(test done for 24 bit bitmap)
1. configs/am43xx_evm_defconfig : modify
CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=1,NAND,SPLASH"
2. include/configs/am43xx_evm.h : added
#if 1 // added
/* Splash scrren support */
#ifdef CONFIG_SPLASH
/*#define CONFIG_AM335X_LCD*/
#define CONFIG_LCD
#define CONFIG_LCD_NOSTDOUT
#define CONFIG_SYS_WHITE_ON_BLACK
#define LCD_BPP LCD_COLOR32
#define CONFIG_VIDEO_BMP_GZIP
#define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE (1280*800*4 + 64)
#define CONFIG_CMD_UNZIP
#define CONFIG_CMD_BMP
#define CONFIG_BMP_16BPP
#define CONFIG_BMP_24BMP
#define CONFIG_BMP_32BPP
#define CONFIG_CONSOLE_SCROLL_LINES 5
#endif
#endif
3. board/ti/am43xx/mux.c
#if 1 // added
static struct module_pin_mux lcd_pin_mux[] = {
{OFFSET(lcd_data0), (MODE(0) | PULLUDDIS)}, /* LCD-Data(0) */
{OFFSET(lcd_data1), (MODE(0) | PULLUDDIS)}, /* LCD-Data(1) */
{OFFSET(lcd_data2), (MODE(0) | PULLUDDIS)}, /* LCD-Data(2) */
{OFFSET(lcd_data3), (MODE(0) | PULLUDDIS)}, /* LCD-Data(3) */
{OFFSET(lcd_data4), (MODE(0) | PULLUDDIS)}, /* LCD-Data(4) */
{OFFSET(lcd_data5), (MODE(0) | PULLUDDIS)}, /* LCD-Data(5) */
{OFFSET(lcd_data6), (MODE(0) | PULLUDDIS)}, /* LCD-Data(6) */
{OFFSET(lcd_data7), (MODE(0) | PULLUDDIS)}, /* LCD-Data(7) */
{OFFSET(lcd_data8), (MODE(0) | PULLUDDIS)}, /* LCD-Data(8) */
{OFFSET(lcd_data9), (MODE(0) | PULLUDDIS)}, /* LCD-Data(9) */
{OFFSET(lcd_data10), (MODE(0) | PULLUDDIS)}, /* LCD-Data(10) */
{OFFSET(lcd_data11), (MODE(0) | PULLUDDIS)}, /* LCD-Data(11) */
{OFFSET(lcd_data12), (MODE(0) | PULLUDDIS)}, /* LCD-Data(12) */
{OFFSET(lcd_data13), (MODE(0) | PULLUDDIS)}, /* LCD-Data(13) */
{OFFSET(lcd_data14), (MODE(0) | PULLUDDIS)}, /* LCD-Data(14) */
{OFFSET(lcd_data15), (MODE(0) | PULLUDDIS)}, /* LCD-Data(15) */
{OFFSET(gpmc_ad8), (MODE(1) | PULLUDDIS)}, /* LCD-Data(16) */
{OFFSET(gpmc_ad9), (MODE(1) | PULLUDDIS)}, /* LCD-Data(17) */
{OFFSET(gpmc_ad10), (MODE(1) | PULLUDDIS)}, /* LCD-Data(18) */
{OFFSET(gpmc_ad11), (MODE(1) | PULLUDDIS)}, /* LCD-Data(19) */
{OFFSET(gpmc_ad12), (MODE(1) | PULLUDDIS)}, /* LCD-Data(20) */
{OFFSET(gpmc_ad13), (MODE(1) | PULLUDDIS)}, /* LCD-Data(21) */
{OFFSET(gpmc_ad14), (MODE(1) | PULLUDDIS)}, /* LCD-Data(22) */
{OFFSET(gpmc_ad15), (MODE(1) | PULLUDDIS)}, /* LCD-Data(23) */
{OFFSET(lcd_vsync), (MODE(0) | PULLUDDIS)}, /* LCD-VSync */
{OFFSET(lcd_hsync), (MODE(0) | PULLUDDIS)}, /* LCD-HSync */
{OFFSET(lcd_ac_bias_en), (MODE(0) | PULLUDDIS)},/* LCD-DE */
{OFFSET(lcd_pclk), (MODE(0) | PULLUDDIS)}, /* LCD-CLK */
{-1},
};
#endif
#if defined(CONFIG_NAND)
configure_module_pin_mux(nand_pin_mux);
#elif defined(CONFIG_EMMC_BOOT)
configure_module_pin_mux(mmc1_pin_mux);
#endif
#if 1 // added
configure_module_pin_mux(lcd_pin_mux);
#endif
} else if (board_is_sk() || board_is_idk()) {
configure_module_pin_mux(rgmii1_pin_mux);
4. board/ti/am43xx/omap3_dss.c : created
#include <asm/io.h>
/*#include <asm/arch/dss.h>*/
#include <video_fb.h>
#ifndef DSS_H
#define DSS_H
/* DSS Base Registers */
#define OMAP3_DSS_BASE 0x4832A000
#define OMAP3_DISPC_BASE 0x4832A400
/*#define OMAP3_VENC_BASE 0x48320C00*/
#define OMAP3_RFBI_BASE 0x4832A800
/* DSS Registers */
struct dss_regs {
u32 revision; /* 0x00 */
u8 res1[12]; /* 0x04 */
u32 sysconfig; /* 0x10 */
u32 sysstatus; /* 0x14 */
u32 irqstatus; /* 0x18 */
u8 res2[36]; /* 0x1C */
u32 control; /* 0x40 */
u32 sdi_control; /* 0x44 */
u32 pll_control; /* 0x48 */
};
/* DISPC Registers */
struct dispc_regs {
u32 revision; /* 0x00 */
u8 res1[12]; /* 0x04 */
u32 sysconfig; /* 0x10 */
u32 sysstatus; /* 0x14 */
u32 irqstatus; /* 0x18 */
u32 irqenable; /* 0x1C */
u8 res2[32]; /* 0x20 */
u32 control; /* 0x40 */
u32 config; /* 0x44 */
u32 reserve_2; /* 0x48 */
u32 default_color0; /* 0x4C */
u32 default_color1; /* 0x50 */
u32 trans_color0; /* 0x54 */
u32 trans_color1; /* 0x58 */
u32 line_status; /* 0x5C */
u32 line_number; /* 0x60 */
u32 timing_h; /* 0x64 */
u32 timing_v; /* 0x68 */
u32 pol_freq; /* 0x6C */
u32 divisor; /* 0x70 */
u32 global_alpha; /* 0x74 */
u32 size_dig; /* 0x78 */
u32 size_lcd; /* 0x7C */
u32 gfx_ba0; /* 0x80 */
u32 gfx_ba1; /* 0x84 */
u32 gfx_position; /* 0x88 */
u32 gfx_size; /* 0x8C */
u8 unused[16]; /* 0x90 */
u32 gfx_attributes; /* 0xA0 */
u32 gfx_fifo_threshold; /* 0xA4 */
u32 gfx_fifo_size_status; /* 0xA8 */
u32 gfx_row_inc; /* 0xAC */
u32 gfx_pixel_inc; /* 0xB0 */
u32 gfx_window_skip; /* 0xB4 */
u32 gfx_table_ba; /* 0xB8 */
};
/* Few Register Offsets */
#define TFTSTN_SHIFT 3
#define DATALINES_SHIFT 8
#define GFX_ENABLE 1
#define GFX_FORMAT_SHIFT 1
#define LOADMODE_SHIFT 1
#define DSS_SOFTRESET (1 << 1)
#define DSS_RESETDONE 1
/* Enabling Display controller */
#define LCD_ENABLE 1
#define DIG_ENABLE (1 << 1)
#define GO_LCD (1 << 5)
#define GO_DIG (1 << 6)
#define GP_OUT0 (1 << 15)
#define GP_OUT1 (1 << 16)
/* LCD display type */
#define PASSIVE_DISPLAY 0
#define ACTIVE_DISPLAY 1
/* TFTDATALINES */
#define LCD_INTERFACE_12_BIT 0
#define LCD_INTERFACE_16_BIT 1
#define LCD_INTERFACE_18_BIT 2
#define LCD_INTERFACE_24_BIT 3
/* Polarity */
#define DSS_IVS (1 << 12)
#define DSS_IHS (1 << 13)
#define DSS_IPC (1 << 14)
#define DSS_IEO (1 << 15)
#define DSS_ONOFF (1 << 17)
/* GFX format */
#define GFXFORMAT_BITMAP1 (0x0 << 1)
#define GFXFORMAT_BITMAP2 (0x1 << 1)
#define GFXFORMAT_BITMAP4 (0x2 << 1)
#define GFXFORMAT_BITMAP8 (0x3 << 1)
#define GFXFORMAT_RGB12 (0x4 << 1)
#define GFXFORMAT_ARGB16 (0x5 << 1)
#define GFXFORMAT_RGB16 (0x6 << 1)
#define GFXFORMAT_RGB24_UNPACKED (0x8 << 1)
#define GFXFORMAT_RGB24_PACKED (0x9 << 1)
#define GFXFORMAT_ARGB32 (0xC << 1)
#define GFXFORMAT_RGBA32 (0xD << 1)
#define GFXFORMAT_RGBx32 (0xE << 1)
/* Panel Configuration */
struct panel_config {
u32 timing_h;
u32 timing_v;
u32 pol_freq;
u32 divisor;
u32 lcd_size;
u32 panel_type;
u32 data_lines;
u32 load_mode;
u32 panel_color;
u32 gfx_format;
void *frame_buffer;
};
#define DSS_HBP(bp) (((bp) - 1) << 20)
#define DSS_HFP(fp) (((fp) - 1) << 8)
#define DSS_HSW(sw) ((sw) - 1)
#define DSS_VBP(bp) ((bp) << 20)
#define DSS_VFP(fp) ((fp) << 8)
#define DSS_VSW(sw) ((sw) - 1)
#define PANEL_TIMING_H(bp, fp, sw) (DSS_HBP(bp) | DSS_HFP(fp) | DSS_HSW(sw))
#define PANEL_TIMING_V(bp, fp, sw) (DSS_VBP(bp) | DSS_VFP(fp) | DSS_VSW(sw))
#define PANEL_LCD_SIZE(xres, yres) ((yres - 1) << 16 | (xres - 1))
#endif
/*
* Configure Timings for DVI D
*/
static const struct panel_config dvid_cfg = {
.timing_h = 0x01d0631d, /* Horizontal timing */
.timing_v = 0x00a00a02, /* Vertical timing */
.pol_freq = 0x00027000, /* Pol Freq */
.divisor = 0x00010002, /* 72Mhz Pixel Clock */
.lcd_size = 0x031f04ff, /* 1280x800 */
.panel_type = 0x01, /* TFT */
.data_lines = 0x03, /* 24 Bit RGB */
.load_mode = 0x02, /* Frame Mode */
.panel_color = 0, /* BLACK */
.gfx_format = GFXFORMAT_RGB24_UNPACKED,
};
void omap3_dss_panel_config(const struct panel_config *panel_cfg)
{
struct dispc_regs *dispc = (struct dispc_regs *) OMAP3_DISPC_BASE;
struct dss_regs *dss = (struct dss_regs *) OMAP3_DSS_BASE;
writel(DSS_SOFTRESET, &dss->sysconfig);
while (!(readl(&dss->sysstatus) & DSS_RESETDONE))
;
//printf("%s: called, dispc->sysconfig = 0x%x.\n", __FUNCTION__, readl(&dispc->sysconfig));
writel(0x00002015, &dispc->sysconfig);
writel(panel_cfg->timing_h, &dispc->timing_h);
writel(panel_cfg->timing_v, &dispc->timing_v);
writel(panel_cfg->pol_freq, &dispc->pol_freq);
writel(panel_cfg->divisor, &dispc->divisor);
writel(panel_cfg->lcd_size, &dispc->size_lcd);
writel(panel_cfg->load_mode << LOADMODE_SHIFT, &dispc->config);
writel( GP_OUT0 | GP_OUT1 |
panel_cfg->panel_type << TFTSTN_SHIFT |
panel_cfg->data_lines << DATALINES_SHIFT, &dispc->control);
writel(panel_cfg->panel_color, &dispc->default_color0);
writel((u32) panel_cfg->frame_buffer, &dispc->gfx_ba0);
writel((u32) panel_cfg->frame_buffer, &dispc->gfx_ba1);
#if 0
printf("%s: dispc->config = 0x%x\n", __FUNCTION__, readl(&dispc->config));
printf("%s: dispc->control = 0x%x\n", __FUNCTION__, readl(&dispc->control));
printf("%s: panel_cfg->framebuffer = 0x%p\n", __FUNCTION__, panel_cfg->frame_buffer);
#endif
if (!panel_cfg->frame_buffer)
return;
writel(0xa0 | panel_cfg->gfx_format | GFX_ENABLE, &dispc->gfx_attributes);
writel(1, &dispc->gfx_row_inc);
writel(1, &dispc->gfx_pixel_inc);
writel(panel_cfg->lcd_size, &dispc->gfx_size);
}
/* Enable LCD and DIGITAL OUT in DSS */
void omap3_dss_enable(void)
{
struct dispc_regs *dispc = (struct dispc_regs *) OMAP3_DISPC_BASE;
u32 l;
l = readl(&dispc->control);
#if 0
l |= LCD_ENABLE | GO_LCD | DIG_ENABLE | GO_DIG | GP_OUT0 | GP_OUT1;
#else
l |= LCD_ENABLE | GO_LCD;
#endif
writel(l, &dispc->control);
#if 0
printf("%s: dispc->config = 0x%x\n", __FUNCTION__, readl(&dispc->config));
printf("%s: dispc->control = 0x%x\n", __FUNCTION__, l);
#endif
}
5. board/ti/am43xx/board.c
#if 1 // added
#include <mmc.h>
#include <fat.h>
#include <lcd.h>
#endif
static void enable_lcd_power(void)
{
u32 temp;
puts("enable_lcd_power, 2.5V\n");
/* enable module */
writel(GPIO_CTRL_ENABLEMODULE, AM33XX_GPIO3_BASE + OMAP_GPIO_CTRL);
/* enable output for GPIO3_17 */
writel(GPIO_SETDATAOUT(17), AM33XX_GPIO3_BASE + OMAP_GPIO_SETDATAOUT);
temp = readl(AM33XX_GPIO3_BASE + OMAP_GPIO_OE);
temp = temp & ~(GPIO_OE_ENABLE(17));
writel(temp, AM33XX_GPIO3_BASE + OMAP_GPIO_OE);
udelay(200000);
puts("enable_lcd_power\n");
/* enable module */
writel(GPIO_CTRL_ENABLEMODULE, AM33XX_GPIO0_BASE + OMAP_GPIO_CTRL);
/* enable output for GPIO0_24 */
writel(GPIO_SETDATAOUT(24), AM33XX_GPIO0_BASE + OMAP_GPIO_SETDATAOUT);
temp = readl(AM33XX_GPIO0_BASE + OMAP_GPIO_OE);
temp = temp & ~(GPIO_OE_ENABLE(24));
writel(temp, AM33XX_GPIO0_BASE + OMAP_GPIO_OE);
udelay(1000);
{
// PRCM_CM_PER_DSS_CLKCTRL (0xa20)
writel(0x2, 0x44df8800 + 0xa20);
printf("%s: Display PLL setup.\n", __FUNCTION__);
// Display PLL setup
{
// PRCM_CM_CLKMODE_DPLL_DISP (0x620); ST_MN_BYPASS
writel(0x4, 0x44df2800 + 0x620);
while (!(readl( 0x44df2800 + 0x624) & (0x1<<8)))
;
// PRCM_CM_CLKSEL_DPLL_DISP (0x62c) : DPLL_MULT & DPLL_DIV
writel(0xED27, 0x44df2800 + 0x62c);
// PRCM_CM_DIV_M2_DPLL_DISP(0x630) : DPLL_CLKOUT_DIV
writel(0x1, 0x44df2800 + 0x630);
// PRCM_CM_CLKMODE_DPLL_DISP (0x620) : ST_DPLL_CLK
writel(0x7, 0x44df2800 + 0x620);
while (!(readl( 0x44df2800 + 0x624) & 0x1))
;
}
printf("%s: Display PLL setup done.\n", __FUNCTION__);
#if 0
// CM_PER : 0x44DF8800 (Clock Module Peripheral Registers)
printf("PRCM_CM_PER_LCDC_CLKSTCTRL = 0x%x\n", readl( 0x44df8800 + 0x800)); // 0x2
printf("PRCM_CM_PER_DSS_CLKSTCTRL = 0x%x\n", readl( 0x44df8800 + 0xa00)); // 0xE02
printf("PRCM_CM_PER_DSS_CLKCTRL = 0x%x\n", readl( 0x44df8800 + 0xa20)); // 0x2
printf("\n");
// CM_WKUP : 0x44DF2800 (Clock Module Wakeup Registers)
printf("PRCM_CM_CLKMODE_DPLL_DISP = 0x%x\n", readl( 0x44df2800 + 0x620)); // 0x7
printf("PRCM_CM_IDLEST_DPLL_DISP = 0x%x\n", readl( 0x44df2800 + 0x624)); // 0x1
printf("PRCM_CM_CLKSEL_DPLL_DISP = 0x%x\n", readl( 0x44df2800 + 0x62c)); // 0xED27
printf("PRCM_CM_DIV_M2_DPLL_DISP = 0x%x\n", readl( 0x44df2800 + 0x630)); // 0x201
printf("\n");
#endif
}
}
void lcd_backlight_1(void)
{
u32 temp;
puts("enable backlight power\n");
/* enable module */
writel(GPIO_CTRL_ENABLEMODULE, AM33XX_GPIO0_BASE + OMAP_GPIO_CTRL);
/* enable output for GPIO0_7 */
temp = readl(AM33XX_GPIO0_BASE + OMAP_GPIO_OE);
temp = temp & ~(GPIO_OE_ENABLE(7));
writel(temp, AM33XX_GPIO0_BASE + OMAP_GPIO_OE);
/* enable module */
writel(GPIO_CTRL_ENABLEMODULE, AM33XX_GPIO0_BASE + OMAP_GPIO_CTRL);
/* enable output for GPIO0_3 */
writel(GPIO_SETDATAOUT(3), AM33XX_GPIO0_BASE + OMAP_GPIO_SETDATAOUT);
temp = readl(AM33XX_GPIO0_BASE + OMAP_GPIO_OE);
temp = temp & ~(GPIO_OE_ENABLE(3));
writel(temp, AM33XX_GPIO0_BASE + OMAP_GPIO_OE);
}
// added
#if defined(CONFIG_LCD) && !defined(CONFIG_SPL_BUILD)
#include "./omap3_dss.c"
void dss_init(void);
void lcdbacklight(int on)
{
enable_lcd_power();
}
vidinfo_t panel_info = {
.vl_col = 1280,
.vl_row = 800,
.vl_bpix = 5,
.priv = 0
};
// call from common/lcd.c
void lcd_ctrl_init(void *lcdbase)
{
lcdbacklight(1);
dss_init();
/* Modify panel into to real resolution */
panel_info.vl_col = 1280;
panel_info.vl_row = 800;
lcd_set_flush_dcache(1);
}
// call from common/lcd.c
void lcd_enable(void)
{
}
void splash_screen(void)
{
struct mmc *mmc = NULL;
int err;
printf("%s: read splash.bmp.gz from device [mmc 0:1].\n", __FUNCTION__);
mmc = find_mmc_device(0);
if (!mmc)
printf("Error finding mmc device\n");
mmc_init(mmc);
err = fat_register_device(&mmc->block_dev,
CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
if (!err) {
err = file_fat_read("splash.bmp.gz", (void *)0x82000000, 0);
if (err < 0) {
printf("%s: can't found \"splash.bmp.gz\" from [mmc 0:1].\n", __FUNCTION__);
}
else {
bmp_display(0x82000000, 0, 0);
}
}
else {
printf("%s %s: mmc device not found.\n", __FILE__, __FUNCTION__);
}
// LCD display on
lcd_backlight_1();
}
void dss_init(void)
{
struct panel_config *panel = (struct panel_config *)&dvid_cfg;
panel->frame_buffer = (void *)gd->fb_base;
omap3_dss_panel_config(panel);
omap3_dss_enable();
}
#endif
#ifdef CONFIG_BOARD_LATE_INIT
int board_late_init(void)
{
// added
#if !defined(CONFIG_SPL_BUILD)
splash_screen();
#endif
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
set_board_info_env(NULL);
6. scripts/check-config.sh : modify
CONFIG_SPLASH error -> modify from Error to warning
7. splash.bmp.gz copy to SD card