LCD驱动(输入子系统)

发布者:CrystalBreeze最新更新时间:2016-04-01 来源: eefocus关键字: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 “asm/io.h“
#include “asm/uaccess.h“
#include “asm/div64.h“
 
#include “asm/mach/map.h“
#include “asm/arch/regs-lcd.h“
#include “asm/arch/regs-gpio.h“
#include “asm/arch/fb.h“
 
static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red,
                             unsigned int green, unsigned int blue,
                             unsigned int transp, struct fb_info *info);
 
 
struct lcd_regs {
     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 reserved[9];
    unsigned long dithmode;
    unsigned long tpal;
    unsigned long lcdintpnd;
    unsigned long lcdsrcpnd;
    unsigned long lcdintmsk;
    unsigned long lpcsel;
};
 
static struct fb_info *s3c_lcd;
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 volatile struct lcd_regs* lcd_regs;
static u32 pseudo_palette[16];
 
 
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 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;
 
     
     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))[regno] = val;
     pseudo_palette[regno] = val;
     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)
{
     // 1. 分配一个fb_info 
     s3c_lcd = framebuffer_alloc(0, NULL);
 
     // 2. 设置 //
     // 2.1 设置固定的参数 //
     strcpy(s3c_lcd->fix.id, "mylcd");
     s3c_lcd->fix.smem_len = 240*320*16/8;
     s3c_lcd->fix.type     = FB_TYPE_PACKED_PIXELS;
     s3c_lcd->fix.visual   = FB_VISUAL_TRUECOLOR;
     s3c_lcd->fix.line_length = 240*2;
     // 2.2 设置可变的参数 
     s3c_lcd->var.xres           = 240;
     s3c_lcd->var.yres           = 320;
     s3c_lcd->var.xres_virtual   = 240;
     s3c_lcd->var.yres_virtual   = 320;
     s3c_lcd->var.bits_per_pixel = 16;
 
     // RGB:565 
     s3c_lcd->var.red.offset     = 11;
     s3c_lcd->var.red.length     = 5;
     s3c_lcd->var.green.offset   = 5;
     s3c_lcd->var.green.length   = 6;
 
     s3c_lcd->var.blue.offset    = 0;
     s3c_lcd->var.blue.length    = 5;
 
     s3c_lcd->var.activate       = FB_ACTIVATE_NOW;
     // 2.3 设置操作函数 
     s3c_lcd->fbops              = &s3c_lcdfb_ops;
     // 2.4 其他的设置 
     s3c_lcd->pseudo_palette = pseudo_palette;
     //s3c_lcd->screen_base  = ;  // 显存的虚拟地址 
     s3c_lcd->screen_size   = 240*324*16/8;
 
     // 3. 硬件相关的操作 
     // 3.1 配置GPIO用于LCD 
     gpbcon = ioremap(0x56000010, 8);
     gpbdat = gpbcon+1;
     gpccon = ioremap(0x56000020, 4);
     gpdcon = ioremap(0x56000030, 4);
     gpgcon = ioremap(0x56000060, 4);
 
     *gpccon  = 0xaaaaaaaa;   //GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND 
     *gpdcon  = 0xaaaaaaaa;   // GPIO管脚用于VD[23:8] 
     *gpbcon &= ~(3);  // GPB0设置为输出引脚 
     *gpbcon |= 1;
     *gpbdat &= ~1;     // 输出低电平 
 
     *gpgcon |= (3<<8); //GPG4用作LCD_PWREN 
     // 3.2 根据LCD手册设置LCD控制器, 比如VCLK的频率等 
     lcd_regs = ioremap(0x4D000000, sizeof(struct lcd_regs));
 
     // bit[17:8]: VCLK = HCLK / [(CLKVAL+1) x 2], LCD手册P14
      *            10MHz(100ns) = 100MHz / [(CLKVAL+1) x 2]
      *            CLKVAL = 4
      * bit[6:5]: 0b11, TFT LCD
      * bit[4:1]: 0b1100, 16 bpp for TFT
      * bit[0]  : 0 = Disable the video output and the LCD control signal.
     //
     lcd_regs->lcdcon1  = (4<<8) | (3<<5) | (0x0c<<1);
 
#if 1
     // 垂直方向的时间参数
      * bit[31:24]: VBPD, VSYNC之后再过多长时间才能发出第1行数据
      *             LCD手册 T0-T2-T1=4
      *             VBPD=3
      * bit[23:14]: 多少行, 320, 所以LINEVAL=320-1=319
      * bit[13:6] : VFPD, 发出最后一行数据之后,再过多长时间才发出VSYNC
      *             LCD手册T2-T5=322-320=2, 所以VFPD=2-1=1
      * bit[5:0]  : VSPW, VSYNC信号的脉冲宽度, LCD手册T1=1, 所以VSPW=1-1=0
      //
     lcd_regs->lcdcon2  = (3<<24) | (319<<14) | (1<<6) | (0<<0);
 
 
     // 水平方向的时间参数
      * bit[25:19]: HBPD, VSYNC之后再过多长时间才能发出第1行数据
      *             LCD手册 T6-T7-T8=17
      *             HBPD=16
      * bit[18:8]: 多少列, 240, 所以HOZVAL=240-1=239
      * bit[7:0] : HFPD, 发出最后一行里最后一个象素数据之后,再过多长时间才发出HSYNC
      *             LCD手册T8-T11=251-240=11, 所以HFPD=11-1=10
      //
     lcd_regs->lcdcon3 = (16<<19) | (239<<8) | (10<<0);
 
     // 水平方向的同步信号
      * bit[7:0] : HSPW, HSYNC信号的脉冲宽度, LCD手册T7=5, 所以HSPW=5-1=4
      //
     lcd_regs->lcdcon4 = 4;
 
#else
lcd_regs->lcdcon2 = S3C2410_LCDCON2_VBPD(5) | \
               S3C2410_LCDCON2_LINeval_r(319) | \
               S3C2410_LCDCON2_VFPD(3) | \
               S3C2410_LCDCON2_VSPW(1);
 
lcd_regs->lcdcon3 = S3C2410_LCDCON3_HBPD(10) | \
               S3C2410_LCDCON3_HOZVAL(239) | \
               S3C2410_LCDCON3_HFPD(1);
 
lcd_regs->lcdcon4 = S3C2410_LCDCON4_MVAL(13) | \
               S3C2410_LCDCON4_HSPW(0);
 
#endif
     // 信号的极性 
      * bit[11]: 1=565 format
      * bit[10]: 0 = The video data is fetched at VCLK falling edge
      * bit[9] : 1 = HSYNC信号要反转,即低电平有效 
      * bit[8] : 1 = VSYNC信号要反转,即低电平有效 
      * bit[6] : 0 = VDEN不用反转
      * bit[3] : 0 = PWREN输出0
      * bit[1] : 0 = BSWP
      * bit[0] : 1 = HWSWP 2440手册P413
      //
     lcd_regs->lcdcon5 = (1<<11) | (0<<10) | (1<<9) | (1<<8) | (1<<0);
     // 3.3 分配显存(framebuffer), 并把地址告诉LCD控制器 
     s3c_lcd->screen_base = dma_alloc_writecombine(NULL, s3c_lcd->fix.smem_len, &s3c_lcd->fix.smem_start, GFP_KERNEL);
     lcd_regs->lcdsaddr1  = (s3c_lcd->fix.smem_start >> 1) & ~(3<<30);
     lcd_regs->lcdsaddr2  = ((s3c_lcd->fix.smem_start + s3c_lcd->fix.smem_len) >> 1) & 0x1fffff;
     lcd_regs->lcdsaddr3  = (240*16/16);  // 一行的长度(单位: 2字节) 
     //s3c_lcd->fix.smem_start = xxx;  // 显存的物理地址 
     // 启动LCD 
     lcd_regs->lcdcon1 |= (1<<0); // 使能LCD控制器 
     lcd_regs->lcdcon5 |= (1<<3); // 使能LCD本身 
     *gpbdat |= 1;     // 输出高电平, 使能背光
 
     // 4. 注册 
     register_framebuffer(s3c_lcd);
     return 0;
}
 
static void lcd_exit(void)
{
     unregister_framebuffer(s3c_lcd);
     lcd_regs->lcdcon1 &= ~(1<<0); // 关闭LCD本身 
     *gpbdat &= ~1;     // 关闭背光 
     dma_free_writecombine(NULL, s3c_lcd->fix.smem_len, s3c_lcd->screen_base, s3c_lcd->fix.smem_start);
     iounmap(lcd_regs);
     iounmap(gpbcon);
     iounmap(gpccon);
     iounmap(gpdcon);
     iounmap(gpgcon);
     framebuffer_release(s3c_lcd);
}
 
module_init(lcd_init);
module_exit(lcd_exit);
 
MODULE_LICENSE("GPL");
 
============================================================
解析:
 
LCD驱动程序
 
假设
app:  open("/dev/fb0", ...)   主设备号: 29, 次设备号: 0
--------------------------------------------------------------
kernel:
         fb_open
          int fbidx = iminor(inode);
          struct fb_info *info = = registered_fb[0];
 
app:  read()
---------------------------------------------------------------
kernel:
fb_read
int fbidx = iminor(inode);
struct fb_info *info = registered_fb[fbidx];
if (info->fbops->fb_read)
return info->fbops->fb_read(info, buf, count, ppos);
         
src = (u32 __iomem *) (info->screen_base + p);
dst = buffer;
*dst++ = fb_readl(src++);
copy_to_user(buf, buffer, c)        
 
