您的位置:首页 > 编程语言 > Go语言

基于s3c2440的u-boot-2010.3 LCD驱动流程以及LOGO的显示详解

2014-12-10 15:10 736 查看
  如果需要在UBOOT的阶段就要显示LOGO,直到内核启动完毕后UI接管FrameBuffer为止。这样可以避免内核启动过程的这段时间大约5-8秒内的黑屏。所以我们要为u-boot添加LCD驱动并且了解LCD驱动的流程便于修改。

u-boot的启动流程:从文件层面上看主要流程是在两个文件中:cpu/arm920t/start.s,lib_arm/board.c,

其中start.s
是用汇编写的初始化cpu的堆栈 中断向量 时钟频率 SDRAM,并把c部分的代码从nand flash拷贝到SDRAM中,board.c的代码主要是初始化各外设比如串口 i2c LCD等,所以LCD驱动的开始在board.c中。下面分析board.c的部分源码

typedef
int (init_fnc_t) (void);//定义一个函数数据类型

int print_cpuinfo (void);

/***一个函数数组里面是各种初始化函数***/
init_fnc_t *init_sequence[] = {
#if defined(CONFIG_ARCH_CPU_INIT)
arch_cpu_init,/* basic arch cpu dependent setup */
#endif
board_init,/*
初始化开发板的相关外设  下面会详细分析 */
#if defined(CONFIG_USE_IRQ)
interrupt_init,/* set up exceptions */
#endif
timer_init,/* initialize timer */
#ifdef CONFIG_FSL_ESDHC
get_clocks,
#endif
env_init,/* initialize environment */
init_baudrate,/* initialze baudrate settings */
serial_init,/* serial communications setup */
console_init_f,/* stage 1 init of console */
display_banner,/* say that we are here */
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo,/* display cpu info (and speed) */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard,/* display board info */
#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
init_func_i2c,
#endif
dram_init,/* configure available RAM banks */
#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
arm_pci_init,
#endif
display_dram_config,
NULL,
};

/*******c入口*******/
void start_armboot (void)
{
init_fnc_t **init_fnc_ptr;//定义一个init_fnc_t类型的指针
char *s;
#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
unsigned long addr;
#endif

/* Pointer is writable since we allocated a register for it */
gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));//u-boot的全局变量存储各种信息
/* compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__("": : :"memory");

memset ((void*)gd, 0, sizeof (gd_t));
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
memset (gd->bd, 0, sizeof (bd_t));

gd->flags |= GD_FLG_RELOC;

monitor_flash_len = _bss_start - _armboot_start;

/******************下面这个循环将上面数组的函数都执行一遍********************/
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}

/* armboot_start is defined in the board-specific linker script */
mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,
CONFIG_SYS_MALLOC_LEN);

#ifndef CONFIG_SYS_NO_FLASH
/* configure available FLASH banks */
display_flash_config (flash_init ());
#endif /* CONFIG_SYS_NO_FLASH */

#ifdef CONFIG_VFD
#ifndef PAGE_SIZE
# define PAGE_SIZE 4096
#endif
/*
* reserve memory for VFD display (always full pages)
*/
/* bss_end is defined in the board-specific linker script */
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
vfd_setmem (addr);
gd->fb_base = addr;
#endif /* CONFIG_VFD */

#ifdef CONFIG_LCD
/* board init may have inited fb_base */
if (!gd->fb_base) {
#ifndef PAGE_SIZE
# define PAGE_SIZE 4096
#endif
/*
* reserve memory for LCD display (always full pages)
*/
/* bss_end is defined in the board-specific linker script */
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
lcd_setmem (addr);
gd->fb_base = addr;
}
#endif /* CONFIG_LCD */

#if defined(CONFIG_CMD_NAND)
puts ("NAND:  ");
nand_init();/* go init the NAND */
#endif

#if defined(CONFIG_CMD_ONENAND)
onenand_init();
#endif

#ifdef CONFIG_HAS_DATAFLASH
AT91F_DataflashInit();
dataflash_print_info();
#endif

/* initialize environment */
env_relocate ();

#ifdef CONFIG_VFD
/* must do this after the framebuffer is allocated */
drv_vfd_init();//mini2440的LCD初始化和此函数无关

#endif
/* CONFIG_VFD */

#ifdef CONFIG_SERIAL_MULTI
serial_initialize();
#endif

/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");

stdio_init ();/* 初始化设备列表mini2440LCD设备初始化就在这里
 下面会详细分析此函数*/

jumptable_init ();

#if defined(CONFIG_API)
/* Initialize API */
api_init ();
#endif

cosole_init_r ();/* fully init console as a device */

