linux/drivers/video/fbdev/atafb_iplan2p8.c
<<
>>
Prefs
   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
  31void 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
 242void 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
 288void 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
 326MODULE_LICENSE("GPL");
 327
 328int init_module(void)
 329{
 330        return 0;
 331}
 332
 333void cleanup_module(void)
 334{
 335}
 336#endif /* MODULE */
 337
 338
 339    /*
 340     *  Visible symbols for modules
 341     */
 342
 343EXPORT_SYMBOL(atafb_iplan2p8_copyarea);
 344EXPORT_SYMBOL(atafb_iplan2p8_fillrect);
 345EXPORT_SYMBOL(atafb_iplan2p8_linefill);
 346