This is a note to let you know that I've just added the patch titled fbdev: imxfb: fix left margin setting to the 6.1-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: fbdev-imxfb-fix-left-margin-setting.patch and it can be found in the queue-6.1 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 0f4f621ac35a0c9239682e9a27ef712cfcfe3543 Author: Dario Binacchi <dario.binacchi@xxxxxxxxxxxxxxxxxxxx> Date: Sat Nov 11 11:41:50 2023 +0100 fbdev: imxfb: fix left margin setting [ Upstream commit 5758844105f7dd9a0a04990cd92499a1a593dd36 ] 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@xxxxxxxxxxxxxxxxxxxx> Signed-off-by: Helge Deller <deller@xxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c index 36ada87b49a4..32b8374abeca 100644 --- a/drivers/video/fbdev/imxfb.c +++ b/drivers/video/fbdev/imxfb.c @@ -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. @@ -598,6 +613,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, @@ -606,6 +622,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", @@ -613,7 +636,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) @@ -639,7 +662,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) |