?? lcd_drv.c
字號:
#include <linux/kernel.h>#include <linux/init.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/delay.h>#include <linux/slab.h>#include <asm/fcntl.h>#include <asm/unistd.h>#include <asm/io.h>#include <asm/uaccess.h>#include "ep7312_sys.h"#include "lcd_struct.h"// ioctl 命令ID#define LCD_Clear 0#define LCD_Draw_Pixel 1#define LCD_Draw_VLine 2#define LCD_Draw_HLine 3#define LCD_Draw_Rectangle 4#define LCD_Draw_Buf 5#define LCD_Write_EN 10#define LCD_Write_CN 11#define LCD_Save_SCR 12#define LCD_Load_SCR 13#define LCD_Release_SCR 14// 定義LCD的主設備號#define DEV_MAJOR 60// 定義LCD顯示模式參數//#define SCR_X 160 /* LCD屏幕寬度 *///#define SCR_Y 160 /* LCD屏幕高度 */#define SCR_X 320 /* LCD屏幕寬度 */#define SCR_Y 240 /* LCD屏幕高度 *///#define BPP 32 /* LCD顯示模式 *///#define BPP 16 /* LCD顯示模式 *///#define BPP 24 /* LCD顯示模式 *///#define BPP 8 /* LCD顯示模式 */#define BPP 4 /* LCD顯示模式 *///#define BPP 2 /* LCD顯示模式 *///#define BPP 1 /* LCD顯示模式 */// 半字節復制標志#define LowS 0 /* 取字節低四位標志 */#define HighS 1 /* 取字節高四位標志 */// LCD顯示緩存的基址static unsigned char * __lcd_base;/* 設置LCD寄存器 */static void setup_lcd(void){ // 禁用LCD設備 SYSCON1 &= ~0x00001000; // 設置LCD控制寄存器 // 顯示緩存容量[0:12] : 320 * 240 * 12 / (8*16) = 0x1c1f // 線長度[13:18] : 320 / 16 - 1 = 0x13 // 像素預定標[19:24] : 0x01 // AC預定標[25:29] : 0x13 // 灰度使能[30] : = 1, 使用灰度級顯示 // 灰度級模式[31] : = 1, 4 bpp模式(16灰度級) //LCDCON = 0xe60f7c1f;// LCDCON = 0xe60a7c1f; //320*720 //LCDCON =0xe60a6257; //320x240x1// LCDCON =0xe60920c8; //160x160x1// LCDCON =0xe60a64af; //320x240x2 LCDCON =0xe60a695f; //320x240x4 //LCDCON =0xe60a72bf; //320x240x8// LCDCON =0xe60a72bf; //320x240x16/(8*32) // LCDCON =0xe60a7c1f; //320x240x24/(8*32)// LCDCON =0xe60a72bf; //320x240x32/(8*64) // 設置調色板顏色寄存器的低位和高位有效字 PALLSW = 0x76543210; /* 低位有效字 */ PALMSW = 0xfedcba98; /* 高位有效字 */ // 設置LCD顯示緩沖區在系統存儲區域的起始位置 FBADDR = 0xc; // 啟用LCD設備 SYSCON1 |= 0x00001000; return;}// 限制橫坐標范圍// 使橫坐標在0至SCR_X之間static int xFormat(int x){ int fx; fx = x; fx = (fx < 0) ? 0 : fx; fx = (fx >= SCR_X) ? (SCR_X - 1) : fx; return fx;}// 限制縱坐標范圍// 使縱坐標在0至SCR_Y之間static int yFormat(int y){ int fy; fy = y; fy = (fy < 0) ? 0 : fy; fy = (fy >= SCR_Y) ? (SCR_Y - 1) : fy; return fy;}// 釋放保存屏幕緩沖區static void lcd_kernel_release_screen(struct save_struct * buffer){ if ((*buffer).save_buf != NULL) { // 釋放緩沖區 kfree((*buffer).save_buf); // 恢復緩沖區初始化設置 (*buffer).save_buf = NULL; (*buffer).save_w = (*buffer).save_h = 0; }}// 保存屏幕部分區域的內容static void lcd_kernel_save_screen(int x1, int y1, int x2, int y2, struct save_struct * buffer){ unsigned char * fb_lptr; /* 每行第一個點的顯存地址 */ unsigned char bufferByte; /* 臨時緩存字節 */ long buffer_size; /* 保存屏幕緩沖區的字節數 */ int factorCount; /* 每行需要存取的半字節的個數 */ int sb_sign, fb_sign; /* 半字節復制標志, = LowS: 復制低四位, = HighS: 復制高四位*/ int p_sb; /* 保存屏幕緩沖區指針偏移量 */ int p_fb; /* 顯示緩沖區指針偏移量 */ int currLine; /* 當前行的縱坐標 */ int tmp, i; // 修正保存范圍坐標, 使其在屏幕的顯示范圍之內 x1 = xFormat(x1); x2 = xFormat(x2); y1 = yFormat(y1); y2 = yFormat(y2); // 修正保存范圍的橫坐標, 使x2值永遠大于x1的值 if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; } // 修正保存范圍的縱坐標, 使y2值永遠大于y1的值 if (y1 > y2) { tmp = y1; y1 = y2; y2 = tmp; } // 計算新保存的屏幕的寬度和高度 (*buffer).save_w = x2 - x1 + 1; (*buffer).save_h = y2 - y1 + 1; // 計算新緩沖區大小 buffer_size = (*buffer).save_w * (*buffer).save_h * 3 * BPP / 8 + 1; // 申請新的屏幕緩沖區 (*buffer).save_buf = kmalloc(buffer_size, GFP_KERNEL); // 初始化保存屏幕半字節復制標志 sb_sign = LowS; // 計算每行中半字節的個數 factorCount = (*buffer).save_w * 3; // 初始化屏幕緩沖區指針偏移量 p_sb = 0; // 復制顯存的內容到保存屏幕緩沖區中 for (currLine = y1; currLine <= y2; currLine++) { // 計算當前行第一個點的顯存地址 fb_lptr = __lcd_base + (x1 + currLine * SCR_X) * 3 * BPP / 8; // 初始化顯存半字節復制標志 fb_sign = (x1 & 0x1); // 初始化顯示緩沖區指針偏移量 p_fb = 0; // 復制顯存當前行的內容 for (i = 0; i < factorCount; i++) { // 臨時緩沖字節清零 bufferByte &= 0x00; // 根據顯存半字節復制標志, 將顯存中當前字節的內容的低四位(或高四位) // 復制到臨時緩沖字節的低四位中 if (fb_sign == LowS) bufferByte = (fb_lptr[p_fb] & 0x0f); else bufferByte = (fb_lptr[p_fb] & 0xf0) >> 4; // 根據保存屏幕緩沖區半字節復制標志, // 對保存屏幕緩沖區當前字節中相應的四位清零; // 如果是要復制高四位的內容, // 還要將臨時緩沖字節的低四位內容移到高四位中 if (sb_sign == HighS) { (*buffer).save_buf[p_sb] &= 0x0f; bufferByte = bufferByte << 4; } else (*buffer).save_buf[p_sb] &= 0xf0; // 用臨時緩沖字節更新保存屏幕緩沖區的當前字節 (*buffer).save_buf[p_sb] |= bufferByte; // 根據半字節復制標志, 設置相應的指針偏移量 if (fb_sign == HighS) p_fb++; if (sb_sign == HighS) p_sb++; // 更新半字節復制標志 sb_sign ^= 0x1; fb_sign ^= 0x1; } }}// 加載屏幕部分區域的內容static void lcd_kernel_load_screen(int x1, int y1, struct save_struct buffer){ unsigned char * fb_lptr; /* 每行第一個點的顯存地址 */ unsigned char bufferByte; /* 臨時緩存字節 */ int factorCount; /* 每行需要存取的半字節的個數 */ int sb_sign, fb_sign; /* 半字節復制標志, = LowS: 復制低四位, = HighS: 復制高四位*/ int p_sb; /* 保存屏幕緩沖區指針偏移量 */ int p_fb; /* 顯示緩沖區指針偏移量 */ int x2, y2; /* 加載區域右下角的坐標 */ int currLine; /* 當前行的縱坐標 */ int i; // 修正加載范圍坐標, 使其在屏幕的顯示范圍之內 x1 = xFormat(x1); y1 = xFormat(y1); // 計算加載范圍右下角的坐標 x2 = x1 + buffer.save_w - 1; y2 = y1 + buffer.save_h - 1; // 如果加載范圍超出屏幕的顯示范圍 // 則不作任何操作返回 if (x2 >= SCR_X || y2 >= SCR_Y) { printk(KERN_INFO "Load position out of screen boundary!\n"); return; } // 如果尚未執行保存屏幕的操作, // 則不作任何操作返回 if (buffer.save_buf == NULL) { printk(KERN_INFO "No Saved Screen!\n"); return; } // 初始化保存屏幕半字節復制標志 sb_sign = LowS; // 計算每行中半字節的個數 factorCount = buffer.save_w * 3; // 初始化屏幕緩沖區指針偏移量 p_sb = 0; // 加載保存屏幕緩沖區的內容到顯存中 for (currLine = y1; currLine <= y2; currLine++) { // 計算當前行第一個點的顯存地址 fb_lptr = __lcd_base + (x1 + currLine * SCR_X) * 3 * BPP / 8; // 初始化顯存半字節復制標志 fb_sign = (x1 & 0x1); // 初始化顯示緩沖區指針偏移量 p_fb = 0; // 加載當行的內容到顯存中 for (i = 0; i < factorCount; i++) { // 臨時緩沖字節清零 bufferByte &= 0x00; // 根據保存屏幕半字節復制標志, 將保存屏幕緩沖區中 // 當前字節的內容的低四位(或高四位) // 復制到臨時緩沖字節的低四位中 if (sb_sign == LowS) bufferByte = (buffer.save_buf[p_sb] & 0x0f); else bufferByte = (buffer.save_buf[p_sb] & 0xf0) >> 4; // 根據顯存半字節復制標志, // 對顯存當前字節中相應的四位清零; // 如果是要復制高四位的內容, // 還要將臨時緩沖字節的低四位內容移到高四位中 if (fb_sign == HighS) { fb_lptr[p_fb] &= 0x0f; bufferByte = bufferByte << 4; } else fb_lptr[p_fb] &= 0xf0; // 用臨時緩沖字節更新顯存內容 fb_lptr[p_fb] |= bufferByte; // 根據半字節復制標志, 設置相應的指針偏移量 if (fb_sign == HighS) p_fb++; if (sb_sign == HighS) p_sb++; // 更新半字節復制標志 sb_sign ^= 0x1; fb_sign ^= 0x1; } }}// 繪制一個像素點static void lcd_kernel_pixel(int x, int y, COLOR color){ unsigned char* fb_ptr; /* 更新像素點對應的顯存地址 */ unsigned short* fb_ptr_halfword; unsigned int* fb_ptr_word; unsigned int pointeraddr; //COLOR pure_color=0x0000; unsigned char pure_color_byte = 0x00; /* 更新顏色信息 */ unsigned short pure_color_halfword = 0x0000; unsigned int pure_color_word = 0x00000000; // 如果坐標越界則不做任何操作, 直接返回 if ( x < 0 || x >= SCR_X|| y < 0 || y >= SCR_Y) { printk("out of bounds\n"); return; } // 計算當前點對應的顯存地址 //fb_ptr = __lcd_base + (x + y * SCR_X) * 3 * BPP / 8; fb_ptr = __lcd_base + (x + y * SCR_X) * 1 * BPP / 8; //by ywc 4bpp,8bpp fb_ptr_halfword = (unsigned short *)(__lcd_base + (x + y * SCR_X) * 1 * BPP / 8);//by ywc pointeraddr = (((unsigned int )(__lcd_base + (x + y * SCR_X) * 1 * BPP / 8)));//by ywc fb_ptr_word =(unsigned int *)(pointeraddr&~0x3); //fb_ptr_word =__lcd_base + (x + y * SCR_X) * 1 * BPP / (8); switch (BPP) { case 1: switch(x & 0x07){ case 0: pure_color_byte = (color & 0x01 ) <<0; // add by ywc *(fb_ptr) &= 0xfe; *(fb_ptr) |= pure_color_byte; break; case 1: pure_color_byte = (color & 0x01 ) <<1; // add by ywc *(fb_ptr) &= 0xfd; *(fb_ptr) |= pure_color_byte; break; case 2: pure_color_byte = (color & 0x01 ) <<2; // add by ywc *(fb_ptr) &= 0xfb; *(fb_ptr) |= pure_color_byte; break; case 3: pure_color_byte = (color & 0x01 ) <<3; // add by ywc *(fb_ptr) &= 0xf7; *(fb_ptr) |= pure_color_byte; break; case 4: pure_color_byte = (color & 0x01 ) <<4; // add by ywc *(fb_ptr) &= 0xef; *(fb_ptr) |= pure_color_byte; break; case 5: pure_color_byte = (color & 0x01 ) <<5; // add by ywc *(fb_ptr) &= 0xdf; *(fb_ptr) |= pure_color_byte; break; case 6: pure_color_byte = (color & 0x01 ) <<6; // add by ywc *(fb_ptr) &= 0xbf; *(fb_ptr) |= pure_color_byte; break; case 7: pure_color_byte = (color & 0x01 ) <<7; // add by ywc *(fb_ptr) &= 0x7f; *(fb_ptr) |= pure_color_byte; break; } break; case 2: switch(x & 0x03){ case 0: pure_color_byte = (color & 0x03 ) <<0; // add by ywc *(fb_ptr) &= 0xfc; *(fb_ptr) |= pure_color_byte; break; case 1: pure_color_byte = (color & 0x03 ) <<2; // add by ywc *(fb_ptr) &= 0xf3; *(fb_ptr) |= pure_color_byte; break; case 2: pure_color_byte = (color & 0x03 ) <<4; // add by ywc *(fb_ptr) &= 0xcf; *(fb_ptr) |= pure_color_byte; break; case 3: pure_color_byte = (color & 0x03 ) <<6; // add by ywc *(fb_ptr) &= 0x3f; *(fb_ptr) |= pure_color_byte; break; } break; case 4: if (x & 0x1) { pure_color_byte = (color & 0x0f) << 4; // add by ywc *fb_ptr &= 0x0f; *fb_ptr |= pure_color_byte; } else { pure_color_byte = ( color & 0x0f ); // add by ywc *(fb_ptr) &= 0xf0; *(fb_ptr) |= pure_color_byte; } break; case 8: pure_color_byte = ( color & 0xff); // why not ? by ywc *(fb_ptr) = pure_color_byte; break; case 15: break; case 16: pure_color_halfword = ( color & 0xffff); // why not ? by ywc if(y==212)printk("color=%8x,fb_ptr_halfword=%p\n",color,fb_ptr_halfword); *(fb_ptr_halfword) = pure_color_halfword; break; /* case 24: printk("color=%8x,fb_ptr_word=%p\n",color,fb_ptr); *(fb_ptr) = ( color & 0x0000ff); // 24 bit=3 byte; *(fb_ptr+1) = ( color & 0x00ff00)>>4; *(fb_ptr+2) = ( color & 0xff0000)>>8; printk("pure_color_word=%8x\n",pure_color_word); break; */ case 32: pure_color_word = ( color & 0x00ffffff); // why not ? by ywc // if(y==212) printk("color=%8x,fb_ptr_word=%p\n",color,fb_ptr_word); *(fb_ptr_word) = pure_color_word; break; default: break; } //pure_color = ( color & 0x00ff); // why not ? by ywc //*(fb_ptr) = pure_color; // 更新像素點的顏色信息 // 處理x坐標為奇數的情況 /* if (x & 0x1) { pure_color = (color & 0x000f) << 4; // add by ywc *fb_ptr &= 0x0f; *fb_ptr |= pure_color; } // 處理x坐標為偶數的情況 else { pure_color = ( color & 0x000f ); // add by ywc *(fb_ptr) &= 0xf0; *(fb_ptr) |= pure_color; }*/ return;}// 繪制一條垂直直線static void lcd_kernel_vline(int x, int y1, int y2, COLOR color){ int tmp; int i = 0; // 如果起始點的y坐標大于終止點的y坐標, 則交換起始點和終止點 if (y1 > y2) { tmp = y1; y1 = y2; y2 = tmp;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -