atafb_iplan2p4.c 7.1 KB

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