LCD 驱动源码完全注释

 
LCD 驱动源码完全注释  

2007-08-31 19:47:19|  分类: 驱动程序开发 |  标签: |字号 订阅

LCD 驱动源码完全注释

lcd_struct.h

/*****************************

 定义LCD所用数据结构

******************************/

#ifndef _LCD_STRUC_DEF

#define _LCD_STRUC_DEF

/* LCD颜色类型

 * COLOR[0-3]  : 红

 * COLOR[4-7]  : 绿

 * COLOR[8-11] : 蓝

 * COLOR[12-15]: 保留半字节

 */

//typedef unsigned short  COLOR;

typedef unsigned int  COLOR;

 

// 保存屏幕缓冲区结构

struct save_struct

{

 int save_w;

 int save_h;

 unsigned char * save_buf;

};

// LCD显示命令的参数结构

struct lcd_display

{

 int x1, y1;      /* 第一个点的x, y坐标 */

 int x2, y2;      /* 第二个点的x, y坐标 */

       

        unsigned char * lcd_buf;   //add by ywc

        int lcd_buf_size;

 int lcd_row;

 unsigned char codes[32];  /* 字符点阵数据 */

 COLOR color;     /* 显示颜色 */

};

// LCD屏幕命令的参数结构

struct lcd_screen

{

 int x1, y1;      /* 第一个点的x, y坐标 */

 int x2, y2;      /* 第二个点的x, y坐标 */

 struct save_struct * buffer; /* 保存屏幕缓冲区 */

};

#endif // _LCD_STRUC_DEF

 

ep7312_sys.h

/***************************

 定义ep7312系统寄存器

***************************/

#ifndef _SYS_EP7312_REG

#define _SYS_EP7312_REG

#define SYSCON1   *(unsigned long*)0xff000100      /* 系统寄存器1 */

#define SYSCON2   *(unsigned long*)0xff001100      /* 系统寄存器2 */ 

 

#define PADR   *(unsigned char*)0xff000000        /* 端口A数据寄存器 */

#define PADDR   *(unsigned char*)0xff000040        /* 端口A方向寄存器 */

#define PBDR   *(unsigned char*)0xff000001         /* 端口B数据寄存器 */

#define PBDDR   *(unsigned char*)0xff000041      /* 端口B方向寄存器 */

#define LCDCON   *(unsigned long*)0xff0002c0      /* LCD控制寄存器 */

#define PALLSW   *(unsigned long*)0xff000540      /* 调色板颜色寄存低位有效字 */

#define PALMSW   *(unsigned long*)0xff000580      /* 调色板颜色寄存高位有效字 */

#define FBADDR   *(unsigned long*)0xff001000      /* LCD显示帧缓存起始地址 */

#define COM2DATA   *(volatile unsigned char *)0xff001480   /* 串口2数据寄存器 */

#define COM2CONTROL  *(volatile unsigned long *)0xff001140   /* 串口2控制寄存器 */

#define INTSR   *(unsigned long *)0xff000240

#define EINT2   0x00000040

#endif //_SYS_EP7312_REG

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;

 }

 // 计算两点的垂直距离

 tmp = y2 - y1;

 // 用点组成垂直的直线

 for (i = 0; i <= tmp; i++ )

 {

  lcd_kernel_pixel(x, y1 + i,color);

 }

 return;

}

// 绘制一条水平直线

static void lcd_kernel_hline(int x1, int x2, int y, COLOR color)

{      

 int tmp;

 int i = 0;

 // 如果起始点的x坐标大于终止点的x坐标, 则交换起始点和终止点

 if (x1 > x2)

 {

  tmp = x1;

  x1 = x2;

  x2 = tmp;

 }

 // 计算两点的水平距离

 tmp = x2 - x1;

 // 用点组成水平的直线

 for (i = 0; i <= tmp; i++ )

 {

  lcd_kernel_pixel(x1 + i, y, color);

 }

 return;

}

// 绘制一个矩形边框

// 边框左上角坐标为(start_x, start_y)

// 边框右下角坐标为(end_x, end_y))

static void lcd_kernel_rectangle(int start_x,int start_y,int end_x,int end_y,COLOR color)

{

 lcd_kernel_vline(start_x, start_y, end_y, color); /* 绘制左边框 */

 lcd_kernel_vline(end_x, start_y, end_y, color);  /* 绘制右边框 */

 lcd_kernel_hline(start_x, end_x, start_y, color); /* 绘制上边框 */

 lcd_kernel_hline(start_x, end_x, end_y, color);  /* 绘制下边框 */

 return;

}

// 显示一个ASCII字符

// codes为指定ASCII字符的8 x 16点阵数组

static void lcd_kernel_text_en(int x, int y, unsigned char* codes, COLOR color)

{

 int i, j;

 // 显示8 x 16的点阵

 for (i = 0;i < 16; i++)

 {

  // 移动x坐标至要显示的字符的右侧的边界上

  x += 8;

  

  // 从左向右显示一行点

  for (j = 0; j < 8; j++)

  {

   // x坐标向左移一个像素

   x--;

   // 根据点阵信息显示一个指定颜色的点

   if ((codes[i] >> j) & 0x1)

   {

    lcd_kernel_pixel(x, y, color);

   }

  }

  // 开始显示新的一行, y坐标向下移一个像素

  y++;

 }

 return;

}

// 显示一个中文字符

// codes为指定中文字符的16 * 16点阵数组

static void lcd_kernel_text_chs(int x, int y, unsigned char* codes, COLOR color)

{

 int i, j, k;

 // 显示16 * 16的点阵

 for(i = 0;i < 16; i++)

 {

  // 循环两次,

  // 先显示字符的左半部分的一行,

  // 然后显示字符的右半部分的一行

  for (j = 0; j < 2; j++)

  {

   // 计算x坐标的位置

   // 左半部分的起始点为x + 8

   // 右半部分的起始点为x + 16

   x += 8 * ( j + 1);

   // 从左向右显示左(右)半部分的一行

   for (k = 0; k < 8; k++)

   {

    // x坐标向左移一个像素

    x--;

    // 根据点阵信息显示一个指定颜色的点

    // codes[2 * i + j]计算行点阵在数组中的位置:

    // 2 * i + 0 为左半部分的行点阵信息

    // 2 * i + 1 为右半部分的行点阵信息

    if ((codes[2 * i + j] >> k) & 0x1)

    {

     lcd_kernel_pixel(x,y,color);

    }

   }

  }

  // 开始显示新的一行,

  // x坐标回到原先位置,

  // y坐标向下移一个像素

  x -= 8;

  ++y;

 }

 return;

}

// 用指定颜色清屏

static void lcd_kernel_clear(COLOR color)

{

 unsigned char buffer[3];

 long i;

        COLOR  pure_color;

       printk("\nclear the screen to color '%d' !!!\n",color);

       pure_color=color&0x0000f;

       pure_color|=(color&0x000f)<<4;

 // 根据像素点的位置, 设置相应的更新字节

 // 以两个像素点为一组, 共三个字节

// buffer[0] = color & 0xff;  //green(M)+red(L)

// buffer[1] = ((color & 0xf00) >> 8) + ((color & 0x0f) << 4);//red(M)+blue(L)

// buffer[2] = color >> 4;//blue(M)+green(L)

  // *(__lcd_base + i) = 0x11;

//  *(__lcd_base + i) = buffer[i % 3];

 // 更新显示缓冲区

 

// for (i = 0; i < SCR_X * SCR_Y * 3 * BPP / 8; i++)

 for (i = 0; i < SCR_X * SCR_Y * 1 * BPP / 8; i++){

      *(__lcd_base + i) = pure_color;

         /* if (i & 0x1)

         {

            pure_color = (color & 0x000f) << 4;            // add by ywc

     *(__lcd_base + i) &= 0x0f; 

     *(__lcd_base + i) |= pure_color;

                 }else{

            pure_color = (color & 0x000f);            // add by ywc

     *(__lcd_base + i) &= 0xf0; 

     *(__lcd_base + i) |= pure_color;

                 } */

 }

}

// 打开LCD设备文件

static int lcd_kernel_open(struct inode *node, struct file *file)

{

 return 0;

}

// 对LCD设备文件进行读操作

static int lcd_kernel_read(struct file *file, char *buff, size_t count, loff_t *offp)

{

 return 0;

}

// 对LCD设备文件进行写操作

static int lcd_kernel_write(struct file *file, const char *buff, size_t count, loff_t *offp)

{

 return 0;

}

/

// by ywc 2004-04-17  对LCD设备文件按字节进行写操作(应用程序无法通过write

//调用到该函数???暂时没有找出原因,所以先通过ioctl复制位图缓冲到显存

//static int lcd_kernel_writeb(struct file *file, const char *buff, size_t count, loff_t *offp)

static int lcd_kernel_writeb(const char *buff, size_t count, int rownum)

{

   int i;

          unsigned char * fb_ptr;

         fb_ptr=(unsigned char *)__lcd_base;

       

        // printk("\n!!!enter the lcd_kernel_writeb()");

         for(i=0;i<count;i++){

            //*(fb_ptr+20*rownum+i)=*(buff+i);

     *(fb_ptr+i)=*(buff+i);

         }

        return 0;

}

static int lcd_kernel_writew(const char *buff, size_t count, int rownum)

{

   int i;

         // unsigned char * fb_ptr;

   unsigned long * fb_ptr_word;

         fb_ptr_word=(unsigned long *)__lcd_base;

       

        // printk("\n!!!enter the lcd_kernel_writeb()");

         for(i=0;i<count/4;i++){

            *(fb_ptr_word+i)=*((unsigned long *)buff+i);

         }

        return 0;

}

///

// 对LCD设备文件进行读写之外的其它操作

static int lcd_kernel_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

{

 // 根据指令ID, 调用相应的操作

 switch (cmd)

 {

  // 清屏

  case LCD_Clear:

  {

   struct lcd_display clear_display;

   // 复制显示结构

   if (copy_from_user(&clear_display, (struct lcd_display*)arg, sizeof(struct lcd_display)))

   {

    printk("System: copy_from_user error!\n");

    printk("Caller: lcd_kernel_ioctl -> LCD_Clear!\n");

    return -1;

   }

   // 调用清屏函数

   lcd_kernel_clear(clear_display.color);

   break;

  }

  // 绘制像素点

  case LCD_Draw_Pixel:

  {

   struct lcd_display pixel_display;

   // 复制显示结构

   if ( copy_from_user(&pixel_display, (struct lcd_display*)arg, sizeof(struct lcd_display)))

   {

    printk("System: copy_from_user error!\n");

    printk("Caller: lcd_kernel_ioctl -> LCD_Draw_Pixel!\n");

    return -1;

   }

   // 调用画点函数

   lcd_kernel_pixel(pixel_display.x1, pixel_display.y1, pixel_display.color);

   break;

  }

  // 绘制垂直直线

  case LCD_Draw_VLine:

  {

   struct lcd_display vline_display;

   // 复制显示结构

   if ( copy_from_user(&vline_display, (struct lcd_display*)arg, sizeof(struct lcd_display)))

   {

    printk("System: copy_from_user error!\n");

    printk("Caller: lcd_kernel_ioctl -> LCD_Draw_VLine!\n");

    return -1;

   }

   // 调用画线函数

   lcd_kernel_vline(vline_display.x1, vline_display.y1, vline_display.y2, vline_display.color);

   break;

  }

  // 绘制水平直线

  case LCD_Draw_HLine: 

  {

   struct lcd_display hline_display;

   // 复制显示结构

   if ( copy_from_user(&hline_display,(struct lcd_display*)arg,sizeof(struct lcd_display)))

   {

    printk("System: copy_from_user error!\n");

    printk("Caller: lcd_kernel_ioctl -> LCD_Draw_HLine!\n");

    return -1;

   }

 

   // 调用画线函数

   lcd_kernel_hline(hline_display.x1, hline_display.x2, hline_display.y1, hline_display.color);

   break;

  }

  // 绘制矩形边框

  case LCD_Draw_Rectangle:

  {

   struct lcd_display rect_display;

   // 复制显示结构

   if (copy_from_user(&rect_display, (struct lcd_display*)arg, sizeof(struct lcd_display)))

   {

    printk("System: copy_from_user error!\n");

    printk("Caller: lcd_kernel_ioctl -> LCD_Draw_Rectangle!\n");

                   

    return -1;

   }

   // 调用画矩形边框函数

   lcd_kernel_rectangle(rect_display.x1, rect_display.y1, rect_display.x2, rect_display.y2, rect_display.color);

   break;

  } 

               

                //将位图缓冲区写入显存 add by ywc 2004-04-18

  case LCD_Draw_Buf:

  {

   struct lcd_display buf_display;

   // 复制显示结构

   if ( copy_from_user(&buf_display, (struct lcd_display*)arg, sizeof(struct lcd_display)))

   {

    printk("System: copy_from_user error!\n");

    printk("Caller: lcd_kernel_ioctl -> LCD_Draw_Buf!\n");

    return -1;

   }

   //调用复制位图缓冲到显存的函数

   //lcd_kernel_writeb(buf_display.lcd_buf, buf_display.lcd_buf_size,buf_display.lcd_row);

   lcd_kernel_writew(buf_display.lcd_buf, buf_display.lcd_buf_size,buf_display.lcd_row);

   break;

  }     

       

  // 显示一个ASCII字符

  case LCD_Write_EN:

  {

   struct lcd_display en_display;

   // 复制显示结构

   if ( copy_from_user(&en_display, (struct lcd_display*)arg, sizeof(struct lcd_display)))

   {

    printk("System: copy_from_user error!\n");

    printk("Caller: lcd_kernel_ioctl -> LCD_Write_EN!\n");

                   

    return -1;

   }

   // 调用显示字符函数

   lcd_kernel_text_en(en_display.x1, en_display.y1, en_display.codes, en_display.color);

   

   break;                                                         

  }

  // 显示一个中文字符

  case LCD_Write_CN:

  {

   struct lcd_display cn_display;

   // 复制显示结构

   if ( copy_from_user(&cn_display,(struct lcd_display*)arg,sizeof(struct lcd_display)))

   {

    printk("System: copy_from_user error!\n");

    printk("Caller: lcd_kernel_ioctl -> LCD_Write_EN!\n");

                   

    return -1;

   }

   // 调用显示字符函数

   lcd_kernel_text_chs(cn_display.x1, cn_display.y1, cn_display.codes, cn_display.color);

   

   break;       

  }

  // 保存屏幕指定部分内容

  case LCD_Save_SCR:

  {

   // 调用保存屏幕函数

   lcd_kernel_save_screen((*(struct lcd_screen*)arg).x1, (*(struct lcd_screen*)arg).y1,

         (*(struct lcd_screen*)arg).x2, (*(struct lcd_screen*)arg).y2,

         (*(struct lcd_screen*)arg).buffer);

   

   break;       

  }

  // 加载保存的屏幕内容到指定位置

  case LCD_Load_SCR:

  {

   struct lcd_screen load_screen;

   // 复制屏幕结构

   if ( copy_from_user(&load_screen,(struct lcd_screen*)arg,sizeof(struct lcd_screen)))

   {

    printk("System: copy_from_user error!\n");

    printk("Caller: lcd_kernel_ioctl -> LCD_Load_SCR!\n");

                   

    return -1;

   }

   // 调用加载屏幕函数

   lcd_kernel_load_screen(load_screen.x1, load_screen.y1, *load_screen.buffer);

   

   break;       

  }

  // 释放保存的屏幕内容

  case LCD_Release_SCR:

  {

   lcd_kernel_release_screen((*(struct lcd_screen*)arg).buffer);

   

   break;       

  }

  default:

   printk("Unknown LCD command ID.\n");

 }

 return 0;

}

// 释放LCD设备文件

static int lcdexp_release(struct inode *node, struct file *file)

{

 // 缓存基址复位

  __lcd_base = (unsigned char *)0xc0000000;

 return 0;

}

// LCD设备文件操作结构

static struct file_operations lcd_fops = {

 open:           lcd_kernel_open,  /* 打开设备文件 */

 read:           lcd_kernel_read,  /* 设备文件的读操作 */

 ioctl:   lcd_kernel_ioctl,  /* 设备文件的其它操作 */

 //write:          lcd_kernel_write,  /* 设备文件的写操作 */

 write:          lcd_kernel_writeb,  /* 设备文件的写操作 */

 release:        lcdexp_release,   /* 释放设备文件 */

};

// 初始化LCD设备

static int __init lcd_kernel_init(void)

{

 int result;   /* 注册设备结果 */

 long i;

 // 设置显示缓存基地址

 __lcd_base = (unsigned char*)0xc0000000;

 // 注册LCD系统设备

 printk("\nRegistering LCD Device\t--->\t");

 result = register_chrdev(DEV_MAJOR, "lcd_ep7312", &lcd_fops);

 if (result < 0)

 {

  printk(KERN_INFO "[FAILED: Cannot register lcd_ep7312!]\n");

  return -EBUSY;

 }

 else

  printk("[OK]\n");

 printk("Initializing LCD Device\t--->\t\n");

 // 设置LCD

  setup_lcd();

  //  printk(" \nsetup_lcd runing end !//y ywc");

 

    // 初始化显示缓冲区内容

// for (i=0; i < SCR_X * SCR_Y * 3 * BPP / 8; i++)

/* for (i=0; i < SCR_X * SCR_Y * 1* BPP / 8; i++)

 {

            *__lcd_base++ = 0x00;

            

        // *__lcd_base= 0x11;

    __lcd_base++; 

       

            //   *(__lcd_base)&= 0xf0;

//   *(__lcd_base)|= 0x04;

//   *(__lcd_base)&= 0x0f;

//   *(__lcd_base)|= 0x40;

//   __lcd_base++;      

 }

*/

 //printk("\n__lcd_base=%p,*__lcd_base=%x\n",--__lcd_base,*__lcd_base);

 

 // 复位显存基地址

 __lcd_base =(unsigned char*)0xc0000000;

 //printk("\n__lcd_base=%x\n",__lcd_base);

 printk("[OK]\n");

 // 显示成功加载信息

 printk("\nEP7312 LCD Driver installed.\n");

// printk("Written by BIT200009123.\n");

 return 0;

}

// 释放LCD设备

static void __exit lcd_kernel_exit(void)

{

 // 注销LCD设备, 并释放保存屏幕缓冲区

 printk("Unregistering LCD Device\t--->\t");

 unregister_chrdev(DEV_MAJOR, "lcd_ep7312");

 printk("[OK]\n");

 return;

}

// 初始化模块

module_init(lcd_kernel_init);

// 卸载模块

module_exit(lcd_kernel_exit);

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值