在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) { 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)); } }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);}實現了上面的內容之后,接下來需要在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的圖片。具體的實現方式和平臺相關,代碼就不貼了。
新聞熱點
疑難解答