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:
- <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>
- <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>
- <span style="font-size:14px;"> imx6qdl-sabresd {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- ......
- MX6QDL_PAD_EIM_DA0__GPIO3_IO00 0x80000000
- >;
- };</span>
- <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:
- <span style="font-size:14px;">#Kris,20160406, Porting lcd driver.
- CONFIG_COG_T700MIXN=y</span>
drivers/Makefile:
- <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:
- <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:
- <span style="font-size:14px;">#Kris,20160406, Porting lcd driver.
- obj-$(CONFIG_COG_T700MIXN) += cog_t700mixn.o</span>
drivers/video/mxc/cog_t700mixn.c:
- <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", },
- { }
- };
- 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;
-
-
- 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");
- }
-
-
- 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__);
- }
-
-
- 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