aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert@linux-m68k.org>2008-12-21 09:48:12 -0500
committerGeert Uytterhoeven <geert@linux-m68k.org>2009-01-12 14:56:31 -0500
commit96f47d6105203ab06c2004e26979dea153bce073 (patch)
tree39dce6e593746e55084a4b1c65cf66f66932a07c
parent2cd1de0a0ff1d3da08ff1f1437cf4a44deae6a00 (diff)
fbdev: c2p/atafb - Add support for Atari interleaved bitplanes
The c2p() for normal bitplanes is not suitable for interleaved bitplanes with 2 bytes of interleave, causing a garbled penguin logo. Add c2p_iplan2(). Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/atafb.c15
-rw-r--r--drivers/video/c2p.h5
-rw-r--r--drivers/video/c2p_core.h47
-rw-r--r--drivers/video/c2p_iplan2.c153
5 files changed, 208 insertions, 14 deletions
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index e39e33e797da..4fc29eae5152 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -72,7 +72,7 @@ obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o
72obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o 72obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o
73obj-$(CONFIG_FB_SGIVW) += sgivwfb.o 73obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
74obj-$(CONFIG_FB_ACORN) += acornfb.o 74obj-$(CONFIG_FB_ACORN) += acornfb.o
75obj-$(CONFIG_FB_ATARI) += atafb.o c2p.o atafb_mfb.o \ 75obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \
76 atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o 76 atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
77obj-$(CONFIG_FB_MAC) += macfb.o 77obj-$(CONFIG_FB_MAC) += macfb.o
78obj-$(CONFIG_FB_HECUBA) += hecubafb.o 78obj-$(CONFIG_FB_HECUBA) += hecubafb.o
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index f932c138fe1d..477ce55bbae9 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -122,7 +122,6 @@ static struct atafb_par {
122 void *screen_base; 122 void *screen_base;
123 int yres_virtual; 123 int yres_virtual;
124 u_long next_line; 124 u_long next_line;
125 u_long next_plane;
126#if defined ATAFB_TT || defined ATAFB_STE 125#if defined ATAFB_TT || defined ATAFB_STE
127 union { 126 union {
128 struct { 127 struct {
@@ -1392,14 +1391,7 @@ set_screen_base:
1392 par->screen_base = screen_base + var->yoffset * linelen; 1391 par->screen_base = screen_base + var->yoffset * linelen;
1393 par->hw.falcon.xoffset = 0; 1392 par->hw.falcon.xoffset = 0;
1394 1393
1395 // FIXME!!! sort of works, no crash
1396 //par->next_line = linelen;
1397 //par->next_plane = yres_virtual * linelen;
1398 par->next_line = linelen; 1394 par->next_line = linelen;
1399 par->next_plane = 2;
1400 // crashes
1401 //par->next_plane = linelen;
1402 //par->next_line = yres_virtual * linelen;
1403 1395
1404 return 0; 1396 return 0;
1405} 1397}
@@ -2662,10 +2654,9 @@ static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
2662 src += pitch; 2654 src += pitch;
2663 } 2655 }
2664 } else { 2656 } else {
2665 // only used for logo; broken 2657 c2p_iplan2(info->screen_base, image->data, dx, dy, width,
2666 c2p(info->screen_base, image->data, dx, dy, width, height, 2658 height, par->next_line, image->width,
2667 par->next_line, par->next_plane, image->width, 2659 info->var.bits_per_pixel);
2668 info->var.bits_per_pixel);
2669 } 2660 }
2670} 2661}
2671 2662
diff --git a/drivers/video/c2p.h b/drivers/video/c2p.h
index daafd872601c..53641298b924 100644
--- a/drivers/video/c2p.h
+++ b/drivers/video/c2p.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Fast C2P (Chunky-to-Planar) Conversion 2 * Fast C2P (Chunky-to-Planar) Conversion
3 * 3 *
4 * Copyright (C) 2003 Geert Uytterhoeven 4 * Copyright (C) 2003-2008 Geert Uytterhoeven
5 * 5 *
6 * This file is subject to the terms and conditions of the GNU General Public 6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive 7 * License. See the file COPYING in the main directory of this archive
@@ -14,3 +14,6 @@ extern void c2p(void *dst, const void *src, u32 dx, u32 dy, u32 width,
14 u32 height, u32 dst_nextline, u32 dst_nextplane, 14 u32 height, u32 dst_nextline, u32 dst_nextplane,
15 u32 src_nextline, u32 bpp); 15 u32 src_nextline, u32 bpp);
16 16
17extern void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
18 u32 height, u32 dst_nextline, u32 src_nextline,
19 u32 bpp);
diff --git a/drivers/video/c2p_core.h b/drivers/video/c2p_core.h
index 3573cf723e43..e1035a865fb9 100644
--- a/drivers/video/c2p_core.h
+++ b/drivers/video/c2p_core.h
@@ -96,6 +96,53 @@ static inline void transp8(u32 d[], unsigned int n, unsigned int m)
96 96
97 97
98 /* 98 /*
99 * Transpose operations on 4 32-bit words
100 */
101
102static inline void transp4(u32 d[], unsigned int n, unsigned int m)
103{
104 u32 mask = get_mask(n);
105
106 switch (m) {
107 case 1:
108 /* First n x 1 block */
109 _transp(d, 0, 1, n, mask);
110 /* Second n x 1 block */
111 _transp(d, 2, 3, n, mask);
112 return;
113
114 case 2:
115 /* Single n x 2 block */
116 _transp(d, 0, 2, n, mask);
117 _transp(d, 1, 3, n, mask);
118 return;
119 }
120
121 c2p_unsupported();
122}
123
124
125 /*
126 * Transpose operations on 4 32-bit words (reverse order)
127 */
128
129static inline void transp4x(u32 d[], unsigned int n, unsigned int m)
130{
131 u32 mask = get_mask(n);
132
133 switch (m) {
134 case 2:
135 /* Single n x 2 block */
136 _transp(d, 2, 0, n, mask);
137 _transp(d, 3, 1, n, mask);
138 return;
139 }
140
141 c2p_unsupported();
142}
143
144
145 /*
99 * Compose two values, using a bitmask as decision value 146 * Compose two values, using a bitmask as decision value
100 * This is equivalent to (a & mask) | (b & ~mask) 147 * This is equivalent to (a & mask) | (b & ~mask)
101 */ 148 */
diff --git a/drivers/video/c2p_iplan2.c b/drivers/video/c2p_iplan2.c
new file mode 100644
index 000000000000..19156dc6158c
--- /dev/null
+++ b/drivers/video/c2p_iplan2.c
@@ -0,0 +1,153 @@
1/*
2 * Fast C2P (Chunky-to-Planar) Conversion
3 *
4 * Copyright (C) 2003-2008 Geert Uytterhoeven
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/module.h>
12#include <linux/string.h>
13
14#include <asm/unaligned.h>
15
16#include "c2p.h"
17#include "c2p_core.h"
18
19
20 /*
21 * Perform a full C2P step on 16 8-bit pixels, stored in 4 32-bit words
22 * containing
23 * - 16 8-bit chunky pixels on input
24 * - permutated planar data (2 planes per 32-bit word) on output
25 */
26
27static void c2p_16x8(u32 d[4])
28{
29 transp4(d, 8, 2);
30 transp4(d, 1, 2);
31 transp4x(d, 16, 2);
32 transp4x(d, 2, 2);
33 transp4(d, 4, 1);
34}
35
36
37 /*
38 * Array containing the permutation indices of the planar data after c2p
39 */
40
41static const int perm_c2p_16x8[4] = { 1, 3, 0, 2 };
42
43
44 /*
45 * Store a full block of iplan2 data after c2p conversion
46 */
47
48static inline void store_iplan2(void *dst, u32 bpp, u32 d[4])
49{
50 int i;
51
52 for (i = 0; i < bpp/2; i++, dst += 4)
53 put_unaligned_be32(d[perm_c2p_16x8[i]], dst);
54}
55
56
57 /*
58 * Store a partial block of iplan2 data after c2p conversion
59 */
60
61static inline void store_iplan2_masked(void *dst, u32 bpp, u32 d[4], u32 mask)
62{
63 int i;
64
65 for (i = 0; i < bpp/2; i++, dst += 4)
66 put_unaligned_be32(comp(d[perm_c2p_16x8[i]],
67 get_unaligned_be32(dst), mask),
68 dst);
69}
70
71
72 /*
73 * c2p_iplan2 - Copy 8-bit chunky image data to an interleaved planar
74 * frame buffer with 2 bytes of interleave
75 * @dst: Starting address of the planar frame buffer
76 * @dx: Horizontal destination offset (in pixels)
77 * @dy: Vertical destination offset (in pixels)
78 * @width: Image width (in pixels)
79 * @height: Image height (in pixels)
80 * @dst_nextline: Frame buffer offset to the next line (in bytes)
81 * @src_nextline: Image offset to the next line (in bytes)
82 * @bpp: Bits per pixel of the planar frame buffer (2, 4, or 8)
83 */
84
85void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
86 u32 height, u32 dst_nextline, u32 src_nextline, u32 bpp)
87{
88 union {
89 u8 pixels[16];
90 u32 words[4];
91 } d;
92 u32 dst_idx, first, last, w;
93 const u8 *c;
94 void *p;
95
96 dst += dy*dst_nextline+(dx & ~15)*bpp;
97 dst_idx = dx % 16;
98 first = 0xffffU >> dst_idx;
99 first |= first << 16;
100 last = 0xffffU ^ (0xffffU >> ((dst_idx+width) % 16));
101 last |= last << 16;
102 while (height--) {
103 c = src;
104 p = dst;
105 w = width;
106 if (dst_idx+width <= 16) {
107 /* Single destination word */
108 first &= last;
109 memset(d.pixels, 0, sizeof(d));
110 memcpy(d.pixels+dst_idx, c, width);
111 c += width;
112 c2p_16x8(d.words);
113 store_iplan2_masked(p, bpp, d.words, first);
114 p += bpp*2;
115 } else {
116 /* Multiple destination words */
117 w = width;
118 /* Leading bits */
119 if (dst_idx) {
120 w = 16 - dst_idx;
121 memset(d.pixels, 0, dst_idx);
122 memcpy(d.pixels+dst_idx, c, w);
123 c += w;
124 c2p_16x8(d.words);
125 store_iplan2_masked(p, bpp, d.words, first);
126 p += bpp*2;
127 w = width-w;
128 }
129 /* Main chunk */
130 while (w >= 16) {
131 memcpy(d.pixels, c, 16);
132 c += 16;
133 c2p_16x8(d.words);
134 store_iplan2(p, bpp, d.words);
135 p += bpp*2;
136 w -= 16;
137 }
138 /* Trailing bits */
139 w %= 16;
140 if (w > 0) {
141 memcpy(d.pixels, c, w);
142 memset(d.pixels+w, 0, 16-w);
143 c2p_16x8(d.words);
144 store_iplan2_masked(p, bpp, d.words, last);
145 }
146 }
147 src += src_nextline;
148 dst += dst_nextline;
149 }
150}
151EXPORT_SYMBOL_GPL(c2p_iplan2);
152
153MODULE_LICENSE("GPL");