#if defined(CONFIG_ARCH_MISC_INIT)
/* miscellaneous arch dependent initialisations */
arch_misc_init ();
#endif
#if defined(CONFIG_MISC_INIT_R)
/* miscellaneous platform dependent initialisations */
misc_init_r ();
#endif
      // extern void  Port_Init(void);
  //  Port_Init();
/* enable exceptions */
enable_interrupts ();
      extern  int    usb_init_slave(void);
                 usb_init_slave();

/* Perform network card initialisation if necessary */
#ifdef CONFIG_DRIVER_TI_EMAC
/* XXX: this needs to be moved to board init */
extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
if (getenv ("ethaddr")) {
uchar enetaddr[6];
eth_getenv_enetaddr("ethaddr", enetaddr);
davinci_eth_set_mac_addr(enetaddr);
}
#endif

#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
/* XXX: this needs to be moved to board init */
if (getenv ("ethaddr")) {
uchar enetaddr[6];
eth_getenv_enetaddr("ethaddr", enetaddr);
smc_set_mac_addr(enetaddr);
}
#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */

/* Initialize from environment */
if ((s = getenv ("loadaddr")) != NULL) {
load_addr = simple_strtoul (s, NULL, 16);
}
#if defined(CONFIG_CMD_NET)
if ((s = getenv ("bootfile")) != NULL) {
copy_filename (BootFile, s, sizeof (BootFile));
}
#endif

#ifdef BOARD_LATE_INIT
board_late_init ();
#endif

#ifdef CONFIG_GENERIC_MMC
puts ("MMC:   ");
mmc_initialize (gd->bd);
#endif

#ifdef CONFIG_BITBANGMII
bb_miiphy_init();
#endif
#if defined(CONFIG_CMD_NET)
#if defined(CONFIG_NET_MULTI)
puts ("Net:   ");
#endif
eth_initialize(gd->bd);
#if defined(CONFIG_RESET_PHY_R)
debug ("Reset Ethernet PHY\n");
reset_phy();
#endif
#endif

/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}

/* NOTREACHED - no way out of command loop except booting */
}

以上是board.c中源码的分析,下面将介绍和lcd相关的上面提到的board_init()和stadio_init()函数

在board/embedclub/smdk2440a/smdk2440a.c文件中

//*****************以下部分是我的LCD模组SPI初始化代码,如果大家的不用初始化则没有此部分*********/

#define LCD_CS_SHIFT 5

#define LCD_CLK_SHIFT 4

#define LCD_DAT_SHIFT 6

#define LCD_RST_SHIFT 0

static void set_cs(int cs)  

{  

        struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
int reg;  
reg = gpio->GPFDAT;  
reg &= ~(0x1 << LCD_CS_SHIFT);  
reg |= (cs << LCD_CS_SHIFT);  
gpio->GPFDAT = reg;  

}  

  

static void set_clk(int clk)  

{  

        struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
int reg;  
reg = gpio->GPFDAT;  
reg &= ~(0x1 << LCD_CLK_SHIFT);  
reg |= (clk << LCD_CLK_SHIFT);  
gpio->GPFDAT = reg;  

}  

  

static void set_sdi(int outdata)  

{  

        struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
int reg;  

reg = gpio->GPFDAT;  
reg &= ~(0x1 << LCD_DAT_SHIFT);  
reg |= (outdata << LCD_DAT_SHIFT);  
gpio->GPFDAT = reg;  

}  

 

static void set_res(int res)  

{  

       

        struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
int reg;  

reg = gpio->GPFDAT;  
reg &= ~(0x1 << LCD_RST_SHIFT);  
reg |= (res << LCD_RST_SHIFT);  
gpio->GPFDAT = reg;   

}  

static void lcd_reset()  

{  

       set_res(1);

udelay(20000);  
 
set_res(0);
udelay(10000);  
set_res(1);
udelay(120000);  

}   

static chushihua_gpio(void)

{

set_cs(1);

set_clk(1);

set_sdi(1);

 set_res(1);

udelay(10000); 

}

static void send_cmd(unsigned char cmd)  

{  

unsigned char i;

set_cs(0);

 udelay(10);

set_clk(0);

set_sdi(0);

udelay(100);

set_clk(1);

 udelay(100);

for(i=0;i<8;i++)

    {

    set_clk(0); 

  

      if (cmd&0x80)

       {

          set_sdi(1);

        }

       else

         {

         set_sdi(0);
}

    udelay(100);

      set_clk(1);
udelay(100);

      cmd=cmd<<1;

    }

set_cs(1);

 udelay(10);

}  

  

static void send_date(unsigned char date)  

