2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 static 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
)
28 u32 ge_cmd
= 0, tmp
, i
;
31 printk(KERN_WARNING
"hw_bitblt_1: Invalid operation: %d\n", op
);
35 if (op
!= VIA_BITBLT_FILL
&& !src_mem
&& src_addr
== dst_addr
) {
48 if (op
== VIA_BITBLT_FILL
) {
50 case 0x00: /* blackness */
51 case 0x5A: /* pattern inversion */
52 case 0xF0: /* pattern copy */
53 case 0xFF: /* whiteness */
56 printk(KERN_WARNING
"hw_bitblt_1: Invalid fill rop: "
73 printk(KERN_WARNING
"hw_bitblt_1: Unsupported bpp %d\n",
77 writel(tmp
, engine
+ 0x04);
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
);
86 tmp
= src_x
| (src_y
<< 16);
87 writel(tmp
, engine
+ 0x08);
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
);
95 tmp
= dst_x
| (dst_y
<< 16);
96 writel(tmp
, engine
+ 0x0C);
98 if ((width
- 1) & 0xFFFFF000 || (height
- 1) & 0xFFFFF000) {
99 printk(KERN_WARNING
"hw_bitblt_1: Unsupported width/height "
100 "%d %d\n", width
, height
);
103 tmp
= (width
- 1) | ((height
- 1) << 16);
104 writel(tmp
, engine
+ 0x10);
106 if (op
!= VIA_BITBLT_COLOR
)
107 writel(fg_color
, engine
+ 0x18);
109 if (op
== VIA_BITBLT_MONO
)
110 writel(bg_color
, engine
+ 0x1C);
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
);
120 writel(tmp
, engine
+ 0x30);
123 if (dst_addr
& 0xE0000007) {
124 printk(KERN_WARNING
"hw_bitblt_1: Unsupported destination "
125 "address %X\n", dst_addr
);
129 writel(tmp
, engine
+ 0x34);
131 if (op
== VIA_BITBLT_FILL
)
135 if (tmp
& 0xFFFFC007 || dst_pitch
& 0xFFFFC007) {
136 printk(KERN_WARNING
"hw_bitblt_1: Unsupported pitch %X %X\n",
140 tmp
= (tmp
>> 3) | (dst_pitch
<< (16 - 3));
141 writel(tmp
, engine
+ 0x38);
143 if (op
== VIA_BITBLT_FILL
)
144 ge_cmd
|= fill_rop
<< 24 | 0x00002000 | 0x00000001;
146 ge_cmd
|= 0xCC000000; /* ROP=SRCCOPY */
148 ge_cmd
|= 0x00000040;
149 if (op
== VIA_BITBLT_MONO
)
150 ge_cmd
|= 0x00000002 | 0x00000100 | 0x00020000;
152 ge_cmd
|= 0x00000001;
154 writel(ge_cmd
, engine
);
156 if (op
== VIA_BITBLT_FILL
|| !src_mem
)
159 tmp
= (width
* height
* (op
== VIA_BITBLT_MONO
? 1 : (dst_bpp
>> 3)) +
162 for (i
= 0; i
< tmp
; i
++)
163 writel(src_mem
[i
], engine
+ VIA_MMIO_BLTBASE
);
168 static 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
)
173 u32 ge_cmd
= 0, tmp
, i
;
176 printk(KERN_WARNING
"hw_bitblt_2: Invalid operation: %d\n", op
);
180 if (op
!= VIA_BITBLT_FILL
&& !src_mem
&& src_addr
== dst_addr
) {
182 ge_cmd
|= 0x00008000;
187 ge_cmd
|= 0x00004000;
193 if (op
== VIA_BITBLT_FILL
) {
195 case 0x00: /* blackness */
196 case 0x5A: /* pattern inversion */
197 case 0xF0: /* pattern copy */
198 case 0xFF: /* whiteness */
201 printk(KERN_WARNING
"hw_bitblt_2: Invalid fill rop: "
218 printk(KERN_WARNING
"hw_bitblt_2: Unsupported bpp %d\n",
222 writel(tmp
, engine
+ 0x04);
224 if (op
== VIA_BITBLT_FILL
)
228 if (tmp
& 0xFFFFC007 || dst_pitch
& 0xFFFFC007) {
229 printk(KERN_WARNING
"hw_bitblt_2: Unsupported pitch %X %X\n",
233 tmp
= (tmp
>> 3) | (dst_pitch
<< (16 - 3));
234 writel(tmp
, engine
+ 0x08);
236 if ((width
- 1) & 0xFFFFF000 || (height
- 1) & 0xFFFFF000) {
237 printk(KERN_WARNING
"hw_bitblt_2: Unsupported width/height "
238 "%d %d\n", width
, height
);
241 tmp
= (width
- 1) | ((height
- 1) << 16);
242 writel(tmp
, engine
+ 0x0C);
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
);
249 tmp
= dst_x
| (dst_y
<< 16);
250 writel(tmp
, engine
+ 0x10);
252 if (dst_addr
& 0xE0000007) {
253 printk(KERN_WARNING
"hw_bitblt_2: Unsupported destination "
254 "address %X\n", dst_addr
);
258 writel(tmp
, engine
+ 0x14);
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
);
267 tmp
= src_x
| (src_y
<< 16);
268 writel(tmp
, engine
+ 0x18);
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
);
277 writel(tmp
, engine
+ 0x1C);
280 if (op
!= VIA_BITBLT_COLOR
)
281 writel(fg_color
, engine
+ 0x4C);
283 if (op
== VIA_BITBLT_MONO
)
284 writel(bg_color
, engine
+ 0x50);
286 if (op
== VIA_BITBLT_FILL
)
287 ge_cmd
|= fill_rop
<< 24 | 0x00002000 | 0x00000001;
289 ge_cmd
|= 0xCC000000; /* ROP=SRCCOPY */
291 ge_cmd
|= 0x00000040;
292 if (op
== VIA_BITBLT_MONO
)
293 ge_cmd
|= 0x00000002 | 0x00000100 | 0x00020000;
295 ge_cmd
|= 0x00000001;
297 writel(ge_cmd
, engine
);
299 if (op
== VIA_BITBLT_FILL
|| !src_mem
)
302 tmp
= (width
* height
* (op
== VIA_BITBLT_MONO
? 1 : (dst_bpp
>> 3)) +
305 for (i
= 0; i
< tmp
; i
++)
306 writel(src_mem
[i
], engine
+ VIA_MMIO_BLTBASE
);
311 int viafb_init_engine(struct fb_info
*info
)
313 struct viafb_par
*viapar
= info
->par
;
314 void __iomem
*engine
;
315 u32 vq_start_addr
, vq_end_addr
, vq_start_low
, vq_end_low
, vq_high
,
316 vq_len
, chip_name
= viapar
->shared
->chip_info
.gfx_chip_name
;
318 engine
= ioremap_nocache(info
->fix
.mmio_start
, info
->fix
.mmio_len
);
319 viapar
->shared
->engine_mmio
= engine
;
321 printk(KERN_WARNING
"viafb_init_accel: ioremap failed, "
322 "hardware acceleration disabled\n");
327 case UNICHROME_CLE266
:
330 case UNICHROME_PM800
:
331 case UNICHROME_CN700
:
332 case UNICHROME_CX700
:
333 case UNICHROME_CN750
:
334 case UNICHROME_K8M890
:
335 case UNICHROME_P4M890
:
336 case UNICHROME_P4M900
:
337 viapar
->shared
->hw_bitblt
= hw_bitblt_1
;
339 case UNICHROME_VX800
:
340 case UNICHROME_VX855
:
341 viapar
->shared
->hw_bitblt
= hw_bitblt_2
;
344 viapar
->shared
->hw_bitblt
= NULL
;
347 viapar
->fbmem_free
-= CURSOR_SIZE
;
348 viapar
->shared
->cursor_vram_addr
= viapar
->fbmem_free
;
349 viapar
->fbmem_used
+= CURSOR_SIZE
;
351 viapar
->fbmem_free
-= VQ_SIZE
;
352 viapar
->shared
->vq_vram_addr
= viapar
->fbmem_free
;
353 viapar
->fbmem_used
+= VQ_SIZE
;
355 /* Init AGP and VQ regs */
357 case UNICHROME_K8M890
:
358 case UNICHROME_P4M900
:
359 writel(0x00100000, engine
+ VIA_REG_CR_TRANSET
);
360 writel(0x680A0000, engine
+ VIA_REG_CR_TRANSPACE
);
361 writel(0x02000000, engine
+ VIA_REG_CR_TRANSPACE
);
365 writel(0x00100000, engine
+ VIA_REG_TRANSET
);
366 writel(0x00000000, engine
+ VIA_REG_TRANSPACE
);
367 writel(0x00333004, engine
+ VIA_REG_TRANSPACE
);
368 writel(0x60000000, engine
+ VIA_REG_TRANSPACE
);
369 writel(0x61000000, engine
+ VIA_REG_TRANSPACE
);
370 writel(0x62000000, engine
+ VIA_REG_TRANSPACE
);
371 writel(0x63000000, engine
+ VIA_REG_TRANSPACE
);
372 writel(0x64000000, engine
+ VIA_REG_TRANSPACE
);
373 writel(0x7D000000, engine
+ VIA_REG_TRANSPACE
);
375 writel(0xFE020000, engine
+ VIA_REG_TRANSET
);
376 writel(0x00000000, engine
+ VIA_REG_TRANSPACE
);
381 vq_start_addr
= viapar
->shared
->vq_vram_addr
;
382 vq_end_addr
= viapar
->shared
->vq_vram_addr
+ VQ_SIZE
- 1;
384 vq_start_low
= 0x50000000 | (vq_start_addr
& 0xFFFFFF);
385 vq_end_low
= 0x51000000 | (vq_end_addr
& 0xFFFFFF);
386 vq_high
= 0x52000000 | ((vq_start_addr
& 0xFF000000) >> 24) |
387 ((vq_end_addr
& 0xFF000000) >> 16);
388 vq_len
= 0x53000000 | (VQ_SIZE
>> 3);
391 case UNICHROME_K8M890
:
392 case UNICHROME_P4M900
:
393 vq_start_low
|= 0x20000000;
394 vq_end_low
|= 0x20000000;
395 vq_high
|= 0x20000000;
396 vq_len
|= 0x20000000;
398 writel(0x00100000, engine
+ VIA_REG_CR_TRANSET
);
399 writel(vq_high
, engine
+ VIA_REG_CR_TRANSPACE
);
400 writel(vq_start_low
, engine
+ VIA_REG_CR_TRANSPACE
);
401 writel(vq_end_low
, engine
+ VIA_REG_CR_TRANSPACE
);
402 writel(vq_len
, engine
+ VIA_REG_CR_TRANSPACE
);
403 writel(0x74301001, engine
+ VIA_REG_CR_TRANSPACE
);
404 writel(0x00000000, engine
+ VIA_REG_CR_TRANSPACE
);
407 writel(0x00FE0000, engine
+ VIA_REG_TRANSET
);
408 writel(0x080003FE, engine
+ VIA_REG_TRANSPACE
);
409 writel(0x0A00027C, engine
+ VIA_REG_TRANSPACE
);
410 writel(0x0B000260, engine
+ VIA_REG_TRANSPACE
);
411 writel(0x0C000274, engine
+ VIA_REG_TRANSPACE
);
412 writel(0x0D000264, engine
+ VIA_REG_TRANSPACE
);
413 writel(0x0E000000, engine
+ VIA_REG_TRANSPACE
);
414 writel(0x0F000020, engine
+ VIA_REG_TRANSPACE
);
415 writel(0x1000027E, engine
+ VIA_REG_TRANSPACE
);
416 writel(0x110002FE, engine
+ VIA_REG_TRANSPACE
);
417 writel(0x200F0060, engine
+ VIA_REG_TRANSPACE
);
419 writel(0x00000006, engine
+ VIA_REG_TRANSPACE
);
420 writel(0x40008C0F, engine
+ VIA_REG_TRANSPACE
);
421 writel(0x44000000, engine
+ VIA_REG_TRANSPACE
);
422 writel(0x45080C04, engine
+ VIA_REG_TRANSPACE
);
423 writel(0x46800408, engine
+ VIA_REG_TRANSPACE
);
425 writel(vq_high
, engine
+ VIA_REG_TRANSPACE
);
426 writel(vq_start_low
, engine
+ VIA_REG_TRANSPACE
);
427 writel(vq_end_low
, engine
+ VIA_REG_TRANSPACE
);
428 writel(vq_len
, engine
+ VIA_REG_TRANSPACE
);
432 /* Set Cursor Image Base Address */
433 writel(viapar
->shared
->cursor_vram_addr
, engine
+ VIA_REG_CURSOR_MODE
);
434 writel(0x0, engine
+ VIA_REG_CURSOR_POS
);
435 writel(0x0, engine
+ VIA_REG_CURSOR_ORG
);
436 writel(0x0, engine
+ VIA_REG_CURSOR_BG
);
437 writel(0x0, engine
+ VIA_REG_CURSOR_FG
);
441 void viafb_show_hw_cursor(struct fb_info
*info
, int Status
)
443 struct viafb_par
*viapar
= info
->par
;
444 u32 temp
, iga_path
= viapar
->iga_path
;
446 temp
= readl(viapar
->shared
->engine_mmio
+ VIA_REG_CURSOR_MODE
);
463 writel(temp
, viapar
->shared
->engine_mmio
+ VIA_REG_CURSOR_MODE
);
466 void viafb_wait_engine_idle(struct fb_info
*info
)
468 struct viafb_par
*viapar
= info
->par
;
471 while (!(readl(viapar
->shared
->engine_mmio
+ VIA_REG_STATUS
) &
472 VIA_VR_QUEUE_BUSY
) && (loop
< MAXLOOP
)) {
477 while ((readl(viapar
->shared
->engine_mmio
+ VIA_REG_STATUS
) &
478 (VIA_CMD_RGTR_BUSY
| VIA_2D_ENG_BUSY
| VIA_3D_ENG_BUSY
)) &&
485 printk(KERN_ERR
"viafb_wait_engine_idle: not syncing\n");