- 论坛徽章:
- 0
|
编译,加载到内核后。执行echo hello > /dev/tty1 LCD屏幕上没有反应。纠结几天了。麻烦大家抽空指导一下。内核版本linux-2.6.32
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <asm/io.h>
#include <asm/div64.h>
#include <asm/mach/map.h>
#include <mach/regs-lcd.h>
#include <mach/regs-gpio.h>
#include <mach/fb.h>
#define M5D(n) ((n)&0x1fffff)
static volatile unsigned long * GPCCON;
static volatile unsigned long * GPCDAT;
static volatile unsigned long * GPDCON;
static volatile unsigned long * GPGCON;
static volatile unsigned long * GPGUP;
/*由于LCD寄存器太多,逐个映射比较复杂,这里我们设置一个寄存器结构体 */
struct lcd_reg{
unsigned long LCDCON1;
unsigned long LCDCON2;
unsigned long LCDCON3;
unsigned long LCDCON4;
unsigned long LCDCON5;
unsigned long LCDSADDR1;
unsigned long LCDSADDR2;
unsigned long LCDSADDR3;
unsigned long REDLUT;
unsigned long GREENLUT;
unsigned long BLUELUT;
unsigned long UNUSED[8];
unsigned long DITHMOD;
unsigned long TPAL;
unsigned long LCDINTPND;
unsigned long LCDSRCPND;
unsigned long LCDINTMSK;
unsigned long TCONSEL;
};
static u32 pseudo_pal[16];
static volatile struct lcd_reg * lcdreg;
static struct fb_info * fbinfo;
static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
{
chan &= 0xffff;
chan >>= 16 - bf->length;
return chan << bf->offset;
}
static int lcd_setcolreg(unsigned regno,unsigned red, unsigned green, unsigned blue,unsigned transp, struct fb_info *info){
unsigned int val;
u32 *pal = fbinfo->pseudo_palette;
if (regno > 16)
return 1;
val |= chan_to_field(red, &info->var.red);
val |= chan_to_field(green, &info->var.green);
val |= chan_to_field(blue, &info->var.blue);
pal[regno] = val;
// printk("pal[%d] = %d\n",regno,val);
return 0;
}
static struct fb_ops lcd_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = lcd_setcolreg, //虚拟调色板的设置
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
static int __init Mylcd_init(void)
{
int ret;
/*1、 分配一个fb_info结构体 */
fbinfo = framebuffer_alloc(0, NULL);
/*2、 对fbinfo结构体进行设置 */
/*2.1 设置固定参数 */
strcpy(fbinfo->fix.id,"mylcd" ; /*字符串形式的标示符 */
fbinfo->fix.smem_len = 240 * 320 * 2; //缓存的长度
fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; //看FB_TYPE_
fbinfo->fix.visual = FB_VISUAL_TRUECOLOR; //设置为真彩色
fbinfo->fix.line_length = 240 * 2; //一行占有的字节数
/*2.2 设置可变参数*/
fbinfo->var.xres = 240; //可见屏一行有240个像素点
fbinfo->var.yres = 320; //可见屏一列有320个像素点
fbinfo->var.bits_per_pixel = 16; //每个像素点的位数
/* 颜色RGB565 */
fbinfo->var.red.offset = 11; //红色的起始bit
fbinfo->var.red.length = 5; //红色所占的位数
fbinfo->var.red.offset = 5; //绿色的起始bit
fbinfo->var.red.length = 6; //绿色所占的位数
fbinfo->var.red.offset = 0; //蓝色的起始bit
fbinfo->var.red.length = 5; //蓝色所占的位数
fbinfo->var.activate = FB_ACTIVATE_NOW;
/*2.3 设置操作函数 */
fbinfo->fbops = &lcd_ops;
/*2.4 其他的设置*/
// fbinfo->pseudo_palette;
// fbinfo->screen_base; //显存的虚拟地址
fbinfo->screen_size = 240*320*16/8; //显存的大小
fbinfo->pseudo_palette = pseudo_pal; //设置虚拟调色板
/*3、 硬件相关操作,包括1、配置GPIO寄存器,用于LCD;2、根据LCD手册设置LCD控制器;3、分配显存*/
/* 设置缓存的开始物理地址 */
// fbinfo->fix.smem_start;
/* 3.2配置GPIO管脚用于LCD */
GPCCON = ioremap(0x56000020,4);
// GPCDAT = GPCCON + 1;
*GPCCON = 0xaaaaaaaa; //VD0~VD7,LEND~LRCPEVB对应的管脚GPC0~GPC15
GPDCON = ioremap(0x56000030,4);
*GPDCON = 0xaaaaaaaa; //VD8~VD23对应的管脚GPD0~GPD15
GPGCON = ioremap(0x56000060,4);
// GPGUP = GPGCON + 2;
*GPGCON |= (3 << ; //LCD_PWREN对应管脚GPG4
// * GPGUP |= (1 << 4); //禁止内部上拉
/* 3.3配置LCD的寄存器 */
lcdreg = ioremap(0x4d000000,sizeof(struct lcd_reg));
lcdreg->LCDCON1 |= (0x9 << | (0x0 << 7) | (0x3 << 5) | (0xc << 1) | (0x0 << 0); //对LCDCON1进行设置,使CLKVAL=9,PNRMODE=3,BPPMODE=C,ENVID=0
// printk("lcdcon1 = %lx",&lcdreg->LCDCON1);
lcdreg->LCDCON2 |= (0x1 << 24) | (0x13f << 14) | (0x5 << 6) | (0x1 << 0); //对LCDCON2进行设置,使VSPW=5,VBPD=36,VFPD=5,LINEVAL=319
// printk("lcdcon2 = %lx",&lcdreg->LCDCON2);
lcdreg->LCDCON3 |= (0x24 << 19) | (0xef << | (0x13 << 0); //对LCDCON3进行设置,使HBPD=36,HFBPD=36,HOZVAL=239
// printk("lcdcon3 = %lx",&lcdreg->LCDCON3);
lcdreg->LCDCON4 |= (0x5 << 0); //设置LCDCON4的HSPW=5
// printk("lcdcon4 = %lx",&lcdreg->LCDCON4);
lcdreg->LCDCON5 |= (0x1 << 11) | (0x0 << 3) | (0x0 << 1) | (0x1 << 0); //设置LCDCON5的FRM565=1,BSWP=0,HWSWP=1,PWREN=0 关闭LCD电源
// lcdreg->TPAL |= (0x1 << 24) | ((0xff0000 & 0xffffff) << 0); //打开临时调色板
// printk("lcdcon5 = %lx",&lcdreg->LCDCON5);
/* 3.4分配显存 */
fbinfo->screen_base = dma_alloc_writecombine(NULL, fbinfo->fix.smem_len,(dma_addr_t *)&fbinfo->fix.smem_start, GFP_KERNEL);
lcdreg->LCDSADDR1 |= ((fbinfo->fix.smem_start >> 22) << 21) | (M5D(fbinfo->fix.smem_start >> 1) << 0); //设置LCDSADDR1
// printk("lcdsaddr1 = %lx",&lcdreg->LCDSADDR1);
lcdreg->LCDSADDR2 |= (M5D((fbinfo->fix.smem_start + fbinfo->fix.smem_len) >> 1) << 0); //设置LCDBASEL/
// printk("lcdsaddr2 = %lx",&lcdreg->LCDSADDR2);
lcdreg->LCDSADDR3 |= (0x0 << 11) | (0xf0 << 0); //设置OFFSIZE=0x0,PAGEWIDTH=240*16\16
// printk("lcdsaddr3= %lx",&lcdreg->LCDSADDR3);
/* 3.5打开LCD电源 */
lcdreg->LCDCON1 |= 0x1; //打开LCD控制器,使能LCD
lcdreg->LCDCON5 |= (0x1 << 3) | (0x1 << 2); //打开LCD本身电源
/*4、 注册平台设备 */
ret = register_framebuffer(fbinfo); //注册framebuffer
return 0;
}
static void __exit Mylcd_exit(void)
{
unregister_framebuffer(fbinfo); //释放帧内存
lcdreg->LCDCON1 &= ~0x1; //打开LCD控制器,使能LCD
lcdreg->LCDCON5 &= ~(0x1 << 3); //关闭LCD电源,关闭LCD
// dma_free_writecombine
dma_free_writecombine(NULL, fbinfo->fix.smem_len,fbinfo->screen_base, fbinfo->fix.smem_start);
// dma_free_writecombine (&fb->dev->dev, fb->fb.fix.smem_len,
// fb->fb.screen_base, fb->fb.fix.smem_start);
iounmap(GPDCON);
iounmap(GPGCON);
iounmap(lcdreg);
framebuffer_release(fbinfo);
}
module_init(Mylcd_init);
module_exit(Mylcd_exit);
MODULE_AUTHOR("chai hao" ;
MODULE_DESCRIPTION("My framebuffer driver" ;
MODULE_LICENSE("GPL" ; |
|