imx6 uboot lcd

本文记录imx6 uboot中关于lcd初始化的过程。

uboot中相关的文件:

  cpu/arm_cortexa8/start.S

  lib_arm/board.c

  board/freescale/mx6q_sabresd/mx6q_sabresd.c

  common/stdio.c

  common/lcd.c

  drivers/video/ipu_common.c

/* 汇编调用C语言 */
./cpu/arm_cortexa8/start.S:

ldr    pc, _start_armboot    @ jump to C code         ------+
                                                            |
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);                     |
                                                                                  |
                                                                                  |
    stdio_init ();    /* get the devices list going. */     ------------------+   |
                                                                              |   |
    jumptable_init ();                                                        |   |
                                                                              |   |
    ......                                                                    |   |
                                                                              |   |
    for (;;) {                                                                |   |
        main_loop ();                                                         |   |
    }                                                                         |   |
                                                                              |   |
    /* NOTREACHED - no way out of command loop except booting */              |   |
}                                                                             |   |
                                                                              |   |
init_fnc_t *init_sequence[] = {                                       <-------|---+
#if defined(CONFIG_ARCH_CPU_INIT)                                             |
    arch_cpu_init,        /* basic arch cpu dependent setup */                |
#endif                                                                        |
    board_init,        /* basic board dependent setup */     -------------+   |
#if defined(CONFIG_USE_IRQ)                                               |   |
    interrupt_init,        /* set up exceptions */                        |   |
#endif                                                                    |   |
    timer_init,        /* initialize timer */                             |   |
    env_init,        /* initialize environment */                         |   |
    init_baudrate,        /* initialze baudrate settings */               |   |
    serial_init,        /* serial communications setup */                 |   |
    console_init_f,        /* stage 1 init of console */                  |   |
    display_banner,        /* say that we are here */                     |   |
#if defined(CONFIG_DISPLAY_CPUINFO)                                       |   |
    print_cpuinfo,        /* display cpu info (and speed) */              |   |
#endif                                                                    |   |
#if defined(CONFIG_DISPLAY_BOARDINFO)                                     |   |
    checkboard,        /* display board info */                           |   |
#endif                                                                    |   |
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)                  |   |
    init_func_i2c,                                                        |   |
#endif                                                                    |   |
    dram_init,        /* configure available RAM banks */                 |   |
#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)                       |   |
    arm_pci_init,                                                         |   |
#endif                                                                    |   |
    display_dram_config,                                                  |   |
    NULL,                                                                 |   |
};                                                                        |   |
                                                                          |   |
board/freescale/mx6q_sabresd/mx6q_sabresd.c                               |   |
int board_init(void)                                   <------------------+   |
{                                                                             |
/* need set Power Supply Glitch to 0x41736166                                 |
*and need clear Power supply Glitch Detect bit                                |
* when POR or reboot or power on Otherwise system                             |
*could not be power off anymore*/                                             |
    u32 reg;                                                                  |
    writel(0x41736166, SNVS_BASE_ADDR + 0x64);/*set LPPGDR*/                  |
    udelay(10);                                                               |
    reg = readl(SNVS_BASE_ADDR + 0x4c);                                       |
    reg |= (1 << 3);                                                          |
    writel(reg, SNVS_BASE_ADDR + 0x4c);/*clear LPSR*/                         |
                                                                              |
    mxc_iomux_v3_init((void *)IOMUXC_BASE_ADDR);                              |
    setup_boot_device();                                                      |
    fsl_set_system_rev();                                                     |
                                                                              |
    /* board id for linux */                                                  |
    gd->bd->bi_arch_number = MACH_TYPE_MX6Q_SABRESD;                          |
                                                                              |
    /* address of boot parameters */                                          |
    gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;                            |
                                                                              |
    setup_uart();                                                             |
#ifdef CONFIG_DWC_AHSATA                                                      |
    if (cpu_is_mx6q())                                                        |
        setup_sata();                                                         |
#endif                                                                        |
                                                                              |
#ifdef CONFIG_VIDEO_MX5                                                       |
    /* Enable lvds power */                                                   |
#ifdef UBOOT_SHOW_LOGO                                                        |
    setup_lvds_poweron();                                                     |
#endif                                                                        |
    panel_info_init();                                                        |
                                                                              |
    gd->fb_base = CONFIG_FB_BASE;                                             |
#ifdef CONFIG_ARCH_MMU                                                        |
    gd->fb_base = ioremap_nocache(iomem_to_phys(gd->fb_base), 0);             |
#endif                                                                        |
#endif                                                                        |
                                                                              |
#ifdef CONFIG_NAND_GPMI                                                       |
//    setup_gpmi_nand();                                                      |
#endif                                                                        |
                                                                              |
#if defined(CONFIG_ENET_RMII) && !defined(CONFIG_DWC_AHSATA)                  |
    setup_fec();                                                              |
#endif                                                                        |
                                                                              |
#ifdef CONFIG_MXC_EPDC                                                        |
    setup_epdc();                                                             |
#endif                                                                        |
    return 0;                                                                 |
}                                                                             |
                                                                              |
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);                                               |
}                                                             |
                                                              |
