1 /* 2 * linux/drivers/video/iplan2p8.c -- Low level frame buffer operations for 3 * interleaved bitplanes à la Atari (8 4 * planes, 2 bytes interleave) 5 * 6 * Created 5 Apr 1997 by Geert Uytterhoeven 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file COPYING in the main directory of this archive for 10 * more details. 11 */ 12 13 #include <linux/module.h> 14 #include <linux/string.h> 15 #include <linux/fb.h> 16 17 #include <asm/setup.h> 18 19 #include "atafb.h" 20 21 #define BPL 8 22 #include "atafb_utils.h" 23 24 25 /* Copies a 8 plane column from 's', height 'h', to 'd'. */ 26 27 /* This expands a 8 bit color into two longs for two movepl (8 plane) 28 * operations. 29 */ 30 31 void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line, 32 int sy, int sx, int dy, int dx, 33 int height, int width) 34 { 35 /* bmove() has to distinguish two major cases: If both, source and 36 * destination, start at even addresses or both are at odd 37 * addresses, just the first odd and last even column (if present) 38 * require special treatment (memmove_col()). The rest between 39 * then can be copied by normal operations, because all adjacent 40 * bytes are affected and are to be stored in the same order. 41 * The pathological case is when the move should go from an odd 42 * address to an even or vice versa. Since the bytes in the plane 43 * words must be assembled in new order, it seems wisest to make 44 * all movements by memmove_col(). 45 */ 46 47 u8 *src, *dst; 48 u32 *s, *d; 49 int w, l , i, j; 50 u_int colsize; 51 u_int upwards = (dy < sy) || (dy == sy && dx < sx); 52 53 colsize = height; 54 if (!((sx ^ dx) & 15)) { 55 /* odd->odd or even->even */ 56 57 if (upwards) { 58 src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); 59 dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); 60 if (sx & 15) { 61 memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2); 62 src += BPL * 2; 63 dst += BPL * 2; 64 width -= 8; 65 } 66 w = width >> 4; 67 if (w) { 68 s = (u32 *)src; 69 d = (u32 *)dst; 70 w *= BPL / 2; 71 l = next_line - w * 4; 72 for (j = height; j > 0; j--) { 73 for (i = w; i > 0; i--) 74 *d++ = *s++; 75 s = (u32 *)((u8 *)s + l); 76 d = (u32 *)((u8 *)d + l); 77 } 78 } 79 if (width & 15) 80 memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL), 81 0xff00ff00, height, next_line - BPL * 2); 82 } else { 83 src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); 84 dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); 85 86 if ((sx + width) & 15) { 87 src -= BPL * 2; 88 dst -= BPL * 2; 89 memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2); 90 width -= 8; 91 } 92 w = width >> 4; 93 if (w) { 94 s = (u32 *)src; 95 d = (u32 *)dst; 96 w *= BPL / 2; 97 l = next_line - w * 4; 98 for (j = height; j > 0; j--) { 99 for (i = w; i > 0; i--) 100 *--d = *--s; 101 s = (u32 *)((u8 *)s - l); 102 d = (u32 *)((u8 *)d - l); 103 } 104 } 105 if (sx & 15) 106 memmove32_col(dst - (width - 16) / (8 / BPL), 107 src - (width - 16) / (8 / BPL), 108 0xff00ff, colsize, -next_line - BPL * 2); 109 } 110 } else { 111 /* odd->even or even->odd */ 112 if (upwards) { 113 u32 *src32, *dst32; 114 u32 pval[4], v, v1, mask; 115 int i, j, w, f; 116 117 src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); 118 dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); 119 120 mask = 0xff00ff00; 121 f = 0; 122 w = width; 123 if (sx & 15) { 124 f = 1; 125 w += 8; 126 } 127 if ((sx + width) & 15) 128 f |= 2; 129 w >>= 4; 130 for (i = height; i; i--) { 131 src32 = (u32 *)src; 132 dst32 = (u32 *)dst; 133 134 if (f & 1) { 135 pval[0] = (*src32++ << 8) & mask; 136 pval[1] = (*src32++ << 8) & mask; 137 pval[2] = (*src32++ << 8) & mask; 138 pval[3] = (*src32++ << 8) & mask; 139 } else { 140 pval[0] = dst32[0] & mask; 141 pval[1] = dst32[1] & mask; 142 pval[2] = dst32[2] & mask; 143 pval[3] = dst32[3] & mask; 144 } 145 146 for (j = w; j > 0; j--) { 147 v = *src32++; 148 v1 = v & mask; 149 *dst32++ = pval[0] | (v1 >> 8); 150 pval[0] = (v ^ v1) << 8; 151 v = *src32++; 152 v1 = v & mask; 153 *dst32++ = pval[1] | (v1 >> 8); 154 pval[1] = (v ^ v1) << 8; 155 v = *src32++; 156 v1 = v & mask; 157 *dst32++ = pval[2] | (v1 >> 8); 158 pval[2] = (v ^ v1) << 8; 159 v = *src32++; 160 v1 = v & mask; 161 *dst32++ = pval[3] | (v1 >> 8); 162 pval[3] = (v ^ v1) << 8; 163 } 164 165 if (f & 2) { 166 dst32[0] = (dst32[0] & mask) | pval[0]; 167 dst32[1] = (dst32[1] & mask) | pval[1]; 168 dst32[2] = (dst32[2] & mask) | pval[2]; 169 dst32[3] = (dst32[3] & mask) | pval[3]; 170 } 171 172 src += next_line; 173 dst += next_line; 174 } 175 } else { 176 u32 *src32, *dst32; 177 u32 pval[4], v, v1, mask; 178 int i, j, w, f; 179 180 src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); 181 dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); 182 183 mask = 0xff00ff; 184 f = 0; 185 w = width; 186 if ((dx + width) & 15) 187 f = 1; 188 if (sx & 15) { 189 f |= 2; 190 w += 8; 191 } 192 w >>= 4; 193 for (i = height; i; i--) { 194 src32 = (u32 *)src; 195 dst32 = (u32 *)dst; 196 197 if (f & 1) { 198 pval[0] = dst32[-1] & mask; 199 pval[1] = dst32[-2] & mask; 200 pval[2] = dst32[-3] & mask; 201 pval[3] = dst32[-4] & mask; 202 } else { 203 pval[0] = (*--src32 >> 8) & mask; 204 pval[1] = (*--src32 >> 8) & mask; 205 pval[2] = (*--src32 >> 8) & mask; 206 pval[3] = (*--src32 >> 8) & mask; 207 } 208 209 for (j = w; j > 0; j--) { 210 v = *--src32; 211 v1 = v & mask; 212 *--dst32 = pval[0] | (v1 << 8); 213 pval[0] = (v ^ v1) >> 8; 214 v = *--src32; 215 v1 = v & mask; 216 *--dst32 = pval[1] | (v1 << 8); 217 pval[1] = (v ^ v1) >> 8; 218 v = *--src32; 219 v1 = v & mask; 220 *--dst32 = pval[2] | (v1 << 8); 221 pval[2] = (v ^ v1) >> 8; 222 v = *--src32; 223 v1 = v & mask; 224 *--dst32 = pval[3] | (v1 << 8); 225 pval[3] = (v ^ v1) >> 8; 226 } 227 228 if (!(f & 2)) { 229 dst32[-1] = (dst32[-1] & mask) | pval[0]; 230 dst32[-2] = (dst32[-2] & mask) | pval[1]; 231 dst32[-3] = (dst32[-3] & mask) | pval[2]; 232 dst32[-4] = (dst32[-4] & mask) | pval[3]; 233 } 234 235 src -= next_line; 236 dst -= next_line; 237 } 238 } 239 } 240 } 241 242 void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color, 243 int sy, int sx, int height, int width) 244 { 245 u32 *dest; 246 int rows, i; 247 u32 cval[4]; 248 249 dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL)); 250 if (sx & 15) { 251 u8 *dest8 = (u8 *)dest + 1; 252 253 expand8_col2mask(color, cval); 254 255 for (i = height; i; i--) { 256 fill8_col(dest8, cval); 257 dest8 += next_line; 258 } 259 dest += BPL / 2; 260 width -= 8; 261 } 262 263 expand16_col2mask(color, cval); 264 rows = width >> 4; 265 if (rows) { 266 u32 *d = dest; 267 u32 off = next_line - rows * BPL * 2; 268 for (i = height; i; i--) { 269 d = fill16_col(d, rows, cval); 270 d = (u32 *)((long)d + off); 271 } 272 dest += rows * BPL / 2; 273 width &= 15; 274 } 275 276 if (width) { 277 u8 *dest8 = (u8 *)dest; 278 279 expand8_col2mask(color, cval); 280 281 for (i = height; i; i--) { 282 fill8_col(dest8, cval); 283 dest8 += next_line; 284 } 285 } 286 } 287 288 void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line, 289 int dy, int dx, u32 width, 290 const u8 *data, u32 bgcolor, u32 fgcolor) 291 { 292 u32 *dest; 293 const u16 *data16; 294 int rows; 295 u32 fgm[4], bgm[4], m; 296 297 dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL)); 298 if (dx & 15) { 299 fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++); 300 dest += BPL / 2; 301 width -= 8; 302 } 303 304 if (width >= 16) { 305 data16 = (const u16 *)data; 306 expand16_2col2mask(fgcolor, bgcolor, fgm, bgm); 307 308 for (rows = width / 16; rows; rows--) { 309 u16 d = *data16++; 310 m = d | ((u32)d << 16); 311 *dest++ = (m & fgm[0]) ^ bgm[0]; 312 *dest++ = (m & fgm[1]) ^ bgm[1]; 313 *dest++ = (m & fgm[2]) ^ bgm[2]; 314 *dest++ = (m & fgm[3]) ^ bgm[3]; 315 } 316 317 data = (const u8 *)data16; 318 width &= 15; 319 } 320 321 if (width) 322 fill8_2col((u8 *)dest, fgcolor, bgcolor, *data); 323 } 324 325 #ifdef MODULE 326 MODULE_LICENSE("GPL"); 327 328 int init_module(void) 329 { 330 return 0; 331 } 332 333 void cleanup_module(void) 334 { 335 } 336 #endif /* MODULE */ 337 338 339 /* 340 * Visible symbols for modules 341 */ 342 343 EXPORT_SYMBOL(atafb_iplan2p8_copyarea); 344 EXPORT_SYMBOL(atafb_iplan2p8_fillrect); 345 EXPORT_SYMBOL(atafb_iplan2p8_linefill); 346