MLK-14399: 4.9 rebase: LVDS panel does not work on iMX6SX Auto
authorCristina Ciocan <cristina-mihaela.ciocan@nxp.com>
Thu, 9 Mar 2017 18:13:17 +0000 (20:13 +0200)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:10:54 +0000 (15:10 -0500)
The LCDIF driver fails at boot time because it cannot read display timings
from device tree. This is a fake error because the LCDIF DT node contains a
display device property which leads to the display driver that also provides
the timings.

This fake error case has been introduced by
commit 5443a75ed038 ("MLK-14283: dts: fix DE polarity for lcdif") and
commit 56412d6a83d8 ("MLK-13996: lcdif: Use DE polarity specified in DTS")
which fixed DE polarity panel differences for different boards.

This patch adds support for choosing a particular video mode from the ones
provided by the display driver, thus also fixing the DE polarity issue
initially fixed by the above mentioned 2 patches.

Signed-off-by: Cristina Ciocan <cristina-mihaela.ciocan@nxp.com>
Documentation/devicetree/bindings/display/mxsfb.txt
arch/arm/boot/dts/imx7d-sdb-mipi-dsi.dts
drivers/video/fbdev/mxc/mxcfb_hx8363_wvga.c
drivers/video/fbdev/mxsfb.c

index 96ec517..99e4b1a 100644 (file)
@@ -7,6 +7,12 @@ Required properties:
 - interrupts: Should contain lcdif interrupts
 - display : phandle to display node (see below for details)
 
+Optional properties:
+- disp-dev: Display device driver name
+- disp-videomode: Display device video mode name; this is used if the panel
+  supports multiple video modes, in order to chose the right one (see below for
+  examples)
+
 * display node
 
 Required properties:
@@ -47,3 +53,46 @@ lcdif@80030000 {
                };
        };
 };
+
+Examples - optional properties:
+
+Snippet from imx7d-sdb-mipi-dsi.dts:
+
+&lcdif {
+       disp-dev = "mipi_dsi_samsung";
+       disp-videomode = "TRUULY-WVGA-SYNC-LOW";
+};
+
+&mipi_dsi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_mipi_dsi_reset>;
+       lcd_panel = "TRULY-WVGA-TFT3P5581E";
+       resets = <&mipi_dsi_reset>;
+       status = "okay";
+};
+
+In the above example, the panel supports 2 video modes (snippet from
+drivers/video/fbdev/mxc/mxcfb_hx8363_wvga.c):
+
+#define ACTIVE_HIGH_NAME       "TRUULY-WVGA-SYNC-HIGH"
+#define ACTIVE_LOW_NAME                "TRUULY-WVGA-SYNC-LOW"
+
+static struct fb_videomode truly_lcd_modedb[] = {
+       {
+               ACTIVE_HIGH_NAME, 50, 480, 854, 41042,
+               40, 60,
+               3, 3,
+               8, 4,
+               0x0,
+               FB_VMODE_NONINTERLACED,
+               0,
+       }, {
+               ACTIVE_LOW_NAME, 50, 480, 854, 41042,
+               40, 60,
+               3, 3,
+               8, 4,
+               FB_SYNC_OE_LOW_ACT,
+               FB_VMODE_NONINTERLACED,
+               0,
+       },
+};
index bbfca36..327d976 100644 (file)
@@ -19,6 +19,7 @@
 
 &lcdif {
        disp-dev = "mipi_dsi_samsung";
+       disp-videomode = "TRUULY-WVGA-SYNC-LOW";
 };
 
 &mipi_dsi {
index d6052bc..155e849 100644 (file)
@@ -128,15 +128,26 @@ static void parse_variadic(int n, u8 *buf, ...)
 
 static int hx8363bl_brightness;
 
+#define ACTIVE_HIGH_NAME       "TRUULY-WVGA-SYNC-HIGH"
+#define ACTIVE_LOW_NAME                "TRUULY-WVGA-SYNC-LOW"
+
 static struct fb_videomode truly_lcd_modedb[] = {
        {
-        "TRUULY-WVGA", 50, 480, 854, 41042,
-        40, 60,
-        3, 3,
-        8, 4,
-        0x0,
-        FB_VMODE_NONINTERLACED,
-        0,
+               ACTIVE_HIGH_NAME, 50, 480, 854, 41042,
+               40, 60,
+               3, 3,
+               8, 4,
+               0x0,
+               FB_VMODE_NONINTERLACED,
+               0,
+       }, {
+               ACTIVE_LOW_NAME, 50, 480, 854, 41042,
+               40, 60,
+               3, 3,
+               8, 4,
+               FB_SYNC_OE_LOW_ACT,
+               FB_VMODE_NONINTERLACED,
+               0,
        },
 };
 
index 62840ec..775cdfc 100644 (file)
@@ -233,6 +233,8 @@ struct mxsfb_layer {
        struct mxsfb_info       *fbi;
 };
 
+#define NAME_LEN       32
+
 struct mxsfb_info {
        struct fb_info *fb_info;
        struct platform_device *pdev;
@@ -255,12 +257,14 @@ struct mxsfb_info {
        struct completion flip_complete;
        int cur_blank;
        int restore_blank;
-       char disp_dev[32];
+       char disp_dev[NAME_LEN];
        struct mxc_dispdrv_handle *dispdrv;
        int id;
        struct fb_var_screeninfo var;
        struct pm_qos_request pm_qos_req;
 
+       char disp_videomode[NAME_LEN];
+
 #ifdef CONFIG_FB_MXC_OVERLAY
        struct mxsfb_layer overlay;
 #endif
@@ -1277,7 +1281,7 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host)
        struct device_node *display_np;
        struct device_node *timings_np;
        struct display_timings *timings = NULL;
-       const char *disp_dev;
+       const char *disp_dev, *disp_videomode;
        u32 width;
        int i;
        int ret = 0;
@@ -1325,6 +1329,13 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host)
        ret = of_property_read_string(np, "disp-dev", &disp_dev);
        if (!ret) {
                memcpy(host->disp_dev, disp_dev, strlen(disp_dev));
+
+               if (!of_property_read_string(np, "disp-videomode",
+                                           &disp_videomode)) {
+                       memcpy(host->disp_videomode, disp_videomode,
+                              strlen(disp_videomode));
+               }
+
                /* Timing is from encoder driver */
                goto put_display_node;
        }
@@ -1439,7 +1450,20 @@ static int mxsfb_dispdrv_init(struct platform_device *pdev,
        memcpy(disp_dev, host->disp_dev, strlen(host->disp_dev));
        disp_dev[strlen(host->disp_dev)] = '\0';
 
+       /* Use videomode name from dtb, if any given */
+       if (host->disp_videomode) {
+               setting.dft_mode_str = kmalloc(NAME_LEN, GFP_KERNEL);
+               if (setting.dft_mode_str) {
+                       memset(setting.dft_mode_str, 0x0, NAME_LEN);
+                       memcpy(setting.dft_mode_str, host->disp_videomode,
+                              strlen(host->disp_videomode));
+               }
+       }
+
        host->dispdrv = mxc_dispdrv_gethandle(disp_dev, &setting);
+
+       kfree(setting.dft_mode_str);
+
        if (IS_ERR(host->dispdrv)) {
                if (PTR_ERR(host->dispdrv) == -EPROBE_DEFER)
                        return PTR_ERR(host->dispdrv);