common/lcd.c                                                  |
int drv_lcd_init (void)               <-----------------------+
{
    struct stdio_dev lcddev;
    int rc;
    //framebuffer基地址
    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);    //将lcd设备添加到uboot的设备链表中                 |
                                                                                         |
    return (rc == 0) ? 1 : rc;                                                           |
}                                                                                        |
                                                                                         |
#define    NBITS(type)    (sizeof(type) * 8)                                             |
                                                                                         |
board/freescale/mx6q_sabresd/mx6q_sabresd.c                                              |
vidinfo_t panel_info = {                                                                 |
    .vl_refresh = 85,                                                                    |
    .vl_col = 800,                                                                       |
    .vl_row = 600,                                                                       |
    .vl_pixclock = 26666667,                                                             |
    .vl_left_margin = 8,                                                                 |
    .vl_right_margin = 100,                                                              |
    .vl_upper_margin = 4,                                                                |
    .vl_lower_margin = 8,                                                                |
    .vl_hsync = 4,                                                                       |
    .vl_vsync = 1,                                                                       |
    .vl_sync = 0,                                                                        |
    .vl_mode = 0,                                                                        |
    .vl_flag = 0,                                                                        |
    .vl_bpix = 3,                                                                        |
    cmap:0,                                                                              |
};                                                                                       |
typedef struct vidinfo {                                                                 |
    ushort    vl_col;        /* Number of columns (i.e. 640) */                          |
    ushort    vl_row;        /* Number of rows (i.e. 480) */                             |
    ushort    vl_width;    /* Width of display area in millimeters */                    |
    ushort    vl_height;    /* Height of display area in millimeters */                  |
                                                                                         |
    /* LCD configuration register */                                                     |
    u_char    vl_clkp;    /* Clock polarity */                                           |
    u_char    vl_oep;        /* Output Enable polarity */                                |
    u_char    vl_hsp;        /* Horizontal Sync polarity */                              |
    u_char    vl_vsp;        /* Vertical Sync polarity */                                |
    u_char    vl_dp;        /* Data polarity */                                          |
    u_char    vl_bpix;    /* Bits per pixel, 0 = 1, 1 = 2, 2 = 4, 3 = 8, 4 = 16 */       |
    u_char    vl_lbw;        /* LCD Bus width, 0 = 4, 1 = 8 */                           |
    u_char    vl_splt;    /* Split display, 0 = single-scan, 1 = dual-scan */            |
    u_char    vl_clor;    /* Color, 0 = mono, 1 = color */                               |
    u_char    vl_tft;        /* 0 = passive, 1 = TFT */                                  |
                                                                                         |
    /* Horizontal control register. Timing from data sheet */                            |
    ushort    vl_hpw;        /* Horz sync pulse width */                                 |
    u_char    vl_blw;        /* Wait before of line */                                   |
    u_char    vl_elw;        /* Wait end of line */                                      |
                                                                                         |
    /* Vertical control register. */                                                     |
    u_char    vl_vpw;        /* Vertical sync pulse width */                             |
    u_char    vl_bfw;        /* Wait before of frame */                                  |
    u_char    vl_efw;        /* Wait end of frame */                                     |
                                                                                         |
    /* PXA LCD controller params */                                                      |
    struct    pxafb_info pxa;                                                            |
} vidinfo_t;                                                                             |
                                                                                         |
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;                                                                      |    |
}                                                                                  |    |
                                                                                   |    |
void lcd_ctrl_init(void *lcdbase)                                                  |    |
{                                                                                  |    |
    //计算要使用的framebuffer大小 col*row*bpp/8 字节                               |    |
    u32 mem_len = panel_info.vl_col *                                              |    |
        panel_info.vl_row *                                                        |    |
        NBITS(panel_info.vl_bpix) / 8;                                             |    |
                                                                                   |    |
    /*                                                                             |    |
     * We rely on lcdbase being a physical address, i.e., either MMU off,          |    |
     * or 1-to-1 mapping. Might want to add some virt2phys here.                   |    |
     */                                                                            |    |
    if (!lcdbase)                                                                  |    |
        return;                                                                    |    |
    //将framebuffer清0                                                             |    |
    memset(lcdbase, 0, mem_len);                                                   |    |
}                                                                                  |    |
                                                                                   |    |
common/lcd.c                                                                       |    |
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);                                        |                                |
}                                                      |                                |
//显示logo                                             |                                |
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, 地址转为16进制                                        |
        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                                                                                  |
                                                                                        |
        //显示logo,根据x,y坐标                                                          |
        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 */                  |          |
}                                                                            |          |
                                                                             |          |
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                                                                                  |
                                                                                        |
#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                                                                                  |
                                                                                        |
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;

#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
    imx_pwm_config(pwm0, 25000, 50000);
    imx_pwm_enable(pwm0);

    mxc_iomux_v3_setup_pad(MX6DL_PAD_SD1_DAT2__GPIO_1_19);
    reg = readl(GPIO1_BASE_ADDR + GPIO_GDIR);
    reg |= (1 << 19);
    writel(reg, GPIO1_BASE_ADDR + GPIO_GDIR);

    reg = readl(GPIO1_BASE_ADDR + GPIO_DR);
#ifdef UBOOT_SHOW_LOGO
    reg |= (1 << 19);
#else
    reg &= ~(1 << 19);
#endif
    writel(reg, GPIO1_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);

#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 */
    // 20C_403C
    reg = readl(CCM_BASE_ADDR + CLKCTL_CSCDR3);
    /* source */
    //ipu1_hsp_clk_sel
    reg |= (0x3 << 9);
    /* divider */
    reg &= ~(0x7 << 11);
    reg |= (0x1 << 11);
    //540M/2 = 270M
    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 */
    writel(0x1, ANATOP_BASE_ADDR + 0x34);

    /* pll2_pfd_352M */
    writel(0x1 << 7, ANATOP_BASE_ADDR + 0x104);
    /* divider */
    writel(0x3F, ANATOP_BASE_ADDR + 0x108);
    //This field controls the fractional divide value. The resulting frequency shall be 480*18/PFD0_FRAC where
    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);
    }
    ret = ipuv3_fb_init(&lvds_xga, di, IPU_PIX_FMT_RGB666, DI_PCLK_LDB, 65000000); //18 bit -----+
    //ret = ipuv3_fb_init(&lvds_xga, di, IPU_PIX_FMT_RGB24, DI_PCLK_LDB, 65000000);  //24 bit    |
                                                      |            |                             |
    if (ret)                                          |            |                             |
        puts("LCD cannot be configured \n");          +--------------------+                     |
                                                                   |       |                     |