问1. registered_fb在哪里被设置?
答1. register_framebuffer
 
怎么写LCD驱动程序?
1. 分配一个fb_info结构体: framebuffer_alloc
2. 设置
3. 注册: register_framebuffer
4. 硬件相关的操作
 
测试:
1. make menuconfig去掉原来的驱动程序
-> Device Drivers
  -> Graphics support
S3C2410 LCD framebuffer support
 
2. make uImage
   make modules  
之后会在内核的linux-2.6.22.6/drivers/video目录下生成:
    cfbcopyarea.ko 
    cfbfillrect.ko 
    cfbimgblt.ko
拷贝到lcd.ko所在目录下即可。
 
3. 使用新的uImage启动开发板:
 
4. 
insmod cfbcopyarea.ko 
insmod cfbfillrect.ko 
insmod cfbimgblt.ko 
insmod lcd.ko
 
echo hello > /dev/tty1  // 可以在LCD上看见hello
cat lcd.ko > /dev/fb0   // 花屏
 
5. 修改 /etc/inittab
tty1::askfirst:-/bin/sh
用新内核重启开发板
 
insmod cfbcopyarea.ko 
insmod cfbfillrect.ko 
insmod cfbimgblt.ko 
insmod lcd.ko
insmod buttons.ko
 
关键字:LCD驱动  输入子系统 引用地址:LCD驱动(输入子系统)

上一篇:触摸屏驱动程序(输入子系统)
下一篇:按键驱动--定时器消抖

推荐阅读最新更新时间:2024-03-16 14:49

