Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.17-rc5 434 lines 10 kB view raw
1/* 2 * Generic fillrect for frame buffers with packed pixels of any depth. 3 * 4 * Copyright (C) 2000 James Simmons (jsimmons@linux-fbdev.org) 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file COPYING in the main directory of this archive for 8 * more details. 9 * 10 * NOTES: 11 * 12 * The code for depths like 24 that don't have integer number of pixels per 13 * long is broken and needs to be fixed. For now I turned these types of 14 * mode off. 15 * 16 * Also need to add code to deal with cards endians that are different than 17 * the native cpu endians. I also need to deal with MSB position in the word. 18 * 19 */ 20#include <linux/config.h> 21#include <linux/module.h> 22#include <linux/string.h> 23#include <linux/fb.h> 24#include <asm/types.h> 25 26#if BITS_PER_LONG == 32 27# define FB_WRITEL fb_writel 28# define FB_READL fb_readl 29#else 30# define FB_WRITEL fb_writeq 31# define FB_READL fb_readq 32#endif 33 34 /* 35 * Compose two values, using a bitmask as decision value 36 * This is equivalent to (a & mask) | (b & ~mask) 37 */ 38 39static inline unsigned long 40comp(unsigned long a, unsigned long b, unsigned long mask) 41{ 42 return ((a ^ b) & mask) ^ b; 43} 44 45 /* 46 * Create a pattern with the given pixel's color 47 */ 48 49#if BITS_PER_LONG == 64 50static inline unsigned long 51pixel_to_pat( u32 bpp, u32 pixel) 52{ 53 switch (bpp) { 54 case 1: 55 return 0xfffffffffffffffful*pixel; 56 case 2: 57 return 0x5555555555555555ul*pixel; 58 case 4: 59 return 0x1111111111111111ul*pixel; 60 case 8: 61 return 0x0101010101010101ul*pixel; 62 case 12: 63 return 0x0001001001001001ul*pixel; 64 case 16: 65 return 0x0001000100010001ul*pixel; 66 case 24: 67 return 0x0000000001000001ul*pixel; 68 case 32: 69 return 0x0000000100000001ul*pixel; 70 default: 71 panic("pixel_to_pat(): unsupported pixelformat\n"); 72 } 73} 74#else 75static inline unsigned long 76pixel_to_pat( u32 bpp, u32 pixel) 77{ 78 switch (bpp) { 79 case 1: 80 return 0xfffffffful*pixel; 81 case 2: 82 return 0x55555555ul*pixel; 83 case 4: 84 return 0x11111111ul*pixel; 85 case 8: 86 return 0x01010101ul*pixel; 87 case 12: 88 return 0x00001001ul*pixel; 89 case 16: 90 return 0x00010001ul*pixel; 91 case 24: 92 return 0x00000001ul*pixel; 93 case 32: 94 return 0x00000001ul*pixel; 95 default: 96 panic("pixel_to_pat(): unsupported pixelformat\n"); 97 } 98} 99#endif 100 101 /* 102 * Aligned pattern fill using 32/64-bit memory accesses 103 */ 104 105static void 106bitfill_aligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat, unsigned n, int bits) 107{ 108 unsigned long first, last; 109 110 if (!n) 111 return; 112 113 first = FB_SHIFT_HIGH(~0UL, dst_idx); 114 last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); 115 116 if (dst_idx+n <= bits) { 117 // Single word 118 if (last) 119 first &= last; 120 FB_WRITEL(comp(pat, FB_READL(dst), first), dst); 121 } else { 122 // Multiple destination words 123 124 // Leading bits 125 if (first!= ~0UL) { 126 FB_WRITEL(comp(pat, FB_READL(dst), first), dst); 127 dst++; 128 n -= bits - dst_idx; 129 } 130 131 // Main chunk 132 n /= bits; 133 while (n >= 8) { 134 FB_WRITEL(pat, dst++); 135 FB_WRITEL(pat, dst++); 136 FB_WRITEL(pat, dst++); 137 FB_WRITEL(pat, dst++); 138 FB_WRITEL(pat, dst++); 139 FB_WRITEL(pat, dst++); 140 FB_WRITEL(pat, dst++); 141 FB_WRITEL(pat, dst++); 142 n -= 8; 143 } 144 while (n--) 145 FB_WRITEL(pat, dst++); 146 147 // Trailing bits 148 if (last) 149 FB_WRITEL(comp(pat, FB_READL(dst), last), dst); 150 } 151} 152 153 154 /* 155 * Unaligned generic pattern fill using 32/64-bit memory accesses 156 * The pattern must have been expanded to a full 32/64-bit value 157 * Left/right are the appropriate shifts to convert to the pattern to be 158 * used for the next 32/64-bit word 159 */ 160 161static void 162bitfill_unaligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat, 163 int left, int right, unsigned n, int bits) 164{ 165 unsigned long first, last; 166 167 if (!n) 168 return; 169 170 first = FB_SHIFT_HIGH(~0UL, dst_idx); 171 last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); 172 173 if (dst_idx+n <= bits) { 174 // Single word 175 if (last) 176 first &= last; 177 FB_WRITEL(comp(pat, FB_READL(dst), first), dst); 178 } else { 179 // Multiple destination words 180 // Leading bits 181 if (first) { 182 FB_WRITEL(comp(pat, FB_READL(dst), first), dst); 183 dst++; 184 pat = pat << left | pat >> right; 185 n -= bits - dst_idx; 186 } 187 188 // Main chunk 189 n /= bits; 190 while (n >= 4) { 191 FB_WRITEL(pat, dst++); 192 pat = pat << left | pat >> right; 193 FB_WRITEL(pat, dst++); 194 pat = pat << left | pat >> right; 195 FB_WRITEL(pat, dst++); 196 pat = pat << left | pat >> right; 197 FB_WRITEL(pat, dst++); 198 pat = pat << left | pat >> right; 199 n -= 4; 200 } 201 while (n--) { 202 FB_WRITEL(pat, dst++); 203 pat = pat << left | pat >> right; 204 } 205 206 // Trailing bits 207 if (last) 208 FB_WRITEL(comp(pat, FB_READL(dst), first), dst); 209 } 210} 211 212 /* 213 * Aligned pattern invert using 32/64-bit memory accesses 214 */ 215static void 216bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, unsigned n, int bits) 217{ 218 unsigned long val = pat, dat; 219 unsigned long first, last; 220 221 if (!n) 222 return; 223 224 first = FB_SHIFT_HIGH(~0UL, dst_idx); 225 last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); 226 227 if (dst_idx+n <= bits) { 228 // Single word 229 if (last) 230 first &= last; 231 dat = FB_READL(dst); 232 FB_WRITEL(comp(dat ^ val, dat, first), dst); 233 } else { 234 // Multiple destination words 235 // Leading bits 236 if (first!=0UL) { 237 dat = FB_READL(dst); 238 FB_WRITEL(comp(dat ^ val, dat, first), dst); 239 dst++; 240 n -= bits - dst_idx; 241 } 242 243 // Main chunk 244 n /= bits; 245 while (n >= 8) { 246 FB_WRITEL(FB_READL(dst) ^ val, dst); 247 dst++; 248 FB_WRITEL(FB_READL(dst) ^ val, dst); 249 dst++; 250 FB_WRITEL(FB_READL(dst) ^ val, dst); 251 dst++; 252 FB_WRITEL(FB_READL(dst) ^ val, dst); 253 dst++; 254 FB_WRITEL(FB_READL(dst) ^ val, dst); 255 dst++; 256 FB_WRITEL(FB_READL(dst) ^ val, dst); 257 dst++; 258 FB_WRITEL(FB_READL(dst) ^ val, dst); 259 dst++; 260 FB_WRITEL(FB_READL(dst) ^ val, dst); 261 dst++; 262 n -= 8; 263 } 264 while (n--) { 265 FB_WRITEL(FB_READL(dst) ^ val, dst); 266 dst++; 267 } 268 // Trailing bits 269 if (last) { 270 dat = FB_READL(dst); 271 FB_WRITEL(comp(dat ^ val, dat, last), dst); 272 } 273 } 274} 275 276 277 /* 278 * Unaligned generic pattern invert using 32/64-bit memory accesses 279 * The pattern must have been expanded to a full 32/64-bit value 280 * Left/right are the appropriate shifts to convert to the pattern to be 281 * used for the next 32/64-bit word 282 */ 283 284static void 285bitfill_unaligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, 286 int left, int right, unsigned n, int bits) 287{ 288 unsigned long first, last, dat; 289 290 if (!n) 291 return; 292 293 first = FB_SHIFT_HIGH(~0UL, dst_idx); 294 last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); 295 296 if (dst_idx+n <= bits) { 297 // Single word 298 if (last) 299 first &= last; 300 dat = FB_READL(dst); 301 FB_WRITEL(comp(dat ^ pat, dat, first), dst); 302 } else { 303 // Multiple destination words 304 305 // Leading bits 306 if (first != 0UL) { 307 dat = FB_READL(dst); 308 FB_WRITEL(comp(dat ^ pat, dat, first), dst); 309 dst++; 310 pat = pat << left | pat >> right; 311 n -= bits - dst_idx; 312 } 313 314 // Main chunk 315 n /= bits; 316 while (n >= 4) { 317 FB_WRITEL(FB_READL(dst) ^ pat, dst); 318 dst++; 319 pat = pat << left | pat >> right; 320 FB_WRITEL(FB_READL(dst) ^ pat, dst); 321 dst++; 322 pat = pat << left | pat >> right; 323 FB_WRITEL(FB_READL(dst) ^ pat, dst); 324 dst++; 325 pat = pat << left | pat >> right; 326 FB_WRITEL(FB_READL(dst) ^ pat, dst); 327 dst++; 328 pat = pat << left | pat >> right; 329 n -= 4; 330 } 331 while (n--) { 332 FB_WRITEL(FB_READL(dst) ^ pat, dst); 333 dst++; 334 pat = pat << left | pat >> right; 335 } 336 337 // Trailing bits 338 if (last) { 339 dat = FB_READL(dst); 340 FB_WRITEL(comp(dat ^ pat, dat, last), dst); 341 } 342 } 343} 344 345void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) 346{ 347 unsigned long pat, fg; 348 unsigned long width = rect->width, height = rect->height; 349 int bits = BITS_PER_LONG, bytes = bits >> 3; 350 u32 bpp = p->var.bits_per_pixel; 351 unsigned long __iomem *dst; 352 int dst_idx, left; 353 354 if (p->state != FBINFO_STATE_RUNNING) 355 return; 356 357 if (p->fix.visual == FB_VISUAL_TRUECOLOR || 358 p->fix.visual == FB_VISUAL_DIRECTCOLOR ) 359 fg = ((u32 *) (p->pseudo_palette))[rect->color]; 360 else 361 fg = rect->color; 362 363 pat = pixel_to_pat( bpp, fg); 364 365 dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1)); 366 dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8; 367 dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp; 368 /* FIXME For now we support 1-32 bpp only */ 369 left = bits % bpp; 370 if (p->fbops->fb_sync) 371 p->fbops->fb_sync(p); 372 if (!left) { 373 void (*fill_op32)(unsigned long __iomem *dst, int dst_idx, 374 unsigned long pat, unsigned n, int bits) = NULL; 375 376 switch (rect->rop) { 377 case ROP_XOR: 378 fill_op32 = bitfill_aligned_rev; 379 break; 380 case ROP_COPY: 381 fill_op32 = bitfill_aligned; 382 break; 383 default: 384 printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n"); 385 fill_op32 = bitfill_aligned; 386 break; 387 } 388 while (height--) { 389 dst += dst_idx >> (ffs(bits) - 1); 390 dst_idx &= (bits - 1); 391 fill_op32(dst, dst_idx, pat, width*bpp, bits); 392 dst_idx += p->fix.line_length*8; 393 } 394 } else { 395 int right; 396 int r; 397 int rot = (left-dst_idx) % bpp; 398 void (*fill_op)(unsigned long __iomem *dst, int dst_idx, 399 unsigned long pat, int left, int right, 400 unsigned n, int bits) = NULL; 401 402 /* rotate pattern to correct start position */ 403 pat = pat << rot | pat >> (bpp-rot); 404 405 right = bpp-left; 406 switch (rect->rop) { 407 case ROP_XOR: 408 fill_op = bitfill_unaligned_rev; 409 break; 410 case ROP_COPY: 411 fill_op = bitfill_unaligned; 412 break; 413 default: 414 printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n"); 415 fill_op = bitfill_unaligned; 416 break; 417 } 418 while (height--) { 419 dst += dst_idx >> (ffs(bits) - 1); 420 dst_idx &= (bits - 1); 421 fill_op(dst, dst_idx, pat, left, right, 422 width*bpp, bits); 423 r = (p->fix.line_length*8) % bpp; 424 pat = pat << (bpp-r) | pat >> r; 425 dst_idx += p->fix.line_length*8; 426 } 427 } 428} 429 430EXPORT_SYMBOL(cfb_fillrect); 431 432MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); 433MODULE_DESCRIPTION("Generic software accelerated fill rectangle"); 434MODULE_LICENSE("GPL");