wang12zhedi 发表于 2012-11-12 17:06:41

很郁闷呀 LCD的背光灯亮啦,但是屏幕就是不亮呀 怎么回事

#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/workqueue.h>
#include <linux/wait.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/uaccess.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 DBGprintkprintk
//#define DBGprintk(...)

//LCDCON1定义
#define CLKVAL 4
#define MMODE0
#define PNRMODE 3
#define BPPMODE 12
#define ENVIDOFF 0
#define ENVIDON 1

//LCDCON2定义
#define VBPD 2
#define LINEVAL (272-1)
#define VFPD 4//原值4
#define VSPW 8//原值8
//LCDCON3定义
#define HBPD 10
#define HOZVAL (480-1)
#define HFPD 19
//LCDCON4定义
#define MVAL 13
#define HSPW 30
//LCDCON5定义

#define BPP24BL      0
#define FRM565      1
#define INVVCLK   0
#define INVVLINE    1
#define INVVFRAME   1
#define INVVD       0
#define INVVDEN   0
#define INVPWREN    0
#define INVLEND   0
#define PWRENOFF    0
#define PWRENON   1
#define ENLEND      0
#define BSWP      0
#define HWSWP       1//2440手册
//LCDSADD3定义
#define OFFSIZE 0//因为虚拟屏幕和物理屏幕大小一样->0
#define LCDSADDR3 480//因为虚拟屏幕和物理屏幕大小一样->480

//这个结构体中寄存器名字使用大写的话会出现莫明奇妙的错误需要再试试
struct s3c2440_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;//BLUELUT地址0X4D000028
    unsigned long        reserved;//地址0X4D00004C,二者相差9个字节为什么不是bluelut【9】
    unsigned long        dithmode;
    unsigned long        tpal;
    unsigned long        lcdintpnd;
    unsigned long        lcdsrcpnd;
    unsigned long        lcdintmsk;
    unsigned long        tconsel;
        };

//有些需要定义成指针,因为 对应的函数是返回指针的函数
struct s3c2440_reg *s3c2440_regs;
static struct fb_info *mylcd_info;
//static volatile unsigned long *GPBCON;
//static volatile unsigned long *GPBDAT;
static volatile unsigned long *GPCCON;
static volatile unsigned long *GPDCON;
static volatile unsigned long *GPGCON;
static u32 pseudo_palette;//


/* from pxafb.c */
static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
{
   
        chan &= 0xffff;//取出低16位
        chan >>= 16 - bf->length;//chan保存相应颜色的取值
        return chan << bf->offset; //
        DBGprintk(" chan_to_field\n");
}

//设置调色板
static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red,
                             unsigned int green, unsigned int blue,
                             unsigned int transp, struct fb_info *info)
{
        unsigned int val;
       
        if (regno > 16)
                return 1;

        /* 用red,green,blue三原色构造出val */
        val= chan_to_field(red,        &info->var.red);
        val |= chan_to_field(green, &info->var.green);
        val |= chan_to_field(blue,        &info->var.blue);
       
        //((u32 *)(info->pseudo_palette)) = val;
        pseudo_palette = val;
       
        DBGprintk(" val= %d\n",val);
        DBGprintk(" s3c_lcdfb_setcolreg\n");
        return 0;
}


static struct fb_ops s3c_lcdfb_ops = {
        .owner                = THIS_MODULE,
        .fb_setcolreg        = s3c_lcdfb_setcolreg,
        .fb_fillrect        = cfb_fillrect,
        .fb_copyarea        = cfb_copyarea,
        .fb_imageblit        = cfb_imageblit,
};

static int lcd_init(void)
{/*分配一个fb_info */
mylcd_info = framebuffer_alloc(0,NULL);
if(mylcd_info ==NULL)//检查分配是否成功
        DBGprintk(" framebuffer_alloc fail \n");
/*设置固定的参数 */
strcpy(mylcd_info->fix.id, "mylcd");
mylcd_info->fix.smem_len = 480*272*16/8;//RGB565=16
mylcd_info->fix.type   = FB_TYPE_PACKED_PIXELS;/* Packed Pixels塞满 像素        */
mylcd_info->fix.visual   = FB_VISUAL_TRUECOLOR; /* TFT真彩色*/
mylcd_info->fix.line_length = 480*16/8;//一行480个像素 一个像素16位

/*设置可变的参数 */
//硬件确定的分辨率
mylcd_info->var.xres         = 480;
mylcd_info->var.yres         = 272;
//虚拟分辨率;可以通过软件更该 类似电脑分辨率
mylcd_info->var.xres_virtual   = 480;
mylcd_info->var.yres_virtual   = 272;
mylcd_info->var.bits_per_pixel = 16;

/* RGB:565   ->红色偏移值11绿色偏移值5 蓝色偏移值0*/
mylcd_info->var.red.offset   = 11;
mylcd_info->var.red.length   = 5;

mylcd_info->var.green.offset   = 5;
mylcd_info->var.green.length   = 6;

mylcd_info->var.blue.offset    = 0;
mylcd_info->var.blue.length    = 5;

mylcd_info->var.activate       = FB_ACTIVATE_NOW;//看不懂就用默认值 默认值支持大多数

/*设置操作函数 */
mylcd_info->fbops            = &s3c_lcdfb_ops;

/*其他的设置 */
mylcd_info->pseudo_palette = pseudo_palette; /* 伪16色颜色表可能是兼容以前的程序,需要设置假的调色板*/
mylcd_info->screen_size   = 480*272*16/8;

/* 3.1 配置GPIO用于LCD */
//GPBCON = ioremap(0x56000010, 8);//ioremap是一个返回指针的函数
//GPBDAT = GPBCON+1;
GPCCON = ioremap(0x56000020, 4);
GPDCON = ioremap(0x56000030, 4);
GPGCON = ioremap(0x56000060, 4);
//向GPCCVON写入值,特别注意GPCCON是指针
*GPCCON=0xaaaa02a9;   /* GPIO管脚用于VD,LCDVF,VM,VFRAME,VLINE,VCLK,LEND */
*GPDCON= 0xaaaaaaaa;   /* GPIO管脚用于VD */
*GPGCON |= (3<<8); /* GPG4用作LCD_PWREN */

s3c2440_regs = ioremap(0X4D000000, sizeof(struct s3c2440_reg));
s3c2440_regs->lcdcon1= (CLKVAL <<8)|(MMODE<<7)|(PNRMODE<<5)|(BPPMODE<<1)|(ENVIDOFF<<0);
s3c2440_regs->lcdcon2= (VBPD<<24)|(LINEVAL<<14)|(VFPD<<6)|(VSPW<<0);
s3c2440_regs->lcdcon3= (HBPD<<19)|(HOZVAL<<8)|(HFPD<<0);
s3c2440_regs->lcdcon4 =(MVAL<<8)|(HSPW<<0);
s3c2440_regs->lcdcon5 =(FRM565<<11)|(INVVCLK<<10)|(INVVLINE<<9)|(INVVFRAME<<8)|(1<<3)|(1<<2)|(HWSWP<<0);

// 分配显存(framebuffer),专用函数dma_alloc_writecombine分配 */
mylcd_info->screen_base = dma_alloc_writecombine(NULL, mylcd_info->fix.smem_len, &mylcd_info->fix.smem_start, GFP_KERNEL);
//并把地址告诉LCD控制器
s3c2440_regs->lcdsaddr1 = (mylcd_info->fix.smem_start >> 1) & ~(3<<30);//最高两位不需要 ->& ~(3<<30)
s3c2440_regs->lcdsaddr2 = ((mylcd_info->fix.smem_start + mylcd_info->fix.smem_len) >> 1) & 0x1fffff;//只关心21位-> & 0x1fffff
//                                 起始地址   +             大小=结束地址            
s3c2440_regs->lcdsaddr3 = (480*16/16);/* 一行的长度(单位: 2字节) */       

/* 启动LCD */

s3c2440_regs->lcdcon5|= (0<<5)|(PWRENON<<3); /* 使能LCD本身 */
s3c2440_regs->lcdcon1|= (ENVIDON<<0); /* 使能LCD控制器 */


DBGprintk(" lcd_init\n");
/* 4. 注册 */
register_framebuffer(mylcd_info);

return 0;
}


static void lcd_exit(void)
{
        unregister_framebuffer(mylcd_info);
        s3c2440_regs->lcdcon1 &= ~(1<<0); /* 关闭LCD本身 */
       
        dma_free_writecombine(NULL, mylcd_info->fix.smem_len, mylcd_info->screen_base, mylcd_info->fix.smem_start);
        iounmap(s3c2440_regs);
       
        iounmap(GPCCON);
        iounmap(GPDCON);
        iounmap(GPGCON);
        framebuffer_release(mylcd_info);
        DBGprintk(" lcd_exit\n");
}


module_init(lcd_init);
module_exit(lcd_exit);
MODULE_LICENSE("GPL");

embedsky_lhh 发表于 2012-11-13 09:45:39

LCD的时序对了么,在系统里边LCD驱动你加到video中好些,有专门的fb管理,应用操作方便

wang12zhedi 发表于 2012-11-13 12:58:28

终于找到问题啦,加载自己的驱动时需要把原来的驱动LCD去掉,我在配置内核的时候去掉的多啦
页: [1]
查看完整版本: 很郁闷呀 LCD的背光灯亮啦,但是屏幕就是不亮呀 怎么回事