?? lcd_drv_org.c
字號(hào):
#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 命令I(lǐng)D
#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_Write_EN 10
#define LCD_Write_CN 11
#define LCD_Save_SCR 12
#define LCD_Load_SCR 13
#define LCD_Release_SCR 14
// 定義LCD的主設(shè)備號(hào)
#define DEV_MAJOR 60
// 定義LCD顯示模式參數(shù)
#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顯示模式 */
// 半字節(jié)復(fù)制標(biāo)志
#define LowS 0 /* 取字節(jié)低四位標(biāo)志 */
#define HighS 1 /* 取字節(jié)高四位標(biāo)志 */
// LCD顯示緩存的基址
static unsigned char * __lcd_base;
/* 設(shè)置LCD寄存器 */
static void setup_lcd(void)
{
// 禁用LCD設(shè)備
SYSCON1 &= ~0x00001000;
// 設(shè)置LCD控制寄存器
// 顯示緩存容量[0:12] : 320 * 240 * 12 / (8*16) = 0x1c1f
// 線長度[13:18] : 320 / 16 - 1 = 0x13
// 像素預(yù)定標(biāo)[19:24] : 0x01
// AC預(yù)定標(biāo)[25:29] : 0x13
// 灰度使能[30] : = 1, 使用灰度級(jí)顯示
// 灰度級(jí)模式[31] : = 1, 4 bpp模式(16灰度級(jí))
//LCDCON = 0xe60f7c1f;
// LCDCON = 0xe60a7c1f; //320*720
// LCDCON =0xe60a6257; //320x240x1
// LCDCON =0xe60a64af; //320x240x2
LCDCON =0xe60920c8; //160x160x1
printk("\n[test by ywc] lcd driver:LCDCON address=%p",&LCDCON);
// LCDCON =0xe60a695f; //320x240x4
// LCDCON =0xe60a72bf; //320x240x8
// LCDCON =0xe60a72bf; //320x240x16/(8*32)
// LCDCON =0xe60a7c1f; //320x240x24/(8*32)
// LCDCON =0xe60a72bf; //320x240x32/(8*64)
// 設(shè)置調(diào)色板顏色寄存器的低位和高位有效字
PALLSW = 0x76543210; /* 低位有效字 */
PALMSW = 0xfedcba98; /* 高位有效字 */
// 設(shè)置LCD顯示緩沖區(qū)在系統(tǒng)存儲(chǔ)區(qū)域的起始位置
FBADDR = 0xc;
// 啟用LCD設(shè)備
SYSCON1 |= 0x00001000;
return;
}
// 限制橫坐標(biāo)范圍
// 使橫坐標(biāo)在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;
}
// 限制縱坐標(biāo)范圍
// 使縱坐標(biāo)在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;
}
// 釋放保存屏幕緩沖區(qū)
static void lcd_kernel_release_screen(struct save_struct * buffer)
{
if ((*buffer).save_buf != NULL)
{
// 釋放緩沖區(qū)
kfree((*buffer).save_buf);
// 恢復(fù)緩沖區(qū)初始化設(shè)置
(*buffer).save_buf = NULL;
(*buffer).save_w = (*buffer).save_h = 0;
}
}
// 保存屏幕部分區(qū)域的內(nèi)容
static void lcd_kernel_save_screen(int x1, int y1, int x2, int y2, struct save_struct * buffer)
{
unsigned char * fb_lptr; /* 每行第一個(gè)點(diǎn)的顯存地址 */
unsigned char bufferByte; /* 臨時(shí)緩存字節(jié) */
long buffer_size; /* 保存屏幕緩沖區(qū)的字節(jié)數(shù) */
int factorCount; /* 每行需要存取的半字節(jié)的個(gè)數(shù) */
int sb_sign, fb_sign; /* 半字節(jié)復(fù)制標(biāo)志, = LowS: 復(fù)制低四位, = HighS: 復(fù)制高四位*/
int p_sb; /* 保存屏幕緩沖區(qū)指針偏移量 */
int p_fb; /* 顯示緩沖區(qū)指針偏移量 */
int currLine; /* 當(dāng)前行的縱坐標(biāo) */
int tmp, i;
// 修正保存范圍坐標(biāo), 使其在屏幕的顯示范圍之內(nèi)
x1 = xFormat(x1);
x2 = xFormat(x2);
y1 = yFormat(y1);
y2 = yFormat(y2);
// 修正保存范圍的橫坐標(biāo), 使x2值永遠(yuǎn)大于x1的值
if (x1 > x2)
{
tmp = x1;
x1 = x2;
x2 = tmp;
}
// 修正保存范圍的縱坐標(biāo), 使y2值永遠(yuǎn)大于y1的值
if (y1 > y2)
{
tmp = y1;
y1 = y2;
y2 = tmp;
}
// 計(jì)算新保存的屏幕的寬度和高度
(*buffer).save_w = x2 - x1 + 1;
(*buffer).save_h = y2 - y1 + 1;
// 計(jì)算新緩沖區(qū)大小
buffer_size = (*buffer).save_w * (*buffer).save_h * 3 * BPP / 8 + 1;
// 申請(qǐng)新的屏幕緩沖區(qū)
(*buffer).save_buf = kmalloc(buffer_size, GFP_KERNEL);
// 初始化保存屏幕半字節(jié)復(fù)制標(biāo)志
sb_sign = LowS;
// 計(jì)算每行中半字節(jié)的個(gè)數(shù)
factorCount = (*buffer).save_w * 3;
// 初始化屏幕緩沖區(qū)指針偏移量
p_sb = 0;
// 復(fù)制顯存的內(nèi)容到保存屏幕緩沖區(qū)中
for (currLine = y1; currLine <= y2; currLine++)
{
// 計(jì)算當(dāng)前行第一個(gè)點(diǎn)的顯存地址
fb_lptr = __lcd_base + (x1 + currLine * SCR_X) * 3 * BPP / 8;
// 初始化顯存半字節(jié)復(fù)制標(biāo)志
fb_sign = (x1 & 0x1);
// 初始化顯示緩沖區(qū)指針偏移量
p_fb = 0;
// 復(fù)制顯存當(dāng)前行的內(nèi)容
for (i = 0; i < factorCount; i++)
{
// 臨時(shí)緩沖字節(jié)清零
bufferByte &= 0x00;
// 根據(jù)顯存半字節(jié)復(fù)制標(biāo)志, 將顯存中當(dāng)前字節(jié)的內(nèi)容的低四位(或高四位)
// 復(fù)制到臨時(shí)緩沖字節(jié)的低四位中
if (fb_sign == LowS)
bufferByte = (fb_lptr[p_fb] & 0x0f);
else
bufferByte = (fb_lptr[p_fb] & 0xf0) >> 4;
// 根據(jù)保存屏幕緩沖區(qū)半字節(jié)復(fù)制標(biāo)志,
// 對(duì)保存屏幕緩沖區(qū)當(dāng)前字節(jié)中相應(yīng)的四位清零;
// 如果是要復(fù)制高四位的內(nèi)容,
// 還要將臨時(shí)緩沖字節(jié)的低四位內(nèi)容移到高四位中
if (sb_sign == HighS)
{
(*buffer).save_buf[p_sb] &= 0x0f;
bufferByte = bufferByte << 4;
}
else
(*buffer).save_buf[p_sb] &= 0xf0;
// 用臨時(shí)緩沖字節(jié)更新保存屏幕緩沖區(qū)的當(dāng)前字節(jié)
(*buffer).save_buf[p_sb] |= bufferByte;
// 根據(jù)半字節(jié)復(fù)制標(biāo)志, 設(shè)置相應(yīng)的指針偏移量
if (fb_sign == HighS)
p_fb++;
if (sb_sign == HighS)
p_sb++;
// 更新半字節(jié)復(fù)制標(biāo)志
sb_sign ^= 0x1;
fb_sign ^= 0x1;
}
}
}
// 加載屏幕部分區(qū)域的內(nèi)容
static void lcd_kernel_load_screen(int x1, int y1, struct save_struct buffer)
{
unsigned char * fb_lptr; /* 每行第一個(gè)點(diǎn)的顯存地址 */
unsigned char bufferByte; /* 臨時(shí)緩存字節(jié) */
int factorCount; /* 每行需要存取的半字節(jié)的個(gè)數(shù) */
int sb_sign, fb_sign; /* 半字節(jié)復(fù)制標(biāo)志, = LowS: 復(fù)制低四位, = HighS: 復(fù)制高四位*/
int p_sb; /* 保存屏幕緩沖區(qū)指針偏移量 */
int p_fb; /* 顯示緩沖區(qū)指針偏移量 */
int x2, y2; /* 加載區(qū)域右下角的坐標(biāo) */
int currLine; /* 當(dāng)前行的縱坐標(biāo) */
int i;
// 修正加載范圍坐標(biāo), 使其在屏幕的顯示范圍之內(nèi)
x1 = xFormat(x1);
y1 = xFormat(y1);
// 計(jì)算加載范圍右下角的坐標(biāo)
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;
}
// 如果尚未執(zhí)行保存屏幕的操作,
// 則不作任何操作返回
if (buffer.save_buf == NULL)
{
printk(KERN_INFO "No Saved Screen!\n");
return;
}
// 初始化保存屏幕半字節(jié)復(fù)制標(biāo)志
sb_sign = LowS;
// 計(jì)算每行中半字節(jié)的個(gè)數(shù)
factorCount = buffer.save_w * 3;
// 初始化屏幕緩沖區(qū)指針偏移量
p_sb = 0;
// 加載保存屏幕緩沖區(qū)的內(nèi)容到顯存中
for (currLine = y1; currLine <= y2; currLine++)
{
// 計(jì)算當(dāng)前行第一個(gè)點(diǎn)的顯存地址
fb_lptr = __lcd_base + (x1 + currLine * SCR_X) * 3 * BPP / 8;
// 初始化顯存半字節(jié)復(fù)制標(biāo)志
fb_sign = (x1 & 0x1);
// 初始化顯示緩沖區(qū)指針偏移量
p_fb = 0;
// 加載當(dāng)行的內(nèi)容到顯存中
for (i = 0; i < factorCount; i++)
{
// 臨時(shí)緩沖字節(jié)清零
bufferByte &= 0x00;
// 根據(jù)保存屏幕半字節(jié)復(fù)制標(biāo)志, 將保存屏幕緩沖區(qū)中
// 當(dāng)前字節(jié)的內(nèi)容的低四位(或高四位)
// 復(fù)制到臨時(shí)緩沖字節(jié)的低四位中
if (sb_sign == LowS)
bufferByte = (buffer.save_buf[p_sb] & 0x0f);
else
bufferByte = (buffer.save_buf[p_sb] & 0xf0) >> 4;
// 根據(jù)顯存半字節(jié)復(fù)制標(biāo)志,
// 對(duì)顯存當(dāng)前字節(jié)中相應(yīng)的四位清零;
// 如果是要復(fù)制高四位的內(nèi)容,
// 還要將臨時(shí)緩沖字節(jié)的低四位內(nèi)容移到高四位中
if (fb_sign == HighS)
{
fb_lptr[p_fb] &= 0x0f;
bufferByte = bufferByte << 4;
}
else
fb_lptr[p_fb] &= 0xf0;
// 用臨時(shí)緩沖字節(jié)更新顯存內(nèi)容
fb_lptr[p_fb] |= bufferByte;
// 根據(jù)半字節(jié)復(fù)制標(biāo)志, 設(shè)置相應(yīng)的指針偏移量
if (fb_sign == HighS)
p_fb++;
if (sb_sign == HighS)
p_sb++;
// 更新半字節(jié)復(fù)制標(biāo)志
sb_sign ^= 0x1;
fb_sign ^= 0x1;
}
}
}
// 繪制一個(gè)像素點(diǎn)
static void lcd_kernel_pixel(int x, int y, COLOR color)
{
unsigned char* fb_ptr; /* 更新像素點(diǎn)對(duì)應(yīng)的顯存地址 */
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;
static int once = 0;
// 如果坐標(biāo)越界則不做任何操作, 直接返回
if ( x < 0 || x >= SCR_X|| y < 0 || y >= SCR_Y)
{
printk("out of bounds\n");
return;
}
// 計(jì)算當(dāng)前點(diǎn)對(duì)應(yīng)的顯存地址
//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
if(once<3){
once++;
printk("\n[test by ywc]lcd driver:fb_ptr=0x%p",&fb_ptr);
}
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;
// 更新像素點(diǎn)的顏色信息
// 處理x坐標(biāo)為奇數(shù)的情況
/* if (x & 0x1)
{
pure_color = (color & 0x000f) << 4; // add by ywc
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -