简单的Framebuffer驱动

来源:互联网 发布:人工智能英文介绍双语 编辑:程序博客网 时间:2024/06/05 05:54
简单的Framebuffer驱动
[ 2005-12-1 11:41:29 | By: ericshi ]
  /*****************************************************************************/
/*
*sed1335fb.c -- Driver for sed1335 lcd control framebuffer device
*
******************************************************************************/

#i nclude <linux/config.h>
#i nclude <linux/types.h>
#i nclude <linux/kernel.h>
#i nclude <linux/fs.h>
#i nclude <linux/mm.h>
#i nclude <linux/wait.h>
#i nclude <linux/poll.h>
#i nclude <linux/types.h>
#i nclude <linux/delay.h>
#i nclude <asm/param.h>
#i nclude <asm/dma.h>
#i nclude <asm/irq.h>
#i nclude <asm/coldfire.h>
#i nclude <asm/mcfsim.h>
#i nclude <asm/mcfdma.h>
#i nclude <asm/mcftimer.h>

#i nclude <linux/fb.h>

/* LCD parameters */

#define LCD_XRES        320
#define LCD_YRES        240
#define LCD_BPP         1/* Bits per pixel */
/* how many bytes per row on screen */
#define BYTES_PER_ROW (LCD_XRES/(8/LCD_BPP))
#define SED1335FB_MAJOR101
//#define LCD_REFRESH_RATE 100
#define PIO_REFRESH_TIMER_TICKS  4
#define TIMEOUT_VALUE 0x1000

#defineSED1335FB_BUFSIZE((LCD_XRES * LCD_YRES * LCD_BPP)/8 )
/*LCD controller command/status defines
* Value to use for timeout when polling for LCD controller ready */
#define LCD_CS 4
#define LCD_RST 2
#define LCD_RD 25
#define LCD_WR 26
#define LCD_A0 23
static u8 DATABUS[]={13,14,15,16,18,19,20,21};


#define SYSSET   0x40
#define SLEEP    0x53
#define DISPON   0x59
#define DISPOFF  0x58
#define SCROLL   0x44
#define CSRFORM  0x5D
#define CGRAMADR 0x50
#define CSRDIRR  0x4C
#define CSRDIRL  0x4D
#define CSRDIRU  0x4E
#define CSRDIRD  0x4F
#define HDOTSCR  0x5A
#define OVLAY0x5B
#define CSRW0x46
#define CSRR0x47
#define MWRITE0x42
#define MREAD0x43
#define MBAR2_ADDR 0x80000000

static char sysset[8] = { 0x30, 0x87, 0x07, 0x27, 0x42, 0xef, 0x28, 0x00 };
static char scroll[10] =
    { 0x00, 0x00, 0xf0, 0x00, 0x40, 0xf0, 0x00, 0x80, 0x00, 0x00 };

/* Frame buffer memory  */
unsigned char sed1335fb_buff[SED1335FB_BUFSIZE];
unsigned char tmp_buff[SED1335FB_BUFSIZE];

/* Globals */
struct fb_fix_screeninfo fix;

struct timer_list pio_timer;

void setbit(u8 n,u8 v)
{
#ifdef DIRECT

if(v==0)
*(volatile  unsigned int  *)(MBAR2_ADDR+0x04)&=~(1<<n);
else
*(volatile  unsigned int  *)(MBAR2_ADDR+0x04)|=(1<<n);
#else
if(v==1)
*(volatile  unsigned int  *)(MBAR2_ADDR+0x04)&=~(1<<n);
else
*(volatile  unsigned int  *)(MBAR2_ADDR+0x04)|=(1<<n);
#endif
}
void init_io()
{
    u32 mask;
    u8 i;
    /* Init I/O */
    mask=0;
    for(i=0;i<8;i++)
mask|=(1<<DATABUS[i]);
    mask|=(1<<LCD_A0);
    mask|=(1<<LCD_CS);
    mask|=(1<<LCD_RD);
    mask|=(1<<LCD_RST);
    mask|=(1<<LCD_WR);
    *(volatile u32 *)(MBAR2_ADDR+0x0C)|=mask;
    *(volatile u32 *)(MBAR2_ADDR+0x08)|=mask;
    #ifdef DIRECT
    *(volatile u32 *)(MBAR2_ADDR+0x04)|=mask;
    #else
    *(volatile u32 *)(MBAR2_ADDR+0x04)&=~mask;
    #endif
  
}

void write_data(unsigned char data)
{
    unsigned int i,temp;
    temp=*(volatile  unsigned int  *)(MBAR2_ADDR+0x04);
   
    for(i=0;i<8;i++)
    {
    #ifdef DIRECT
    if((data>>i)&0x01)
    #else
        if(!((data>>i)&0x01))
    #endif
temp |= (1<<DATABUS[i]);
else
temp &= ~(1<<DATABUS[i]);
    }
    *(volatile  unsigned int  *)(MBAR2_ADDR+0x04)=temp;

    setbit(LCD_A0,0);
    setbit(LCD_WR,0);
    setbit(LCD_WR,1);

}

/* Do command write */
void write_cmd(unsigned char data)
{
    unsigned int i,temp;
   
    temp=*(volatile  unsigned int  *)(MBAR2_ADDR+0x04);
   
    for(i=0;i<8;i++)
    {
    #ifdef DIRECT
    if((data>>i)&0x01)
    #else
        if(!((data>>i)&0x01))
    #endif
temp |= (1<<DATABUS[i]);
else
temp &= ~(1<<DATABUS[i]);
    }

    *(volatile  unsigned int  *)(MBAR2_ADDR+0x04)=temp;  
   
    setbit(LCD_A0,1);
    setbit(LCD_WR,0);
    setbit(LCD_WR,1);

}
/*****************************************************************************/
/* Use PIO to copy frame buffer contents to LCD controller                   */
/*****************************************************************************/
void sed1335fb_pio_copy(unsigned long sed1335_pio)
{
    unsigned short i;

    /* Re-init refresh timer */
    del_timer(&pio_timer);
    pio_timer.expires = jiffies + PIO_REFRESH_TIMER_TICKS;
    add_timer(&pio_timer);

    /* Set cursor shift direction to right */
    write_cmd(CSRDIRR);

    /* Set cursor to start of the screen */
    write_cmd(CSRW);

    /* Prepare LCD controller to do auto mode write */
    write_data(0x00);
    write_data(0x00);

    /* begin write data */
    write_cmd(MWRITE);

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

if (tmp_buff[i] != sed1335fb_buff[i]) {
write_cmd(CSRW);
write_data(((char*)&i)[1]);
write_data(((char*)&i)[0]);
write_cmd(MWRITE);
tmp_buff[i] = sed1335fb_buff[i];
write_data(sed1335fb_buff[i]);
}
    }
}

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

static ssize_t
sed1335fb_read(struct file *filp,char *buf,
       size_t count,loff_t *ppos)
{
    ssize_t copy_size;
    char *base_addr;

    if (count < 0)
return -EINVAL;

    base_addr = (char *) fix.smem_start;
    copy_size = (count + *ppos <= fix.smem_len ? count : fix.smem_len - *ppos);
    copy_to_user(buf, base_addr + *ppos, copy_size);

    return copy_size;
}

static ssize_t
sed1335fb_write(struct file *flip,const char *buf,
size_t count,loff_t *ppos)
{
    int copy_size;
    char *base_addr;

    if (count < 0)
return -EINVAL;
    base_addr = (char *) fix.smem_start;
    copy_size = (count + *ppos <= fix.smem_len ? count : fix.smem_len - *ppos);
 
    copy_from_user(base_addr + *ppos, buf, copy_size);
 
    return copy_size;
}

//#define  FILE_OP_DEBUG

static int
sed1335fb_mmap(struct file *file, struct vm_area_struct *vma)
{
#ifdef  FILE_OP_DEBUG
    printk("%s(%d): %s()/n", __FILE__, __LINE__, __FUNCTION__);
#endif
    vma->vm_start = fix.smem_start + vma->vm_offset;

    return 0;
}

int sed1335fb_open(struct inode *inode, struct file *filp)
{
#ifdef  FILE_OP_DEBUG
    printk("%s(%d): %s()/n", __FILE__, __LINE__, __FUNCTION__);
#endif
    return (0);
}

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

int sed1335fb_release(struct inode *inode, struct file *filp)
{
#ifdef FILE_OP_DEBUG
    printk("%s(%d): %s()/n", __FILE__, __LINE__, __FUNCTION__);
#endif
    return (0);
}

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


int
sed1335fb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
    struct fb_var_screeninfo var;
    int rc = 0;
    int i;

#ifdef FILE_OP_DEBUG
    printk("%s(%d): sed1335fb_ioctl()/n", __FILE__, __LINE__);
#endif

    switch (cmd) {
    case FBIOGET_VSCREENINFO:
i = verify_area(VERIFY_WRITE, (void *) arg,
sizeof(struct fb_var_screeninfo));
var.xres = LCD_XRES;/* visible resolution           */
var.yres = LCD_YRES;
var.xres_virtual = LCD_XRES;/* virtual resolution           */
var.yres_virtual = LCD_YRES;
var.xoffset = 0;/* offset from virtual to visible */
var.yoffset = 0;/* resolution                   */
var.bits_per_pixel = LCD_BPP;/* guess what                   */
var.grayscale = 1;/* != 0 Graylevels instead of colors */
//memcpy_tofs((void *) arg, &var, sizeof(var));
copy_to_user((void *) arg, &var, sizeof(var));
break;
    case FBIOGET_FSCREENINFO:
i = verify_area(VERIFY_WRITE, (void *) arg,
sizeof(struct fb_fix_screeninfo));
if (i)
    return i;
//memcpy_tofs((void *) arg, &fix, sizeof(fix));
copy_to_user((void *) arg, &fix, sizeof(fix));
return i;
    default:
rc = -EINVAL;
break;
    }

    return (rc);
}

/*
*Exported file operations structure for driver...
*/

struct file_operations sed1335fb_fops = {
    read:sed1335fb_read,
    write:sed1335fb_write,
    ioctl:sed1335fb_ioctl,
    mmap:sed1335fb_mmap,
    open:sed1335fb_open,
    release:sed1335fb_release,
};

/* * Setup LCD module parameters */

int lcd_init(void)
{
    int i = 0;
    for(i=0;i<100000;i++);
    write_cmd(SYSSET);
    for (i = 0; i < 8; i++)
write_data(sysset[i]);
    write_cmd(SCROLL);
    for (i = 0; i < 10; i++)
write_data(scroll[i]);
    write_cmd(HDOTSCR);
    write_data(0x00);
    write_cmd(OVLAY);
    write_data(0x0C);
    write_cmd(DISPON);

    write_data(0x54);
    write_cmd(CSRDIRR);
    write_cmd(CSRW);
    write_data(0x00);
    write_data(0x00);
    write_cmd(MWRITE);
    for (i = 0; i < SED1335FB_BUFSIZE; i++)
write_data(0x00);

    write_cmd(CSRW);
    write_data(0x00);
    write_data(0x00);
    write_cmd(CSRFORM);
    write_data(0x07);
    write_data(0x07);
    write_cmd(DISPON);
    write_data(0x04);
    return (0);
}

void sed1335fb_init(void)
{
    int result;
    init_io();
    /* Set CS*/
    setbit(LCD_CS,0);
    /* Reset Sed1335 */
    setbit(LCD_RST,0);
    mdelay(5);
    setbit(LCD_RST,1);
    /* Do LCD init */
    if (lcd_init()) {
printk(/*KERN_WARNING*/
       "sed1335fb: can't init LCD controller, exiting/n");
return;
    }


    fix.smem_start = (unsigned long) sed1335fb_buff;
    fix.smem_len = SED1335FB_BUFSIZE;/* Length of frame buffer mem */
    fix.type = FB_TYPE_PACKED_PIXELS;/* see FB_TYPE_*           */
    fix.type_aux = 0;/* Interleave for interleaved Planes */
    fix.visual = FB_VISUAL_MONO01;/* see FB_VISUAL_*              */
    fix.xpanstep = 0;/* zero if no hardware panning  */
    fix.ypanstep = 0;/* zero if no hardware panning  */
    fix.ywrapstep = 0;/* zero if no hardware ywrap    */
    fix.line_length = LCD_XRES / (8 * LCD_BPP);/* length of a line in bytes    */
 
    /* Register character device */
    result = register_chrdev(SED1335FB_MAJOR, "fb", &sed1335fb_fops);
    if (result < 0) {
printk(KERN_WARNING "sed1335fb: can't get major %d/n",
       SED1335FB_MAJOR);
return;
    }
    //printk("sed1335fb: using PIO mode/n");
    /* Set up PIO timer */
    for (result=0;result < SED1335FB_BUFSIZE;result++)
    tmp_buff[result] = 0; //sed1335fb_buff[result] + 1;
    pio_timer.function = sed1335fb_pio_copy;
    pio_timer.expires = jiffies + PIO_REFRESH_TIMER_TICKS;
    add_timer(&pio_timer);
    printk("******sed1335fb_init() finished8*****/n");
}
module_init(sed1335fb_init);
//MODULE_LICENSE("GPL");
/*****************************************************************************/
原创粉丝点击