atafb_iplan2p8.c 8.2 KB

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