11.LCD drive

1.LCD display principle

Here Insert Picture Description

2.LCD drive frame:

1. Allocate fb_info
2. Set
3. Register register_framebuffer
4. hardware-specific operations

3. About fb_info

Linux Kernel Framebuffer all the abstract structure called the fb_info, fb_info structure contains a complete property Framebuffer device and set of operations, so that each device must have a Framebuffer fb_info. In other words, LCD driver fb_info is constructed, and the registration process fb_info system. fb_info structure is defined in include / linux / fb.h file inside
a lot of focus on the following fb_info structure member variables: var, fix, fbops, screen_size , screen_base
Here Insert Picture Description

The main steps of the procedure are as follows:
1. Assign a fb_info
static struct fb_info *s3c_lcd;
s3c_lcd = framebuffer_alloc(0, NULL);
2. Set

 2.1 fixed parameters set
 reference fb.h
Here Insert Picture Description

	strcpy(s3c_lcd->fix.id, "mylcd");
	s3c_lcd->fix.smem_len = 480*272*16/8;/*显存长度 565 */
	s3c_lcd->fix.type     = FB_TYPE_PACKED_PIXELS;
	s3c_lcd->fix.visual   = FB_VISUAL_TRUECOLOR; /* TFT */
	s3c_lcd->fix.line_length = 480*2;/*1行480像素,每个像素 16/8=2字节*/

  2.2 provided with a variable parameter
Here Insert Picture DescriptionHere Insert Picture Description

	s3c_lcd->var.xres           = 480;
	s3c_lcd->var.yres           = 272;
	s3c_lcd->var.xres_virtual   = 480;
	s3c_lcd->var.yres_virtual   = 272;
	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;

/ * The RGB: 565 * /
  2.3 setting operation function

static struct fb_ops s3c_lcdfb_ops = {
	.owner		= THIS_MODULE,
	.fb_setcolreg	= s3c_lcdfb_setcolreg,
	/*下面三个函数 每个ops都有*/
	.fb_fillrect	= cfb_fillrect,
	.fb_copyarea	= cfb_copyarea,
	.fb_imageblit	= cfb_imageblit,
};
s3c_lcd->fbops              = &s3c_lcdfb_ops;

  2.4 Other settings

s3c_lcd->pseudo_palette = pseudo_palette;
//s3c_lcd->screen_base  = ;  /* 显存的虚拟地址 */ 
s3c_lcd->screen_size   = 480*272*16/8;
3. Hardware related operations

  3.1 GPIO configured for LCD
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description

	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 The LCD controller provided LCD Manual, such as frequency of VCLK
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
VSPW = Tl +. 1. 1 = 0 = VSPW
the VBPD. 1 + T2 = T0-Tl-377-322-1 = = = the VBPD. 4. 3
LINEVAL. 1 = + T5 = = 319 LINEVAL 320.
VFPD. 1 = + = 322-320 = T2-T5 = 2. 1 VFPD
figure above VSYNC pins polarity inversion
Here Insert Picture Description
Here Insert Picture Description
HSPW the T7 +. 1 = = =. 5. 4 HSPW
HbpD +. 1 = the T7-T8-T6 = = = 16. 17 HbpD 273-25-251
the HOZVAL + T11. 1 = 239 = 240 = the HOZVAL
HFPD + T8-T11. 1 = = = 251-240 = 10. 11 HFPD
HSYNC same polarity to reverse
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description

	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(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 assignment memory (framebuffer), and the address to the LCD controller
  reference memory allocated by the kernel
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description

	s3c_lcd->screen_base = dma_alloc_writecombine(NULL, s3c_lcd->fix.smem_len, 	&s3c_lcd->fix.smem_start, GFP_KERNEL);
	/*把显存地址告诉LCD控制器*/
	/*最低1位和最高两位都不要*/
	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  = (480*16/16);  /* 一行的长度(单位: 2字节) */	
		/* 启动LCD */
	lcd_regs->lcdcon1 |= (1<<0); /* 使能LCD控制器 */
	lcd_regs->lcdcon5 |= (1<<3); /* 使能LCD本身 */
	*gpbdat |= 1;     /* 输出高电平, 使能背光 */
4. Register
/* 4. 注册 */
	register_framebuffer(s3c_lcd);
5. Exit logout
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);
}
6. Register
module_init(lcd_init);
module_exit(lcd_exit);

MODULE_LICENSE("GPL");

7. complementary palette

Here Insert Picture Description
Reference kernel atmel_lcdfb.c
Here Insert Picture Description

/* from pxafb.c */
static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
{
	chan &= 0xffff;//保留低16位
	chan >>= 16 - bf->length;//右移位数,保留16-位数
	return chan << bf->offset;//把16-位数 左移 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;

	/* 用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))[regno] = val;
	pseudo_palette[regno] = val;
	return 0;

}
8. Test:

1. In the make menuconfig /work/system/linux-2.6.22.6 remove the original driver
-> the Drivers Device
-> Graphics Support
S3C2410 the LCD the framebuffer Support

2.在/work/system/linux-2.6.22.6 make uImage
在/work/system/linux-2.6.22.6 make modules

3. The new start uImage Development Board:
load driving three

Here Insert Picture Description

4.insmod cfbcopyarea.ko
insmod cfbfillrect.ko
insmod cfbimgblt.ko
insmod lcd.ko

echo hello> / dev / tty1 // hello can be seen on the LCD
CAT lcd.ko> / dev / FB0 // all matter thrown so the video memory
5. Modify / etc / inittab
tty1 :: askfirst: - / bin / SH
reboot with the new kernel development board

cfbcopyarea.ko insmod
insmod cfbfillrect.ko
insmod cfbimgblt.ko
insmod lcd.ko
insmod buttons.ko

Published 66 original articles · won praise 1 · views 1162

Guess you like

Origin blog.csdn.net/qq_16933601/article/details/103358395