[SPRD] Q 版本开机 logo 显示原理

195 阅读3分钟

基础知识

开机 logo 和充电 logo 资源位置

vendor\sprd\release\bmp\unisoc_bmp

根据你的编译选项使用对应 logo bmp

vendor\sprd\release\pac_config\sl9832e_1h10_64b.ini

BootLogo=1@./vendor/sprd/release/bmp/unisoc_bmp/samsung_720_1280_24bit.bmp

Fastboot_Logo=1@./vendor/sprd/release/bmp/unisoc_bmp/samsung_720_1280_24bit.bmp

编译后开机 logo 位置 vendor\sprd\release\IDH\sl9832e_1h10_64b_Natv-user\SHARKLE_9832e_64b_halo

代码流程

正常启动模式和 fastboot 启动模式

最终都是通过 lcd_splash(LOGO_PART); 进行绘制显示 logo

bsp\bootloader\u-boot\common\loader\boot_mode.c


void normal_mode(void)
{
#ifndef CONFIG_ZEBU
	vibrator_hw_init();

	set_vibrator(1);
	vlx_nand_boot(BOOT_PART, BACKLIGHT_ON, LCD_ON);
#else
	vlx_nand_boot_zebu(BOOT_PART, BACKLIGHT_ON, LCD_ON);
#endif
	return;
}


void fastboot_mode(void)
{
	debugf("enter\n");
#ifdef CONFIG_SPLASH_SCREEN
extern int drv_lcd_init (void);
	debug("[LCD] Drawing the logo...\n");
	drv_lcd_init();
	lcd_splash(LOGO_PART);
	lcd_enable();

	vibrator_hw_init();
	set_vibrator(1);

	extern void set_backlight(uint32_t value);
	fastboot_lcd_printf();
	set_backlight(BACKLIGHT_ON);
	mdelay(400);
	set_vibrator(0);
#endif
	
#if (defined CONFIG_X86) && (defined CONFIG_MOBILEVISOR) && (defined CONFIG_SPRD_SOC_SP9853I)
	tos_start_notify();
#endif
#ifdef CONFIG_SECBOOT
	if (get_lock_status() == VBOOT_STATUS_UNLOCK){
		debugf("INFO: LOCK FLAG IS : UNLOCK!!!\n");
		lcd_printf("\n   INFO: LOCK FLAG IS : UNLOCK!!!\n");
	}
	get_secboot_base_from_dt();
#endif

	do_fastboot();

	return;
}

BOOT_PART 其实就是 logo 字符串,搜索找到定义位于

bsp\bootloader\u-boot\include\loader_common.h

#define SPL_PART "spl"
#define LOGO_PART "logo"
#define CHARGER_LOGO_PART "chargelogo"
#define BOOT_PART "boot"
#define RECOVERY_PART "recovery"
#define FACTORY_PART "prodnv"
#define PRODUCTINFO_FILE_PATITION  "miscdata"
#define DT_PART "dt"

继续跟进正常启动模式下,vlx_nand_boot(BOOT_PART, BACKLIGHT_ON, LCD_ON);

bsp\bootloader\u-boot\common\loader\loader_nvm.c