LCD驱动器SD0432与嵌入式系统的接口设计
摘要:集成LCD显示驱动器SD0432是深圳兴威帆电子有限公司生产的低工作电压串行接口芯片,它内部具有看门狗(WDT)及语音输出电路。文中介绍了SD0432的工作特性及工作原理,给出了SD0432与8051嵌入式微处理器的接口电路及部分程序代码。 关键词:LCD显示驱动器 SD0432 嵌入式系统芯片8051 看门狗(WDT) 1 SD0432的主要特性 现今,随着LCD价格的下降,LCD的使用已经越来越普遍了,如在电脑显示器方面,大有LCD显示器取代CRT显示器的趋势。同时由于LCD显示器具有直观、小巧轻薄、耐用等特性,因而得到了广泛的使用。 SD0432是具有128段(32%26;#215;4位)和映射存储器
[应用]
stm32 TFTLCD驱动原理(三)
代码的实现 (1) 首先是对 TFTLCD 进行引脚初始化 static void LCD_GPIO_Config ( void ) { GPIO_InitTypeDef GPIO_InitStructure; /* 使能复用IO时钟:复用为fsmc功能 */ RCC_APB2PeriphClockCmd ( RCC_APB2Periph_AFIO, ENABLE ); /* 使能FSMC对应相应管脚时钟 */ RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, ENABLE ); FSMC_LCD_CS_
[单片机]
新型LCD驱动电路IP核的总体设计
  本文介绍了LCD的通用驱动电路IP核设计,采用自顶向下的设计方法将其划分为几个主要模块,分别介绍各个模块的功能,用VHDL语言对其进行描述,用FPGA实现并通过了仿真验证。该IP核具有良好的移植性,可驱动不同规模的LCD电路。    引言   LCD因具有工作电压低、功耗小、显示信息量大、寿命长、易集成、方便携带和电磁辐射污染小等优点,在显示技术中异军突起,被广泛应用于手机、PDA产品、手持式仪器仪表等便携式电子产品与设备中。   LCD驱动电路是液晶显示系统的重要组成部分,是一种计算机(或MCU)和液晶屏之间的接口电路,其主要功能是通过调制输出到液晶显示器件电极上的电位信号的相位、峰值、频率等参数来建立交流驱动电场。由于L
[电源管理]
新型<font color='red'>LCD驱动</font>电路IP核的总体设计
SEP3203与伪彩LCD驱动SSD1770的接口设计
SSD1770是晶门科技公司于2005年推出的一款用于点阵显示系统的单片CMOS彩色STN LCD驱动控制器。目前,SSD1770已经应用于传统的工控机领域8080系列微控制器的连接,而在32位嵌入式系统领域内的应用还很少,本文主要研究LCD控制器SSD1770与ARM7TDMI内核的嵌入式微处理器SEP3203之间的系数连接及底层、上层软件开发,并最终在产品中得到应用。 1 系统介绍 1.1 系统构成   系统主要由SEP3203处理器和伪彩点阵型图形LCD控制器SSD1770组成,系统接口示意图如图1所示。    1.2 SEP3203概述   SEP3203是由东南大学国家专用集成电路(ASIC)与系统工程技
[应用]
mini2440 LCD驱动
mini2440集成了lcd控制器的接口,板子上接的lcd硬件是统宝240*320,TFT型lcd。lcd驱动对应的文件为s3c2410fb.c。要读懂这个驱动必须了解linux platform子系统的知识。因为这个驱动是以platform驱动的形式注册到内核。而且还需要frambuffer驱动的知识,因为这个驱动还是frambuffer接口的。lcd驱动在模块初始化的时候,调用platform注册函数将自己注册到内核,利用linux设备模型核心的机制调用platform_bus总线的match函数找到相应的设备,然后由linux设备模型核心调用s3c2410fb.c中的s3c2410fb_probe ,进行硬件相关初始化,并初
[单片机]
S3C2440,Linux,LCD驱动
到了神秘的LCD驱动了,信息还真有点胆怯,但是还是不得不走下去。对刚刚学习的linux驱动坐一下总结,毕竟是Linux内核当中的东东,而且是那么的繁琐。做一总结,等用笔记把学过东西几下来,这样就不会忘了。哈哈! 那就开始!!! 在编写裸机LCD程序的时候,首先就是硬件初始化操作。有一个寄存器当中存放了帧缓冲的起始地址。这个参数是非常重要的。当配置好硬件后,帧缓冲中的数据能够脱离CPU不停地将真缓冲当中的数据写入到LCD屏。如果我们要现实一个图片的话只需要将图片数据放到帧缓冲当中,这样就非常的方便了。 在linux当中,把整个LCD驱动分为两层:LCD帧缓冲区层和LCD硬件驱动层。LCD帧缓冲区层其实就是将内核中的一部分空间当作一个
[单片机]
S3C2440上LCD驱动(FramBuffer)实例开发详解(一)
嵌入式Linux之我行,主要讲述和总结了本人在学习嵌入式linux中的每个步骤。一为总结经验,二希望能给想入门嵌入式Linux的朋友提供方便。如有错误之处,谢请指正。 一、开发环境 编译器:arm-linux-gcc-4.3.2 二、背景知识 1. LCD工作的硬件需求: 要使一块LCD正常的显示文字或图像,不仅需要LCD驱动器,而且还需要相应的LCD控制器。在通常情况下,生产厂商把LCD驱动器会以COF/COG的形式与LCD玻璃基板制作在一起,而LCD控制器则是由外部的电路来实现,现在很多的MCU内部都集成了LCD控制器,如S3C2410/2440等。通过LCD控制器就可以产生LCD驱动器所需要的控制信号来控制STN/T
[单片机]
S3C2440上<font color='red'>LCD驱动</font>(FramBuffer)实例开发详解(一)
传京东方将入股LCD驱动IC封测厂颀邦
集微网消息,传京东方看上全球最大TFT-LCD专业封测厂台湾颀邦,将寻紫光与南茂结盟模式,认购颀邦位于苏州厂的颀中科技股权,若无意外,第3季底前双方将完成股权移转的合约签订。 消息是否属实,目前无法从公司获得证实。 京东方目前每年面板的产量至少2300万片,是颀邦公司在大陆的最大客户;京东方继北京、合肥、重庆等三地三座8.5代厂投产后,前年又投入逾300亿元人民币兴建第四座8.5代福州厂,且该新厂就在日前悄悄完工投产,委托释出到颀邦进行的封测代工订单,也快速拉高,是挤爆颀邦下半年产能的关键所在。 京东方集团企图往半导体封测产业链发展,有意打造一条龙的服务,看上有业务合作关系同时是全球最大TFT-LCD专业封测厂的颀邦。 传京东方原
[手机便携]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved