i.MX 6ULL 驱动开发 十九:RGBLCD

一、RGBLCD 硬件原理

【正点原子MP157连载】第十八章 RGB LCD彩条显示实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7_正点原子的博客-CSDN博客

ATK7016 时序参数:
i.MX 6ULL 驱动开发 十九:RGBLCD_第1张图片

二、eLCDIF 接口

eLCDIFI.MX6U 自带的液晶屏幕接口,用于连接 RGB LCD 接口的屏幕。

三、Linux 下 LCD 驱动分析

1、LCD 操作流程

1、初始化 I.MX6UeLCDIF 控制器,重点是 LCD 屏幕宽(width)、高(height)、 hspwhbphfpvspwvbpvfp 等信息。

2、初始化 LCD 像素时钟。

3、设置 RGBLCD 显存。

4、应用程序直接通过操作显存来操作 LCD,实现在 LCD 上显示字符、图片等信息。

2、Framebuffer 设备

Linux 内核中使用 Framebuffer 提供统一的标准接口显示设备。Framebuffer 翻译过来就是帧缓冲,简称 fbfb 是一种机制,将系统中所有跟显示有关的硬件以及软件集合起来,虚拟出一个 fb 设备,当我们编写好 LCD 驱动以后会生成一个名为 /dev/fbX(X=0~n) 的设备,应用程序通过访问 /dev/fbX 这个设备就可以访问 LCD

NXP 官方的 Linux 内核默认已经开启了 LCD 驱动,因此我们是可以看到 /dev/fb0 这样一个设备,如下所示:

# ls -l /dev/fb0
crw-rw----    1 root     root       29,   0 Jan  1 00:00 /dev/fb0
#

/dev/fb0 就是 LCD 对应的设备文件, /dev/fb0 是个字符设备,fbfile_operations 操作集定义在 drivers/video/fbdev/core/fbmem.c 文件中。

3、驱动分析

1、通过设备树确定驱动文件

设备树信息如下:

// 文件路径:linux-imx-4.1.15\arch\arm\boot\dts\imx6ull.dtsi

lcdif: lcdif@021c8000 {
    compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif";
    reg = <0x021c8000 0x4000>;
    interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&clks IMX6UL_CLK_LCDIF_PIX>,
         <&clks IMX6UL_CLK_LCDIF_APB>,
         <&clks IMX6UL_CLK_DUMMY>;
    clock-names = "pix", "axi", "disp_axi";
    status = "disabled";
};

通过 fsl,imx6ul-lcdiffsl,imx28-lcdif 查找驱动文件,驱动文件路径:linux-imx-4.1.15\drivers\video\fbdev\mxsfb.c

驱动分析待完成……。

四、重要结构体

1、fb_info

struct fb_info {
	atomic_t count;
	int node;
	int flags;
	struct mutex lock;		/* Lock for open/release/ioctl funcs */
	struct mutex mm_lock;		/* Lock for fb_mmap and smem_* fields */
	struct fb_var_screeninfo var;	/* Current var */
	struct fb_fix_screeninfo fix;	/* Current fix */
	struct fb_monspecs monspecs;	/* Current Monitor specs */
	struct work_struct queue;	/* Framebuffer event queue */
	struct fb_pixmap pixmap;	/* Image hardware mapper */
	struct fb_pixmap sprite;	/* Cursor hardware mapper */
	struct fb_cmap cmap;		/* Current cmap */
	struct list_head modelist;      /* mode list */
	struct fb_videomode *mode;	/* current mode */

#ifdef CONFIG_FB_BACKLIGHT
	/* assigned backlight device */
	/* set before framebuffer registration, 
	   remove after unregister */
	struct backlight_device *bl_dev;

	/* Backlight level curve */
	struct mutex bl_curve_mutex;	
	u8 bl_curve[FB_BACKLIGHT_LEVELS];
#endif
#ifdef CONFIG_FB_DEFERRED_IO
	struct delayed_work deferred_work;
	struct fb_deferred_io *fbdefio;
#endif

	struct fb_ops *fbops;
	struct device *device;		/* This is the parent */
	struct device *dev;		/* This is this fb device */
	int class_flag;                    /* private sysfs flags */
#ifdef CONFIG_FB_TILEBLITTING
	struct fb_tile_ops *tileops;    /* Tile Blitting */
#endif
	char __iomem *screen_base;	/* Virtual address */
	unsigned long screen_size;	/* Amount of ioremapped VRAM or 0 */ 
	void *pseudo_palette;		/* Fake palette of 16 colors */ 
#define FBINFO_STATE_RUNNING	0
#define FBINFO_STATE_SUSPENDED	1
	u32 state;			/* Hardware state i.e suspend */
	void *fbcon_par;                /* fbcon use-only private area */
	/* From here on everything is device dependent */
	void *par;
	/* we need the PCI or similar aperture base/size not
	   smem_start/size as smem_start may just be an object
	   allocated inside the aperture so may not actually overlap */
	struct apertures_struct {
		unsigned int count;
		struct aperture {
			resource_size_t base;
			resource_size_t size;
		} ranges[0];
	} *apertures;

