mxsfb: DATA_FORMAT_24_BIT flag outputs invalid colours

Juergen Beisert jbe at pengutronix.de
Fri May 24 06:28:33 EDT 2013


Hector Palacios wrote:
> Hi Juergen,
>
> On 05/23/2013 03:31 PM, Juergen Beisert wrote:
> > Hi Maxime,
> >
> > maxime.ripard at free-electrons.com wrote:
> >> On Thu, May 23, 2013 at 01:55:28PM +0200, Hector Palacios wrote:
> >>> I'm using an i.MX28 based board with lcd connected with 18bits data
> >>> bus. My platform uses 32 bits per pixel:
> >>>
> >>> 	mxsfb_pdata.default_bpp = 32;
> >>> 	mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT;
> >>>
> >>> With these settings the mxsfb.c driver sets flag DATA_FORMAT_24_BIT
> >>> at HW_LCDIF_CTRL register in function mxsfb_set_par():
> >>>
> >>> 	case 32:
> >>> 		dev_dbg(&host->pdev->dev, "Setting up RGB888/666 mode\n");
> >>> 		ctrl |= CTRL_SET_WORD_LENGTH(3);
> >>> 		switch (host->ld_intf_width) {
> >>> 		case STMLCDIF_8BIT:
> >>> 			dev_dbg(&host->pdev->dev,
> >>> 					"Unsupported LCD bus width mapping\n");
> >>> 			return -EINVAL;
> >>> 		case STMLCDIF_16BIT:
> >>> 		case STMLCDIF_18BIT:
> >>> 			/* 24 bit to 18 bit mapping */
> >>> 			ctrl |= CTRL_DF24; /* ignore the upper 2 bits in
> >>> 					    *  each colour component
> >>> 					    */
> >>> 			break;
> >>> 		case STMLCDIF_24BIT:
> >>> 			/* real 24 bit */
> >>> 			break;
> >>> 		}
> >>>
> >>> According to the manual, this flag does:
> >>> 	0x0: ALL_24_BITS_VALID: Data input to the block is in 24 bpp
> >>> format, such that all RGB 888 data is contained in 24 bits.
> >>> 	0x1: DROP_UPPER_2_BITS_PER_BYTE — Data input to the block is
> >>> actually RGB 18 bpp, but there is 1 colour per byte, hence the upper
> >>> 2 bits in each byte do not contain any useful data, and should be
> >>> dropped.
> >>>
> >>> The setting of this flag is producing bad colours with true colour
> >>> images (i.e. the Linux penguin is displayed ok, but QT applications
> >>> or images displayed with fbv are not).
> >>> I believe the setting of this flag is not correct (after all, if my
> >>> bpp is 32, then all 24bit colours are useful and dropping the upper
> >>> 2 bits is a bad idea).
> >>> If I don't set it, then true colour images are displayed correctly.
> >>> The only problem is that the Linux penguin is displayed much darker
> >>> than usual (correct colours, but darker). Perhaps the 224 colour
> >>> format of this image justifies it?
> >>>
> >>> I noticed the cfa10049 platform also uses the same configuration (18
> >>> bits data bus and 32bpp) and was wondering if true colour images are
> >>> correctly displayed in this platform with this flag set (for example
> >>> with fbv application [1]).
> >>
> >> I had the exact same problem, and suggested the exact same solution a
> >> few weeks back.
> >>
> >> https://patchwork.kernel.org/patch/2470441/
> >>
> >> The conclusion of that discussion what that the userspace applications
> >> were not honouring the bitfield correctly set by the mxsfb driver, and
> >> as such, it was not a bug in the driver.
> >>
> >> While this is correct, I wonder, now that since we had that same problem
> >> in a very short amount of time, if we couldn't set this behaviour
> >> dependant of some (dt? kernel argument?) property so that one could
> >> customise it anyway he want.
> >>
> >> Maxime
> >
> > i.MX2[3|8]    LCD1       LCD2       LCD3
> >                24bit      18bit      18bit
> > --------------------------------------------
> > LCD_D0         B0         B0         --
> > LCD_D1         B1         B1         --
> > LCD_D2         B2         B2         B0
> > LCD_D3         B3         B3         B1
> > LCD_D4         B4         B4         B2
> > LCD_D5         B5         B5         B3
> > LCD_D6         B6         G0         B4
> > LCD_D7         B7         G1         B5
> >
> > LCD_D8         G0         G2         --
> > LCD_D9         G1         G3         --
> > LCD_D10        G2         G4         G0
> > LCD_D11        G3         G5         G1
> > LCD_D12        G4         R0         G2
> > LCD_D13        G5         R1         G3
> > LCD_D14        G6         R2         G4
> > LCD_D15        G7         R3         G5
> >
> > LCD_D16        R0         R4         --
> > LCD_D17        R1         R5         --
> > LCD_D18        R2                    R0
> > LCD_D19        R3                    R1
> > LCD_D20        R4                    R2
> > LCD_D21        R5                    R3
> > LCD_D22        R6                    R4
> > LCD_D23        R7                    R5
> >
> > Is your display connected like LCD2 or LCD3? LCD3 must still handled like
> > a 24 bit display shown in LCD1, while only the LCD2-case is the "24 bit
> > to 18 bit mapping" case.
> >
> > At least my current tests with an i.MX23 and a connection like LCD2 are
> > working here with a Qt application. Qt honours the pixel bitfield
> > description. And I'm using the "bits-per-pixel = <32>" and "bus-width =
> > <18>" entries in the device tree.
>
> I have a 24bit LCD display but my connection to it is done at 18bits data
> width. Represented below as LCD4.
> NOTE: In my LCD4 column, notation Rx/Gx/Bx represent the color bit in
> memory as well as the display data line.
> Since we use 32bpp each channel has 8 bits (R7..R0, etc.).
> I understand that you have an 18bit display and that your notation in LCD2
> column represents the display data lines, not the color bit indexes in
> memory.
>
> i.MX2[3|8]    LCD1       LCD2       LCD3	LCD4
>               24bit      18bit      18bit	24bit connected at 18bit
> -------------------------------------------------------
> LCD_D0         B0         B0         --		B2
> LCD_D1         B1         B1         --		B3
> LCD_D2         B2         B2         B0		B4
> LCD_D3         B3         B3         B1		B5
> LCD_D4         B4         B4         B2		B6
> LCD_D5         B5         B5         B3		B7
> LCD_D6         B6         G0         B4		G2
> LCD_D7         B7         G1         B5		G3
>
> LCD_D8         G0         G2         --		G4
> LCD_D9         G1         G3         --		G5
> LCD_D10        G2         G4         G0		G6
> LCD_D11        G3         G5         G1		G7
> LCD_D12        G4         R0         G2		R2
> LCD_D13        G5         R1         G3		R3
> LCD_D14        G6         R2         G4		R4
> LCD_D15        G7         R3         G5		R5
>
> LCD_D16        R0         R4         --		R6
> LCD_D17        R1         R5         --		R7
> LCD_D18        R2                    R0
> LCD_D19        R3                    R1
> LCD_D20        R4                    R2
> LCD_D21        R5                    R3
> LCD_D22        R6                    R4
> LCD_D23        R7                    R5
>
> For 32bpp (RGB888) and 18bit data bus I would expect the LCD controller to
> take the six *most significant* bits [7..2] from each color byte out to the
> LCD data bus (LCD_D17..D0) in the order depicted in my LCD4 column.
>
> I'm not sure what the DATA_FORMAT_24_BIT flag is doing, but dropping the
> two most significant bits of color in memory doesn't seem to be a good idea
> unless (maybe) color is in 18bpp. Previous kernels did not even touch this
> flag.
>
> Does the following patch make sense?
>
> diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
> index b1c1a80..bb0a4e1 100644
> --- a/drivers/video/mxsfb.c
> +++ b/drivers/video/mxsfb.c
> @@ -298,9 +298,6 @@ static int mxsfb_check_var(struct fb_var_screeninfo
> *var, break;
>                  case STMLCDIF_16BIT:
>                  case STMLCDIF_18BIT:
> -                       /* 24 bit to 18 bit mapping */
> -                       rgb = def_rgb666;
> -                       break;
>                  case STMLCDIF_24BIT:
>                          /* real 24 bit */
>                          rgb = def_rgb888;
> @@ -424,11 +421,6 @@ static int mxsfb_set_par(struct fb_info *fb_info)
>                          return -EINVAL;
>                  case STMLCDIF_16BIT:
>                  case STMLCDIF_18BIT:
> -                       /* 24 bit to 18 bit mapping */
> -                       ctrl |= CTRL_DF24; /* ignore the upper 2 bits in
> -                                           *  each colour component
> -                                           */
> -                       break;
>                  case STMLCDIF_24BIT:
>                          /* real 24 bit */
>                          break;
>
> The setting of def_rgb666 for a 32bpp color depth does not make sense to me
> because the color in memory is really rgb888.
>
> With this patch, my true color images are displayed ok and so does the
> penguin logo. I don't know however how other displays connections at 18bit
> will do.

Your 24 bit display is connected like a regular 18 bit display. So they should 
work in the same way with the same settings. You *must* always skip two data 
bits from the memory RGB888 to form a RGB666 value.

I just did some measurement here with my i.MX23 based hardware.

I'm using 32 bits per pixel and the 18 bit display interface (LCD_D[0..17]).

And surprise, surprise: the i.MX23 *always* maps the 24 bit input data to the 
18 bit interface. And what does the DATA_FORMAT_24_BIT aka. CTRL_DF24 do???
Just simple: it seems its meaning changes with the interface width. The 
documentation says:

  0 = all 24 bits are valid
  1 = drop upper 2 bits per byte

This text seems valid for a real 24 bit display (but I cannot test it). From 
my measurement its meaning changes when used with an 18 bit display to:

  0 = drop lower 2 bits per byte
  1 = drop upper 2 bits per byte

When this bit is 0:

      red     green    blue
   10000001|00001111|10001111 (memory layout)

   100000..|000011..|100011.. (at the display)

When this bit is 1:

      red     green    blue
   10000001|00001111|10001111 (memory layout)

   ..000001|..001111|..001111 (at the display)

Hope it does help you.

Regards,
Juergen

-- 
Pengutronix e.K.                              | Juergen Beisert             |
Linux Solutions for Science and Industry      | http://www.pengutronix.de/  |



More information about the linux-arm-kernel mailing list