I.MX6 U-boot lvds display hacking

时间:2022-09-29 09:24:43
/***********************************************************************************
 *                    I.MX6 U-boot lvds display hacking
 * 声明:
 *   本文主要是为了跟踪I.MX6中的U-boot中显示部分代码,查看是否支持24bit显示。
 *
 *                                           2015-10-8 晴 深圳 南山平山村 曾剑锋
 **********************************************************************************/
                                                                                                    
cat cpu/arm_cortexa8/start.S                                                                        
    .globl _start                                                                                   
    _start: b   reset          ---------------------------+                                         
        ldr pc, _undefined_instruction                    |                                         
        ldr pc, _software_interrupt                       |                                         
        ldr pc, _prefetch_abort                           |                                         
        ldr pc, _data_abort                               |                                         
        ldr pc, _not_used                                 |                                         
        ldr pc, _irq                                      |                                         
        ldr pc, _fiq                                      |                                         
                                                          |                                         
    _undefined_instruction: .word undefined_instruction   |                                         
    _software_interrupt:    .word software_interrupt      |                                         
    _prefetch_abort:    .word prefetch_abort              |                                         
    _data_abort:        .word data_abort                  |                                         
    _not_used:      .word not_used                        |                                         
    _irq:           .word irq                             |                                         
    _fiq:           .word fiq                             |                                         
                                                          |                                         
cat cpu/arm_cortexa8/start.S                              |                                         
    /*                                                    |                                         
     * the actual reset code                              |                                         
     */                                                   |                                         
                                                          |                                         
    reset:                     <--------------------------+                                         
        /*                                                                                          
         * set the cpu to SVC32 mode                                                                
         */                                                                                         
        mrs    r0, cpsr                                                                             
        bic    r0, r0, #0x1f                                                                        
        orr    r0, r0, #0xd3                                                                        
        msr    cpsr,r0                                                                              
                                                                                                    
    #if (CONFIG_OMAP34XX)                                                                           
        /* Copy vectors to mask ROM indirect addr */                                                
        adr    r0, _start        @ r0 <- current position of code                                   
        add    r0, r0, #4        @ skip reset vector                                                
        mov    r2, #64            @ r2 <- size to copy                                              
        add    r2, r0, r2        @ r2 <- source end address                                         
        mov    r1, #SRAM_OFFSET0    @ build vect addr                                               
        mov    r3, #SRAM_OFFSET1                                                                    
        add    r1, r1, r3                                                                           
        mov    r3, #SRAM_OFFSET2                                                                    
        add    r1, r1, r3                                                                           
    next:                                                                                           
        ldmia    r0!, {r3 - r10}        @ copy from source address [r0]                             
        stmia    r1!, {r3 - r10}        @ copy to   target address [r1]                             
        cmp    r0, r2            @ until source end address [r2]                                    
        bne    next            @ loop until equal */                                                
    #if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT)                         
        /* No need to copy/exec the clock code - DPLL adjust already done                           
         * in NAND/oneNAND Boot.                                                                    
         */                                                                                         
        bl    cpy_clk_code        @ put dpll adjust code behind vectors                             
    #endif /* NAND Boot */                                                                          
    #endif                                                                                          
        /* the mask ROM code should have PLL and others stable */                                   
    #ifndef CONFIG_SKIP_LOWLEVEL_INIT                                                               
        bl    cpu_init_crit                                                                         
    #endif                                                                                          
                                                                                                    
    #ifndef CONFIG_SKIP_RELOCATE_UBOOT                                                              
    relocate:               @ relocate U-Boot to RAM                                                
        adr r0, _start      @ r0 <- current position of code                                        
        ldr r1, _TEXT_BASE      @ test if we run from flash or RAM                                  
        cmp r0, r1          @ don't reloc during debug                                              
        beq stack_setup                                                                             
                                                                                                    
        ldr r2, _armboot_start                                                                      
        ldr r3, _bss_start                                                                          
        sub r2, r3, r2      @ r2 <- size of armboot                                                 
        add r2, r0, r2      @ r2 <- source end address                                              
                                                                                                    
    copy_loop:              @ copy 32 bytes at a time                                               
        ldmia   r0!, {r3 - r10}     @ copy from source address [r0]                                 
        stmia   r1!, {r3 - r10}     @ copy to   target address [r1]                                 
        cmp r0, r2          @ until source end addreee [r2]                                         
        ble copy_loop                                                                               
    #endif  /* CONFIG_SKIP_RELOCATE_UBOOT */                                                        
                                                                                                    
    stack_setup:                                                                                    
        ldr r0, _TEXT_BASE      @ upper 128 KiB: relocated uboot                                    
        sub r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area                                            
        sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE @ bdinfo                                              
    #ifdef CONFIG_USE_IRQ                                                                           
        sub r0, r0, #(CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ)                                  
    #endif                                                                                          
        sub sp, r0, #12     @ leave 3 words for abort-stack                                         
        and sp, sp, #~7     @ 8 byte alinged for (ldr/str)d                                         
                                                                                                    
        /* Clear BSS (if any). Is below tx (watch load addr - need space) */                        
    clear_bss:                                                                                      
        ldr r0, _bss_start      @ find start of bss segment                                         
        ldr r1, _bss_end        @ stop here                                                         
        mov r2, #0x00000000     @ clear value                                                       
    clbss_l:                                                                                        
        str r2, [r0]        @ clear BSS location                                                    
        cmp r0, r1          @ are we at the end yet                                                 
        add r0, r0, #4      @ increment clear index pointer                                         
        bne clbss_l         @ keep clearing till at end                                             
                                                                                                    
    #ifdef CONFIG_ARCH_MMU                                                                          
        bl board_mmu_init                                                                           
    #endif                                                                                          
        ldr pc, _start_armboot  @ jump to C code              -------+                              
                                                                     |                              
    _start_armboot: .word start_armboot          ---------+   <------+                              
                                                          |                                         
