aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/offb.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-12-27 19:10:16 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-01-02 20:09:25 -0500
commit1bb0b7d21584b3f878e2bc880db62351ddee5185 (patch)
tree5d2d4b9402e1ef5a3e403b0280a4be8a864694a4 /drivers/video/offb.c
parent9b961ed21a7c92c4768b9871a1c7e68d90f5267d (diff)
offb: Fix setting of the pseudo-palette for >8bpp
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> CC: stable@kernel.org
Diffstat (limited to 'drivers/video/offb.c')
-rw-r--r--drivers/video/offb.c50
1 files changed, 23 insertions, 27 deletions
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index da7cf7936b24..0c4f34311eda 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -101,36 +101,32 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
101 u_int transp, struct fb_info *info) 101 u_int transp, struct fb_info *info)
102{ 102{
103 struct offb_par *par = (struct offb_par *) info->par; 103 struct offb_par *par = (struct offb_par *) info->par;
104 int i, depth; 104
105 u32 *pal = info->pseudo_palette; 105 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
106 106 u32 *pal = info->pseudo_palette;
107 depth = info->var.bits_per_pixel; 107 u32 cr = red >> (16 - info->var.red.length);
108 if (depth == 16) 108 u32 cg = green >> (16 - info->var.green.length);
109 depth = (info->var.green.length == 5) ? 15 : 16; 109 u32 cb = blue >> (16 - info->var.blue.length);
110 110 u32 value;
111 if (regno > 255 || 111
112 (depth == 16 && regno > 63) || 112 if (regno >= 16)
113 (depth == 15 && regno > 31)) 113 return -EINVAL;
114 return 1; 114
115 115 value = (cr << info->var.red.offset) |
116 if (regno < 16) { 116 (cg << info->var.green.offset) |
117 switch (depth) { 117 (cb << info->var.blue.offset);
118 case 15: 118 if (info->var.transp.length > 0) {
119 pal[regno] = (regno << 10) | (regno << 5) | regno; 119 u32 mask = (1 << info->var.transp.length) - 1;
120 break; 120 mask <<= info->var.transp.offset;
121 case 16: 121 value |= mask;
122 pal[regno] = (regno << 11) | (regno << 5) | regno;
123 break;
124 case 24:
125 pal[regno] = (regno << 16) | (regno << 8) | regno;
126 break;
127 case 32:
128 i = (regno << 8) | regno;
129 pal[regno] = (i << 16) | i;
130 break;
131 } 122 }
123 pal[regno] = value;
124 return 0;
132 } 125 }
133 126
127 if (regno > 255)
128 return -EINVAL;
129
134 red >>= 8; 130 red >>= 8;
135 green >>= 8; 131 green >>= 8;
136 blue >>= 8; 132 blue >>= 8;