{  
unsigned char i;

set_cs(0);

 udelay(10);

set_clk(0);

set_sdi(1);

udelay(100);

set_clk(1);

 udelay(100);

for(i=0;i<8;i++)

    {

    set_clk(0); 

  

      if (date&0x80)

       {

          set_sdi(1);

        }

       else

         {

         set_sdi(0);
}

    udelay(100);

      set_clk(1);
udelay(100);

      date=date<<1;

    }

set_cs(1);

 udelay(10);

  

}  

  

static void set_hx8369(void)  

{  

  

 lcd_reset(); //Set_EXTC

send_cmd(0xB9);  // SET password   

        send_date(0xFF);     

        send_date(0x83);     

        send_date(0x69);  

  

        send_cmd(0xB1);  //Set Power   

        send_date(0x01);                             

        send_date(0x00);                             

        send_date(0x34);                             

        send_date(0x06);                             

        send_date(0x00);                             

        send_date(0x11);                             

        send_date(0x11);                             

        send_date(0x2A);   
send_date(0x32); 
send_date(0x3F); 
send_date(0x3F);                           

        send_date(0x07);                             

        send_date(0x23);                             

        send_date(0x01);                             

        send_date(0xE6);                             

        send_date(0xE6);                             

        send_date(0xE6);                             

        send_date(0xE6);                             

        send_date(0xE6);  

  

  udelay(120000); 

        send_cmd(0xB2);  // SET Display  480x800   

        send_date(0x00);     

        send_date(0x2B);     

        send_date(0x03);     

        send_date(0x03);     

        send_date(0x70);     

        send_date(0x00);     

        send_date(0xFF);     

        send_date(0x00);     

        send_date(0x00);     

        send_date(0x00);     

        send_date(0x00);     

        send_date(0x03);     

        send_date(0x03);     

        send_date(0x00);     

        send_date(0x01);  

  

        send_cmd(0xB4);  // SET Display  480x800   

        send_date(0x00);     

        send_date(0x0C);     

        send_date(0xA0);   

        send_date(0x0E);     

        send_date(0x06);  

  

        send_cmd(0xB6);  // SET VCOM   

        send_date(0x35);     

        send_date(0x35);  

  

    udelay(120000); 

        send_cmd(0xD5);  // SET GIP  

        send_date(0x00);     

        send_date(0x05);     

        send_date(0x03);     

        send_date(0x00);     

        send_date(0x01);     

        send_date(0x09);     

        send_date(0x10);     

        send_date(0x80);     

        send_date(0x37);     

        send_date(0x37);     

        send_date(0x20);     

        send_date(0x31);     

        send_date(0x46);     

        send_date(0x8A);     

        send_date(0x57);     

        send_date(0x9B);     

        send_date(0x20);     

        send_date(0x31);     

        send_date(0x46);     

        send_date(0x8A);     

        send_date(0x57);     

        send_date(0x9B);     

        send_date(0x07);     

        send_date(0x0F);     

        send_date(0x02);     

        send_date(0x00);  

  

        send_cmd(0xE0); // SET Gamma  

        send_date(0x00);   

        send_date(0x08);   

        send_date(0x0D);   

        send_date(0x2D);   

        send_date(0x34);   

        send_date(0x3F);   

        send_date(0x19);   

        send_date(0x38);   

        send_date(0x09);   

        send_date(0x0E);   

        send_date(0x0E);   

        send_date(0x12);   

        send_date(0x14);   

        send_date(0x12);   

        send_date(0x14);   

        send_date(0x13);   

        send_date(0x19);   

        send_date(0x00);   

        send_date(0x08);   

        send_date(0x0D);   

        send_date(0x2D);   

        send_date(0x34);   

        send_date(0x3F);   

        send_date(0x19);   

        send_date(0x38);   

        send_date(0x09);   

        send_date(0x0E);   

        send_date(0x0E);   

        send_date(0x12);   

        send_date(0x14);   

        send_date(0x12);   

        send_date(0x14);   

        send_date(0x13);   

        send_date(0x19);   

  udelay(120000);   

   send_cmd(0xC1);   

    send_date(0x01); //enable DGC function   

    send_date(0x02); //SET R-GAMMA   

    send_date(0x08);   

    send_date(0x12);   

    send_date(0x1A);   

    send_date(0x22);   

    send_date(0x2A);   

    send_date(0x31);   

    send_date(0x36);   

    send_date(0x3F);   

    send_date(0x48);   

    send_date(0x51);   

    send_date(0x58);   

    send_date(0x60);   

    send_date(0x68);   

    send_date(0x70);   

    send_date(0x78);   

    send_date(0x80);   

    send_date(0x88);   

    send_date(0x90);   

    send_date(0x98);   

    send_date(0xA0);   

    send_date(0xA7);   

    send_date(0xAF);   

    send_date(0xB6);   

    send_date(0xBE);   

    send_date(0xC7);   

    send_date(0xCE);   

    send_date(0xD6);   

    send_date(0xDE);   

    send_date(0xE6);   

    send_date(0xEF);   

    send_date(0xF5);   

    send_date(0xFB);   

    send_date(0xFC);   

    send_date(0xFE);   

    send_date(0x8C);   

    send_date(0xA4);   

    send_date(0x19);   

    send_date(0xEC);   

    send_date(0x1B);   

    send_date(0x4C);   

    send_date(0x40);     

    

    send_date(0x02); //SET G-Gamma   

    send_date(0x08);   

    send_date(0x12);   

    send_date(0x1A);   

    send_date(0x22);   

    send_date(0x2A);   

    send_date(0x31);   

    send_date(0x36);   

    send_date(0x3F);   

    send_date(0x48);   

    send_date(0x51);   

    send_date(0x58);   

    send_date(0x60);   

    send_date(0x68);   

    send_date(0x70);   

    send_date(0x78);   

    send_date(0x80);   

    send_date(0x88);   

    send_date(0x90);   

    send_date(0x98);   

    send_date(0xA0);   

    send_date(0xA7);   

    send_date(0xAF);   

    send_date(0xB6);   

    send_date(0xBE);   

    send_date(0xC7);   

    send_date(0xCE);   

    send_date(0xD6);   

    send_date(0xDE);   

    send_date(0xE6);   

    send_date(0xEF);   

    send_date(0xF5);   

    send_date(0xFB);   

    send_date(0xFC);   

    send_date(0xFE);   

    send_date(0x8C);   

    send_date(0xA4);   

    send_date(0x19);   

    send_date(0xEC);   

    send_date(0x1B);   

    send_date(0x4C);   

    send_date(0x40);   

      

    send_date(0x02); //SET B-Gamma   

    send_date(0x08);   

    send_date(0x12);   

    send_date(0x1A);   

    send_date(0x22);   

    send_date(0x2A);   

    send_date(0x31);   

    send_date(0x36);   

    send_date(0x3F);   

    send_date(0x48);   

    send_date(0x51);   

    send_date(0x58);   

    send_date(0x60);   

    send_date(0x68);   

    send_date(0x70);   

    send_date(0x78);   

    send_date(0x80);   

    send_date(0x88);   

    send_date(0x90);   

    send_date(0x98);   

    send_date(0xA0);   

    send_date(0xA7);   

    send_date(0xAF);   

    send_date(0xB6);   

    send_date(0xBE);   

    send_date(0xC7);   

    send_date(0xCE);   

    send_date(0xD6);   

    send_date(0xDE);   

    send_date(0xE6);   

    send_date(0xEF);   

    send_date(0xF5);   

    send_date(0xFB);   

    send_date(0xFC);   

    send_date(0xFE);   

    send_date(0x8C);   

    send_date(0xA4);   

    send_date(0x19);   

    send_date(0xEC);   

    send_date(0x1B);   

    send_date(0x4C);   

    send_date(0x40);   

    send_cmd(0x3A);   

 

    send_date(0x55);       

                                                        

    send_cmd(0x11);    

                                  

    udelay(120000);   

  

    send_cmd(0x29);  
send_cmd(0x2c); 

}  

void lcd_config()  

{  
chushihua_gpio();  
set_hx8369();   

}  

/*****************以上部分是我的LCD模组SPI初始化代码,如果大家的不用初始化则没有此部分*********/

int board_init (void)//初始化时钟IO等,我在此处初始化LCD
{
struct s3c24x0_clock_power * const clk_power =
s3c24x0_get_base_clock_power();
struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();

/* to reduce PLL lock time, adjust the LOCKTIME register */
clk_power->LOCKTIME = 0xFFFFFF;

/* configure MPLL */
clk_power->MPLLCON = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV);

/* some delay between MPLL and UPLL */
delay (4000);

/* configure UPLL */
clk_power->UPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV);

/* some delay between MPLL and UPLL */
delay (8000);

/* set up the I/O ports */
gpio->GPACON = 0x007FFFFF;

#if defined(CONFIG_SMDK2440) 
gpio->GPBCON = 0x00295551;
#else
gpio->GPBCON = 0x00044556;
#endif

gpio->GPBUP = 0x000007FF;

#if defined(CONFIG_SMDK2440) 
gpio->GPCCON = 0xAAAAA6AA;
gpio->GPCDAT &= ~(1<<5);
#else
gpio->GPCCON = 0xAAAAAAAA;
#endif
gpio->GPCUP = 0xFFFFFFFF;
gpio->GPDCON = 0xAAAAAAAA;
gpio->GPDUP = 0xFFFFFFFF;

    gpio->GPECON = 0xAAAAAAAA;
gpio->GPEUP = 0x0000FFFF;
gpio->GPFCON = 0x000055AA;
gpio->GPFUP = 0x000000FF;
gpio->GPGCON = 0xFF95FF3A;
gpio->GPGUP = 0x0000FFFF;
gpio->GPHCON = 0x0016FAAA;
gpio->GPHUP = 0x000007FF;

gpio->EXTINT0=0x22222222;
gpio->EXTINT1=0x22222222;
gpio->EXTINT2=0x22222222;

#if defined(CONFIG_S3C2410)
/* arch number of SMDK2410-Board */
gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
#endif

#if defined(CONFIG_S3C2440)
/* arch number of S3C2440-Board */
gd->bd->bi_arch_number = MACH_TYPE_SMDK2440A;
//gd->bd->bi_arch_number = 782;
#endif

//printf("Start Linux parameters at 0x30000100\n");
//printf("MACH_TYPE=%d\n", gd->bd->bi_arch_number);
//printf("Linux command line is: %s\n",CONFIG_BOOTARGS);

/* adress of boot parameters */
gd->bd->bi_boot_params = 0x30000100;

icache_enable();
dcache_enable();
        
       lcd_config()  ;//此处初始化lcd的配置
如果大家不用初始化LCD,则不必关心board_init函数
return 0;
}

在common/stadio.c中

int
stdio_init (void)   //初始化板子的外设
{
#if !defined(CONFIG_RELOC_FIXUP_WORKS)
/* already relocated for current ARM implementation */
ulong relocation_offset = gd->reloc_off;
int i;

/* relocate device name pointers */
for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) {
stdio_names[i] = (char *) (((ulong) stdio_names[i]) +
relocation_offset);
}
#endif /* !CONFIG_RELOC_FIXUP_WORKS */

/* Initialize the list */
INIT_LIST_HEAD(&(devs.list));

#ifdef CONFIG_ARM_DCC_MULTI
drv_arm_dcc_init ();
#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
#endif
#ifdef CONFIG_LCD
drv_lcd_init ();//和mini2440LCD无关
#endif
#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
drv_video_init ();//此函数初始化mini2440的LCD控制器以及显示LOGO

#endif

#ifdef CONFIG_KEYBOARD
drv_keyboard_init ();

#endif

#ifdef CONFIG_LOGBUFFER
drv_logbuff_init ();

#endif
drv_system_init ();

#ifdef CONFIG_SERIAL_MULTI
serial_stdio_init ();

#endif

#ifdef CONFIG_USB_TTY
drv_usbtty_init ();

#endif

#ifdef CONFIG_NETCONSOLE
drv_nc_init ();

#endif

#ifdef CONFIG_JTAG_CONSOLE
drv_jtag_console_init ();

#endif

return (0);

}

下面介绍drv_video_init
()函数

在driver/video/cfb_console.c

int drv_video_init (void) //初始化LCD控制器并显示LOGO

{
int skip_dev_init;
struct stdio_dev console_dev;

/* Check if video initialization should be skipped */
if (board_video_skip())
return 0;

/* Init video chip - returns with framebuffer cleared */
skip_dev_init = (video_init ()== -1);//初始化LCD控制器并显示LOGO

#if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
PRINTD ("KBD: Keyboard init ...\n");
skip_dev_init |= (VIDEO_KBD_INIT_FCT == -1);

#endif

if (skip_dev_init)
return 0;

/* Init vga device */
memset (&console_dev, 0, sizeof (console_dev));
strcpy (console_dev.name, "vga");
console_dev.ext = DEV_EXT_VIDEO;/* Video extensions */
console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
console_dev.putc = video_putc;/* 'putc' function */
console_dev.puts = video_puts;/* 'puts' function */
console_dev.tstc = NULL;/* 'tstc' function */
console_dev.getc = NULL;/* 'getc' function */

#if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
/* Also init console device */
console_dev.flags |= DEV_FLAGS_INPUT;
console_dev.tstc = VIDEO_TSTC_FCT;/* 'tstc' function */
console_dev.getc = VIDEO_GETC_FCT;/* 'getc' function */

#endif /* CONFIG_VGA_AS_SINGLE_DEVICE */

if (stdio_register (&console_dev) != 0)
return 0;

/* Return success */
return 1;

下面介绍video_init ()也在cfb_console.c中

static int video_init (void)

{
unsigned char color8;

if ((pGD = video_hw_init ()) == NULL)//配置LCD控制寄存器数值
return -1;

video_fb_address = (void *) VIDEO_FB_ADRS;

#ifdef CONFIG_VIDEO_HW_CURSOR
video_init_hw_cursor (VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT);

#endif

/* Init drawing pats */
switch (VIDEO_DATA_FORMAT) {
case GDF__8BIT_INDEX:
video_set_lut (0x01, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL);
video_set_lut (0x00, CONSOLE_BG_COL, CONSOLE_BG_COL, CONSOLE_BG_COL);
fgx = 0x01010101;
bgx = 0x00000000;
break;
case GDF__8BIT_332RGB:
color8 = ((CONSOLE_FG_COL & 0xe0) |
 ((CONSOLE_FG_COL >> 3) & 0x1c) | CONSOLE_FG_COL >> 6);
fgx = (color8 << 24) | (color8 << 16) | (color8 << 8) | color8;
color8 = ((CONSOLE_BG_COL & 0xe0) |
 ((CONSOLE_BG_COL >> 3) & 0x1c) | CONSOLE_BG_COL >> 6);
bgx = (color8 << 24) | (color8 << 16) | (color8 << 8) | color8;
break;
case GDF_15BIT_555RGB:
fgx = (((CONSOLE_FG_COL >> 3) << 26) |
      ((CONSOLE_FG_COL >> 3) << 21) | ((CONSOLE_FG_COL >> 3) << 16) |
      ((CONSOLE_FG_COL >> 3) << 10) | ((CONSOLE_FG_COL >> 3) << 5) |
      (CONSOLE_FG_COL >> 3));
bgx = (((CONSOLE_BG_COL >> 3) << 26) |
      ((CONSOLE_BG_COL >> 3) << 21) | ((CONSOLE_BG_COL >> 3) << 16) |
      ((CONSOLE_BG_COL >> 3) << 10) | ((CONSOLE_BG_COL >> 3) << 5) |
      (CONSOLE_BG_COL >> 3));
break;
case GDF_16BIT_565RGB:
fgx = (((CONSOLE_FG_COL >> 3) << 27) |
      ((CONSOLE_FG_COL >> 2) << 21) | ((CONSOLE_FG_COL >> 3) << 16) |
      ((CONSOLE_FG_COL >> 3) << 11) | ((CONSOLE_FG_COL >> 2) << 5) |
      (CONSOLE_FG_COL >> 3));
bgx = (((CONSOLE_BG_COL >> 3) << 27) |
      ((CONSOLE_BG_COL >> 2) << 21) | ((CONSOLE_BG_COL >> 3) << 16) |
      ((CONSOLE_BG_COL >> 3) << 11) | ((CONSOLE_BG_COL >> 2) << 5) |
      (CONSOLE_BG_COL >> 3));
break;
case GDF_32BIT_X888RGB:
fgx = (CONSOLE_FG_COL << 16) | (CONSOLE_FG_COL << 8) | CONSOLE_FG_COL;
bgx = (CONSOLE_BG_COL << 16) | (CONSOLE_BG_COL << 8) | CONSOLE_BG_COL;
break;
case GDF_24BIT_888RGB:
fgx = (CONSOLE_FG_COL << 24) | (CONSOLE_FG_COL << 16) |
(CONSOLE_FG_COL << 8) | CONSOLE_FG_COL;
bgx = (CONSOLE_BG_COL << 24) | (CONSOLE_BG_COL << 16) |
(CONSOLE_BG_COL << 8) | CONSOLE_BG_COL;
break;
}
eorx = fgx ^ bgx;

#ifdef CONFIG_VIDEO_LOGO
/* Plot the logo and get start point of console */
PRINTD ("Video: Drawing the logo ...\n");
video_console_address =
video_logo ();//显示LOGO

#else
video_console_address = video_fb_address;

#endif

/* Initialize the console */
console_col = 0;
console_row = 0;

return 0;

}

在driver/video/s3c2410_fb.c中

void *video_hw_init (void)

{

    struct s3c24x0_lcd * const lcd = s3c24x0_get_base_lcd();

    GraphicDevice *pGD = (GraphicDevice *)&smi;

    int videomode;

    unsigned long t1, hsynch, vsynch;

    char *penv;

    int tmp, i, bits_per_pixel;

    struct ctfb_res_modes *res_mode;

    struct ctfb_res_modes var_mode;

//    unsigned char videoout;

 

    /* Search for video chip */

    printf("Video: ");

    tmp = 0;

 

         videomode = CFG_SYS_DEFAULT_VIDEO_MODE;

         /* get video mode via environment */

         if ((penv = getenv ("videomode")) != NULL) {

                 /* deceide if it is a string */

                 if (penv[0] <= '9') {

                         videomode = (int) simple_strtoul (penv, NULL, 16);

                         tmp = 1;

                 }

         } else {

                 tmp = 1;

         }

         if (tmp) {

                 /* parameter are vesa modes */

                 /* search params */

                 for (i = 0; i < VESA_MODES_COUNT; i++) {

                         if (vesa_modes[i].vesanr == videomode)

                                 break;

                 }

                 if (i == VESA_MODES_COUNT) {

                         printf ("no VESA Mode found, switching to mode 0x%x ", CFG_SYS_DEFAULT_VIDEO_MODE);

                         i = 0;

                }

                 res_mode =

                         (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].

                                                                  resindex];

                 bits_per_pixel = vesa_modes[i].bits_per_pixel;

         } else {

 

                res_mode = (struct ctfb_res_modes *) &var_mode;

                 bits_per_pixel = video_get_params (res_mode, penv);

         }

 

         /* calculate hsynch and vsynch freq (info only) */

         t1 = (res_mode->left_margin + res_mode->xres +

               res_mode->right_margin + res_mode->hsync_len) / 8;

         t1 *= 8;

         t1 *= res_mode->pixclock;

         t1 /= 1000;

         hsynch = 1000000000L / t1;

         t1 *=

                 (res_mode->upper_margin + res_mode->yres +

                  res_mode->lower_margin + res_mode->vsync_len);

         t1 /= 1000;

         vsynch = 1000000000L / t1;

 

         /* fill in Graphic device struct */

         sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,

                  res_mode->yres, bits_per_pixel, (hsynch / 1000),

                  (vsynch / 1000));

         printf ("%s\n", pGD->modeIdent);

         pGD->winSizeX = res_mode->xres;

         pGD->winSizeY = res_mode->yres;

         pGD->plnSizeX = res_mode->xres;

         pGD->plnSizeY = res_mode->yres;

             

         switch (bits_per_pixel) {

         case 8:

                 pGD->gdfBytesPP = 1;

                 pGD->gdfIndex = GDF__8BIT_INDEX;

                 break;

         case 15:

                 pGD->gdfBytesPP = 2;

                 pGD->gdfIndex = GDF_15BIT_555RGB;

                 break;

         case 16:

                 pGD->gdfBytesPP = 2;

                 pGD->gdfIndex = GDF_16BIT_565RGB;

                 break;

         case 24:

                 pGD->gdfBytesPP = 3;

                 pGD->gdfIndex = GDF_24BIT_888RGB;

                 break;

         }

 

         /* statically configure settings */     