cat lib_arm/board.c                                       |                                         
    void start_armboot (void)                    <--------+                                        
    {                                                                                               
        init_fnc_t **init_fnc_ptr;                                                                  
        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));                        
        /* 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);                                   
                                                                                                    
    #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                                                                                          
                                                                                                    
    #ifdef CONFIG_GENERIC_MMC                                                                       
        puts ("MMC:   ");                                                                           
        mmc_initialize (gd->bd);                                                                    
    #endif                                                                                          
                                                                                                    
        /* initialize environment */                                                                
        env_relocate ();                                                                            
                                                                                                    
    #ifdef CONFIG_VFD                                                                               
        /* must do this after the framebuffer is allocated */                                       
        drv_vfd_init();                                                                             
    #endif /* CONFIG_VFD */                                                                         
                                                                                                    
    #ifdef CONFIG_SERIAL_MULTI                                                                      
        serial_initialize();                                                                        
    #endif                                                                                          
                                                                                                    
        /* IP Address */                                                                            
        gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");                                              
                                                                                                    
    #if defined CONFIG_SPLASH_SCREEN && defined CONFIG_VIDEO_MX5                                    
        setup_splash_image();                                                                       
    #endif                                                                                          
                                                                                                    
        stdio_init ();    /* get the devices list going. */   -------------------+                  
                                                                                 |                  
        jumptable_init ();                                                       |                  
                                                                                 |                  
    #if defined(CONFIG_API)                                                      |                  
        /* Initialize API */                                                     |                  
        api_init ();                                                             |                  
    #endif                                                                       |                  
                                                                                 |                  
        console_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                                                                       |                  
                                                                                 |                  
        /* enable exceptions */                                                  |                  
        enable_interrupts ();                                                    |                  
                                                                                 |                  
        /* 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                                                                       |                  
                                                                                 |                  
    #ifdef CONFIG_DRIVER_CS8900                                                  |                  
        /* XXX: this needs to be moved to board init */                          |                  
        cs8900_get_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 */                |                  
                                                                                 |                  
    #if defined(CONFIG_ENC28J60_ETH) && !defined(CONFIG_ETHADDR)                 |                  
        extern void enc_set_mac_addr (void);                                     |                  
        enc_set_mac_addr ();                                                     |                  
    #endif /* CONFIG_ENC28J60_ETH && !CONFIG_ETHADDR*/                           |                  
                                                                                 |                  
        /* 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_ANDROID_RECOVERY                                               |                  
        check_recovery_mode();                                                   |                  
    #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                                                                       |                  
    #ifdef CONFIG_FASTBOOT                                                       |                  
        check_fastboot_mode();                                                   |                  
    #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 */             |                  
    }                                                                            |                  
                                                                                 |                  
cat common/stdio.c                                                               |                  
    int stdio_init (void)                    <-----------------------------------+                  
    {                                                                                               
    #ifndef CONFIG_ARM    /* 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                                                                                          
                                                                                                    
        /* 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 ();                     ----------------------------------+                    
    #endif                                                                     |                    
    #if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)                   |                    
        drv_video_init ();                                                     |                    
    #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);                                                            |                    
    }                                                                          |                    
                                                                               |                    
cat common/stdio.c                                                             |                    
    int drv_lcd_init (void)                    <-------------------------------+                    
    {                                                                                               
        struct stdio_dev lcddev;                                                                    
        int rc;                                                                                     
                                                                                                    
        lcd_base = (void *)(gd->fb_base);                                                           
                                                                                                    
        lcd_line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;                     
                                                                                                    
        lcd_init (lcd_base);        /* LCD initialization */        ----------+                     
                                                                              |                     
        /* Device initialization */                                           |                     
        memset (&lcddev, 0, sizeof (lcddev));                                 |                     
                                                                              |                     
        strcpy (lcddev.name, "lcd");                                          |                     
        lcddev.ext   = 0;           /* No extensions */                       |                     
        lcddev.flags = DEV_FLAGS_OUTPUT;    /* Output only */                 |                     
        lcddev.putc  = lcd_putc;        /* 'putc' function */                 |                     
        lcddev.puts  = lcd_puts;        /* 'puts' function */                 |                     
                                                                              |                     
        rc = stdio_register (&lcddev);                                        |                     
                                                                              |                     
        return (rc == 0) ? 1 : rc;                                            |                     
    }                                                                         |                     
                                                                              |                     
cat common/lcd.c                                                              |                     
    static int lcd_init (void *lcdbase)                   <-------------------+                     
    {                                                                                               
        /* Initialize the lcd controller */                                                         
        debug ("[LCD] Initializing LCD frambuffer at %p\n", lcdbase);                               
                                                                                                    
        lcd_ctrl_init (lcdbase);                                                                    
        lcd_is_enabled = 1;                                                                         
        lcd_clear (NULL, 1, 1, NULL);   /* dummy args */  -------------+                            
        lcd_enable ();                                    -------------*---------------+            
                                                                       |               |            
        /* Initialize the console */                                   |               |            
        console_col = 0;                                               |               |            
    #ifdef CONFIG_LCD_INFO_BELOW_LOGO                                  |               |            
        console_row = 7 + BMP_LOGO_HEIGHT / VIDEO_FONT_HEIGHT;         |               |            
    #else                                                              |               |            
        console_row = 1;    /* leave 1 blank line below logo */        |               |            
    #endif                                                             |               |            
                                                                       |               |            
        return 0;                                                      |               |            
    }                +-------------------------------------------------+               |            
                     |                                                                 |            
cat common/lcd.c     V                                                                 |            
    static int lcd_clear (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])         |            
    {                                                                                  |            
    #if LCD_BPP == LCD_MONOCHROME                                                      |            
        /* Setting the palette */                                                      |            
        lcd_initcolregs();                                                             |            
                                                                                       |            
    #elif LCD_BPP == LCD_COLOR8                                                        |            
        /* Setting the palette */                                                      |            
        lcd_setcolreg  (CONSOLE_COLOR_BLACK,       0,    0,    0);                     |            
        lcd_setcolreg  (CONSOLE_COLOR_RED,    0xFF,    0,    0);                       |            
        lcd_setcolreg  (CONSOLE_COLOR_GREEN,       0, 0xFF,    0);                     |            
        lcd_setcolreg  (CONSOLE_COLOR_YELLOW,    0xFF, 0xFF,    0);                    |            
        lcd_setcolreg  (CONSOLE_COLOR_BLUE,        0,    0, 0xFF);                     |            
        lcd_setcolreg  (CONSOLE_COLOR_MAGENTA,    0xFF,    0, 0xFF);                   |            
        lcd_setcolreg  (CONSOLE_COLOR_CYAN,       0, 0xFF, 0xFF);                      |            
        lcd_setcolreg  (CONSOLE_COLOR_GREY,    0xAA, 0xAA, 0xAA);                      |            
        lcd_setcolreg  (CONSOLE_COLOR_WHITE,    0xFF, 0xFF, 0xFF);                     |            
    #endif                                                                             |            
                                                                                       |            
    #ifndef CONFIG_SYS_WHITE_ON_BLACK                                                  |            
        lcd_setfgcolor (CONSOLE_COLOR_BLACK);                                          |            
        lcd_setbgcolor (CONSOLE_COLOR_WHITE);                                          |            
    #else                                                                              |            
        lcd_setfgcolor (CONSOLE_COLOR_WHITE);                                          |            
        lcd_setbgcolor (CONSOLE_COLOR_BLACK);                                          |            
    #endif    /* CONFIG_SYS_WHITE_ON_BLACK */                                          |            
                                                                                       |            
    #ifdef    LCD_TEST_PATTERN                                                         |            
        test_pattern();                                                                |            
    #else                                                                              |            
        /* set framebuffer to background color */                                      |            
        memset ((char *)lcd_base,                                                      |            
            COLOR_MASK(lcd_getbgcolor()),                                              |            
            lcd_line_length*panel_info.vl_row);                                        |            
    #endif                                                                             |            
        /* Paint the logo and retrieve LCD base address */                             |            
        debug ("[LCD] Drawing the logo...\n");                                         |            
        lcd_console_address = lcd_logo ();   --------+                                 |            
                                                     |                                 |            
        console_col = 0;                             |                                 |            
        console_row = 0;                             |                                 |            
                                                     |                                 |            
        return (0);                                  |                                 |            
    }                                                |                                 |            
                                                     |                                 |            