#ifdef I2C_GPIO_EEPROM_PROCESS        //WRITE process              |       |                     |
            //write singal byte                                    |       |                     |
#if 1                                                              |       |                     |
        {                                                          |       |                     |
            Load_config_from_mmc();                                |       |                     |
        }                                                          |       |                     |
#endif                                                             |       |                     |
#endif                                                             |       |                     |
                                                                   |       |                     |
    /*                                                             |       |                     |
     * LVDS0 mux to IPU1 DI0.                                      |       |                     |
     * LVDS1 mux to IPU1 DI1.                                      |       |                     |
     */                                                            |       |                     |
#ifdef UBOOT_SHOW_LOGO                                             |       |                     |
    reg = readl(IOMUXC_BASE_ADDR + 0xC);                           |       |                     |
    reg &= ~(0x000003C0);                                          |       |                     |
    reg |= 0x00000100;                                             |       |                     |
    writel(reg, IOMUXC_BASE_ADDR + 0xC);                           |       |                     |
#endif                                                             |       |                     |
    if (di == 1)                                                   |       |                     |
    {                                                              |       |                     |
        writel(0x40C, IOMUXC_BASE_ADDR + 0x8);//18BIT              |       |                     |
        //writel(0x48C, IOMUXC_BASE_ADDR + 0x8);//24BIT            |       |                     |
    }                                                              |       |                     |
    else                                                           |       |                     |
    {                                                              |       |                     |
        writel(0x201, IOMUXC_BASE_ADDR + 0x8);//18BIT              |       |                     |
        //writel(0x221, IOMUXC_BASE_ADDR + 0x8);//24BIT            |       |                     |
    }                                                              |       |                     |
    ......                                                         |       |
}                                                                  |       |                     |
#endif                                                             |       |                     |
                                                                   |       |                     |
                                                                   |       |                     |
include/ipu.h                                                      |       |                     |
typedef enum {                                                     |       |                     |
    DI_PCLK_PLL3,                                                  |       |                     |
    DI_PCLK_LDB,                               <-------------------+       |                     |
    DI_PCLK_TVE                                                            |                     |
} ipu_di_clk_parent_t;                                                     |                     |
                                                                           V                     |
#define IPU_PIX_FMT_RGB666  fourcc('R', 'G', 'B', '6')    /*< 18  RGB-6-6-6    */                |
#define IPU_PIX_FMT_RGB24   fourcc('R', 'G', 'B', '3')    /*< 24  RGB-8-8-8    */                |
                                                                                                 |
#define fourcc(a, b, c, d)\                                                                      |
    (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))                          |
                                                                                                 |
drivers/video/mxc_ipuv3_fb.c                                                                     |
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;                                                                            |   |
}                                                                                          |   |
                                                                                           |   |