//******以上的都是根据环境变量对pGD初始化下面是直接赋值所以上面的没用**/

         //pGD->winSizeX = pGD->plnSizeX = 240;

         //pGD->winSizeY = pGD->plnSizeY = 320;

        pGD->winSizeX = pGD->plnSizeX = 320;

        pGD->winSizeY = pGD->plnSizeY = 240;

         

         pGD->gdfBytesPP = 2;

         pGD->gdfIndex = GDF_16BIT_565RGB;

 

         pGD->frameAdrs = LCD_VIDEO_ADDR;

         pGD->memSize = VIDEO_MEM_SIZE;

 

         board_video_init(pGD);//配置控制寄存器数值

//*******下面初始化LCD的地址寄存器*********//
writel((pGD->frameAdrs >> 1), &lcd->LCDSADDR1); 

 

         /* This marks the end of the frame buffer. */
writel((((readl(&lcd->LCDSADDR1))&0x1fffff) + (pGD->winSizeX+0) * pGD->winSizeY), &lcd->LCDSADDR2); 
writel((pGD->winSizeX & 0x7ff), &lcd->LCDSADDR3); 

 

         /* Clear video memory */

         memset((void *)pGD->frameAdrs, 0, pGD->memSize);

 

         /* Enable  Display  */
writel((readl(&lcd->LCDCON1) | 0x01), & lcd->LCDCON1); /* ENVID = 1 */

 

         return ((void*)&smi);

 }

 

在cfb_console.c中

static void *video_logo (void)

