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