aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/cfbimgblt.c
diff options
context:
space:
mode:
authorAntonino A. Daplas <adaplas@gmail.com>2005-12-13 01:17:21 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-12-13 01:31:17 -0500
commitbe0d9b6c7aeaad1683059c00131cabd4c894c17c (patch)
treef7e55af855531331113cbddb98688f3901d48425 /drivers/video/cfbimgblt.c
parent7275b4b6bc2f783c135c3f0eeecc4fdc6e788aa8 (diff)
[PATCH] fbdev: Fix incorrect unaligned access in little-endian machines
The drawing function cfbfillrect does not work correctly when access is not unsigned-long aligned. It manifests as extra lines of pixels that are not complete drawn. Reversing the shift operator solves the problem, so I would presume that this bug would manifest only on little endian machines. The function cfbcopyarea may also have this bug. Aligned access should present no problems. Signed-off-by: Antonino Daplas <adaplas@pol.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/video/cfbimgblt.c')
-rw-r--r--drivers/video/cfbimgblt.c36
1 files changed, 12 insertions, 24 deletions
diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c
index 7a01742a82af..910e2338a27e 100644
--- a/drivers/video/cfbimgblt.c
+++ b/drivers/video/cfbimgblt.c
@@ -76,18 +76,6 @@ static u32 cfb_tab32[] = {
76#define FB_WRITEL fb_writel 76#define FB_WRITEL fb_writel
77#define FB_READL fb_readl 77#define FB_READL fb_readl
78 78
79#if defined (__BIG_ENDIAN)
80#define LEFT_POS(bpp) (32 - bpp)
81#define SHIFT_HIGH(val, bits) ((val) >> (bits))
82#define SHIFT_LOW(val, bits) ((val) << (bits))
83#define BIT_NR(b) (7 - (b))
84#else
85#define LEFT_POS(bpp) (0)
86#define SHIFT_HIGH(val, bits) ((val) << (bits))
87#define SHIFT_LOW(val, bits) ((val) >> (bits))
88#define BIT_NR(b) (b)
89#endif
90
91static inline void color_imageblit(const struct fb_image *image, 79static inline void color_imageblit(const struct fb_image *image,
92 struct fb_info *p, u8 __iomem *dst1, 80 struct fb_info *p, u8 __iomem *dst1,
93 u32 start_index, 81 u32 start_index,
@@ -109,7 +97,7 @@ static inline void color_imageblit(const struct fb_image *image,
109 val = 0; 97 val = 0;
110 98
111 if (start_index) { 99 if (start_index) {
112 u32 start_mask = ~(SHIFT_HIGH(~(u32)0, start_index)); 100 u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0, start_index));
113 val = FB_READL(dst) & start_mask; 101 val = FB_READL(dst) & start_mask;
114 shift = start_index; 102 shift = start_index;
115 } 103 }
@@ -119,20 +107,20 @@ static inline void color_imageblit(const struct fb_image *image,
119 color = palette[*src]; 107 color = palette[*src];
120 else 108 else
121 color = *src; 109 color = *src;
122 color <<= LEFT_POS(bpp); 110 color <<= FB_LEFT_POS(bpp);
123 val |= SHIFT_HIGH(color, shift); 111 val |= FB_SHIFT_HIGH(color, shift);
124 if (shift >= null_bits) { 112 if (shift >= null_bits) {
125 FB_WRITEL(val, dst++); 113 FB_WRITEL(val, dst++);
126 114
127 val = (shift == null_bits) ? 0 : 115 val = (shift == null_bits) ? 0 :
128 SHIFT_LOW(color, 32 - shift); 116 FB_SHIFT_LOW(color, 32 - shift);
129 } 117 }
130 shift += bpp; 118 shift += bpp;
131 shift &= (32 - 1); 119 shift &= (32 - 1);
132 src++; 120 src++;
133 } 121 }
134 if (shift) { 122 if (shift) {
135 u32 end_mask = SHIFT_HIGH(~(u32)0, shift); 123 u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift);
136 124
137 FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); 125 FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
138 } 126 }
@@ -162,8 +150,8 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
162 u32 i, j, l; 150 u32 i, j, l;
163 151
164 dst2 = (u32 __iomem *) dst1; 152 dst2 = (u32 __iomem *) dst1;
165 fgcolor <<= LEFT_POS(bpp); 153 fgcolor <<= FB_LEFT_POS(bpp);
166 bgcolor <<= LEFT_POS(bpp); 154 bgcolor <<= FB_LEFT_POS(bpp);
167 155
168 for (i = image->height; i--; ) { 156 for (i = image->height; i--; ) {
169 shift = val = 0; 157 shift = val = 0;
@@ -174,21 +162,21 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
174 162
175 /* write leading bits */ 163 /* write leading bits */
176 if (start_index) { 164 if (start_index) {
177 u32 start_mask = ~(SHIFT_HIGH(~(u32)0, start_index)); 165 u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0,start_index));
178 val = FB_READL(dst) & start_mask; 166 val = FB_READL(dst) & start_mask;
179 shift = start_index; 167 shift = start_index;
180 } 168 }
181 169
182 while (j--) { 170 while (j--) {
183 l--; 171 l--;
184 color = (*s & 1 << (BIT_NR(l))) ? fgcolor : bgcolor; 172 color = (*s & 1 << (FB_BIT_NR(l))) ? fgcolor : bgcolor;
185 val |= SHIFT_HIGH(color, shift); 173 val |= FB_SHIFT_HIGH(color, shift);
186 174
187 /* Did the bitshift spill bits to the next long? */ 175 /* Did the bitshift spill bits to the next long? */
188 if (shift >= null_bits) { 176 if (shift >= null_bits) {
189 FB_WRITEL(val, dst++); 177 FB_WRITEL(val, dst++);
190 val = (shift == null_bits) ? 0 : 178 val = (shift == null_bits) ? 0 :
191 SHIFT_LOW(color,32 - shift); 179 FB_SHIFT_LOW(color,32 - shift);
192 } 180 }
193 shift += bpp; 181 shift += bpp;
194 shift &= (32 - 1); 182 shift &= (32 - 1);
@@ -197,7 +185,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
197 185
198 /* write trailing bits */ 186 /* write trailing bits */
199 if (shift) { 187 if (shift) {
200 u32 end_mask = SHIFT_HIGH(~(u32)0, shift); 188 u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift);
201 189
202 FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); 190 FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
203 } 191 }