drivers/video/ipu_common.c                                                                 |   |
int ipu_probe(int di, ipu_di_clk_parent_t di_clk_parent, int di_clk_val)          <--------+   |
{                                                                                              |
    unsigned long ipu_base;                                                                    |
                                                                                               |
#if defined(CONFIG_MXC_HSC)                                                                    |
    u32 temp;                                                                                  |
    u32 *reg_hsc_mcd = (u32 *)MIPI_HSC_BASE_ADDR;                                              |
    u32 *reg_hsc_mxt_conf = (u32 *)(MIPI_HSC_BASE_ADDR + 0x800);                               |
                                                                                               |
     __raw_writel(0xF00, reg_hsc_mcd);                                                         |
                                                                                               |
    /* CSI mode reserved*/                                                                     |
    temp = __raw_readl(reg_hsc_mxt_conf);                                                      |
     __raw_writel(temp | 0x0FF, reg_hsc_mxt_conf);                                             |
                                                                                               |
    temp = __raw_readl(reg_hsc_mxt_conf);                                                      |
    __raw_writel(temp | 0x10000, reg_hsc_mxt_conf);                                            |
#endif                                                                                         |
                                                                                               |
    ipu_base = IPU_CTRL_BASE_ADDR;                                                             |
    /* base fixup */                                                                           |
    if (g_ipu_hw_rev == IPUV3_HW_REV_IPUV3H)    /* IPUv3H */                                   |
        ipu_base += IPUV3H_REG_BASE;                                                           |
    else if (g_ipu_hw_rev == IPUV3_HW_REV_IPUV3M)    /* IPUv3M */                              |
        ipu_base += IPUV3M_REG_BASE;                                                           |
    else            /* IPUv3D, v3E, v3EX */                                                    |
        ipu_base += IPUV3DEX_REG_BASE;                                                         |
    ipu_cpmem_base = (u32 *)(ipu_base + IPU_CPMEM_REG_BASE);                                   |
    ipu_dc_tmpl_reg = (u32 *)(ipu_base + IPU_DC_TMPL_REG_BASE);                                |
                                                                                               |
    g_pixel_clk[0] = &pixel_clk[0];                                                            |
    g_pixel_clk[1] = &pixel_clk[1];                                                            |
                                                                                               |
    g_di_clk[0] = &di_clk[0];                                                                  |
    g_di_clk[1] = &di_clk[1];                                                                  |
    g_di_clk[di]->rate = di_clk_val;                                                           |
                                                                                               |
    g_ipu_clk = &ipu_clk;                                                                      |
    debug("ipu_clk = %u\n", clk_get_rate(g_ipu_clk));                                          |
                                                                                               |
    ipu_reset();                                                                               |
                                                                                               |
    if (di_clk_parent == DI_PCLK_LDB) {                                                        |
        clk_set_parent(g_pixel_clk[di], g_di_clk[di]);                                         |
    } else {                                                                                   |
        clk_set_parent(g_pixel_clk[0], g_ipu_clk);                                             |
        clk_set_parent(g_pixel_clk[1], g_ipu_clk);                                             |
    }                                                                                          |
                                                                                               |
    clk_enable(g_ipu_clk);                                                                     |
                                                                                               |
    __raw_writel(0x807FFFFF, IPU_MEM_RST);                                                     |
    while (__raw_readl(IPU_MEM_RST) & 0x80000000)                                              |
        ;                                                                                      |
                                                                                               |
    ipu_init_dc_mappings();                                                                    |
                                                                                               |
    __raw_writel(0, IPU_INT_CTRL(5));                                                          |
    __raw_writel(0, IPU_INT_CTRL(6));                                                          |
    __raw_writel(0, IPU_INT_CTRL(9));                                                          |
    __raw_writel(0, IPU_INT_CTRL(10));                                                         |
                                                                                               |
    /* DMFC Init */                                                                            |
    ipu_dmfc_init(DMFC_NORMAL, 1);                                                             |
                                                                                               |
    /* Set sync refresh channels as high priority */                                           |
    __raw_writel(0x18800000L, IDMAC_CHA_PRI(0));                                               |
                                                                                               |
    /* Set MCU_T to divide MCU access window into 2 */                                         |
    __raw_writel(0x00400000L | (IPU_MCU_T_DEFAULT << 18), IPU_DISP_GEN);                       |
                                                                                               |
    clk_disable(g_ipu_clk);                                                                    |
                                                                                               |
    return 0;                                                                                  |
}                                                                                              |
                                                                                               |
/*                                                                                             |
 * Probe routine for the framebuffer driver. It is called during the                           |
 * driver binding process.      The following functions are performed in                       |
 * this routine: Framebuffer initialization, Memory allocation and                             |
 * mapping, Framebuffer registration, IPU initialization.                                      |
 *                                                                                             |
 * @return      Appropriate error code to the kernel common code                               |
 */                                                                                            |
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;

    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;

    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;
}
Author

Tony Liu

2016-8-23, Shenzhen

posted @ 2016-08-23 13:19  SuperTao1024  阅读(2325)  评论(0编辑  收藏  举报