cat common/lcd.c                                     |                                 |            
    static void *lcd_logo (void)         <-----------+                                 |            
    {                                                                                  |            
    #ifdef CONFIG_SPLASH_SCREEN                                                        |            
        char *s;                                                                       |            
        ulong addr;                                                                    |            
        static int do_splash = 1;                                                      |            
                                                                                       |            
        // get the "splashimage=0x30000000\0"                                          |            
        if (do_splash && (s = getenv("splashimage")) != NULL) {                        |            
            int x = 0, y = 0;                                                          |            
            do_splash = 0;                                                             |            
                                                                                       |            
            // get the image address                                                   |            
            addr = simple_strtoul (s, NULL, 16);                                       |            
                                                                                       |            
    #ifdef CONFIG_SPLASH_SCREEN_ALIGN                                                  |            
            // get the "splashpos=m,m\0"                                               |            
            if ((s = getenv ("splashpos")) != NULL) {                                  |            
                // the first position x and y, default was center                      |            
                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 */                                            |            
                                                                                       |            
    #ifdef CONFIG_VIDEO_BMP_GZIP                                                       |            
            // get the image struct                                                    |            
            bmp_image_t *bmp = (bmp_image_t *)addr;                                    |            
            unsigned long len;                                                         |            
                                                                                       |            
            if (!((bmp->header.signature[0]=='B') &&                                   |            
                  (bmp->header.signature[1]=='M'))) {                                  |            
                addr = (ulong)gunzip_bmp(addr, &len);                                  |            
            }                                                                          |            
    #endif                                                                             |            
            /**                                                                        |            
             * We currently offer uboot boot picture size is 800*480,                  |            
              * so the picture do not need to be offset ,                              |            
             * just let x and y equal to zero that drawing picture at top left corner  |            
             *                 write by zengjf    2015/4/8                             |            
             */                                                                        |            
            x = 0;                                                                     |            
              y = 0;                                                                   |            
                                                                                       |            
                                                                                       |            
            if (lcd_display_bitmap (addr, x, y) == 0) {       -------------------+     |            
                return ((void *)lcd_base);                                       |     |            
            }                                                                    |     |            
        }                                                                        |     |            
    #endif /* CONFIG_SPLASH_SCREEN */                                            |     |            
                                                                                 |     |            
    #ifdef CONFIG_LCD_LOGO                                                       |     |            
        bitmap_plot (0, 0);                                                      |     |            
    #endif /* CONFIG_LCD_LOGO */                                                 |     |            
                                                                                 |     |            
    #ifdef CONFIG_LCD_INFO                                                       |     |            
        console_col = LCD_INFO_X / VIDEO_FONT_WIDTH;                             |     |            
        console_row = LCD_INFO_Y / VIDEO_FONT_HEIGHT;                            |     |            
        lcd_show_board_info();                                                   |     |            
    #endif /* CONFIG_LCD_INFO */                                                 |     |            
                                                                                 |     |            
    #if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)         |     |            
        return ((void *)((ulong)lcd_base + BMP_LOGO_HEIGHT * lcd_line_length));  |     |            
    #else                                                                        |     |            
        return ((void *)lcd_base);                                               |     |            
    #endif /* CONFIG_LCD_LOGO && !CONFIG_LCD_INFO_BELOW_LOGO */                  |     |            
    }                                                                            |     |            
                                                                                 |     |            
cat common/lcd.c                                                                 |     |            
    int lcd_display_bitmap(ulong bmp_image, int x, int y)     <------------------+     |            
    {                                                                                  |            
    #if !defined(CONFIG_MCC200)                                                        |            
        ushort *cmap = NULL;                                                           |            
    #endif                                                                             |            
        ushort *cmap_base = NULL;                                                      |            
        ushort i, j;                                                                   |            
        uchar *fb;                                                                     |            
        bmp_image_t *bmp=(bmp_image_t *)bmp_image;                                     |            
        uchar *bmap;                                                                   |            
        ushort padded_line;                                                            |            
        unsigned long width, height, byte_width;                                       |            
        unsigned long pwidth = panel_info.vl_col;                                      |            
        unsigned colors, bpix, bmp_bpix;                                               |            
        unsigned long compression;                                                     |            
    #if defined(CONFIG_PXA250)                                                         |            
        struct pxafb_info *fbi = &panel_info.pxa;                                      |            
    #elif defined(CONFIG_MPC823)                                                       |            
        volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;                          |            
        volatile cpm8xx_t *cp = &(immr->im_cpm);                                       |            
    #endif                                                                             |            
                                                                                       |            
        if (!((bmp->header.signature[0]=='B') &&                                       |            
            (bmp->header.signature[1]=='M'))) {                                        |            
            printf ("Error: no valid bmp image at %lx\n", bmp_image);                  |            
            return 1;                                                                  |            
        }                                                                              |            
                                                                                       |            
        width = le32_to_cpu (bmp->header.width);                                       |            
        height = le32_to_cpu (bmp->header.height);                                     |            
        bmp_bpix = le16_to_cpu(bmp->header.bit_count);                                 |            
        colors = 1 << bmp_bpix;                                                        |            
        compression = le32_to_cpu (bmp->header.compression);                           |            
                                                                                       |            
        bpix = NBITS(panel_info.vl_bpix);                                              |            
                                                                                       |            
        if ((bpix != 1) && (bpix != 8) && (bpix != 16) && (bpix != 24)) {              |            
            printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",            |            
                bpix, bmp_bpix);                                                       |            
            return 1;                                                                  |            
        }                                                                              |            
                                                                                       |            
    #if defined(CONFIG_BMP_24BPP)                                                      |            
        /* We support displaying 24bpp BMPs on 16bpp LCDs */                           |            
        if (bpix != bmp_bpix && (bmp_bpix != 24 || bpix != 16) &&                      |            
            (bmp_bpix != 8 || bpix != 16)) {                                           |            
    #else                                                                              |            
        /* We support displaying 8bpp BMPs on 16bpp LCDs */                            |            
        if (bpix != bmp_bpix && (bmp_bpix != 8 || bpix != 16)) {                       |            
    #endif                                                                             |            
            printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",            |            
                bpix,                                                                  |            
                le16_to_cpu(bmp->header.bit_count));                                   |            
            return 1;                                                                  |            
        }                                                                              |            
                                                                                       |            
        debug ("Display-bmp: %d x %d  with %d colors\n",                               |            
            (int)width, (int)height, (int)colors);                                     |            
                                                                                       |            
    #if !defined(CONFIG_MCC200)                                                        |            
        /* MCC200 LCD doesn't need CMAP, supports 1bpp b&w only */                     |            
        if (bmp_bpix == 8) {                                                           |            
    #if defined(CONFIG_PXA250)                                                         |            
            cmap = (ushort *)fbi->palette;                                             |            
    #elif defined(CONFIG_MPC823)                                                       |            
            cmap = (ushort *)&(cp->lcd_cmap[255*sizeof(ushort)]);                      |            
    #elif !defined(CONFIG_ATMEL_LCD)                                                   |            
            cmap = panel_info.cmap;                                                    |            
    #endif                                                                             |            
            cmap_base = cmap;                                                          |            
                                                                                       |            
            /* Set color map */                                                        |            
            for (i=0; i<colors; ++i) {                                                 |            
                bmp_color_table_entry_t cte = bmp->color_table[i];                     |            
    #if !defined(CONFIG_ATMEL_LCD)                                                     |            
                ushort colreg =                                                        |            
                    ( ((cte.red)   << 8) & 0xf800) |                                   |            
                    ( ((cte.green) << 3) & 0x07e0) |                                   |            
                    ( ((cte.blue)  >> 3) & 0x001f) ;                                   |            
    #ifdef CONFIG_SYS_INVERT_COLORS                                                    |            
                *cmap = 0xffff - colreg;                                               |            
    #else                                                                              |            
                *cmap = colreg;                                                        |            
    #endif                                                                             |            
    #if defined(CONFIG_MPC823)                                                         |            
                cmap--;                                                                |            
    #else                                                                              |            
                cmap++;                                                                |            
    #endif                                                                             |            
    #else /* CONFIG_ATMEL_LCD */                                                       |            
                lcd_setcolreg(i, cte.red, cte.green, cte.blue);                        |            
    #endif                                                                             |            
            }                                                                          |            
        }                                                                              |            
    #endif                                                                             |            
                                                                                       |            
        /*                                                                             |            
         * BMP format for Monochrome assumes that the state of a                       |            
         * pixel is described on a per Bit basis, not per Byte.                        |            
         * So, in case of Monochrome BMP we should align widths                        |            
         * on a byte boundary and convert them from Bit to Byte                        |            
         * units.                                                                      |            
         * Probably, PXA250 and MPC823 process 1bpp BMP images in                      |            
         * their own ways, so make the converting to be MCC200                         |            
         * specific.                                                                   |            
         */                                                                            |            
    #if defined(CONFIG_MCC200)                                                         |            
        if (bpix==1)                                                                   |            
        {                                                                              |            
            width = ((width + 7) & ~7) >> 3;                                           |            
            x     = ((x + 7) & ~7) >> 3;                                               |            
            pwidth= ((pwidth + 7) & ~7) >> 3;                                          |            
        }                                                                              |            
    #endif                                                                             |            
        padded_line = (width&0x3) ? ((width&~0x3)+4) : (width);                        |            
    #ifdef CONFIG_SPLASH_SCREEN_ALIGN                                                  |            
        if (x == BMP_ALIGN_CENTER)                                                     |            
            x = max(0, (pwidth - width) / 2);                                          |            
        else if (x < 0)                                                                |            
            x = max(0, pwidth - width + x + 1);                                        |            
                                                                                       |            
        if (y == BMP_ALIGN_CENTER)                                                     |            
            y = max(0, (panel_info.vl_row - height) / 2);                              |            
        else if (y < 0)                                                                |            
            y = max(0, panel_info.vl_row - height + y + 1);                            |            
    #endif /* CONFIG_SPLASH_SCREEN_ALIGN */                                            |            
                                                                                       |            
        if ((x + width)>pwidth)                                                        |            
            width = pwidth - x;                                                        |            
        if ((y + height)>panel_info.vl_row)                                            |            
            height = panel_info.vl_row - y;                                            |            
                                                                                       |            
        bmap = (uchar *)bmp + le32_to_cpu (bmp->header.data_offset);                   |            
        fb   = (uchar *) (lcd_base +                                                   |            
            (y + height - 1) * lcd_line_length + x * bpix / 8);                        |            
                                                                                       |            
        switch (bmp_bpix) {                                                            |            
        case 1: /* pass through */                                                     |            
        case 8:                                                                        |            
            if (bpix != 16)                                                            |            
                byte_width = width;                                                    |            
            else                                                                       |            
                byte_width = width * 2;                                                |            
                                                                                       |            
            for (i = 0; i < height; ++i) {                                             |            
                WATCHDOG_RESET();                                                      |            
                for (j = 0; j < width; j++) {                                          |            
                    if (bpix != 16) {                                                  |            
    #if defined(CONFIG_PXA250) || defined(CONFIG_ATMEL_LCD)                            |            
                        *(fb++) = *(bmap++);                                           |            
    #elif defined(CONFIG_MPC823) || defined(CONFIG_MCC200)                             |            
                        *(fb++) = 255 - *(bmap++);                                     |            
    #endif                                                                             |            
                    } else {                                                           |            
                        *(uint16_t *)fb = cmap_base[*(bmap++)];                        |            
                        fb += sizeof(uint16_t) / sizeof(*fb);                          |            
                    }                                                                  |            
                }                                                                      |            
                bmap += (width - padded_line);                                         |            
                fb   -= (byte_width + lcd_line_length);                                |            
            }                                                                          |            
            break;                                                                     |            
                                                                                       |            
    #if defined(CONFIG_BMP_16BPP)                                                      |            
        case 16:                                                                       |            
            for (i = 0; i < height; ++i) {                                             |            
                WATCHDOG_RESET();                                                      |            
                for (j = 0; j < width; j++) {                                          |            
    #if defined(CONFIG_ATMEL_LCD_BGR555)                                               |            
                    *(fb++) = ((bmap[0] & 0x1f) << 2) |                                |            
                        (bmap[1] & 0x03);                                              |            
                    *(fb++) = (bmap[0] & 0xe0) |                                       |            
                        ((bmap[1] & 0x7c) >> 2);                                       |            
                    bmap += 2;                                                         |            
    #else                                                                              |            
                    *(fb++) = *(bmap++);                                               |            
                    *(fb++) = *(bmap++);                                               |            
    #endif                                                                             |            
                }                                                                      |            
                bmap += (padded_line - width) * 2;                                     |            
                fb   -= (width * 2 + lcd_line_length);                                 |            
            }                                                                          |            
            break;                                                                     |            
    #endif /* CONFIG_BMP_16BPP */                                                      |            
    #if defined(CONFIG_BMP_24BPP)                                                      |            
        case 24:                                                                       |            
            if (bpix != 16) {                                                          |            
                printf("Error: %d bit/pixel mode,"                                     |            
                    "but BMP has %d bit/pixel\n",                                      |            
                    bpix, bmp_bpix);                                                   |            
                break;                                                                 |            
            }                                                                          |            
            for (i = 0; i < height; ++i) {                                             |            
                WATCHDOG_RESET();                                                      |            
                for (j = 0; j < width; j++) {                                          |            
                    *(uint16_t *)fb = ((*(bmap + 2) << 8) & 0xf800)                    |            
                            | ((*(bmap + 1) << 3) & 0x07e0)                            |            
                            | ((*(bmap) >> 3) & 0x001f);                               |            
                    bmap += 3;                                                         |            
                    fb += sizeof(uint16_t) / sizeof(*fb);                              |            
                }                                                                      |            
                bmap += (width - padded_line);                                         |            
                fb   -= ((2*width) + lcd_line_length);                                 |            
            }                                                                          |            
            break;                                                                     |            
    #endif /* CONFIG_BMP_24BPP */                                                      |            
        default:                                                                       |            
            break;                                                                     |            
        };                                                                             |            
                                                                                       |            
        return (0);                                                                    |            
    }                                                                                  |            
    #endif                                                                             |            
                                                                                       |            
