[IMX6Q][Android5.1]移植笔记 --- LCD显示移植(LVDS接口)

Platform: IMX6Q

OS: Android Lollipop 5.1

Freescale Branch: l5.1.1_2.1.0-ga

Kernel Branch: 3.14.52



此例LCD用的是LVDS接口,LDB模块。
 移植分两部分:
HW: 电源以及GPIO部分。
SW: LCD timing,BPP,分辨率。

HW部分:
LCD有DVDD和AVDD两个电源,原理图如下:

[IMX6Q][Android5.1]移植笔记 --- LCD显示移植(LVDS接口)_第1张图片



LCD_AVDD受LCD_VDD控制,LCD_VDD受LCD_PWR_EN pin控制。
本来要考虑各个电源以及reset pin的上电时序,本例中LCD硬件模块已经帮我们做好了,
所以只要控制LCD_PWR_EN,那么上电时序就能正常完成。
LCD_PWR_EN对应的GPIO为GPIO_3_0,开机时只要拉高即可。

LCD_VDD的供电来自SYS_5V,它的最终源头是从PMIC MMPF0100的VGEN2,所以
需要设置其电压,其中要注意的是MMPF0100是通过I2C控制的,驱动加载顺序可能
会在LCD模块后面,所以需要调换下驱动加载顺序,让LCD模块晚于PMIC,这样才
能使用regulator 函数接口。
[IMX6Q][Android5.1]移植笔记 --- LCD显示移植(LVDS接口)_第2张图片


SW部分:
这部分主要根据LCD spec来确定,有分辨率,bpp, timing,如下:
[IMX6Q][Android5.1]移植笔记 --- LCD显示移植(LVDS接口)_第3张图片

[IMX6Q][Android5.1]移植笔记 --- LCD显示移植(LVDS接口)_第4张图片


代码实现:
arch/arm/boot/dts/ecovacsimx6qdl-sabresd.dtsi:
/*Kris,20160406, Porting lcd driver.*/
&ldb {
	status = "okay";

	lvds-channel@0 {
		fsl,data-mapping = "spwg";
		fsl,data-width = <24>;
		primary;
		status = "okay";

		display-timings {
			native-mode = <&timing0>;
			timing0: cog_t700mixn {
				clock-frequency = <50000000>;
				hactive = <1024>;
				vactive = <600>;
				hback-porch = <220>;
				hfront-porch = <40>;
				vback-porch = <21>;
				vfront-porch = <7>;
				hsync-len = <60>;
				vsync-len = <10>;
			};
		};
	};
};
/ {
	/*Kris,20160406, Porting lcd driver.*/
	cog_t700mixn {
		compatible = "cog_t700mixn";
		bl_power_gpio = <&gpio4 14 1>;
		lcd_power_gpio = <&gpio3 0 1>;
		DVDD-supply = <&vgen2_reg>;
	};
};
	imx6qdl-sabresd {
		pinctrl_hog: hoggrp {
			fsl,pins = <
			......
				MX6QDL_PAD_EIM_DA0__GPIO3_IO00	0x80000000
			>;
		};
	mxcfb1: fb@0 {
		compatible = "fsl,mxc_sdc_fb";
		disp_dev = "ldb";
		interface_pix_fmt = "RGB24";
		default_bpp = <32>;
		int_clk = <0>;
		late_init = <0>;
		status = "disabled";
	};

arch/arm/configs/imx_v7_android_defconfig:
#Kris,20160406, Porting lcd driver.
CONFIG_COG_T700MIXN=y

drivers/Makefile:
# regulators early, since some subsystems rely on them to initialize
obj-$(CONFIG_REGULATOR)		+= regulator/

#Kris,20160406, Porting lcd driver.
#Load lcd driver after regulator module to wait it to be ready.
obj-y				+= video/

drivers/video/mxc/Kconfig:
#Kris,20160406, Porting lcd driver.
config COG_T700MIXN
	bool "COG T700MIXN lcd driver."
	default n

drivers/video/mxc/Makefile:
#Kris,20160406, Porting lcd driver.
obj-$(CONFIG_COG_T700MIXN) += cog_t700mixn.o

drivers/video/mxc/cog_t700mixn.c:
#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio.h>

#define DRIVER_NAME "cog-t700mixn"

static const struct of_device_id t700mixn_dt_ids[] = {
	{ .compatible = "cog_t700mixn", },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, t700mixn_dt_ids);

static int t700mixn_probe(struct platform_device *pdev)
{
	static struct regulator *dvdd_regulator;
	struct device_node *lcd = NULL;
	int ret, bl_power_gpio, lcd_power_gpio;

	printk("%s\n", __func__);

	lcd = pdev->dev.of_node;

	//enable backlight power.
	bl_power_gpio = of_get_named_gpio(lcd, "bl_power_gpio", 0);
	if (gpio_is_valid(bl_power_gpio)) {
		ret = gpio_request_one(bl_power_gpio, GPIOF_OUT_INIT_HIGH,
			"bl_power_gpio");
		pr_info("request bl_power_gpio\n");
		if (ret)
			pr_warn("failed to request bl_power_gpio\n");
	}

	//Set VGEN2 of pmic.
	dvdd_regulator = devm_regulator_get(&pdev->dev, "DVDD");
	if (!IS_ERR(dvdd_regulator)) {
		regulator_set_voltage(dvdd_regulator,1500000,1500000);
		ret = regulator_enable(dvdd_regulator);
		if (ret) {
			pr_err("%s:DVDD set voltage error\n", __func__);
			return ret;
		} else {
			dev_info(&pdev->dev,"%s:DVDD set voltage ok\n", __func__);
		}
	} else {
		dvdd_regulator = NULL;
		pr_err("%s: cannot get DVDD voltage error\n", __func__);
	}

	//this gpio control DVDD and AVDD together.
	lcd_power_gpio = of_get_named_gpio(lcd, "lcd_power_gpio", 0);
	if (gpio_is_valid(lcd_power_gpio)) {
		ret = gpio_request_one(lcd_power_gpio, GPIOF_OUT_INIT_HIGH,
			"bl_power_gpio");
		pr_info("request lcd_power_gpio\n");
		if (ret)
			pr_warn("failed to request lcd_power_gpio\n");
	}

	return ret;
}

static struct platform_driver t700mixn_driver = {
	.probe	= t700mixn_probe,
	.driver = {
		.of_match_table = t700mixn_dt_ids,
		.name	= DRIVER_NAME,
		.owner	= THIS_MODULE,
	},
};
module_platform_driver(t700mixn_driver);

MODULE_AUTHOR("Kris.Fei: [email protected]");
MODULE_DESCRIPTION("COG T700MIXN lcd driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRIVER_NAME);

参考:
kernel/Documentation/devicetree/bindings/staging/imx-drm/ldb.txt
kernel/Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt
http://blog.chinaunix.net/uid-20680966-id-3623224.html

你可能感兴趣的:(display,移植,LCD)