天天看点

rk3288 设置imx6ull的lcd控制器的寄存器使用参数设置LCD控制器

使用参数设置LCD控制器

根据芯片手册,一个一个设置寄存器:

  • Framebuffer地址设置(基地址)
  • Framebuffer中数据格式设置
  • LCD时序参数设置
  • LCD引脚极性设置

主要是根据imx6ull的芯片手册一个一个设置相关的寄存器,也没有什么取巧的办法。

static void lcd_controller_enable(struct imx6ull_lcdif *lcdif)
{
	lcdif->CTRL |= (1<<0);
}

static int lcd_controller_init(struct imx6ull_lcdif *lcdif, 
		struct display_timing *dt, int lcd_bpp, int fb_bpp, 
		unsigned int fb_phy)
{
	int lcd_data_bus_width;
	int fb_width;
	int vsync_pol = 0;
	int hsync_pol = 0;
	int dotclk_pol = 0;
	int de_pol = 0;

	switch(lcd_bpp) {
	case 16:
		lcd_data_bus_width = 0x0;
		break;
	case 8:
		lcd_data_bus_width = 0x1;
		break;
	case 18:
		lcd_data_bus_width = 0x2;
		break;
	case 24:
		lcd_data_bus_width = 0x3;
		break;
	default:
		lcd_data_bus_width = 0x0;
		break;
	}

	switch(fb_bpp) {
	case 16:
		fb_width = 0x0;
		break;
	case 8:
		fb_width = 0x1;
		break;
	case 18:
		fb_width = 0x2;
		break;
	case 24:
	case 32:
		fb_width = 0x3;
		break;
	default:
		fb_width = 0x0;
		break;
	}
	/* 
     * 初始化LCD控制器的CTRL寄存器
     * [19]       :  1      : DOTCLK和DVI modes需要设置为1 
     * [17]       :  1      : 设置为1工作在DOTCLK模式
     * [15:14]    : 00      : 输入数据不交换(小端模式)默认就为0,不需设置
     * [13:12]    : 00      : CSC数据不交换(小端模式)默认就为0,不需设置
     * [11:10]    : 11		: 数据总线为24bit
     * [9:8]    根据显示屏资源文件bpp来设置:8位0x1 , 16位0x0 ,24位0x3
     * [5]        :  1      : 设置elcdif工作在主机模式
     * [1]        :  0      : 24位数据均是有效数据,默认就为0,不需设置
	 */	
	lcdif->CTRL = (0<<30) | (0<<29) | (0<<28) | (1<<19) | (1<<17) | (lcd_data_bus_width << 10) |\
			  (fb_width << 8) | (1<<5);

	/*
	* 设置ELCDIF的寄存器CTRL1
	* 根据bpp设置,bpp为24或32才设置
	* [19:16]  : 111  :表示ARGB传输格式模式下,传输24位无压缩数据,A通道不用传输)
	*/	
	if(fb_bpp == 24 || fb_bpp == 32) {
		lcdif->CTRL1 &= ~(0xf << 16);
		lcdif->CTRL1 |= (0x7 << 16);
	} else {
		lcdif->CTRL1 |= (0xf << 16);
	}

	/*
	* 设置ELCDIF的寄存器TRANSFER_COUNT寄存器
	* [31:16]  : 垂直方向上的像素个数  
	* [15:0]   : 水平方向上的像素个数
	*/
	lcdif->TRANSFER_COUNT = (dt->vactive.typ << 16 )| (dt->hactive.typ<<0);


	if(dt->flags & DISPLAY_FLAGS_HSYNC_HIGH)
		hsync_pol = 1;
	if(dt->flags & DISPLAY_FLAGS_VSYNC_HIGH)
		vsync_pol = 1;
	if(dt->flags & DISPLAY_FLAGS_DE_HIGH)
		de_pol = 1;
	if(dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
		dotclk_pol = 1;

	/*
	* 设置ELCDIF的VDCTRL0寄存器
	* [29] 0 : VSYNC输出  ,默认为0,无需设置
	* [28] 1 : 在DOTCLK模式下,设置1硬件会产生使能ENABLE输出
	* [27] 0 : VSYNC低电平有效	,根据屏幕配置文件将其设置为0
	* [26] 0 : HSYNC低电平有效 , 根据屏幕配置文件将其设置为0
	* [25] 1 : DOTCLK下降沿有效 ,根据屏幕配置文件将其设置为1
	* [24] 1 : ENABLE信号高电平有效,根据屏幕配置文件将其设置为1
	* [21] 1 : 帧同步周期单位,DOTCLK mode设置为1
	* [20] 1 : 帧同步脉冲宽度单位,DOTCLK mode设置为1
	* [17:0] :  vysnc脉冲宽度 
	*/
	lcdif->VDCTRL0 = (1 << 28) | (vsync_pol << 27) | (hsync_pol << 26) | (dotclk_pol << 25) | (de_pol << 24) | (1<<21) |
		(1<<20) | (dt->vsync_len.typ << 0);

	/*
	* 设置ELCDIF的VDCTRL1寄存器
	* 设置垂直方向的总周期:上黑框tvb+垂直同步脉冲tvp+垂直有效高度yres+下黑框tvf
	*/	  
	lcdif->VDCTRL1 = dt->vback_porch.typ + dt->vsync_len.typ + dt->vactive.typ + dt->vfront_porch.typ;

	/*
	* 设置ELCDIF的VDCTRL2寄存器
	* [18:31]  : 水平同步信号脉冲宽度
	* [17: 0]   : 水平方向总周期
	* 设置水平方向的总周期:左黑框thb+水平同步脉冲thp+水平有效高度xres+右黑框thf
	*/
	lcdif->VDCTRL2 = (dt->hsync_len.typ << 18)| (dt->hback_porch.typ + dt->hsync_len.typ + dt->hactive.typ + dt->hfront_porch.typ) << 0;

	/*
	* 设置ELCDIF的VDCTRL3寄存器
	* [27:16] :水平方向上的等待时钟数 =thb + thp
	* [15:0]  : 垂直方向上的等待时钟数 = tvb + tvp
	*/ 
	lcdif->VDCTRL3 = (dt->hback_porch.typ + dt->hsync_len.typ) << 16 |
		((dt->vback_porch.typ + dt->vsync_len.typ) << 0);

	/*
	* 设置ELCDIF的VDCTRL4寄存器
	* [18]	   使用VSHYNC、HSYNC、DOTCLK模式此为置1
	* [17:0]  : 水平方向的宽度
	*/ 
	lcdif->VDCTRL4 = (1 << 18) | (dt->hactive.typ);

	/*
	* 设置ELCDIF的CUR_BUF和NEXT_BUF寄存器
	* CUR_BUF	 :	当前显存地址
	* NEXT_BUF :	下一帧显存地址
	* 方便运算,都设置为同一个显存地址
	*/
	lcdif->CUR_BUF = fb_phy;
	lcdif->NEXT_BUF = fb_phy;

	return 0;
}
           

使能LCD函数

static void lcd_controller_enable(struct imx6ull_lcdif *lcdif)
{
	lcdif->CTRL |= (1<<0);
}
           

在probe函数调用函数

probe:
{
	//...
	lcd_controller_init(lcdif, dt, bits_per_pixel, 16,  phy_addr);

	lcd_controller_enable(lcdif);
	//...
}
           

继续阅读