uint32_t uboot_start_time;
void vlx_nand_boot(char *kernel_pname, int backlight_set, int lcd_enable)
{
	boot_img_hdr *hdr = (void *)raw_header;
	char *mode_ptr = NULL;
	uchar *partition = NULL;
	int i = 0;
	int j = 0;
	int ret = 0;
	uchar *dt_adr = DT_ADR;
	uint32_t lcd_init_time;
	uint32_t backlight_on_time;
	uint32_t uboot_consume_time;

#ifdef CONFIG_SOC_IWHALE2
	aon_lpc_config();
#endif
	wakeup_source_enable();
	ap_clk_doze_enable();

#ifdef CONFIG_SPLASH_SCREEN
	lcd_init_time = SCI_GetTickCount();
	printf("lcd start init time:%dms\n", lcd_init_time);
	if(lcd_enable) {
		extern void lcd_enable(void);
		debug("[LCD] Drawing the logo...\n");
		drv_lcd_init();
		lcd_splash(LOGO_PART);
		lcd_enable();
	}
........

再来看看 lcd_splash(LOGO_PART) 干了啥

bsp\bootloader\u-boot\common\splash.c

int lcd_splash(uchar *logo_part_name)
{
	int x = 0, y = 0, ret;
	u8 *addr;
	u8 *s;

	s = getenv("splashimage");
	if (!s) {
		debugf("%s: failed to get env from splashimage\n");
		return -1;
	}
	addr = (u8 *) simple_strtoul(s, NULL, 16);

	ret = splash_screen_prepare(logo_part_name, addr);
	if (ret)
		return ret;

	splash_get_pos(&x, &y);

	return bmp_display(addr, x, y);
}

logo_part_name 值可能是 "logo 或 "chargelogo",还有显示充电logo的时候

从指定分区中读取出 logo bmp存储地址 addr

其实就是 bmp_image

bsp\bootloader\u-boot\common\cmd_bmp.c

int bmp_display(ulong addr, int x, int y)
{
	int ret;
	struct bmp_image *bmp = (struct bmp_image *)addr;
	void *bmp_alloc_addr = NULL;
	unsigned long len;

	if (!((bmp->header.signature[0]=='B') &&
	      (bmp->header.signature[1]=='M')))
		bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr);

	if (!bmp) {
		printf("There is no valid bmp file at the given address\n");
		return 1;
	}

#if defined(CONFIG_LCD)
	ret = lcd_display_bitmap((ulong)bmp, x, y);
#elif defined(CONFIG_VIDEO)
	ret = video_display_bitmap((unsigned long)bmp, x, y);
#else
# error bmp_display() requires CONFIG_LCD or CONFIG_VIDEO
#endif

	if (bmp_alloc_addr)
		free(bmp_alloc_addr);

	return ret;
}

最终在 lcd 中绘制 logo

bsp\bootloader\u-boot\common\lcd.c


int lcd_display_bitmap(ulong bmp_image, int x, int y)
{
	u8 bmp_bpix;
	u16 width, height, bmp_width, fb_width, hdr_size;
	u32 colors;
	u8 *fb, *bmap, *bmap8;
	u16 *fb16, *bmap16, *cmap_base = NULL;
	u32 *fb32;
	rgb24_t *bmap24;
	rgb32_t *bmap32;
	struct bmp_image *bmp = (struct bmp_image *)map_sysmem(bmp_image, 0);
	struct bmp_color_table_entry *palette = bmp->color_table;

	.....
	
	switch (bmp_bpix) {
	case 1:
	case 8:
		cmap_base = configuration_get_cmap();
#ifdef CONFIG_LCD_BMP_RLE8
		u32 compression = get_unaligned_le32(&bmp->header.compression);
		debug("compressed %d %d\n", compression, BMP_BI_RLE8);
		if (compression == BMP_BI_RLE8) {
			lcd_display_rle8_bitmap(bmp, cmap_base, fb, x, y);
			break;
		}
#endif
		if (cmap_base)
			BMP_TO_FB(fb16, u16, bmap8, u8, PIXEL8_TO_INT16, cmap_base);
		else
			BMP_TO_FB(fb16, u16, bmap8, u8, PIXEL16_TO_INT16, palette);
		break;
	case 16:
		BMP_TO_FB(fb16, u16, bmap16, u16, RGB16_TO_INT16);
		break;
	case 24:
		BMP_TO_FB(fb32, u32, bmap24, rgb24_t, RGB24_TO_INT32);
		break;
	case 32:
		BMP_TO_FB(fb32, u32, bmap32, rgb32_t, RGB32_TO_INT32);
		break;
	default:
		break;
	};

	lcd_sync();
	return 0;
}