Uboot中支持lcd和hdmi显示不同的logo图片

在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!\n”);
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!\n”);
return -1;
}

filename = splash_image_select();
filename_hdmi =  CONFIG_SYS_VIDEO_LOGO_HDMI_NAME;
if (!filename) {
    printk("No splash image loaded\n");
    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\n");
    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\n");
    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\n");
    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!\n”);
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\n”,
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)!\n”);
}

    /*
     * 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\n",
               bmp_image);
        free(dst);
        return 1;
    }

#else
printf(“Error: no valid bmp image at %lx\n”, 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\n",
      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\n”,
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\n",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\n");
        break;
    }
    break;
default:
    printf("Error: %d bit/pixel bitmaps not supported by U-Boot\n",
        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的图片。具体的实现方式和平台相关,代码就不贴了。
————————————————
版权声明:本文为CSDN博主「xieshsh_8756」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u010865783/article/details/54953315

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值