1 #include <linux/kernel.h> 2 #include <linux/dma-mapping.h> 3 #include <linux/fb.h> 4 #include <linux/init.h> 5 #include <linux/gfp.h> 6 #include <linux/module.h> 7 #include <asm/gpio.h> 8 9 /* LCD控制器 */ 10 volatile unsigned int *GPF0CON; 11 volatile unsigned int *GPF1CON; 12 volatile unsigned int *GPF2CON; 13 volatile unsigned int *GPF3CON; 14 volatile unsigned int *GPD0CON; 15 volatile unsigned int *GPD0DAT; 16 volatile unsigned int *CLK_SRC_LCD0; 17 volatile unsigned int *CLK_DIV_LCD; 18 volatile unsigned int *LCDBLK_CFG; 19 volatile unsigned int *VIDCON0; 20 volatile unsigned int *VIDCON1; 21 volatile unsigned int *VIDCON2; 22 volatile unsigned int *VIDTCON0; 23 volatile unsigned int *VIDTCON1; 24 volatile unsigned int *VIDTCON2; 25 volatile unsigned int *WINCON0; 26 volatile unsigned int *SHADOWCON; 27 volatile unsigned int *WINCHMAP2; 28 volatile unsigned int *VIDOSD0A; 29 volatile unsigned int *VIDOSD0B; 30 volatile unsigned int *VIDOSD0C; 31 volatile unsigned int *VIDW0nADD0Bn; 32 volatile unsigned int *VIDW0nADD1Bn; 33 volatile unsigned int *VIDW0nADD2; 34 35 struct fb_info *lcd_info; 36 u32 pseudo_palette[16]; 37 38 static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf) { 39 chan &= 0xffff; 40 chan >>= 16 - bf->length; 41 return chan << bf->offset; 42 } 43 44 /* 伪颜色表函数 */ 45 static int lcd_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue, unsigned int transp, struct fb_info *info) { 46 unsigned int val; 47 u32 *pal; 48 49 /* 真彩色,设置伪颜色值 */ 50 if (regno < 16) { 51 pal = pseudo_palette; 52 53 val = chan_to_field(red, &info->var.red); 54 val |= chan_to_field(green, &info->var.green); 55 val |= chan_to_field(blue, &info->var.blue); 56 57 pal[regno] = val; 58 } 59 return 0; 60 61 } 62 63 /* fb_ops结构 */ 64 struct fb_ops lcd_ops = { 65 .owner = THIS_MODULE, 66 .fb_setcolreg = lcd_setcolreg, 67 .fb_fillrect = cfb_fillrect, 68 .fb_copyarea = cfb_copyarea, 69 .fb_imageblit = cfb_imageblit, 70 }; 71 72 static int __init lcd_init(void) { 73 int ret; 74 75 /* 1.分配结构体 */ 76 lcd_info = framebuffer_alloc(0, NULL); 77 if (!lcd_info) { 78 printk("cannot allocate memory\n"); 79 return -ENOMEM; 80 } 81 /* 2.结构体的初始化 */ 82 memcpy(lcd_info->fix.id, "lcd", 16); 83 //lcd_info->fix.smem_start = 84 lcd_info->fix.smem_len = 1024 * 600 * 16 / 8; 85 lcd_info->fix.type = FB_TYPE_PACKED_PIXELS; 86 lcd_info->fix.visual = FB_VISUAL_TRUECOLOR; 87 lcd_info->fix.line_length = 1024 * 2; 88 89 lcd_info->var.xres = 1024; 90 lcd_info->var.yres = 600; 91 lcd_info->var.xres_virtual = 1024; 92 lcd_info->var.yres_virtual = 600; 93 lcd_info->var.xoffset = 0; 94 lcd_info->var.yoffset = 0; 95 lcd_info->var.bits_per_pixel = 16; 96 lcd_info->var.red.offset = 11; 97 lcd_info->var.red.length = 5; 98 lcd_info->var.green.offset = 5; 99 lcd_info->var.green.length = 6; 100 lcd_info->var.blue.offset = 0; 101 lcd_info->var.blue.length = 5; 102 lcd_info->var.activate = FB_ACTIVATE_NOW; 103 104 lcd_info->fbops = &lcd_ops; 105 106 /* 3.申请显示缓冲区 */ 107 lcd_info->screen_base = dma_alloc_writecombine(NULL, lcd_info->fix.smem_len, (dma_addr_t *)&lcd_info->fix.smem_start, GFP_KERNEL); 108 lcd_info->screen_size = lcd_info->fix.smem_len; 109 lcd_info->pseudo_palette = pseudo_palette; 110 111 /* 3.硬件相关的操作 */ 112 // 3.1 gpio初始化 113 GPF0CON = ioremap(0x11400180, 4); 114 GPF1CON = ioremap(0x114001a0, 4); 115 GPF2CON = ioremap(0x114001c0, 4); 116 GPF3CON = ioremap(0x114001e0, 4); 117 GPD0CON = ioremap(0x114000a0, 4); 118 GPD0DAT = ioremap(0x114000a4, 4); 119 writel(0x22222222, GPF0CON); 120 writel(0x22222222, GPF1CON); 121 writel(0x22222222, GPF2CON); 122 writel(0x00222222, GPF3CON); 123 writel(((readl(GPD0CON) & ~(0xf << 4)) | (0x1 << 4)), GPD0CON); 124 writel((readl(GPD0DAT) | (0x1 << 1)), GPD0DAT); 125 126 /* 3.2LCD控制器的初始化*/ 127 // 控制器时钟 128 CLK_SRC_LCD0 = ioremap(0x1003c234,4); 129 CLK_DIV_LCD = ioremap(0x1003c534,4); 130 LCDBLK_CFG = ioremap(0x10010210,4); 131 writel(((readl(CLK_SRC_LCD0)&~(0xf))|0x6),CLK_SRC_LCD0); 132 writel((readl(CLK_DIV_LCD)&~(0xf)),CLK_DIV_LCD); 133 writel((readl(LCDBLK_CFG)|(0x1<<1)),LCDBLK_CFG); 134 135 // LCD控制器的初始化 136 VIDCON0 = ioremap(0x11c00000, 4); 137 VIDCON1 = ioremap(0x11c00004, 4); 138 VIDCON2 = ioremap(0x11c00008, 4); 139 VIDTCON0 = ioremap(0x11c00010, 4); 140 VIDTCON1 = ioremap(0x11c00014, 4); 141 VIDTCON2 = ioremap(0x11c00018, 4); 142 WINCON0 = ioremap(0x11c00020, 4); 143 SHADOWCON= ioremap(0x11c00034, 4); 144 WINCHMAP2 = ioremap(0x11c0003c, 4); 145 VIDOSD0A = ioremap(0x11c00040, 4); 146 VIDOSD0B = ioremap(0x11c00044, 4); 147 VIDOSD0C = ioremap(0x11c00048, 4); 148 VIDW0nADD0Bn = ioremap(0x11c000a0, 4); 149 VIDW0nADD1Bn = ioremap(0x11c000d0, 4); 150 VIDW0nADD2 = ioremap(0x11c00100, 4); 151 152 *VIDCON0 = 14 << 6; 153 *VIDCON1 = (1 << 9) | (1 << 6) | (1 << 5); 154 *VIDCON2 = (3 << 14); 155 *VIDTCON0 = (22 << 16) | (11 << 8) | (9 << 0); 156 *VIDTCON1 = (159 << 16) | (159 << 8) | (10 << 0); 157 *VIDTCON2 = (599 << 11) | (1023 << 0); 158 *WINCON0 = (1 << 16) | (5 << 2); 159 *SHADOWCON = 1; 160 *WINCHMAP2 = (1 << 0) | (1 << 16); 161 *VIDOSD0A = 0; 162 *VIDOSD0B = (1024 << 11) | (600 << 0); 163 *VIDOSD0C = (1024 * 600); 164 *VIDW0nADD0Bn = lcd_info->fix.smem_start; 165 *VIDW0nADD1Bn = lcd_info->fix.smem_start + lcd_info->fix.smem_len; 166 *VIDW0nADD2 = (1024 * 2 << 0); 167 168 // 使能 169 *VIDCON0 |= 0x3; 170 *WINCON0 |= 1; 171 172 /* 5.注册和注销 */ 173 ret = register_framebuffer(lcd_info); 174 if(ret < 0) { 175 printk("register farmebuffer is fail.\n"); 176 return -EAGAIN; 177 } 178 179 return 0; 180 } 181 182 static void __exit lcd_exit(void) { 183 unregister_framebuffer(lcd_info); 184 } 185 186 module_init(lcd_init); 187 module_exit(lcd_exit); 188 MODULE_LICENSE("GPL");