]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
fbdev: imxfb: fix left margin setting
authorDario Binacchi <dario.binacchi@amarulasolutions.com>
Sat, 11 Nov 2023 10:41:50 +0000 (11:41 +0100)
committerHelge Deller <deller@gmx.de>
Thu, 11 Jan 2024 16:09:00 +0000 (17:09 +0100)
The previous setting did not take into account the CSTN mode.
For the H_WAIT_2 bitfield (bits 0-7) of the LCDC Horizontal Configuration
Register (LCDCR), the IMX25RM manual states that:

In TFT mode, it specifies the number of SCLK periods between the end of
HSYNC and the beginning of OE signal, and the total delay time equals
(H_WAIT_2 + 3) of SCLK periods.
In CSTN mode, it specifies the number of SCLK periods between the end of
HSYNC and the first display data in each line, and the total delay time
equals (H_WAIT_2 + 2) of SCLK periods.

The patch handles both cases.

Fixes: 4e47382fbca9 ("fbdev: imxfb: warn about invalid left/right margin")
Fixes: 7e8549bcee00 ("imxfb: Fix margin settings")
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
Signed-off-by: Helge Deller <deller@gmx.de>
drivers/video/fbdev/imxfb.c

index 84201c9608d36cdf81655e97c46a854226186631..7042a43b81d8564502e073143ae8bcf0834c9553 100644 (file)
@@ -42,6 +42,7 @@
 #include <video/videomode.h>
 
 #define PCR_TFT                (1 << 31)
+#define PCR_COLOR      (1 << 30)
 #define PCR_BPIX_8     (3 << 25)
 #define PCR_BPIX_12    (4 << 25)
 #define PCR_BPIX_16    (5 << 25)
@@ -150,6 +151,12 @@ enum imxfb_type {
        IMX21_FB,
 };
 
+enum imxfb_panel_type {
+       PANEL_TYPE_MONOCHROME,
+       PANEL_TYPE_CSTN,
+       PANEL_TYPE_TFT,
+};
+
 struct imxfb_info {
        struct platform_device  *pdev;
        void __iomem            *regs;
@@ -157,6 +164,7 @@ struct imxfb_info {
        struct clk              *clk_ahb;
        struct clk              *clk_per;
        enum imxfb_type         devtype;
+       enum imxfb_panel_type   panel_type;
        bool                    enabled;
 
        /*
@@ -444,6 +452,13 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        if (!is_imx1_fb(fbi) && imxfb_mode->aus_mode)
                fbi->lauscr = LAUSCR_AUS_MODE;
 
+       if (imxfb_mode->pcr & PCR_TFT)
+               fbi->panel_type = PANEL_TYPE_TFT;
+       else if (imxfb_mode->pcr & PCR_COLOR)
+               fbi->panel_type = PANEL_TYPE_CSTN;
+       else
+               fbi->panel_type = PANEL_TYPE_MONOCHROME;
+
        /*
         * Copy the RGB parameters for this display
         * from the machine specific parameters.
@@ -596,6 +611,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
 {
        struct imxfb_info *fbi = info->par;
        u32 ymax_mask = is_imx1_fb(fbi) ? YMAX_MASK_IMX1 : YMAX_MASK_IMX21;
+       u8 left_margin_low;
 
        pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
                var->xres, var->hsync_len,
@@ -604,6 +620,13 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
                var->yres, var->vsync_len,
                var->upper_margin, var->lower_margin);
 
+       if (fbi->panel_type == PANEL_TYPE_TFT)
+               left_margin_low = 3;
+       else if (fbi->panel_type == PANEL_TYPE_CSTN)
+               left_margin_low = 2;
+       else
+               left_margin_low = 0;
+
 #if DEBUG_VAR
        if (var->xres < 16        || var->xres > 1024)
                printk(KERN_ERR "%s: invalid xres %d\n",
@@ -611,7 +634,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
        if (var->hsync_len < 1    || var->hsync_len > 64)
                printk(KERN_ERR "%s: invalid hsync_len %d\n",
                        info->fix.id, var->hsync_len);
-       if (var->left_margin < 3  || var->left_margin > 255)
+       if (var->left_margin < left_margin_low  || var->left_margin > 255)
                printk(KERN_ERR "%s: invalid left_margin %d\n",
                        info->fix.id, var->left_margin);
        if (var->right_margin < 1 || var->right_margin > 255)
@@ -637,7 +660,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
 
        writel(HCR_H_WIDTH(var->hsync_len - 1) |
                HCR_H_WAIT_1(var->right_margin - 1) |
-               HCR_H_WAIT_2(var->left_margin - 3),
+               HCR_H_WAIT_2(var->left_margin - left_margin_low),
                fbi->regs + LCDC_HCR);
 
        writel(VCR_V_WIDTH(var->vsync_len) |