cat board/freescale/mx6q_sabresd/mx6q_sabresd.c                                        |            
    ......                                                                             |            
    #ifndef CONFIG_MXC_EPDC                                                            |            
    #ifdef CONFIG_LCD                                                                  |            
    void lcd_enable(void)             <------------------------------------------------+            
    {                                                                                               
        char *s;                                                                                    
        int ret;                                                                                    
        unsigned int reg;                                                                           
                                                                                                    
        s = getenv("lvds_num");                                                                     
        di = simple_strtol(s, NULL, 10);                                                            
                                                                                                    
        /*                                                                                          
        * hw_rev 2: IPUV3DEX                                                                        
        * hw_rev 3: IPUV3M                                                                          
        * hw_rev 4: IPUV3H                                                                          
        */                                                                                          
        g_ipu_hw_rev = IPUV3_HW_REV_IPUV3H;                                                         
                                                                                                    
        /**                                                                                         
         * zengjf modify don't show uboot logo                                                      
         */                                                                                         
        imx_pwm_config(pwm0, 25000, 50000);                                                         
        imx_pwm_enable(pwm0);                                                                       
                                                                                                    
    #if defined CONFIG_MX6Q                                                                         
        /* PWM backlight */                                                                         
        mxc_iomux_v3_setup_pad(MX6Q_PAD_SD1_DAT3__PWM1_PWMO);                                       
        /* LVDS panel CABC_EN0 */                                                                   
        //mxc_iomux_v3_setup_pad(MX6Q_PAD_NANDF_CS2__GPIO_6_15);                                    
        /* LVDS panel CABC_EN1 */                                                                   
        //mxc_iomux_v3_setup_pad(MX6Q_PAD_NANDF_CS3__GPIO_6_16);                                    
    #elif defined CONFIG_MX6DL                                                                      
        /* PWM backlight */                                                                         
        mxc_iomux_v3_setup_pad(MX6DL_PAD_SD1_DAT3__PWM1_PWMO);                                      
        /* LVDS panel CABC_EN0 */                                                                   
        //mxc_iomux_v3_setup_pad(MX6DL_PAD_NANDF_CS2__GPIO_6_15);                                   
        /* LVDS panel CABC_EN1 */                                                                   
        //mxc_iomux_v3_setup_pad(MX6DL_PAD_NANDF_CS3__GPIO_6_16);                                   
    #endif                                                                                          
        /*                                                                                          
         * Set LVDS panel CABC_EN0 to low to disable                                                
         * CABC function. This function will turn backlight                                         
         * automatically according to display content, so                                           
         * simply disable it to get rid of annoying unstable                                        
         * backlight phenomena.                                                                     
         */                                                                                         
        /*                                                                                          
        reg = readl(GPIO6_BASE_ADDR + GPIO_GDIR);                                                   
        reg |= (1 << 15);                                                                           
        writel(reg, GPIO6_BASE_ADDR + GPIO_GDIR);                                                   
                                                                                                    
        reg = readl(GPIO6_BASE_ADDR + GPIO_DR);                                                     
        reg &= ~(1 << 15);                                                                          
        writel(reg, GPIO6_BASE_ADDR + GPIO_DR);                                                     
        */                                                                                          
                                                                                                    
        /*                                                                                          
         * Set LVDS panel CABC_EN1 to low to disable                                                
         * CABC function.                                                                           
         */                                                                                         
        /*                                                                                          
        reg = readl(GPIO6_BASE_ADDR + GPIO_GDIR);                                                   
        reg |= (1 << 16);                                                                           
        writel(reg, GPIO6_BASE_ADDR + GPIO_GDIR);                                                   
                                                                                                    
        reg = readl(GPIO6_BASE_ADDR + GPIO_DR);                                                     
        reg &= ~(1 << 16);                                                                          
        writel(reg, GPIO6_BASE_ADDR + GPIO_DR);                                                     
        */                                                                                          
                                                                                                    
        /* Disable ipu1_clk/ipu1_di_clk_x/ldb_dix_clk. */                                           
        reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR3);                                                  
        reg &= ~0xC033;                                                                             
        writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR3);                                                  
                                                                                                    
    #if defined CONFIG_MX6Q                                                                         
        /*                                                                                          
         * Align IPU1 HSP clock and IPU1 DIx pixel clock                                            
         * with kernel setting to avoid screen flick when                                           
         * booting into kernel. Developer should change                                             
         * the relevant setting if kernel setting changes.                                          
         * IPU1 HSP clock tree:                                                                     
         * osc_clk(24M)->pll2_528_bus_main_clk(528M)->                                              
         * periph_clk(528M)->mmdc_ch0_axi_clk(528M)->                                               
         * ipu1_clk(264M)                                                                           
         */                                                                                         
        /* pll2_528_bus_main_clk */                                                                 
        /* divider */                                                                               
        writel(0x1, ANATOP_BASE_ADDR + 0x34);                                                       
                                                                                                    
        /* periph_clk */                                                                            
        /* source */                                                                                
        reg = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);                                                  
        reg &= ~(0x3 << 18);                                                                        
        writel(reg, CCM_BASE_ADDR + CLKCTL_CBCMR);                                                  
                                                                                                    
        reg = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);                                                  
        reg &= ~(0x1 << 25);                                                                        
        writel(reg, CCM_BASE_ADDR + CLKCTL_CBCDR);                                                  
                                                                                                    
        /*                                                                                          
         * Check PERIPH_CLK_SEL_BUSY in                                                             
         * MXC_CCM_CDHIPR register.                                                                 
         */                                                                                         
        do {                                                                                        
            udelay(5);                                                                              
            reg = readl(CCM_BASE_ADDR + CLKCTL_CDHIPR);                                             
        } while (reg & (0x1 << 5));                                                                 
                                                                                                    
        /* mmdc_ch0_axi_clk */                                                                      
        /* divider */                                                                               
        reg = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);                                                  
        reg &= ~(0x7 << 19);                                                                        
        writel(reg, CCM_BASE_ADDR + CLKCTL_CBCDR);                                                  
                                                                                                    
        /*                                                                                          
         * Check MMDC_CH0PODF_BUSY in                                                               
         * MXC_CCM_CDHIPR register.                                                                 
         */                                                                                         
        do {                                                                                        
            udelay(5);                                                                              
            reg = readl(CCM_BASE_ADDR + CLKCTL_CDHIPR);                                             
        } while (reg & (0x1 << 4));                                                                 
                                                                                                    
        /* ipu1_clk */                                                                              
        reg = readl(CCM_BASE_ADDR + CLKCTL_CSCDR3);                                                 
        /* source */                                                                                
        reg &= ~(0x3 << 9);                                                                         
        /* divider */                                                                               
        reg &= ~(0x7 << 11);                                                                        
        reg |= (0x1 << 11);                                                                         
        writel(reg, CCM_BASE_ADDR + CLKCTL_CSCDR3);                                                 
                                                                                                    
        /*                                                                                          
         * ipu1_pixel_clk_x clock tree:                                                             
         * osc_clk(24M)->pll2_528_bus_main_clk(528M)->                                              
         * pll2_pfd_352M(452.57M)->ldb_dix_clk(64.65M)->                                            
         * ipu1_di_clk_x(64.65M)->ipu1_pixel_clk_x(64.65M)                                          
         */                                                                                         
        /* pll2_pfd_352M */                                                                         
        /* disable */                                                                               
        writel(0x1 << 7, ANATOP_BASE_ADDR + 0x104);                                                 
        /* divider */                                                                               
        writel(0x3F, ANATOP_BASE_ADDR + 0x108);                                                     
        writel(0x15, ANATOP_BASE_ADDR + 0x104);                                                     
                                                                                                    
        /* ldb_dix_clk */                                                                           
        /* source */                                                                                
        reg = readl(CCM_BASE_ADDR + CLKCTL_CS2CDR);                                                 
        reg &= ~(0x3F << 9);                                                                        
        reg |= (0x9 << 9);                                                                          
        writel(reg, CCM_BASE_ADDR + CLKCTL_CS2CDR);                                                 
        /* divider */                                                                               
        reg = readl(CCM_BASE_ADDR + CLKCTL_CSCMR2);                                                 
        reg |= (0x3 << 10);                                                                         
        writel(reg, CCM_BASE_ADDR + CLKCTL_CSCMR2);                                                 
                                                                                                    
        /* pll2_pfd_352M */                                                                         
        /* enable after ldb_dix_clk source is set */                                                
        writel(0x1 << 7, ANATOP_BASE_ADDR + 0x108);                                                 
                                                                                                    
        /* ipu1_di_clk_x */                                                                         
        /* source */                                                                                
        reg = readl(CCM_BASE_ADDR + CLKCTL_CHSCCDR);                                                
        reg &= ~0xE07;                                                                              
        reg |= 0x803;                                                                               
        writel(reg, CCM_BASE_ADDR + CLKCTL_CHSCCDR);                                                
    #elif defined CONFIG_MX6DL /* CONFIG_MX6Q */                                                    
        /*                                                                                          
         * IPU1 HSP clock tree:                                                                     
         * osc_clk(24M)->pll3_usb_otg_main_clk(480M)->                                              
         * pll3_pfd_540M(540M)->ipu1_clk(270M)                                                      
         */                                                                                         
        /* pll3_usb_otg_main_clk */                                                                 
        /* divider */                                                                               
        writel(0x3, ANATOP_BASE_ADDR + 0x18);                                                       
                                                                                                    
        /* pll3_pfd_540M */                                                                         
        /* divider */                                                                               
        writel(0x3F << 8, ANATOP_BASE_ADDR + 0xF8);                                                 
        writel(0x10 << 8, ANATOP_BASE_ADDR + 0xF4);                                                 
        /* enable */                                                                                
        writel(0x1 << 15, ANATOP_BASE_ADDR + 0xF8);                                                 
                                                                                                    
        /* ipu1_clk */                                                                              
        reg = readl(CCM_BASE_ADDR + CLKCTL_CSCDR3);                                                 
        /* source */                                                                                
        reg |= (0x3 << 9);                                                                          
        /* divider */                                                                               
        reg &= ~(0x7 << 11);                                                                        
        reg |= (0x1 << 11);                                                                         
        writel(reg, CCM_BASE_ADDR + CLKCTL_CSCDR3);                                                 
                                                                                                    
        /*                                                                                          
         * ipu1_pixel_clk_x clock tree:                                                             
         * osc_clk(24M)->pll2_528_bus_main_clk(528M)->                                              
         * pll2_pfd_352M(452.57M)->ldb_dix_clk(64.65M)->                                            
         * ipu1_di_clk_x(64.65M)->ipu1_pixel_clk_x(64.65M)                                          
         */                                                                                         
        /* pll2_528_bus_main_clk */                                                                 
        /* divider */                                                                               
        writel(0x1, ANATOP_BASE_ADDR + 0x34);                                                       
                                                                                                    
        /* pll2_pfd_352M */                                                                         
        /* disable */                                                                               
        writel(0x1 << 7, ANATOP_BASE_ADDR + 0x104);                                                 
        /* divider */                                                                               
        writel(0x3F, ANATOP_BASE_ADDR + 0x108);                                                     
        writel(0x15, ANATOP_BASE_ADDR + 0x104);                                                     
                                                                                                    
        /* ldb_dix_clk */                                                                           
        /* source */                                                                                
        reg = readl(CCM_BASE_ADDR + CLKCTL_CS2CDR);                                                 
        reg &= ~(0x3F << 9);                                                                        
        reg |= (0x9 << 9);                                                                          
        writel(reg, CCM_BASE_ADDR + CLKCTL_CS2CDR);                                                 
        /* divider */                                                                               
        reg = readl(CCM_BASE_ADDR + CLKCTL_CSCMR2);                                                 
        reg |= (0x3 << 10);                                                                         
        writel(reg, CCM_BASE_ADDR + CLKCTL_CSCMR2);                                                 
                                                                                                    
        /* pll2_pfd_352M */                                                                         
        /* enable after ldb_dix_clk source is set */                                                
        writel(0x1 << 7, ANATOP_BASE_ADDR + 0x108);                                                 
                                                                                                    
        /* ipu1_di_clk_x */                                                                         
        /* source */                                                                                
        reg = readl(CCM_BASE_ADDR + CLKCTL_CHSCCDR);                                                
        reg &= ~0xE07;                                                                              
        reg |= 0x803;                                                                               
        writel(reg, CCM_BASE_ADDR + CLKCTL_CHSCCDR);                                                
    #endif    /* CONFIG_MX6DL */                                                                    
                                                                                                    
        /* Enable ipu1/ipu1_dix/ldb_dix clocks. */                                                  
        if (di == 1) {                                                                              
            reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR3);                                              
            reg |= 0xC033;                                                                          
            writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR3);                                              
        } else {                                                                                    
            reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR3);                                              
            reg |= 0x300F;                                                                          
            writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR3);                                              
        }                                                                                           
                                                                                                    
        /**                                                                                         
         * zengjf 2015-7-23 modify to 24bit or 16bit                                                
         *                                                                                          
         * #define IPU_PIX_FMT_BGR24   fourcc('B', 'G', 'R', '3')    /*< 24  BGR-8-8-8 */           
         * #define IPU_PIX_FMT_RGB24   fourcc('R', 'G', 'B', '3')    /*< 24  RGB-8-8-8 */           
         */                                                                                         
        //ret = ipuv3_fb_init(&lvds_xga, di, IPU_PIX_FMT_RGB666,                                    
        //ret = ipuv3_fb_init(&lvds_xga, di, IPU_PIX_FMT_RGB24,                                     
        ret = ipuv3_fb_init(&lvds_xga, di, IPU_PIX_FMT_RGB24,    ---------+                         
                DI_PCLK_LDB, 65000000);                                   |                         
        if (ret)                                                          |                         
            puts("LCD cannot be configured\n");                           |                         
                                                                          |                         
        /*                                                                |                         
         * LVDS0 mux to IPU1 DI0.                                         |                         
         * LVDS1 mux to IPU1 DI1.                                         |                         
         */                                                               |                         
        reg = readl(IOMUXC_BASE_ADDR + 0xC);                              |                         
        reg &= ~(0x000003C0);                                             |                         
        reg |= 0x00000100;                                                |                         
        writel(reg, IOMUXC_BASE_ADDR + 0xC);                              |                         
                                                                          |                         
        if (di == 1)                                                      |                         
            writel(0x40C, IOMUXC_BASE_ADDR + 0x8);                        |                         
        else                                                              |                         
            writel(0x201, IOMUXC_BASE_ADDR + 0x8);                        |                         
    }                                                                     |                         
    #endif                                                                |                         
                                                                          |                         
cat drivers/video/mxc_ipuv3_fb.c                                          V                         
    int ipuv3_fb_init(struct fb_videomode *mode, int di, int interface_pix_fmt,                     
              ipu_di_clk_parent_t di_clk_parent, int di_clk_val)          |                         
    {                                                                     |                         
        int ret;                                                          |                         
                                                                          |                         
        ret = ipu_probe(di, di_clk_parent, di_clk_val);                   |                         
        if (ret)                                                          |                         
            puts("Error initializing IPU\n");                             |                         
                                                                          |                         
        debug("Framebuffer at 0x%x\n", (unsigned int)lcd_base);           |                         
        ret = mxcfb_probe(interface_pix_fmt, mode, di);                   |                         
                                          |                               |                         
        return ret;                       |                               |                         
    }                                     +-------------------------------+                         
                                          |                                                         
cat drivers/video/mxc_ipuv3_fb.c          v                                                         
    static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode, int di)                
    {                                     |                                                         
        struct fb_info *fbi;              |                                                         
        struct mxcfb_info *mxcfbi;        |                                                         
        int ret = 0;                      |                                                         
                                          +----------------------------------+                      
        /*                                                                   |                      
         * Initialize FB structures                                          |                      
         */                                                                  |                      
        fbi = mxcfb_init_fbinfo();                                           |                      
        if (!fbi) {                                                          |                      
            ret = -ENOMEM;                                                   |                      
            goto err0;                                                       |                      
        }                                                                    |                      
        mxcfbi = (struct mxcfb_info *)fbi->par;                              |                      
                                                                             |                      
        if (!g_dp_in_use) {                                                  |                      
            mxcfbi->ipu_ch = MEM_BG_SYNC;                                    |                      
            mxcfbi->blank = FB_BLANK_UNBLANK;                                |                      
        } else {                                                             |                      
            mxcfbi->ipu_ch = MEM_DC_SYNC;                                    |                      
            mxcfbi->blank = FB_BLANK_POWERDOWN;                              |                      
        }                                                                    |                      
                                                                             |                      
        mxcfbi->ipu_di = di;                                                 |                      
                                                                             |                      
        ipu_disp_set_global_alpha(mxcfbi->ipu_ch, 1, 0x80);                  |                      
        ipu_disp_set_color_key(mxcfbi->ipu_ch, 0, 0);                        |                      
        strcpy(fbi->fix.id, "DISP3 BG");                                     |                      
                                                                             |                      
        g_dp_in_use = 1;                                                     |                      
                                                                             |                      
        mxcfb_info[mxcfbi->ipu_di] = fbi;                                    |                      
                                                                             |                      
        /* Need dummy values until real panel is configured */               |                      
        fbi->var.xres = 640;                                                 |                      
        fbi->var.yres = 480;                                                 |                      
        /**                                                                  |                      
         * zengjf 2015-8-23 modify to 24bit display, it can't work well      |                      
         */                                                                  |                      
        fbi->var.bits_per_pixel = 16;                                        |                      
        //fbi->var.bits_per_pixel = 24;                                      |                      
                                                                             |                      
        mxcfbi->ipu_di_pix_fmt = interface_pix_fmt;   <----------------------+                      
        fb_videomode_to_var(&fbi->var, mode);                                                       
                                                                                                    
        mxcfb_check_var(&fbi->var, fbi);                                                            
                                                                                                    
        /* Default Y virtual size is 2x panel size */                                               
        fbi->var.yres_virtual = fbi->var.yres * 2;                                                  
                                                                                                    
        mxcfb_set_fix(fbi);                                                                         
                                                                                                    
        /* alocate fb first */                                                                      
        if (mxcfb_map_video_memory(fbi) < 0)                                                        
            return -ENOMEM;                                                                         
                                                                                                    
        mxcfb_set_par(fbi);                  -------------------------------------+                 
                                                                                  |                 
        /* Setting panel_info for lcd */                                          |                 
        panel_info.vl_col = fbi->var.xres;                                        |                 
        panel_info.vl_row = fbi->var.yres;                                        |                 
        panel_info.vl_bpix = LCD_BPP;   // this same can't wake well   ---------+ |                 
                                                                                | |                 
        lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;  | |                 
                                                                                | |                 
        debug("MXC IPUV3 configured\n"                                          | |                 
            "XRES = %d YRES = %d BitsXpixel = %d\n",                            | |                 
            panel_info.vl_col,                                                  | |                 
            panel_info.vl_row,                                                  | |                 
            panel_info.vl_bpix);                                                | |                 
                                                                                | |                 
        ipu_dump_registers();                                                   | |                 
                                                                                | |                 
        return 0;                                                               | |                 
                                                                                | |                 
    err0:                                                                       | |                 
        return ret;                                                             | |                 
    }                                                                           | |                 
                                                                                | |                 