{
char info[128];
extern char version_string;
int space, len, y_off = 0;

#ifdef CONFIG_SPLASH_SCREEN
char *s;
ulong addr;

if ((s = getenv ("splashimage")) != NULL) {
int x = 0, y = 0;

addr = simple_strtoul (s, NULL, 16);

#ifdef CONFIG_SPLASH_SCREEN_ALIGN
if ((s = getenv ("splashpos")) != NULL) {
if (s[0] == 'm')
x = BMP_ALIGN_CENTER;
else
x = simple_strtol (s, NULL, 0);

if ((s = strchr (s + 1, ',')) != NULL) {
if (s[1] == 'm')
y = BMP_ALIGN_CENTER;
else
y = simple_strtol (s + 1, NULL, 0);
}
}

#endif /* CONFIG_SPLASH_SCREEN_ALIGN */

if (video_display_bitmap (addr, x, y) == 0) {
video_logo_height = 0;
return ((void *) (video_fb_address));
}
}

#endif /* CONFIG_SPLASH_SCREEN */

logo_plot (video_fb_address, VIDEO_COLS, 0, 0);//此函数是真正的显示LOGO函数可以改变X,Y改变LOGO位置

sprintf (info, " %s", &version_string);

space = (VIDEO_LINE_LEN / 2 - VIDEO_INFO_X) / VIDEO_FONT_WIDTH;
len = strlen(info);

if (len > space) {
video_drawchars (VIDEO_INFO_X, VIDEO_INFO_Y,
(uchar *)info, space);
video_drawchars (VIDEO_INFO_X + VIDEO_FONT_WIDTH,
VIDEO_INFO_Y + VIDEO_FONT_HEIGHT,
(uchar *)info + space, len - space);
y_off = 1;
} else
video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *)info);

#ifdef CONFIG_CONSOLE_EXTRA_INFO
{
int i, n = ((video_logo_height - VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT);

for (i = 1; i < n; i++) {
video_get_info_str (i, info);
if (!*info)
continue;

len = strlen(info);
if (len > space) {
video_drawchars (VIDEO_INFO_X,
VIDEO_INFO_Y +
(i + y_off) * VIDEO_FONT_HEIGHT,
(uchar *)info, space);
y_off++;
video_drawchars (VIDEO_INFO_X + VIDEO_FONT_WIDTH,
VIDEO_INFO_Y +
(i + y_off) * VIDEO_FONT_HEIGHT,
(uchar *)info + space,
len - space);
} else {
video_drawstring (VIDEO_INFO_X,
 VIDEO_INFO_Y +
 (i + y_off) * VIDEO_FONT_HEIGHT,
 (uchar *)info);
}
}
}

#endif

return (video_fb_address + video_logo_height * VIDEO_LINE_LEN);

}

#endif

下面总结一下

                       board.c

                        board_init()

                        stdio_init()------------>

                                             common/stdio.c

                                             drv_video_init ()--------->

                                                                        driver/video/cfb_console.c

                                                                          video_init ()--->video_hw_init ()-------->

                                                                                                                        board/embedclu/smdk2440/smdk2440ac

                                                                                                                         board_video_init(pGD)

                                                                           video_logo ()-->logo_plot (video_fb_address, VIDEO_COLS, 0, 0);

修改u-boot的开机logo其实很简单。请见下面步骤。

1. 获取一张BMP的图片,修改之,让其色深必须为8位,即256色,如果用24位,则显示出问题,(至于是否能用24位,有待深究)。

2. 将制作好的BMP图片,放置到<u-boot>/tools/logos下面。

3. 修改<u-boot>/tools/Makefile中的LOGO_BMP,使其指向你的bmp图片。如:LOGO_BMP= logos/test.bmp (此名应该放到:LOGO_BMP赋值的最后,否则会被覆盖掉)

----------------------------------------------------------------------------

ifeq ($(LOGO_BMP),)

LOGO_BMP= logos/denx.bmp

endif

<snip>

ifeq ($(VENDOR),intercontrol)

LOGO_BMP= logos/intercontrol.bmp

endif

LOGO_BMP= logos/test.bmp

----------------------------------------------------------------------------

注:此处的VENDOR信息是从<boards.cfg>文件中来。

重新编译u-boot, 生成u-boot.bin,然后放到板子上进行测试。

如果定义了VIDEO_LOGO和VIDEO_BMP_LOGO
编译时会执行tools目录下的bmp_logo程序,读取"tools/logos/denx.bmp"文件,在include下生成bmp_logo.h文件

文件内容如下:

#define BMP_LOGO_WIDTH        160

#define BMP_LOGO_HEIGHT        96

#define BMP_LOGO_COLORS        31

#define BMP_LOGO_OFFSET        16

unsigned short bmp_logo_palette[] = {

    .......................

};

unsigned char bmp_logo_bitmap[] = {

    .......................

};

显示logo函数就会调用这个数组中的数据,显示到屏上

在cfb_console.c中定义了LOGO的属性

#define VIDEO_LOGO_WIDTH    BMP_LOGO_WIDTH

#define VIDEO_LOGO_HEIGHT    BMP_LOGO_HEIGHT

#define VIDEO_LOGO_LUT_OFFSET    BMP_LOGO_OFFSET

#define VIDEO_LOGO_COLORS    BMP_LOGO_COLORS

这个bmp文件是有要求的,位深度必须为8位,大小也有限制(全屏图片肯定是不行的,读取文件的后半部数据都是0)
自己做个logo图片,jpeg格式就可以,使用linux下的图片工具转成8位的bmp文件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: