您的位置:首页 > 运维架构 > Linux

LCD Driver for Linux2.6.xx+ARM9

2013-01-19 19:21 781 查看
/**

  *   LCD driver

  *   reference:    fbmem.c     s3c2410fb.c   skeletonfb.c   atmel_lcdfb.c

  */

----------------------------------------------------------driver---------------------------------------------------------------

#include <linux/kernel.h>

#include <linux/platform_device.h>

#include <linux/dma-mapping.h>

#include <linux/interrupt.h>

#include <linux/clk.h>

#include <linux/fb.h>

#include <linux/init.h>

#include <linux/delay.h>

//#include <asm/arch/board.h>

//#include <asm/arch/cpu.h>

#include <asm/arch/gpio.h>

#include <asm/arch/regs-lcd.h>

//#define S3C24XX_PA_LCD    (0x4D000000)

//#define SZ_1M               0x00100000

//#define S3C24XX_SZ_LCD    SZ_1M

//#define IRQ_LCD  7

//typedef u32 dma_addr_t;

//static dma_addr_t map_dma; /* physical */

dma_addr_t map_dma; /* physical */

//typedef unsigned char u_char;

//static u_char *  map_cpu; /* virtual */

u_char * map_cpu;   /* virtual */

//typedef unsigned int u_int;

//static u_int map_size;

u_int  map_size;

struct s3c2410fb_hw {

 unsigned long lcdcon1;

 unsigned long lcdcon2;

 unsigned long lcdcon3;

 unsigned long lcdcon4;

 unsigned long lcdcon5;

 unsigned long lcdsaddr1;

 unsigned long lcdsaddr2;

 unsigned long lcdsaddr3;

};

static volatile struct s3c2410fb_hw *pczs3c2410fb_hw;

static struct fb_info *pczfb_info;

/*10^-12 = 1 * 10( -12)*/

/* pixclk is in picoseoncds, our clock is in Hz

 *

 * Hz -> picoseconds is / 10^-12

 */

/*HCLK=100MHz,PCLK=??MHz,*/

/* from pxafb.c */

static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)

{

 chan &= 0xffff;

 chan >>= 16 - bf->length;

 return chan << bf->offset;

}

static int czlcdfb_setcolreg(unsigned int regno, unsigned int red,

        unsigned int green, unsigned int blue,

        unsigned int transp, struct fb_info *info)

{

 unsigned int val;

 //u32 *pal;

 u32 *pal = pczfb_info->pseudo_palette;

 

 switch (pczfb_info->fix.visual) {

 case FB_VISUAL_TRUECOLOR:

   //there be error if this code is here,why??????????

   //u32 *pal = pczfb_info->pseudo_palette;

   val  = chan_to_field(red,   &pczfb_info->var.red);

   val |= chan_to_field(green, &pczfb_info->var.green);

   val |= chan_to_field(blue,  &pczfb_info->var.blue);

   pal[regno] = val;

  break;

  

 default:

  return 1;   /* unknown type */

 }

 return 0;

}

static struct fb_ops czlcdfb_ops = {

 .owner  = THIS_MODULE,

 .fb_setcolreg = czlcdfb_setcolreg,

 .fb_fillrect = cfb_fillrect,

 .fb_copyarea = cfb_copyarea,

 .fb_imageblit = cfb_imageblit,

};

static u32 pseudo_pal[16];

//static u32 palette_buffer[256];

static volatile unsigned long *gpccon = NULL;

//volatile unsigned long *gpcdat = NULL;

static volatile unsigned long *gpdcon = NULL;

//volatile unsigned long *gpddat = NULL;

static volatile unsigned long *gpgcon = NULL;

//static volatile unsigned long *gpgdat = NULL;

static int __init czlcdfb_init(void)

{

 int ret;

 int i = 0;

 unsigned long saddr1, saddr2, saddr3;

 struct fb_fix_screeninfo *czfix;//still forbit,why????

 struct fb_var_screeninfo *czvar;

 

 gpccon = (volatile unsigned long *)ioremap(0x56000020,4);

 //gpcdat = gpccon +1;

 gpdcon = (volatile unsigned long *)ioremap(0x56000030,4);

 //gpddat = gpdcon +1;

 gpgcon = (volatile unsigned long *)ioremap(0x56000060,4);

 //gpgdat = gpgcon +1;

 

 *gpccon  = 0xaaaaaaaa;

 *gpdcon  = 0xaaaaaaaa;

 *gpgcon  |= (0x3<<(4*2));

 

 //pczfb_info = framebuffer_alloc(sizeof(struct fb_info),NULL);

 pczfb_info = framebuffer_alloc(0,NULL);

 printk("framebuffer_alloc successed\n");

 czfix = &pczfb_info->fix;

 czvar = &pczfb_info->var;

 

 //tips:about -> and . 's difference!error: request for member `id' in something not a structure or union

 strcpy(czfix->id, "czlcdfb");

 printk("strcpy successed\n");

//fix

 czfix->type   = FB_TYPE_PACKED_PIXELS;//see FB_TYPE_

 czfix->type_aux  = 0;     //Interleave for interleaved Planes

 czfix->xpanstep  = 0;     //zero if no hardware panning

 czfix->ypanstep  = 0;     //zero if no hardware panning

 czfix->ywrapstep  = 0;    //zero if no hardware ywrap

 czfix->accel   = FB_ACCEL_NONE; //Indicate to driver which

 

 czfix->smem_len  = 320*240*16/8;       //Length of frame buffer mem in bytes

 czfix->line_length = 320*16/8;

 czfix->visual   = FB_VISUAL_TRUECOLOR; /* TFT */

 pczfb_info->screen_size   = 320*240*16/8;

 

 map_size = czfix->smem_len;

 

//if (!request_mem_region(czfix.smem_start,czfix.smem_len, "s3c2410-lcd"))ret = -EBUSY;

//fb_info->screen_base = ioremap(czfix.smem_start, czfix.smem_len);

//fb_info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len,

     //(dma_addr_t *)&info->fix.smem_start, GFP_KERNEL);

 

 map_cpu = dma_alloc_writecombine(NULL, czfix->smem_len, &map_dma, GFP_KERNEL);

 if (!map_cpu)

    return -ENOMEM;

 printk("dma_alloc_writecombine successed\n");

    pczfb_info->screen_base =   map_cpu; 

 czfix->smem_start =   map_dma;

 

//var

 czvar->xres   = 320;     //visible resolution

 czvar->xres_virtual = 320;     //virtual resolution

 czvar->yres   = 240;

 czvar->yres_virtual = 240;

 

 czvar->red.offset = 11;

 czvar->green.offset = 5;

 czvar->blue.offset  = 0;

 czvar->transp.offset = 0;

 czvar->red.length = 5;

 czvar->green.length = 6;

 czvar->blue.length  = 5;

 czvar->transp.length = 0; 

 czvar->activate  = FB_ACTIVATE_NOW;  //set values immediately (or vbl)

 czvar->accel_flags  = 0;     //(OBSOLETE) see fb_info.flags

 czvar->bits_per_pixel = 16;

 czvar->nonstd  = 0;

 //fbinfo->var.height  = mach_info->height;

 //fbinfo->var.width  = mach_info->width;

 czvar->vmode  = FB_VMODE_NONINTERLACED;

 printk("FB_VMODE_NONINTERLACED successed\n");

//there will be oops for the code below,why?????????

#if 0

 czvar->upper_margin = S3C2410_LCDCON2_GET_VBPD(pczs3c2410fb_hw->lcdcon2) + 1;

 czvar->lower_margin = S3C2410_LCDCON2_GET_VFPD(pczs3c2410fb_hw->lcdcon2) + 1;

 czvar->vsync_len  = S3C2410_LCDCON2_GET_VSPW(pczs3c2410fb_hw->lcdcon2) + 1;

 czvar->left_margin  = S3C2410_LCDCON3_GET_HFPD(pczs3c2410fb_hw->lcdcon3) + 1;

 czvar->right_margin = S3C2410_LCDCON3_GET_HBPD(pczs3c2410fb_hw->lcdcon3) + 1;

 czvar->hsync_len  = S3C2410_LCDCON4_GET_HSPW(pczs3c2410fb_hw->lcdcon4) + 1;

#endif 

//pczfb_info 

 pczfb_info->fbops    = &czlcdfb_ops;

 pczfb_info->flags    = FBINFO_FLAG_DEFAULT;//?

 pczfb_info->pseudo_palette  = pseudo_pal;

 printk("pseudo_palette successed\n");

/*

//entry is clear/invalid

#define PALETTE_BUFF_CLEAR (0x80000000) 

// error: 'for' loop initial declaration used outside C99 mode

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

  palette_buffer[i] = PALETTE_BUFF_CLEAR;}

 printk("palette_buffer successed\n");

*/ 

/* 

//irq

 ret = request_irq(IRQ_LCD, s3c2410fb_irq, IRQF_DISABLED, "s3c2410-lcd", "unique_ID for free irq");

 if (ret) {

  printk("cannot get irq %d - err %d\n", irq, ret);

  return -EBUSY;

 }*/

 //error: syntax error before ')' token

 //pczs3c2410fb_hw =((*pczs3c2410fb_hw) *)ioremap(S3C24XX_PA_LCD, S3C24XX_SZ_LCD);

    //error: `s3c2410fb_hw' undeclared (first use in this function)

 //pczs3c2410fb_hw =(s3c2410fb_hw *)ioremap(S3C24XX_PA_LCD, S3C24XX_SZ_LCD);

 

 //pczs3c2410fb_hw =(volatile unsigned long *)ioremap(S3C24XX_PA_LCD, S3C24XX_SZ_LCD);

 pczs3c2410fb_hw =(volatile unsigned long *)ioremap(S3C24XX_PA_LCD, sizeof(struct s3c2410fb_hw));

 printk("pczs3c2410fb_hw successed\n");

 pczs3c2410fb_hw->lcdcon1 = (4<<8)|(3<<5)|(12<<1)|(0<<0);

 pczs3c2410fb_hw->lcdcon2 = (2<<24)|(239<<14)|(6<<6)|(12<<0);

 pczs3c2410fb_hw->lcdcon3 = (24<<19)|(319<<8)|(28<<0);

 pczs3c2410fb_hw->lcdcon4 = (42<<0);

 pczs3c2410fb_hw->lcdcon5 = (1<<11)|(0<<10)|(1<<9)|(1<<8)|(0<<7)|(0<<6)|(0<<5)|(0<<3)|(0<<1)|(1<<0);

 //saddr1 = czfix->smem_start >> 1&0x3fffffff;

 saddr1 = (czfix->smem_start >> 1);

 printk("saddr1 successed\n");

 //saddr2 =( czfix->smem_start+czfix->smem_len)>>1&0xfffff;

 saddr2 = czfix->smem_start;

 saddr2 += (czvar->xres * czvar->yres * czvar->bits_per_pixel)/8;

 saddr2>>= 1;

 printk("saddr2 successed\n");

 //saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH((czvar->xres * czvar->bits_per_pixel / 16) & 0x7ff);

 saddr3 =  S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH(czvar->xres * czvar->bits_per_pixel / 16);

 printk("saddr3 successed\n");

 pczs3c2410fb_hw->lcdsaddr1 = saddr1;

 pczs3c2410fb_hw->lcdsaddr2 = saddr2;

 pczs3c2410fb_hw->lcdsaddr3 = saddr3;

 printk("pczs3c2410fb_hw->lcdsaddr3 = saddr3 successed\n");

#if 0 

 //tips:Unable to handle kernel paging request at virtual address 000b00da, why????????

 writel(saddr1, pczs3c2410fb_hw->lcdsaddr1);

 printk("writel saddr1 successed\n");

 writel(saddr2, pczs3c2410fb_hw->lcdsaddr2);

 printk("writel saddr2 successed\n");

 writel(saddr3, pczs3c2410fb_hw->lcdsaddr3);

 printk("writel saddr3 successed\n");

#endif

 ret = register_framebuffer(pczfb_info);

 if (ret < 0)

  printk("failed to register framebuffer device: %d\n", ret);

 printk("register_framebuffer successed\n");

 pczs3c2410fb_hw->lcdcon5 = pczs3c2410fb_hw->lcdcon5|(1<<3);

 printk("pczs3c2410fb_hw->lcdcon5|(1<<3) successed\n");

 pczs3c2410fb_hw->lcdcon1 = pczs3c2410fb_hw->lcdcon1|(1<<0);

 printk("pczs3c2410fb_hw->lcdcon1|(1<<7) successed\n");

 //*gpgdat  |= 1<<4; //this way is wrong!remember!

 

 return 0;

}

static void __exit czlcdfb_exit(void)

{

  unregister_framebuffer(pczfb_info);

 dma_free_writecombine(NULL, map_size, map_cpu, map_dma);

 iounmap(pczs3c2410fb_hw);

 framebuffer_release(pczfb_info);

 

 iounmap(gpccon);

 iounmap(gpdcon);

 iounmap(gpgcon);

 //pczs3c2410fb_hw->lcdcon1 = (pczs3c2410fb_hw->lcdcon1|(0<<0));

 //pczs3c2410fb_hw->lcdcon5 = (pczs3c2410fb_hw->lcdcon5|(0<<3));

 

 return;

}

module_init(czlcdfb_init);

module_exit(czlcdfb_exit);

MODULE_AUTHOR("chaozang(cz) <zangchao.cn@gmail.com>, copy frm teacher:weidongshan,thanks so much!");

MODULE_DESCRIPTION("LCD Controller framebuffer driver");

MODULE_LICENSE("GPL");

----------------------------------------------------test commands----------------------------------------------------------

# insmod cfbcopyarea.ko

#insmod cfbfillrect.ko

#insmod cfbimgblt.ko

#echo test >/dev/tty1

#echo xxx.ko >/dev/fb0

-----------------------------------------------------------------------------

Contact: zangchao.cn@gmail.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: