1. 程式人生 > 其它 >spi-lcd-st7789-驅動開發-驅動新增framebuf介面(4)

spi-lcd-st7789-驅動開發-驅動新增framebuf介面(4)

技術標籤:linux核心驅動程式

Linux framebuf 介紹

https://blog.csdn.net/xpy123/article/details/46484291

Framebuf 介面新增

參照核心自帶的skeletonfb.c 修改,下面介紹下我自己主要修改的地方:

將framebuf介面單獨在一個檔案中實現 lcd_st7789_fb.c

spi介面的lcd沒有專門的lcd控制器將framebuf視訊記憶體資料直接傳送到spilcd,所以實際的資料部分我放在一個

核心執行緒來做,負責傳送framebuf 視訊記憶體資料的核心執行緒如下:

static int lcd_st7789_fb_send_data_thread_fn(void * data)
 {	 
	 struct fb_info *info = platform_get_drvdata(lcd_st7789_plat_dev);
	 MY_PRINT("Start");
	 while (1){ 
		wait_event_interruptible(send_fb_data_wq, 1 == send_data_flag || 1 == quit_thread_flag);
		if (send_data_flag) {
		//	MY_PRINT("");
			//printk(KERN_WARNING "t1\n");
	 		LCD_Show_Image(0, 0, info->var.width, info->var.height, info->fix.smem_start);
			//printk(KERN_WARNING "t2\n");
			send_data_flag = 0;
		} else { //quit thread
			MY_PRINT("Quit Send Fb Data thread!");
			break;
		}
	 }
	 MY_PRINT("End");
	 return 0;
	 
 }

這個執行緒主要作用是等待一個喚醒訊號,倍喚醒後直接姐那個frambbufe視訊記憶體資料傳送到spilcd.

哪裡喚醒這個視訊記憶體資料傳送執行緒呢?

只要有更新視訊記憶體的函式,都會喚醒它。比如下面幾個函式:

static ssize_t lcd_st7789_fb_sys_write(struct fb_info *info, const char __user *buf,
			 size_t count, loff_t *ppos)
{
	//呼叫底層函式實際傳送資料到 st7789 內部 graphic ram
	ssize_t write_bytes;

	mutex_lock(&mutex_lock_viedeo_memmory);

	if (count > videomemorysize) {
		count = videomemorysize;
	}
	
	write_bytes = fb_sys_write(info, buf, count, ppos);

	send_data_flag = 1;
	wake_up_interruptible(&send_fb_data_wq); //通知執行緒更新lcd資料

	mutex_unlock(&mutex_lock_viedeo_memmory);

	return write_bytes;
}

//用一種顏色填充矩形區域
//除了呼叫sys_fillrect 還要呼叫底層函式LCD_Fill 通過spi介面將是資料傳送到st7789 內部 graphic ram
static void lcd_st7789_fb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
{
	mutex_lock(&mutex_lock_viedeo_memmory);
	
	//1 更新本地快取中資料
	sys_fillrect(p, rect);
	
	send_data_flag = 1;
	wake_up_interruptible(&send_fb_data_wq); //通知執行緒更新lcd資料
	
	mutex_unlock(&mutex_lock_viedeo_memmory);
	
}

//
void lcd_st7789_fb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
{

	mutex_lock(&mutex_lock_viedeo_memmory); //通知執行緒更新lcd資料

	//1 更新本地快取中資料
	sys_copyarea(p, area);

	send_data_flag = 1;	
	wake_up_interruptible(&send_fb_data_wq); //通知執行緒更新lcd資料

	mutex_unlock(&mutex_lock_viedeo_memmory); //通知執行緒更新lcd資料
	
}


static void lcd_st7789_fb_imageblit(struct fb_info *p, const struct fb_image *image)
{
	
	mutex_lock(&mutex_lock_viedeo_memmory); //通知執行緒更新lcd資料

	if (image->depth != 16) {
		printk("Color depth only support 16, invalid depth:%d!!", image->depth);
		return;
	}
	
	//1 更新本地快取中資料
	sys_imageblit(p, image);

	send_data_flag = 1;	
	wake_up_interruptible(&send_fb_data_wq); //通知執行緒更新lcd資料

	mutex_lock(&mutex_lock_viedeo_memmory); //通知執行緒更新lcd資料
}

對於通過cpu的lcd控制器自動傳送rgb訊號的lcd顯示屏來說,一般不需要專門的執行緒來發送視訊記憶體資料,上面對應的介面只要更新視訊記憶體資料就行,視訊記憶體資料傳送到lcd的任務由lcd控制器的硬體自動完成了。

其它關於framebuf的一些處理直接看程式碼就可以了,處理都是模式化的步驟,沒啥特別的。