cat include/configs/mx6dl_sabresd.h                                             | |                 
    #define LCD_BPP        LCD_COLOR16           <------------------------------+ |                 
                                   |                                              |                 
cat include/lcd.h                  |                                              |                 
    #define LCD_MONOCHROME    0    +----------+                                   |                 
    #define LCD_COLOR2        1               |                                   |                 
    #define LCD_COLOR4        2               |                                   |                 
    #define LCD_COLOR8        3               |                                   |                 
    #define LCD_COLOR16       4    <----------+                                   |                 
                                                                                  |                 
cat drivers/video/mxc_ipuv3_fb.c                                                  |                 
    static int mxcfb_set_par(struct fb_info *fbi)          <----------------------+                 
    {                                                                                               
        int retval = 0;                                                                             
        u32 mem_len;                                                                                
        ipu_di_signal_cfg_t sig_cfg;                                                                
        struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;                                 
        uint32_t out_pixel_fmt;                                                                     
                                                                                                    
        ipu_disable_channel(mxc_fbi->ipu_ch);                                                       
        ipu_uninit_channel(mxc_fbi->ipu_ch);                                                        
        mxcfb_set_fix(fbi);                                                                         
                                                                                                    
        mem_len = fbi->var.yres_virtual * fbi->fix.line_length;                                     
        if (!fbi->fix.smem_start || (mem_len > fbi->fix.smem_len)) {                                
            if (fbi->fix.smem_start)                                                                
                mxcfb_unmap_video_memory(fbi);                                                      
                                                                                                    
            if (mxcfb_map_video_memory(fbi) < 0)                                                    
                return -ENOMEM;                                                                     
        }                                                                                           
                                                                                                    
        setup_disp_channel1(fbi);                                                                   
                                                                                                    
        memset(&sig_cfg, 0, sizeof(sig_cfg));                                                       
        if (fbi->var.vmode & FB_VMODE_INTERLACED) {                                                 
            sig_cfg.interlaced = 1;                                                                 
            out_pixel_fmt = IPU_PIX_FMT_YUV444;                                                     
        } else {                                                                                    
            if (mxc_fbi->ipu_di_pix_fmt) {                                                          
                out_pixel_fmt = mxc_fbi->ipu_di_pix_fmt;                                            
                debug(" zengjf1 %d. \n", out_pixel_fmt);                                            
            }                                                                                       
            else                                                                                    
            {                                                                                       
                out_pixel_fmt = IPU_PIX_FMT_RGB666;                                                 
                debug(" zengjf2 %d. \n", out_pixel_fmt);                                            
            }                                                                                       
        }                                                                                           
        if (fbi->var.vmode & FB_VMODE_ODD_FLD_FIRST) /* PAL */                                      
            sig_cfg.odd_field_first = 1;                                                            
        if ((fbi->var.sync & FB_SYNC_EXT) || ext_clk_used)                                          
            sig_cfg.ext_clk = 1;                                                                    
        if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT)                                                   
            sig_cfg.Hsync_pol = 1;                                                                  
        if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)                                                  
            sig_cfg.Vsync_pol = 1;                                                                  
        if (!(fbi->var.sync & FB_SYNC_CLK_LAT_FALL))                                                
            sig_cfg.clk_pol = 1;                                                                    
        if (fbi->var.sync & FB_SYNC_DATA_INVERT)                                                    
            sig_cfg.data_pol = 1;                                                                   
        if (!(fbi->var.sync & FB_SYNC_OE_LOW_ACT))                                                  
            sig_cfg.enable_pol = 1;                                                                 
        if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN)                                                    
            sig_cfg.clkidle_en = 1;                                                                 
                                                                                                    
        debug("zengjf pixclock = %d \n", fbi->var.pixclock);                                        
        debug("pixclock = %ul Hz\n", (u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL));                
        debug("bpp_to_pixfmt: %d\n", fbi->var.bits_per_pixel);                                      
                                                                                                    
        if (ipu_init_sync_panel(mxc_fbi->ipu_di,                                                    
                    (PICOS2KHZ(fbi->var.pixclock)) * 1000UL,                                        
                    fbi->var.xres, fbi->var.yres,                                                   
                    out_pixel_fmt,                                                                  
                    fbi->var.left_margin,                                                           
                    fbi->var.hsync_len,                                                             
                    fbi->var.right_margin,                                                          
                    fbi->var.upper_margin,                                                          
                    fbi->var.vsync_len,                                                             
                    fbi->var.lower_margin,                                                          
                    0, sig_cfg) != 0) {                                                             
            puts("mxcfb: Error initializing panel.\n");                                             
            return -EINVAL;                                                                         
        }                                                                                           
                                                                                                    
        retval = setup_disp_channel2(fbi);        --------------------+                             
        if (retval)                                                   |                             
            return retval;                                            |                             
                                                                      |                             
        if (mxc_fbi->blank == FB_BLANK_UNBLANK)                       |                             
            ipu_enable_channel(mxc_fbi->ipu_ch);                      |                             
                                                                      |                             
        return retval;                                                |                             
    }                                                                 |                             
                                                                      |                             
