aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/via/accel.c
diff options
context:
space:
mode:
authorFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2009-09-22 19:47:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 10:39:52 -0400
commitc3e25673843153ea75fda79a47cf12f10a25ca37 (patch)
treefdc15161f32ca26450614c08b82c293b788ffb40 /drivers/video/via/accel.c
parentc4df5489e40e55f2962b9e8100ebc0d4d1374415 (diff)
viafb: 2D engine rewrite
This patch is a completly rewritten 2D engine. The engine is no longer in a default state but reinitialized every time to allow usage for both framebuffers regardless of their settings. The whole engine handling is concentrated in a big function which takes 16 parameters. Although the number of parameters is worryingly it is good to have a single funtion to deal with this stuff as it allows to easily support different engines and avoids some code duplication. On the way support for the new 2D engine in VX800 was added. As the with less code duplication but it is probably better to duplicate the code as this way is easier to walk if VIA ever decides to release a new engine which changes anything the driver touches. The engine support for VX800 gives a notable boost in speed. There are no known regressions but as this patch changes paths I do neither have the hardware nor documentation to check and has the possibility to put the system in a critical state heavy testing is appreciated. Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> Cc: Scott Fang <ScottFang@viatech.com.cn> Cc: Joseph Chan <JosephChan@via.com.tw> Cc: Harald Welte <laforge@gnumonks.org> Cc: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/via/accel.c')
-rw-r--r--drivers/video/via/accel.c363
1 files changed, 312 insertions, 51 deletions
diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c
index b3e7e8246326..8ac02515a18d 100644
--- a/drivers/video/via/accel.c
+++ b/drivers/video/via/accel.c
@@ -20,8 +20,316 @@
20 */ 20 */
21#include "global.h" 21#include "global.h"
22 22
23void viafb_init_accel(void) 23static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height,
24 u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
25 u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
26 u32 fg_color, u32 bg_color, u8 fill_rop)
24{ 27{
28 u32 ge_cmd = 0, tmp, i;
29
30 if (!op || op > 3) {
31 printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op);
32 return -EINVAL;
33 }
34
35 if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
36 if (src_x < dst_x) {
37 ge_cmd |= 0x00008000;
38 src_x += width - 1;
39 dst_x += width - 1;
40 }
41 if (src_y < dst_y) {
42 ge_cmd |= 0x00004000;
43 src_y += height - 1;
44 dst_y += height - 1;
45 }
46 }
47
48 if (op == VIA_BITBLT_FILL) {
49 switch (fill_rop) {
50 case 0x00: /* blackness */
51 case 0x5A: /* pattern inversion */
52 case 0xF0: /* pattern copy */
53 case 0xFF: /* whiteness */
54 break;
55 default:
56 printk(KERN_WARNING "hw_bitblt_1: Invalid fill rop: "
57 "%u\n", fill_rop);
58 return -EINVAL;
59 }
60 }
61
62 switch (dst_bpp) {
63 case 8:
64 tmp = 0x00000000;
65 break;
66 case 16:
67 tmp = 0x00000100;
68 break;
69 case 32:
70 tmp = 0x00000300;
71 break;
72 default:
73 printk(KERN_WARNING "hw_bitblt_1: Unsupported bpp %d\n",
74 dst_bpp);
75 return -EINVAL;
76 }
77 writel(tmp, engine + 0x04);
78
79 if (op != VIA_BITBLT_FILL) {
80 if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
81 || src_y & 0xFFFFF000) {
82 printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
83 "x/y %d %d\n", src_x, src_y);
84 return -EINVAL;
85 }
86 tmp = src_x | (src_y << 16);
87 writel(tmp, engine + 0x08);
88 }
89
90 if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) {
91 printk(KERN_WARNING "hw_bitblt_1: Unsupported destination x/y "
92 "%d %d\n", dst_x, dst_y);
93 return -EINVAL;
94 }
95 tmp = dst_x | (dst_y << 16);
96 writel(tmp, engine + 0x0C);
97
98 if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) {
99 printk(KERN_WARNING "hw_bitblt_1: Unsupported width/height "
100 "%d %d\n", width, height);
101 return -EINVAL;
102 }
103 tmp = (width - 1) | ((height - 1) << 16);
104 writel(tmp, engine + 0x10);
105
106 if (op != VIA_BITBLT_COLOR)
107 writel(fg_color, engine + 0x18);
108
109 if (op == VIA_BITBLT_MONO)
110 writel(bg_color, engine + 0x1C);
111
112 if (op != VIA_BITBLT_FILL) {
113 tmp = src_mem ? 0 : src_addr;
114 if (dst_addr & 0xE0000007) {
115 printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
116 "address %X\n", tmp);
117 return -EINVAL;
118 }
119 tmp >>= 3;
120 writel(tmp, engine + 0x30);
121 }
122
123 if (dst_addr & 0xE0000007) {
124 printk(KERN_WARNING "hw_bitblt_1: Unsupported destination "
125 "address %X\n", dst_addr);
126 return -EINVAL;
127 }
128 tmp = dst_addr >> 3;
129 writel(tmp, engine + 0x34);
130
131 if (op == VIA_BITBLT_FILL)
132 tmp = 0;
133 else
134 tmp = src_pitch;
135 if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) {
136 printk(KERN_WARNING "hw_bitblt_1: Unsupported pitch %X %X\n",
137 tmp, dst_pitch);
138 return -EINVAL;
139 }
140 tmp = (tmp >> 3) | (dst_pitch << (16 - 3));
141 writel(tmp, engine + 0x38);
142
143 if (op == VIA_BITBLT_FILL)
144 ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
145 else {
146 ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */
147 if (src_mem)
148 ge_cmd |= 0x00000040;
149 if (op == VIA_BITBLT_MONO)
150 ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
151 else
152 ge_cmd |= 0x00000001;
153 }
154 writel(ge_cmd, engine);
155
156 if (op == VIA_BITBLT_FILL || !src_mem)
157 return 0;
158
159 tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) +
160 3) >> 2;
161
162 for (i = 0; i < tmp; i++)
163 writel(src_mem[i], engine + VIA_MMIO_BLTBASE);
164
165 return 0;
166}
167
168static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height,
169 u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
170 u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
171 u32 fg_color, u32 bg_color, u8 fill_rop)
172{
173 u32 ge_cmd = 0, tmp, i;
174
175 if (!op || op > 3) {
176 printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op);
177 return -EINVAL;
178 }
179
180 if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
181 if (src_x < dst_x) {
182 ge_cmd |= 0x00008000;
183 src_x += width - 1;
184 dst_x += width - 1;
185 }
186 if (src_y < dst_y) {
187 ge_cmd |= 0x00004000;
188 src_y += height - 1;
189 dst_y += height - 1;
190 }
191 }
192
193 if (op == VIA_BITBLT_FILL) {
194 switch (fill_rop) {
195 case 0x00: /* blackness */
196 case 0x5A: /* pattern inversion */
197 case 0xF0: /* pattern copy */
198 case 0xFF: /* whiteness */
199 break;
200 default:
201 printk(KERN_WARNING "hw_bitblt_2: Invalid fill rop: "
202 "%u\n", fill_rop);
203 return -EINVAL;
204 }
205 }
206
207 switch (dst_bpp) {
208 case 8:
209 tmp = 0x00000000;
210 break;
211 case 16:
212 tmp = 0x00000100;
213 break;
214 case 32:
215 tmp = 0x00000300;
216 break;
217 default:
218 printk(KERN_WARNING "hw_bitblt_2: Unsupported bpp %d\n",
219 dst_bpp);
220 return -EINVAL;
221 }
222 writel(tmp, engine + 0x04);
223
224 if (op == VIA_BITBLT_FILL)
225 tmp = 0;
226 else
227 tmp = src_pitch;
228 if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) {
229 printk(KERN_WARNING "hw_bitblt_2: Unsupported pitch %X %X\n",
230 tmp, dst_pitch);
231 return -EINVAL;
232 }
233 tmp = (tmp >> 3) | (dst_pitch << (16 - 3));
234 writel(tmp, engine + 0x08);
235
236 if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) {
237 printk(KERN_WARNING "hw_bitblt_2: Unsupported width/height "
238 "%d %d\n", width, height);
239 return -EINVAL;
240 }
241 tmp = (width - 1) | ((height - 1) << 16);
242 writel(tmp, engine + 0x0C);
243
244 if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) {
245 printk(KERN_WARNING "hw_bitblt_2: Unsupported destination x/y "
246 "%d %d\n", dst_x, dst_y);
247 return -EINVAL;
248 }
249 tmp = dst_x | (dst_y << 16);
250 writel(tmp, engine + 0x10);
251
252 if (dst_addr & 0xE0000007) {
253 printk(KERN_WARNING "hw_bitblt_2: Unsupported destination "
254 "address %X\n", dst_addr);
255 return -EINVAL;
256 }
257 tmp = dst_addr >> 3;
258 writel(tmp, engine + 0x14);
259
260 if (op != VIA_BITBLT_FILL) {
261 if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
262 || src_y & 0xFFFFF000) {
263 printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
264 "x/y %d %d\n", src_x, src_y);
265 return -EINVAL;
266 }
267 tmp = src_x | (src_y << 16);
268 writel(tmp, engine + 0x18);
269
270 tmp = src_mem ? 0 : src_addr;
271 if (dst_addr & 0xE0000007) {
272 printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
273 "address %X\n", tmp);
274 return -EINVAL;
275 }
276 tmp >>= 3;
277 writel(tmp, engine + 0x1C);
278 }
279
280 if (op != VIA_BITBLT_COLOR)
281 writel(fg_color, engine + 0x4C);
282
283 if (op == VIA_BITBLT_MONO)
284 writel(bg_color, engine + 0x50);
285
286 if (op == VIA_BITBLT_FILL)
287 ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
288 else {
289 ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */
290 if (src_mem)
291 ge_cmd |= 0x00000040;
292 if (op == VIA_BITBLT_MONO)
293 ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
294 else
295 ge_cmd |= 0x00000001;
296 }
297 writel(ge_cmd, engine);
298
299 if (op == VIA_BITBLT_FILL || !src_mem)
300 return 0;
301
302 tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) +
303 3) >> 2;
304
305 for (i = 0; i < tmp; i++)
306 writel(src_mem[i], engine + VIA_MMIO_BLTBASE);
307
308 return 0;
309}
310
311void viafb_init_accel(struct viafb_shared *shared)
312{
313 switch (shared->chip_info.gfx_chip_name) {
314 case UNICHROME_CLE266:
315 case UNICHROME_K400:
316 case UNICHROME_K800:
317 case UNICHROME_PM800:
318 case UNICHROME_CN700:
319 case UNICHROME_CX700:
320 case UNICHROME_CN750:
321 case UNICHROME_K8M890:
322 case UNICHROME_P4M890:
323 case UNICHROME_P4M900:
324 shared->hw_bitblt = hw_bitblt_1;
325 break;
326 case UNICHROME_VX800:
327 shared->hw_bitblt = hw_bitblt_2;
328 break;
329 default:
330 shared->hw_bitblt = NULL;
331 }
332
25 viaparinfo->fbmem_free -= CURSOR_SIZE; 333 viaparinfo->fbmem_free -= CURSOR_SIZE;
26 viaparinfo->cursor_start = viaparinfo->fbmem_free; 334 viaparinfo->cursor_start = viaparinfo->fbmem_free;
27 viaparinfo->fbmem_used += CURSOR_SIZE; 335 viaparinfo->fbmem_used += CURSOR_SIZE;
@@ -30,30 +338,14 @@ void viafb_init_accel(void)
30 viaparinfo->fbmem_free -= (CURSOR_SIZE + VQ_SIZE); 338 viaparinfo->fbmem_free -= (CURSOR_SIZE + VQ_SIZE);
31 viaparinfo->VQ_start = viaparinfo->fbmem_free; 339 viaparinfo->VQ_start = viaparinfo->fbmem_free;
32 viaparinfo->VQ_end = viaparinfo->VQ_start + VQ_SIZE - 1; 340 viaparinfo->VQ_end = viaparinfo->VQ_start + VQ_SIZE - 1;
33 viaparinfo->fbmem_used += (CURSOR_SIZE + VQ_SIZE); } 341 viaparinfo->fbmem_used += (CURSOR_SIZE + VQ_SIZE);
342}
34 343
35void viafb_init_2d_engine(void) 344void viafb_init_2d_engine(void)
36{ 345{
37 u32 dwVQStartAddr, dwVQEndAddr, linesize; 346 u32 dwVQStartAddr, dwVQEndAddr;
38 u32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH; 347 u32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH;
39 348
40 /* init 2D engine regs to reset 2D engine */
41 writel(0x0, viaparinfo->io_virt + VIA_REG_GEMODE);
42 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
43 writel(0x0, viaparinfo->io_virt + VIA_REG_DSTPOS);
44 writel(0x0, viaparinfo->io_virt + VIA_REG_DIMENSION);
45 writel(0x0, viaparinfo->io_virt + VIA_REG_PATADDR);
46 writel(0x0, viaparinfo->io_virt + VIA_REG_FGCOLOR);
47 writel(0x0, viaparinfo->io_virt + VIA_REG_BGCOLOR);
48 writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPTL);
49 writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPBR);
50 writel(0x0, viaparinfo->io_virt + VIA_REG_OFFSET);
51 writel(0x0, viaparinfo->io_virt + VIA_REG_KEYCONTROL);
52 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
53 writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE);
54 writel(0x0, viaparinfo->io_virt + VIA_REG_PITCH);
55 writel(0x0, viaparinfo->io_virt + VIA_REG_MONOPAT1);
56
57 /* Init AGP and VQ regs */ 349 /* Init AGP and VQ regs */
58 switch (viaparinfo->chip_info->gfx_chip_name) { 350 switch (viaparinfo->chip_info->gfx_chip_name) {
59 case UNICHROME_K8M890: 351 case UNICHROME_K8M890:
@@ -190,37 +482,6 @@ void viafb_init_2d_engine(void)
190 break; 482 break;
191 } 483 }
192 } 484 }
193
194 viafb_set_2d_color_depth(viafbinfo->var.bits_per_pixel);
195
196 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
197 writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE);
198
199 linesize = viafbinfo->var.xres * viafbinfo->var.bits_per_pixel >> 3;
200 writel(VIA_PITCH_ENABLE | (linesize >> 3) | ((linesize >> 3) << 16),
201 viaparinfo->io_virt + VIA_REG_PITCH);
202}
203
204void viafb_set_2d_color_depth(int bpp)
205{
206 u32 dwGEMode;
207
208 dwGEMode = readl(viaparinfo->io_virt + 0x04) & 0xFFFFFCFF;
209
210 switch (bpp) {
211 case 16:
212 dwGEMode |= VIA_GEM_16bpp;
213 break;
214 case 32:
215 dwGEMode |= VIA_GEM_32bpp;
216 break;
217 default:
218 dwGEMode |= VIA_GEM_8bpp;
219 break;
220 }
221
222 /* Set BPP and Pitch */
223 writel(dwGEMode, viaparinfo->io_virt + VIA_REG_GEMODE);
224} 485}
225 486
226void viafb_hw_cursor_init(void) 487void viafb_hw_cursor_init(void)