linux(tina)系统内核驱动显示开机logo

引入

目前本文讲述的的实现开机logo显示方式有两种:

	1.uboot加载读取logo分区图片数据到物理内存中,然后内核部分进行显示。
	2.在驱动中将图片转化为c数组元素进行显示

第一种:数组元素显示

  1. 将bmp图片转化成数组元素,可以借助工具进行转化,转化配置如下图:
    图一
    注意上述几个标注位置,分辨率、不要包含图形头部数据、图片的像素位,这些要根据自己屏幕的配置进行选择,我这边目前使用的是spi接口16bit 565的屏幕,所以配置如上。
    转化的数组如下:
    logo图片数组

  2. 关键lcd驱动logo代码显示部分

    #if BOOTLOGO
      memcpy(fbi->screen_base, bootlogo_240x320,240*320* 2);
    #endif
    
    该部分代码主要是将logo图片的像素数据直接传入frambuffer的显示虚拟地址内,可以等同于将图形数据写入屏幕内,上面的各项参数根据自己屏幕去对应配置,对应于我的屏幕如下:第一个参数是frambuffer的虚拟地址,也就是现存地址,2 代表logo数组名,3,代码要复制的字节数。
    

    上述代码中有已经写好的代码;

第二种:从logo分区加载开机logo,方便后期应用层更换开机logo

1.自定义logo分区,并预置logo图片文件到分区内
	由于我现在使用的全志的tina系统:
	新增logo分区如下:
	tina\device\config\chips\c200s\configs\F1C200s\linux\sys_partition.fex :
	![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/652039a7c90844b999fb95b1bbf1933c.png)

2.uboot部分读取logo分区到物理内存:
在这里插入图片描述
3.内核部分进行显示
在这里插入图片描述
内核部分能获取到uboot存储的logo图片数据关键在这个函数内,上述三个标注解释如下:
1.指定logo的大小2M
2.函数作用:将具有mem后缀的字符串解析成数字
可参考链接:https://blog.csdn.net/sheng__jun/article/details/78125126