cat drivers/video/mxc_ipuv3_fb.c                                      |                             
    static int setup_disp_channel2(struct fb_info *fbi)    <----------+                             
    {                                                                                               
        int retval = 0;                                                                             
        struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;                                 
                                                                                                    
        mxc_fbi->cur_ipu_buf = 1;                                                                   
        if (mxc_fbi->alpha_chan_en)                                                                 
            mxc_fbi->cur_ipu_alpha_buf = 1;                                                         
                                                                                                    
        fbi->var.xoffset = fbi->var.yoffset = 0;                                                    
                                                                                                    
        debug("%s: ipu_ch{%x} xres{%d} yres{%d} line_length{%d} smem_start{%lx} smem_end{%lx}\n",   
            __func__,                                                                               
            mxc_fbi->ipu_ch,                                                                        
            fbi->var.xres,                                                                          
            fbi->var.yres,                                                                          
            fbi->fix.line_length,                                                                   
            fbi->fix.smem_start,                                                                    
            fbi->fix.smem_start +                                                                   
            (fbi->fix.line_length * fbi->var.yres));                                                
                                                                                                    
        retval = ipu_init_channel_buffer(mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,                         
                         bpp_to_pixfmt(fbi),               --------------------+                    
                         fbi->var.xres, fbi->var.yres,                         |                    
                         fbi->fix.line_length,                                 |                    
                         fbi->fix.smem_start +                                 |                    
                         (fbi->fix.line_length * fbi->var.yres),               |                    
                         fbi->fix.smem_start,                                  |                    
                         0, 0);                                                |                    
        if (retval)                                                            |                    
            printf("ipu_init_channel_buffer error %d\n", retval);              |                    
                                                                               |                    
        return retval;                                                         |                    
    }                                                                          |                    
                                                                               |                    
cat drivers/video/mxc_ipuv3_fb.c                                               |                    
    static uint32_t bpp_to_pixfmt(struct fb_info *fbi)     <-------------------+                    
    {                                                                                               
        uint32_t pixfmt = 0;                                                                        
                                                                                                    
        debug("bpp_to_pixfmt: %d\n", fbi->var.bits_per_pixel);                                      
                                                                                                    
        if (fbi->var.nonstd)                                                                        
            return fbi->var.nonstd;                                                                 
                                                                                                    
        switch (fbi->var.bits_per_pixel) {                                                          
        case 24:                                                                                    
            pixfmt = IPU_PIX_FMT_BGR24;                                                             
            break;                                                                                  
        case 32:                                                                                    
            pixfmt = IPU_PIX_FMT_BGR32;                                                             
            break;                                                                                  
        case 16:                                                                                    
            pixfmt = IPU_PIX_FMT_RGB565;                                                            
            break;                                                                                  
        }                                                                                           
        return pixfmt;                                                                              
    }