diff mbox

offb: Fix little-endian support

Message ID 1400073709-15012-1-git-send-email-tiwai@suse.de (mailing list archive)
State New, archived
Headers show

Commit Message

Takashi Iwai May 14, 2014, 1:21 p.m. UTC
Although the color palette was corrected for little endian by the
commit  [e1edf18b: offb: Add palette hack for little endian], the
graphics mode is still shown in psychedelic colors.  For fixing this
properly, we rather need to correct the RGB offsets depending on
endianess.

Since the RGB base offsets are corrected, we don't need the hack for
pallette color entries.  This patch reverts that, too.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 drivers/video/fbdev/offb.c | 51 +++++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

Comments

Benjamin Herrenschmidt June 16, 2014, 7:35 a.m. UTC | #1
On Wed, 2014-05-14 at 15:21 +0200, Takashi Iwai wrote:
>         case 16:                /* RGB 565 */
>                 var->bits_per_pixel = 16;
> -               var->red.offset = 11;
> +               if (fb_be_math(info)) {
> +                       var->red.offset = 11;
> +                       var->green.offset = 5;
> +                       var->blue.offset = 0;
> +               } else {
> +                       var->red.offset = 0;
> +                       var->green.offset = 5;
> +                       var->blue.offset = 11;
> +               }
>                 var->red.length = 5;
> -               var->green.offset = 5;
>                 var->green.length = 6;
> -               var->blue.offset = 0;
>                 var->blue.length = 5;
>                 var->transp.offset = 0;
>                 var->transp.length = 0;
>                 break;

I somewhat doubt that this (and 5:5:5) actually work, do they ? the
green gets split into two separate fields, which we can't express
properly here...

Cheers,
Ben.


--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Benjamin Herrenschmidt June 16, 2014, 11:54 p.m. UTC | #2
On Mon, 2014-06-16 at 17:35 +1000, Benjamin Herrenschmidt wrote:

> I somewhat doubt that this (and 5:5:5) actually work, do they ? the
> green gets split into two separate fields, which we can't express
> properly here...

So the conclusion of further investigation is:

 - The right fix is to fix qemu to flip endian

 - There's an open discussion as to whether qemu could do it
automatically when the guest endian changes on powerpc as a quick fix,
the long run approach is to have a register to control it, I'm working
on it. offb can then "learn" to flick it like it does the palette hack
today.

 - If we want to ever support foreign endian offb with X, we need to do
things a bit differently based on the foreign endian bit that is already
there.

 - We must revert the existing cmap swap patch from the kernel, it's
broken and will break things when we fix qemu (and breaks with real HW
in LE mode). I've sent a revert request to Linus and CC'ed stable.

Cheers,
Ben.


--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Takashi Iwai June 17, 2014, 10:01 a.m. UTC | #3
At Tue, 17 Jun 2014 09:54:07 +1000,
Benjamin Herrenschmidt wrote:
> 
> On Mon, 2014-06-16 at 17:35 +1000, Benjamin Herrenschmidt wrote:
> 
> > I somewhat doubt that this (and 5:5:5) actually work, do they ? the
> > green gets split into two separate fields, which we can't express
> > properly here...
> 
> So the conclusion of further investigation is:
> 
>  - The right fix is to fix qemu to flip endian
> 
>  - There's an open discussion as to whether qemu could do it
> automatically when the guest endian changes on powerpc as a quick fix,
> the long run approach is to have a register to control it, I'm working
> on it. offb can then "learn" to flick it like it does the palette hack
> today.
> 
>  - If we want to ever support foreign endian offb with X, we need to do
> things a bit differently based on the foreign endian bit that is already
> there.
> 
>  - We must revert the existing cmap swap patch from the kernel, it's
> broken and will break things when we fix qemu (and breaks with real HW
> in LE mode). I've sent a revert request to Linus and CC'ed stable.

Yeah, I agree.  Both the current palette fix and my patch are really
wrong band-aiding.

(Though, the issue in X is rather a problem of X itself.  X should
 work with the tweaked RGB offsets.)


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/video/fbdev/offb.c b/drivers/video/fbdev/offb.c
index 7d44d669d5b6..0224a62aa49d 100644
--- a/drivers/video/fbdev/offb.c
+++ b/drivers/video/fbdev/offb.c
@@ -93,13 +93,6 @@  extern boot_infos_t *boot_infos;
 
 #define FB_RIGHT_POS(p, bpp)         (fb_be_math(p) ? 0 : (32 - (bpp)))
 
-static inline u32 offb_cmap_byteswap(struct fb_info *info, u32 value)
-{
-	u32 bpp = info->var.bits_per_pixel;
-
-	return cpu_to_be32(value) >> FB_RIGHT_POS(info, bpp);
-}
-
     /*
      *  Set a single color register. The values supplied are already
      *  rounded down to the hardware's capabilities (according to the
@@ -129,7 +122,7 @@  static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 			mask <<= info->var.transp.offset;
 			value |= mask;
 		}
-		pal[regno] = offb_cmap_byteswap(info, value);
+		pal[regno] = value;
 		return 0;
 	}
 
@@ -451,6 +444,8 @@  static void __init offb_init_fb(const char *name, const char *full_name,
 	else
 		fix->visual = FB_VISUAL_TRUECOLOR;
 
+	info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE | foreign_endian;
+
 	var->xoffset = var->yoffset = 0;
 	switch (depth) {
 	case 8:
@@ -466,35 +461,54 @@  static void __init offb_init_fb(const char *name, const char *full_name,
 		break;
 	case 15:		/* RGB 555 */
 		var->bits_per_pixel = 16;
-		var->red.offset = 10;
+		if (fb_be_math(info)) {
+			var->red.offset = 10;
+			var->green.offset = 5;
+			var->blue.offset = 0;
+		} else {
+			var->red.offset = 0;
+			var->green.offset = 5;
+			var->blue.offset = 10;
+		}
 		var->red.length = 5;
-		var->green.offset = 5;
 		var->green.length = 5;
-		var->blue.offset = 0;
 		var->blue.length = 5;
 		var->transp.offset = 0;
 		var->transp.length = 0;
 		break;
 	case 16:		/* RGB 565 */
 		var->bits_per_pixel = 16;
-		var->red.offset = 11;
+		if (fb_be_math(info)) {
+			var->red.offset = 11;
+			var->green.offset = 5;
+			var->blue.offset = 0;
+		} else {
+			var->red.offset = 0;
+			var->green.offset = 5;
+			var->blue.offset = 11;
+		}
 		var->red.length = 5;
-		var->green.offset = 5;
 		var->green.length = 6;
-		var->blue.offset = 0;
 		var->blue.length = 5;
 		var->transp.offset = 0;
 		var->transp.length = 0;
 		break;
 	case 32:		/* RGB 888 */
 		var->bits_per_pixel = 32;
-		var->red.offset = 16;
+		if (fb_be_math(info)) {
+			var->red.offset = 16;
+			var->green.offset = 8;
+			var->blue.offset = 0;
+			var->transp.offset = 24;
+		} else {
+			var->red.offset = 8;
+			var->green.offset = 16;
+			var->blue.offset = 24;
+			var->transp.offset = 0;
+		}
 		var->red.length = 8;
-		var->green.offset = 8;
 		var->green.length = 8;
-		var->blue.offset = 0;
 		var->blue.length = 8;
-		var->transp.offset = 24;
 		var->transp.length = 8;
 		break;
 	}
@@ -521,7 +535,6 @@  static void __init offb_init_fb(const char *name, const char *full_name,
 	info->fbops = &offb_ops;
 	info->screen_base = ioremap(address, fix->smem_len);
 	info->pseudo_palette = (void *) (info + 1);
-	info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE | foreign_endian;
 
 	fb_alloc_cmap(&info->cmap, 256, 0);