全志f1c100s(tina) linux-3.10 支持spi接口屏移植(2)

本文详细描述了如何在Tina系统的FBTFT驱动框架中实现开机logo的显示,涉及修改UBOOT源码、处理BMP图像数据并将其映射到内存,以便内核能正确显示。展示了从分区读取logo、映射内存到内核空间的过程。
摘要由CSDN通过智能技术生成

背景

		该章节主要讲述在fbtft驱动框架中加入开机logo

实现

		原理:在tina系统的基础上,在bootlogo分区里面去获取开机logo图片,在内核部分进行显示

修改:

		在fbtft-core.c中加入从分区显示的代码,该种显示方式需要用来tina系统uboot源码中去读取logo分区数据到物理内存中,方便内核部分去显示
		tina\lichee\linux-3.10\drivers\video\fbtft\fbtft-core.c
		#define P_LOGO 1
		
		#if P_LOGO
		phys_addr_t bootlogo_addr;
		int bootlogo_sz;
		
		struct bmp_color_table_entry {
			__u8	blue;
			__u8	green;
			__u8	red;
			__u8	reserved;
		} __packed;
		
		struct bmp_header {
			/* Header */
			char signature[2];
			__u32	file_size;
			__u32	reserved;
			__u32	data_offset;
			/* InfoHeader */
			__u32	size;
			__u32	width;
			__u32	height;
			__u16	planes;
			__u16	bit_count;
			__u32	compression;
			__u32	image_size;
			__u32	x_pixels_per_m;
			__u32	y_pixels_per_m;
			__u32	colors_used;
			__u32	colors_important;
			/* ColorTable */
		}  __packed;
		
		struct bmp_image {
			struct bmp_header header;
			/* We use a zero sized array just as a placeholder for variable
			   sized array */
			struct bmp_color_table_entry color_table[0];
		};
		struct sunxi_bmp_store_t {
			int x;
			int y;
			int bit;
			void *buffer;
		};
		
		static int __init bootlogo_parse(char *str)
		{
			char *endp;
		    printk("fb_base = %p\n",str);
			bootlogo_sz = SZ_2M;
			bootlogo_addr = memparse(str, &endp);
			if (*endp == '@') {
				bootlogo_sz = bootlogo_addr;
				bootlogo_addr = memparse(endp + 1, NULL);
			}
		
			return 0;
		}
		__setup("fb_base=", bootlogo_parse);
		
		void *Fb_map_kernel(unsigned long phys_addr, unsigned long size)
		{
			int npages = PAGE_ALIGN(size) / PAGE_SIZE;
			struct page **pages = vmalloc(sizeof(struct page *) * npages);
			struct page **tmp = pages;
			struct page *cur_page = phys_to_page(phys_addr);
			pgprot_t pgprot;
			void *vaddr;
			int i;
		
			if (!pages)
				return 0;
		
			for (i = 0; i < npages; i++)
				*(tmp++) = cur_page++;
		
			pgprot = pgprot_noncached(PAGE_KERNEL);
			vaddr = vmap(pages, npages, VM_MAP, pgprot);
		
			vfree(pages);
			return vaddr;
		}
		
		#if defined(CONFIG_ARCH_SUN3IW1P1)
		static void Fb_unmap_kernel(void *vaddr)
		{
			vunmap(vaddr);
		}
		
		static int Fb_map_kernel_logo(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) {
				printk("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) {
				printk("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')) {
				printk("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) {
				printk("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) {
				printk("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));
				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
		#endif

logo显示位置(在下面函数位置添加):

		int fbtft_register_framebuffer(struct fb_info *fb_info)
		{
		
				。。。。。
				ret = par->fbtftops.init_display(par);
				if (ret < 0)
					goto reg_fail;
				if (par->fbtftops.set_var) {
					ret = par->fbtftops.set_var(par);
					if (ret < 0)
						goto reg_fail;
				}
		
				/*logo 显示*/
		
				Fb_map_kernel_logo(fb_info);			/*加在此处*/
		
				/* update the entire display */
				par->fbtftops.update_display(par, 0, par->info->var.yres - 1);
				。。。。
				
		}

到这里功能已经实现了,可能单独看这篇文章有不懂很突兀,可以看一下我前面的博客,logo显示方式,另外也附上完整c文件:
linux(tina)系统内核驱动显示开机logo
全志f1c100s(tina) linux-3.10 支持spi接口屏移植(1)

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值