LCD显示移植(LVDS接口)
2017-09-14 14:12
148 查看
Platform: IMX6QP
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两个电源,原理图如下:
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 函数接口。
SW部分:
这部分主要根据LCD spec来确定,有分辨率,bpp, timing,如下:
代码实现:
arch/arm/boot/dts/eco/imx6qdl-sabresd.dtsi:
[plain] view
plain copy
<span style="font-size:14px;">/*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>;
};
};
};
};</span>
[plain] view
plain copy
<span style="font-size:14px;">/ {
/*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>;
};
};</span>
[plain] view
plain copy
<span style="font-size:14px;"> imx6qdl-sabresd {
pinctrl_hog: hoggrp {
fsl,pins = <
......
MX6QDL_PAD_EIM_DA0__GPIO3_IO00 0x80000000
>;
};</span>
[plain] view
plain copy
<span style="font-size:14px;"> 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";
};
</span>
arch/arm/configs/imx_v7_android_defconfig:
[plain] view
plain copy
<span style="font-size:14px;">#Kris,20160406, Porting lcd driver.
CONFIG_COG_T700MIXN=y</span>
drivers/Makefile:
[plain] view
plain copy
<span style="font-size:14px;"># 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/</span>
drivers/video/mxc/Kconfig:
[plain] view
plain copy
<span style="font-size:14px;">#Kris,20160406, Porting lcd driver.
config COG_T700MIXN
bool "COG T700MIXN lcd driver."
default n</span>
drivers/video/mxc/Makefile:
[plain] view
plain copy
<span style="font-size:14px;">#Kris,20160406, Porting lcd driver.
obj-$(CONFIG_COG_T700MIXN) += cog_t700mixn.o</span>
drivers/video/mxc/cog_t700mixn.c:
[cpp] view
plain copy
<span style="font-size:14px;">#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");
MODULE_DESCRIPTION("COG T700MIXN lcd driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRIVER_NAME);
</span>
参考:
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
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两个电源,原理图如下:
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 函数接口。
SW部分:
这部分主要根据LCD spec来确定,有分辨率,bpp, timing,如下:
代码实现:
arch/arm/boot/dts/eco/imx6qdl-sabresd.dtsi:
[plain] view
plain copy
<span style="font-size:14px;">/*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>;
};
};
};
};</span>
[plain] view
plain copy
<span style="font-size:14px;">/ {
/*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>;
};
};</span>
[plain] view
plain copy
<span style="font-size:14px;"> imx6qdl-sabresd {
pinctrl_hog: hoggrp {
fsl,pins = <
......
MX6QDL_PAD_EIM_DA0__GPIO3_IO00 0x80000000
>;
};</span>
[plain] view
plain copy
<span style="font-size:14px;"> 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";
};
</span>
arch/arm/configs/imx_v7_android_defconfig:
[plain] view
plain copy
<span style="font-size:14px;">#Kris,20160406, Porting lcd driver.
CONFIG_COG_T700MIXN=y</span>
drivers/Makefile:
[plain] view
plain copy
<span style="font-size:14px;"># 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/</span>
drivers/video/mxc/Kconfig:
[plain] view
plain copy
<span style="font-size:14px;">#Kris,20160406, Porting lcd driver.
config COG_T700MIXN
bool "COG T700MIXN lcd driver."
default n</span>
drivers/video/mxc/Makefile:
[plain] view
plain copy
<span style="font-size:14px;">#Kris,20160406, Porting lcd driver.
obj-$(CONFIG_COG_T700MIXN) += cog_t700mixn.o</span>
drivers/video/mxc/cog_t700mixn.c:
[cpp] view
plain copy
<span style="font-size:14px;">#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");
MODULE_DESCRIPTION("COG T700MIXN lcd driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRIVER_NAME);
</span>
参考:
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
相关文章推荐
- [IMX6Q][Android5.1]移植笔记 --- LCD显示移植(LVDS接口)
- Linux-2.6.32.2内核在mini2440上的移植----通过LCD显示内核启动信息及修改Linux LOGO
- RT-Thread 学习笔记(十三)--- 开启基于RTGUI的LCD显示功能(3)<触屏屏驱动移植和测试>
- LCD显示驱动的移植
- Ti-am335x-uboot-2015.07移植LCD显示logo功能
- linux2.6.32.2 mini2440平台移植-- LCD 显示驱动 ( W35屏 )
- u-boot-2009.08在mini2440上的移植(七)---增加LCD显示功能
- u-boot-2009.08在mini2440上的移植 增加LCD显示功能
- linux2.6.32.2 mini2440平台移植-- LCD 显示驱动 ( W35屏 )
- linux2.6.32.2 mini2440平台移植-- LCD 显示驱动(W35屏)
- linux2.6.32.2 mini2440平台移植-- LCD 显示驱动 ( W35屏 )
- RT-Thread 学习笔记(十一)--- 开启基于RTGUI的LCD显示功能(1)<LCD驱动接口移植>
- Android图形系统的分析与移植 -- 二、Android显示系统软件架构分析
- 【鼓捣树莓派】动态网页控制lcd显示
- S3C2440 Linux驱动移植——LCD
- 51单片机的LCD显示
- 基于TFT的ZLG_GUI和3D显示的移植
- 视频和QT的GUI显示到LCD的不同显示层—透过GUI能看到视频
- C9移植rk3399 视频显示核心代码
- 嵌入式linux------SDL移植(am335x下显示yuv420)