diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-12-27 19:10:16 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2012-01-12 14:34:59 -0500 |
commit | 51a32a1a373e071aec24ffa765d198d591b3d6dd (patch) | |
tree | 3ca125cec33629445f067fe0c7423d9864fb960b | |
parent | 081fa89b1a6e7ed3a05459b88ad974a6f3795a90 (diff) |
offb: Fix setting of the pseudo-palette for >8bpp
commit 1bb0b7d21584b3f878e2bc880db62351ddee5185 upstream.
When using a >8bpp framebuffer, offb advertises truecolor, not directcolor,
and doesn't touch the color map even if it has a corresponding access method
for the real hardware.
Thus it needs to set the pseudo-palette with all 3 components of the color,
like other truecolor framebuffers, not with copies of the color index like
a directcolor framebuffer would do.
This went unnoticed for a long time because it's pretty hard to get offb
to kick in with anything but 8bpp (old BootX under MacOS will do that and
qemu does it).
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/video/offb.c | 50 |
1 files changed, 23 insertions, 27 deletions
diff --git a/drivers/video/offb.c b/drivers/video/offb.c index cb163a5397b..24e1fc6b565 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c | |||
@@ -100,36 +100,32 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
100 | u_int transp, struct fb_info *info) | 100 | u_int transp, struct fb_info *info) |
101 | { | 101 | { |
102 | struct offb_par *par = (struct offb_par *) info->par; | 102 | struct offb_par *par = (struct offb_par *) info->par; |
103 | int i, depth; | 103 | |
104 | u32 *pal = info->pseudo_palette; | 104 | if (info->fix.visual == FB_VISUAL_TRUECOLOR) { |
105 | 105 | u32 *pal = info->pseudo_palette; | |
106 | depth = info->var.bits_per_pixel; | 106 | u32 cr = red >> (16 - info->var.red.length); |
107 | if (depth == 16) | 107 | u32 cg = green >> (16 - info->var.green.length); |
108 | depth = (info->var.green.length == 5) ? 15 : 16; | 108 | u32 cb = blue >> (16 - info->var.blue.length); |
109 | 109 | u32 value; | |
110 | if (regno > 255 || | 110 | |
111 | (depth == 16 && regno > 63) || | 111 | if (regno >= 16) |
112 | (depth == 15 && regno > 31)) | 112 | return -EINVAL; |
113 | return 1; | 113 | |
114 | 114 | value = (cr << info->var.red.offset) | | |
115 | if (regno < 16) { | 115 | (cg << info->var.green.offset) | |
116 | switch (depth) { | 116 | (cb << info->var.blue.offset); |
117 | case 15: | 117 | if (info->var.transp.length > 0) { |
118 | pal[regno] = (regno << 10) | (regno << 5) | regno; | 118 | u32 mask = (1 << info->var.transp.length) - 1; |
119 | break; | 119 | mask <<= info->var.transp.offset; |
120 | case 16: | 120 | value |= mask; |
121 | pal[regno] = (regno << 11) | (regno << 5) | regno; | ||
122 | break; | ||
123 | case 24: | ||
124 | pal[regno] = (regno << 16) | (regno << 8) | regno; | ||
125 | break; | ||
126 | case 32: | ||
127 | i = (regno << 8) | regno; | ||
128 | pal[regno] = (i << 16) | i; | ||
129 | break; | ||
130 | } | 121 | } |
122 | pal[regno] = value; | ||
123 | return 0; | ||
131 | } | 124 | } |
132 | 125 | ||
126 | if (regno > 255) | ||
127 | return -EINVAL; | ||
128 | |||
133 | red >>= 8; | 129 | red >>= 8; |
134 | green >>= 8; | 130 | green >>= 8; |
135 | blue >>= 8; | 131 | blue >>= 8; |