I.MX6 U-boot lvds display hacking

/***********************************************************************************
 *                    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;
    }                                                                                               

 

时间: 2024-10-30 15:07:38

I.MX6 U-boot lvds display hacking的相关文章

I.MX6 Linux I2C device&amp; driver hacking

/******************************************************************************************* * I.MX6 Linux I2C device& driver hacking * 声明: * 1. 本文主要是对Linux I2C驱动进行代码跟踪,主要是为了能够对I2C驱动框架有个全面的了解: * 2. 本文源代码来自myzr_android4_2_2_1_1_0.tar.bz2: * 3. 如果你有兴趣,

I.MX6 Linux kernel LVDS backlight enable

/*************************************************************************** * I.MX6 Linux kernel LVDS backlight enable * 说明: * 由于目前U-boot阶段屏出现反白的现象,所以在U-boot阶段关闭了背光,之前 * 尝试在板级文件中打开背光,但由于那个地方Linux LVDS驱动还没有工作,导致 * 反白的现象还是存在,仅仅是时间变短了,于是最后将enable信号放在驱动

I.MX6 ar1020 SPI device driver hacking

/************************************************************************************ * I.MX6 ar1020 SPI device driver hacking * 声明: * 1. 本文主要是解读I.MX6中ar1020 SPI设备注册,以及驱动调用流程: * 2. 本文主要使用了vim+ctags进行代码跟踪,所以几乎都是函数原型之间的调用: * * 2015-9-5 晴 深圳 南山平山村 曾剑锋 *

I.MX6 AD7606-4 device driver registe hacking

/********************************************************************** * I.MX6 AD7606-4 device driver registe hacking * 说明: * 看一下AD7606的驱动注册上是否存在一些问题. * * 2017-8-4 深圳 龙华樟坑村 曾剑锋 *********************************************************************/ /

I.MX6 PHY fixup 调用流程 hacking

/********************************************************************************** * I.MX6 PHY fixup 调用流程 hacking * 说明: * 跟一下i.MX6中对PHY进行fixup的代码是如何被调用的. * * 2017-4-14 深圳 龙华民治樟坑村 曾剑锋 ******************************************************************

I.MX6 Linux Serial Baud Rate hacking

/******************************************************************************** * I.MX6 Linux Serial Baud Rate hacking * 声明: * 1. 本文的源代码来自:myzr_android4_2_2_1_1_0.tar.bz2: * 2. 本文的目的是为了知道I.MX6串口支持的波特率有哪些,最大是多大, * 并加以验证,因为IMX6DQRM_revC.pdf数据手册上说能达到5

I.MX6 change boot partition 1 to User area

/************************************************************************************ * I.MX6 change boot partition 1 to User area * 说明: * 需要在eMMC中切换U-Boot所在的位置,看一下eMMC的驱动,测试一下效果. * * 2017-5-26 台湾 中和区 曾剑锋 *********************************************

I.MX6 lcd lvds hdmi bootargs

/********************************************************************* * I.MX6 lcd lvds hdmi bootargs * 声明: * 本文主要是记录I.MX6DL使用到的几种显示屏中的bootargs的参数设置. * * 2016-1-18 深圳 南山平山村 曾剑锋 ********************************************************************/ 一.参

LVDS/DVI/HDMI Interface

数字视频信号 以SXGA为例,其时序如下:      垂直:         水平:         图中DSPTMG为使能信号,VSYNC为场同步信号,HSYNC为行同步信号.在行场的消隐期(T1与T7),DSPTMG为低电平,在此期间无有效视频数据.         注意一个重要参数:对于这个时序的SXGA点频是108MHz 1066×1688×60=107.964480MHz   1 Open LVDS Display Interface(OpenLDI)          LVDS,即L