3.__setup()的作用:将bootargs参数的fb_base的值传给 bootlogo_parse 函数 str参数,也就是将图片的存储地址传过来,这样这两者就联系起来了,图片数据获取到了,接下来的就是图片的显示了,因为当前是使用的是bmp图片,所以显示图片的代码如下:
static int Fb_map_kernel_logo(__u32 sel, struct fb_info *info)
{
	void *vaddr = NULL;
	unsigned int paddr =  0;
	void *screen_offset = NULL, *image_offset = NULL;
	char *tmp_buffer = NULL;
	char *bmp_data = NULL;
	struct sunxi_bmp_store_t s_bmp_info;
	struct sunxi_bmp_store_t *bmp_info = &s_bmp_info;
	struct bmp_image *bmp = NULL;
	int zero_num = 0;
	unsigned long x, y, bmp_bpix, fb_width, fb_height;
	unsigned int effective_width, effective_height;
	unsigned int offset;
	int i = 0;

	paddr = bootlogo_addr;
	if (0 == paddr) {
		__wrn("Fb_map_kernel_logo failed!");
		return -1;
	}

	/* parser bmp header */
	offset = paddr & ~PAGE_MASK;

	vaddr = (void *)Fb_map_kernel(paddr, sizeof(struct bmp_header));
	if (0 == vaddr) {
		__wrn("fb_map_kernel failed, paddr=0x%x,size=0x%x\n", paddr,
			sizeof(struct bmp_header));
		return -1;
	}
	/* parser bmp header */
	offset = paddr & ~PAGE_MASK;
	vaddr = (void *)Fb_map_kernel(paddr, sizeof(struct bmp_header));
	if (0 == vaddr) {
		__wrn("fb_map_kernel failed, paddr=0x%x,size=0x%x\n", paddr,
			sizeof(struct bmp_header));
		return -1;
	}
	bmp = (struct bmp_image *)vaddr + offset;
	if ((bmp->header.signature[0] != 'B') ||
		(bmp->header.signature[1] != 'M')) {
		__wrn("this is not a bmp picture\n");
		return -1;
	}

	bmp_bpix = bmp->header.bit_count / 8;

	if ((bmp_bpix != 2) && (bmp_bpix != 3) && (bmp_bpix != 4))
		return -1;

	if (bmp_bpix == 3)
		zero_num = (4 - ((3*bmp->header.width) % 4))&3;

	x = bmp->header.width;
	y = (bmp->header.height & 0x80000000) ? (-bmp->header.height)
		: (bmp->header.height);
	fb_width = info->var.xres;
	fb_height = info->var.yres;
	if ((paddr <= 0) || x <= 1 || y <= 1) {
		__wrn("kernel logo para error!\n");
		return -EINVAL;
	}

	bmp_info->x = x;
	bmp_info->y = y;
	bmp_info->bit = bmp->header.bit_count;
	bmp_info->buffer = (void *)(info->screen_base);

	if (bmp_bpix == 3)
		info->var.bits_per_pixel = 24;
	else if (bmp_bpix == 4)
		info->var.bits_per_pixel = 32;
	else if (bmp_bpix == 2)
		info->var.bits_per_pixel = 16;
	else
		info->var.bits_per_pixel = 32;

	Fb_unmap_kernel(vaddr);

	/* map the total bmp buffer */
	vaddr = (void *)Fb_map_kernel(paddr,
	x * y * bmp_bpix + sizeof(struct bmp_header));
	if (0 == vaddr) {
		__wrn("fb_map_kernel failed, paddr=0x%x,size=0x%x\n", paddr,
			(unsigned int)(x * y
			* bmp_bpix + sizeof(struct bmp_header)));
		return -1;
	}

	bmp = (struct bmp_image *)vaddr + offset;

	tmp_buffer = (char *)bmp_info->buffer;
	screen_offset = (void *)bmp_info->buffer;
	bmp_data = (char *)(vaddr + bmp->header.data_offset);
	image_offset = (void *)bmp_data;
	effective_width = (fb_width < x) ? fb_width : x;
	effective_height = (fb_height < y) ? fb_height : y;
	
	if (bmp->header.height & 0x80000000) {
		if (fb_width > x) {
			screen_offset = (void *)((u32)info->screen_base
			+ (fb_width * (abs(fb_height - y) / 2)
			+ abs(fb_width - x) / 2)
			* (info->var.bits_per_pixel >> 3));
		} else if (fb_width < x) {
				image_offset = (void *)((u32)bmp_data
					+ (x * ((y - fb_height) / 2)
					+ (x - fb_width) / 2)
					* (info->var.bits_per_pixel >> 3));
		}
		for (i = 0; i < effective_height; i++) {
			memcpy((void *)screen_offset, image_offset,
				effective_width
				*(info->var.bits_per_pixel >> 3));
			screen_offset = (void *)((u32)screen_offset
				+ fb_width*(info->var.bits_per_pixel >> 3));
			image_offset = (void *)image_offset
				+ x * (info->var.bits_per_pixel >> 3);
		}
	} else {
	  screen_offset = (void *)((u32)info->screen_base
			+(fb_width * (abs(fb_height - y) / 2)
			+ abs(fb_width - x) / 2)
			* (info->var.bits_per_pixel >> 3));
		image_offset = (void *)((u32)image_offset
			+ (x * (abs(y - fb_height) / 2)
			+ abs(x - fb_width) / 2)
			* (info->var.bits_per_pixel >> 3));
#if 0

		if (3 == bmp_bpix) {
			unsigned char *ptemp = NULL;
			unsigned char temp = 0;
			int h = 0;
			ptemp = (char *)image_offset;

			for (h = 0; h < effective_height; h++) {
				for (i = 0;
				i <= effective_width
					* (info->var.bits_per_pixel >> 3) - 3;
				i += 3) {
					temp = ptemp[i];
					ptemp[i] = ptemp[i+1];
					ptemp[i+1] = temp;
				}
				ptemp = (char *)((void *)bmp_data
					+ h * x
					* (info->var.bits_per_pixel >> 3));
			}
		}
#endif

	image_offset = (void *)bmp_data
		+ (effective_height-1)
		* x *  (info->var.bits_per_pixel >> 3);
		for (i = effective_height-1; i >= 0; i--) {
			memcpy((void *)screen_offset, image_offset,
				effective_width
				*(info->var.bits_per_pixel >> 3));
			screen_offset = (void *)((u32)screen_offset
				+ fb_width*(info->var.bits_per_pixel >> 3));
			image_offset = (void *)bmp_data
				+ i * x *  (info->var.bits_per_pixel >> 3);
		}
	}

	Fb_unmap_kernel(vaddr);
	return 0;
}
#endif

整个显示流程就是上述,具体实现见完整代码:

  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值