您的位置:首页 > 编程语言 > Go语言

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

2017-10-03 09:26 309 查看
本文转载自: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!\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的图片。具体的实现方式和平台相关,代码就不贴了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