	bool skip_vt_switch; /* no VT switch on suspend/resume required */
};

2、mxsfb_info

struct mxsfb_info {
	struct fb_info *fb_info;
	struct platform_device *pdev;
	struct clk *clk_pix;
	struct clk *clk_axi;
	struct clk *clk_disp_axi;
	bool clk_pix_enabled;
	bool clk_axi_enabled;
	bool clk_disp_axi_enabled;
	void __iomem *base;	/* registers */
	u32 sync;		/* record display timing polarities */
	unsigned allocated_size;
	int enabled;
	unsigned ld_intf_width;
	unsigned dotclk_delay;
	const struct mxsfb_devdata *devdata;
	struct regulator *reg_lcd;
	bool wait4vsync;
	struct completion vsync_complete;
	struct completion flip_complete;
	int cur_blank;
	int restore_blank;
	char disp_dev[32];
	struct mxc_dispdrv_handle *dispdrv;
	int id;
	struct fb_var_screeninfo var;
};

五、设备树添加

1、设备树添加说明

Linux 驱动开发 六十二:《mxsfb.txt》翻译_lqonlylove的博客-CSDN博客

Linux 驱动开发 六十三:《display-timing.txt》翻译_lqonlylove的博客-CSDN博客

2、添加设备树

lcdif 节点中追加或修改 LCD 时序相关参数,如题内容如下:

lcdif: lcdif@021c8000 {
    compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif";
    reg = <0x021c8000 0x4000>;
    interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&clks IMX6UL_CLK_LCDIF_PIX>,
         <&clks IMX6UL_CLK_LCDIF_APB>,
         <&clks IMX6UL_CLK_DUMMY>;
    clock-names = "pix", "axi", "disp_axi";
    status = "disabled";
};

&lcdif {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_lcdif_dat
		     &pinctrl_lcdif_ctrl>;

	display = <&display0>;
	status = "okay";

	/* 7寸1024*600 */
	display0: display {
		bits-per-pixel = <32>;	// RGB值(RGB888/666)
		bus-width = <24>;		// 数据线数量

		display-timings {
			native-mode = <&timing0>;
			timing0: timing0 {
			clock-frequency = <51200000>;	// 时钟配置
			hactive = <1024>;				// 水平像素点
			vactive = <600>;				// 垂直像素点
			hfront-porch = <160>;			// HFP 配置
			hback-porch = <140>;			// HBP 配置
			hsync-len = <20>;				// HSPW 配置
			vback-porch = <20>;				// VBP 配置
			vfront-porch = <12>;			// VFP 配置
			vsync-len = <3>;				// VSPW 配置

			hsync-active = <0>;				// HSYNC 信号有效电平
			vsync-active = <0>;				// VSYNC 信号有效电平
			de-active = <1>;				// DE 信号有效电平
			pixelclk-active = <0>;			// 数据更新和数据采样有效电平
			};
		};
	};
};

六、LCD 背光配置

1、确定LCD背光使用的 PIN 引脚

通过原理图确定背光使用的 PIN 引脚。LCD 使用引脚为 BLT_PWMGPIO1_IO08)。LCD 背光使用 PWM 驱动。

2、设备树配置

pinctrl_pwm1: pwm1grp {
	fsl,pins = <
		MX6UL_PAD_GPIO1_IO08__PWM1_OUT   0x110b0
	>;
};

pwm1: pwm@02080000 {
	compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
	reg = <0x02080000 0x4000>;
	interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
	clocks = <&clks IMX6UL_CLK_PWM1>,
		 <&clks IMX6UL_CLK_PWM1>;
	clock-names = "ipg", "per";
	#pwm-cells = <2>;
};

&pwm1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_pwm1>;
	status = "okay";
};

backlight {
	compatible = "pwm-backlight";
	pwms = <&pwm1 0 5000000>;
	brightness-levels = <0 4 8 16 32 64 128 255>;
	default-brightness-level = <7>;
	status = "okay";
};

3、Linux 中相关说明

Linux 驱动开发 六十四:《pwm-backlight.txt》翻译_lqonlylove的博客-CSDN博客

七、特别说明

LCD 驱动 Linux 内核已经写好,我们只需要按照硬件参数配置设备树即可使用。

八、LCD 熄屏关闭

Linuxdrivers/tty/vt/vt.c 源码中配置 LCD 熄屏时间,配置项 static int blankinterval = 10*60 配置 LCD 熄屏时间,将 blankinterval 设置为 0,表示 LCD 常亮。

你可能感兴趣的:(i.MX,6ULL,驱动开发,imx6ull,驱动开发)