zoukankan      html  css  js  c++  java
  • Uboot中支持lcd和hdmi显示不同的logo图片【转】

    本文转载自:http://blog.csdn.net/u010865783/article/details/54953315

    在lcd为竖屏,hdmi显示横屏的情况下,如果按照默认的uboot显示框架来看,只能保证lcd或者hdmi上面显示出来的图片一个是正的,另外一个是旋转了90度的样子。 
    为了能是lcd和hdmi同时支持显示图片都是正的,需要对uboot的框架做修改。如果硬件支持旋转功能的话,就可直接使用硬件旋转,不需要软件来调整。 
    由于项目原因,折腾了一把这个流程,具体实现记录下: 
    1:由于硬件不支持rotation功能,在软件上采用的方法是准备两份logo资源,解析后将两份数据送到不同的显示设备上面做显示。 
    在解析logo的时候需要解析两份资源:

    static int splash_image_load(void)
    {
        int ret;
        char *filename,*filename_hdmi;
        void *splash_image_addr,*splash_image_hdmi_addr;
        char splash_image_char[16], splash_image_hdmi_char[16];
        //分配给lcd资源的地址
        splash_image_addr = memalign(128, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE);
        if(splash_image_addr == NULL) {
            printk("Malloc size for splash image failed!
    ");
            return -1;
        }
        //分配给hdmi资源logo的地址
        splash_image_hdmi_addr = memalign(128, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE);
        if(splash_image_hdmi_addr == NULL) {
            printk("Malloc size for splash image hdmi failed!
    ");
            return -1;
        }
    
        filename = splash_image_select();
        filename_hdmi =  CONFIG_SYS_VIDEO_LOGO_HDMI_NAME;
        if (!filename) {
            printk("No splash image loaded
    ");
            return -1;
        }
        //拿到lcd的logo
        ret = file_fat_read(filename, splash_image_addr, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE);
    
        if(ret < 0) {
            printk("Fail to load splash image
    ");
            free(splash_image_addr);
            return -1;
        }   
        //拿到hdmi的logo
        ret = file_fat_read(filename_hdmi, splash_image_hdmi_addr, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE);
        if(ret < 0) {
            printk("Fail to load splash  hdmi image
    ");
            free(splash_image_hdmi_addr);
            return -1;
        }   
        sprintf(splash_image_char, "%x", (unsigned int) splash_image_addr);
        sprintf(splash_image_hdmi_char, "%x", (unsigned int) splash_image_hdmi_addr);
        //将解析到的地址保存到env中,后续需要再读取出来
        setenv("splashimage", splash_image_char);
        setenv("splashimagehdmi", splash_image_hdmi_char);
        return 0;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    2:添加对hdmi驱动中的支持和在cfb_console.c中添加解析图片的支持

    static int video_init(void)
    {
        unsigned char color8;
    
        pGD = video_hw_init();
        if (pGD == NULL)
            return -1;
        //获取驱动中的hdmi的fb的信息video_hw_hdmi_init在fb的驱动中实现
        pGD_HDMI = video_hw_hdmi_init();
        if (pGD_HDMI == NULL)
            return -1;
            ...
    }
    
    static void *video_logo(void)
    {
        char info[128];
        int space, len;
        __maybe_unused int y_off = 0;
        __maybe_unused ulong addr;
        __maybe_unused char *s,*s_hdmi;
    
        splash_get_pos(&video_logo_xpos, &video_logo_ypos);
    
        //splash_get_pos(&video_logo_xpos, &video_logo_ypos);
        video_hdmi_logo_xpos = BMP_ALIGN_CENTER; //init xpos and ypos
        video_hdmi_logo_ypos = BMP_ALIGN_CENTER;
    
    
    #ifdef CONFIG_SPLASH_SCREEN
        //从env中拿到lcd和hdmi图片的地址
        s = getenv("splashimage");
        s_hdmi = getenv("splashimagehdmi");
    
        if (s != NULL) {
            splash_screen_prepare();
            addr = simple_strtoul(s, NULL, 16);
            //解析lcd的logo资源成送显的数据
            if (video_display_bitmap(addr,
                        video_logo_xpos,
                        video_logo_ypos) == 0) {
                video_logo_height = 0;
                //return ((void *) (video_fb_address));
            }
        }
    
        if (s_hdmi != NULL) {
            //printf("xieshsh debug video display
    ");
            splash_screen_prepare();
            addr = simple_strtoul(s_hdmi, NULL, 16);
        //解析lcd的hdmi资源成送显的数据
            if (video_display_hdmi_bitmap(addr,
                        video_hdmi_logo_xpos,
                        video_hdmi_logo_ypos) == 0) {
                video_hdmi_logo_ypos = 0;
                return ((void *) (video_fb_address));
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    3:接下来需要对添加对hdmi logo的解析成fb的数据

    int video_display_hdmi_bitmap(ulong bmp_image, int x, int y)
    {
        ushort xcount, ycount;
        uchar *fb;
        bmp_image_t *bmp = (bmp_image_t *) bmp_image;
        uchar *bmap;
        ushort padded_line;
        unsigned long width, height, bpp;
        unsigned colors;
        unsigned long compression;
        bmp_color_table_entry_t cte;
    
    #ifdef CONFIG_VIDEO_BMP_GZIP
        unsigned char *dst = NULL;
        ulong len;
    #endif
    
        WATCHDOG_RESET();
    
        if (!((bmp->header.signature[0] == 'B') &&
              (bmp->header.signature[1] == 'M'))) {
    
    #ifdef CONFIG_VIDEO_BMP_GZIP
            /*
             * Could be a gzipped bmp image, try to decrompress...
             */
            len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE;
            dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE);
            if (dst == NULL) {
                printf("Error: malloc in gunzip failed!
    ");
                return 1;
            }
            /*
             * NB: we need to force offset of +2
             * See doc/README.displaying-bmps
             */
            if (gunzip(dst+2, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE-2,
                   (uchar *) bmp_image,
                   &len) != 0) {
                printf("Error: no valid bmp or bmp.gz image at %lx
    ",
                       bmp_image);
                free(dst);
                return 1;
            }
            if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE) {
                printf("Image could be truncated "
                    "(increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!
    ");
            }
    
            /*
             * Set addr to decompressed image
             */
            bmp = (bmp_image_t *)(dst+2);
    
            if (!((bmp->header.signature[0] == 'B') &&
                  (bmp->header.signature[1] == 'M'))) {
                printf("Error: no valid bmp.gz image at %lx
    ",
                       bmp_image);
                free(dst);
                return 1;
            }
    #else
            printf("Error: no valid bmp image at %lx
    ", bmp_image);
            return 1;
    #endif /* CONFIG_VIDEO_BMP_GZIP */
        }
    
        width = le32_to_cpu(bmp->header.width);
        height = le32_to_cpu(bmp->header.height);
        bpp = le16_to_cpu(bmp->header.bit_count);
        colors = le32_to_cpu(bmp->header.colors_used);
        compression = le32_to_cpu(bmp->header.compression);
    
        debug("Display-bmp: %ld x %ld  with %d colors
    ",
              width, height, colors);
    
        if (compression != BMP_BI_RGB
    #ifdef CONFIG_VIDEO_BMP_RLE8
            && compression != BMP_BI_RLE8
    #endif
            ) {
            printf("Error: compression type %ld not supported
    ",
                   compression);
    #ifdef CONFIG_VIDEO_BMP_GZIP
            if (dst)
                free(dst);
    #endif
            return 1;
        }
    
        padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3;
    #ifdef CONFIG_SPLASH_SCREEN_ALIGN
        if (x == BMP_ALIGN_CENTER){
            x = max(0, (int)(VIDEO_HDMI_VISIBLE_COLS - width) / 2);
            printf("VVVVVVVVx=%d",x);
        }
        else if (x < 0)
            x = max(0, (int)(VIDEO_HDMI_VISIBLE_COLS - width + x + 1));
    
        if (y == BMP_ALIGN_CENTER)
            y = max(0, (int)(VIDEO_HDMI_VISIBLE_ROWS - height) / 2);
        else if (y < 0)
            y = max(0, (int)(VIDEO_HDMI_VISIBLE_ROWS - height + y + 1));
    #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
    
        /*
         * Just ignore elements which are completely beyond screen
         * dimensions.
         */
    
        if ((x >= VIDEO_HDMI_VISIBLE_COLS) || (y >= VIDEO_HDMI_VISIBLE_ROWS))
            return 0;
    
        if ((x + width) > VIDEO_HDMI_VISIBLE_COLS)
            width = VIDEO_HDMI_VISIBLE_COLS - x;
        if ((y + height) > VIDEO_HDMI_VISIBLE_ROWS)
            height = VIDEO_HDMI_VISIBLE_ROWS - y;
    
        bmap = (uchar *) bmp + le32_to_cpu(bmp->header.data_offset);
        fb = (uchar *) (video_hdmi_fb_address +
                ((y + height - 1) * VIDEO_HDMI_VISIBLE_COLS * VIDEO_HDMI_PIXEL_SIZE) +
                x * VIDEO_HDMI_PIXEL_SIZE);
    
        /* We handle only 4, 8, or 24 bpp bitmaps */
    
        switch (le16_to_cpu(bmp->header.bit_count)) {
    
        case 24:
            padded_line -= 3 * width;
            ycount = height;
            //printf("xiessh----VIDEO_DATA_FORMAT = %d
    ",VIDEO_HDMI_DATA_FORMAT);
            switch (VIDEO_HDMI_DATA_FORMAT) {
            case GDF_32BIT_X888RGB:
                while (ycount--) {
                    WATCHDOG_RESET();
                    xcount = width;
                    while (xcount--) {
                        FILL_32BIT_X888RGB(bmap[2], bmap[1],
                                   bmap[0]);
                        bmap += 3;
                    }
                    bmap += padded_line;
                    fb -= (VIDEO_HDMI_VISIBLE_COLS + width) *
                                VIDEO_PIXEL_SIZE;
                }
                break;
    
            default:
                printf("Error: 24 bits/pixel bitmap incompatible "
                    "with current video mode
    ");
                break;
            }
            break;
        default:
            printf("Error: %d bit/pixel bitmaps not supported by U-Boot
    ",
                le16_to_cpu(bmp->header.bit_count));
            break;
        }
    
    #ifdef CONFIG_VIDEO_BMP_GZIP
        if (dst) {
            free(dst);
        }
    #endif
    
        if (cfb_do_flush_cache)
            flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
        return (0);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169

    实现了上面的内容之后,接下来需要在uboot的fb中做好映射,主要是将fb0对应的logo的资源送到lcd、fb1对应的logo资源送到hdmi显示,具体的代码和平台相关。

    这样造成的影响是会使uboot阶段显示的内存增加一倍,之前只用了一个图片,现在用到了两个图片,所以内存会增加一倍。

    当android系统起来的时候,因为lcd是竖屏,lcd上面的内容旋转了90度当成了横屏模式在使用,hdmi是横屏,会造成android动画的前半段在hdmi上面显示的android字样变成了垂直显示,知道android的display的java服务启动之后,android的显示系统识别到了hdmi设备,系统才显示正常。

    对于这种情况,hdmi的前半段的异常显示,由于硬件无法rotation,只能采取一个规避的方式解决,将开机启动的logo一直保存到android上层的显示系统识别到hdmi后,才释放boot logo的资源,在这个之前,一直都显示logo的图片。具体的实现方式和平台相关,代码就不贴了。

  • 相关阅读:
    spring requestbody json
    idea 配置自动编译 livereload
    idea hibernate console 执行hql报错
    查找最小的破坏连续性的数字
    xcopy忽略文件 7zip打包
    window 批处理脚本获取上级目录
    substring c# js java
    R语言中使用多重聚合预测算法(MAPA)进行时间序列分析
    R语言使用最优聚类簇数k-medoids聚类进行客户细分
    R语言中的岭回归、套索回归、主成分回归:线性模型选择和正则化
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/7623263.html
Copyright © 2011-2022 走看看