aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/via
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
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')
-rw-r--r--drivers/video/via/accel.c363
-rw-r--r--drivers/video/via/accel.h7
-rw-r--r--drivers/video/via/viafbdev.c226
-rw-r--r--drivers/video/via/viafbdev.h8
4 files changed, 385 insertions, 219 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)
diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h
index 29bf854e8ccf..4d93eba4f3eb 100644
--- a/drivers/video/via/accel.h
+++ b/drivers/video/via/accel.h
@@ -159,9 +159,12 @@
159 159
160#define MAXLOOP 0xFFFFFF 160#define MAXLOOP 0xFFFFFF
161 161
162void viafb_init_accel(void); 162#define VIA_BITBLT_COLOR 1
163#define VIA_BITBLT_MONO 2
164#define VIA_BITBLT_FILL 3
165
166void viafb_init_accel(struct viafb_shared *shared);
163void viafb_init_2d_engine(void); 167void viafb_init_2d_engine(void);
164void set_2d_color_depth(int);
165void viafb_hw_cursor_init(void); 168void viafb_hw_cursor_init(void);
166void viafb_show_hw_cursor(struct fb_info *info, int Status); int 169void viafb_show_hw_cursor(struct fb_info *info, int Status); int
167viafb_wait_engine_idle(void); void viafb_set_2d_color_depth(int bpp); 170viafb_wait_engine_idle(void); void viafb_set_2d_color_depth(int bpp);
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 4a8853a07602..66921de373fe 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -95,11 +95,8 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
95 struct fb_info *info) 95 struct fb_info *info)
96{ 96{
97 int vmode_index, htotal, vtotal; 97 int vmode_index, htotal, vtotal;
98 struct viafb_par *ppar; 98 struct viafb_par *ppar = info->par;
99 u32 long_refresh; 99 u32 long_refresh;
100 struct viafb_par *p_viafb_par;
101 ppar = info->par;
102
103 100
104 DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); 101 DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
105 /* Sanity check */ 102 /* Sanity check */
@@ -144,22 +141,17 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
144 /* Adjust var according to our driver's own table */ 141 /* Adjust var according to our driver's own table */
145 viafb_fill_var_timing_info(var, viafb_refresh, vmode_index); 142 viafb_fill_var_timing_info(var, viafb_refresh, vmode_index);
146 143
147 /* This is indeed a patch for VT3353 */
148 if (!info->par)
149 return -1;
150 p_viafb_par = (struct viafb_par *)info->par;
151 if (p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX800)
152 var->accel_flags = 0;
153
154 return 0; 144 return 0;
155} 145}
156 146
157static int viafb_set_par(struct fb_info *info) 147static int viafb_set_par(struct fb_info *info)
158{ 148{
149 struct viafb_par *viapar = info->par;
159 int vmode_index; 150 int vmode_index;
160 int vmode_index1 = 0; 151 int vmode_index1 = 0;
161 DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); 152 DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
162 153
154 viapar->depth = fb_get_color_depth(&info->var, &info->fix);
163 viafb_update_device_setting(info->var.xres, info->var.yres, 155 viafb_update_device_setting(info->var.xres, info->var.yres,
164 info->var.bits_per_pixel, viafb_refresh, 0); 156 info->var.bits_per_pixel, viafb_refresh, 0);
165 157
@@ -190,9 +182,6 @@ static int viafb_set_par(struct fb_info *info)
190 viafb_bpp = info->var.bits_per_pixel; 182 viafb_bpp = info->var.bits_per_pixel;
191 /* Update viafb_accel, it is necessary to our 2D accelerate */ 183 /* Update viafb_accel, it is necessary to our 2D accelerate */
192 viafb_accel = info->var.accel_flags; 184 viafb_accel = info->var.accel_flags;
193
194 if (viafb_accel)
195 viafb_set_2d_color_depth(info->var.bits_per_pixel);
196 } 185 }
197 186
198 return 0; 187 return 0;
@@ -777,10 +766,11 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
777static void viafb_fillrect(struct fb_info *info, 766static void viafb_fillrect(struct fb_info *info,
778 const struct fb_fillrect *rect) 767 const struct fb_fillrect *rect)
779{ 768{
780 u32 col = 0, rop = 0; 769 struct viafb_par *viapar = info->par;
781 int pitch; 770 u32 fg_color;
771 u8 rop;
782 772
783 if (!viafb_accel) { 773 if (!viapar->shared->hw_bitblt) {
784 cfb_fillrect(info, rect); 774 cfb_fillrect(info, rect);
785 return; 775 return;
786 } 776 }
@@ -788,67 +778,30 @@ static void viafb_fillrect(struct fb_info *info,
788 if (!rect->width || !rect->height) 778 if (!rect->width || !rect->height)
789 return; 779 return;
790 780
791 switch (rect->rop) { 781 if (info->fix.visual == FB_VISUAL_TRUECOLOR)
792 case ROP_XOR: 782 fg_color = ((u32 *)info->pseudo_palette)[rect->color];
783 else
784 fg_color = rect->color;
785
786 if (rect->rop == ROP_XOR)
793 rop = 0x5A; 787 rop = 0x5A;
794 break; 788 else
795 case ROP_COPY:
796 default:
797 rop = 0xF0; 789 rop = 0xF0;
798 break;
799 }
800
801 switch (info->var.bits_per_pixel) {
802 case 8:
803 col = rect->color;
804 break;
805 case 16:
806 col = ((u32 *) (info->pseudo_palette))[rect->color];
807 break;
808 case 32:
809 col = ((u32 *) (info->pseudo_palette))[rect->color];
810 break;
811 }
812
813 /* BitBlt Source Address */
814 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
815 /* Source Base Address */
816 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
817 /* Destination Base Address */
818 writel((info->fix.smem_start - viafbinfo->fix.smem_start) >> 3,
819 viaparinfo->io_virt + VIA_REG_DSTBASE);
820 /* Pitch */
821 pitch = (info->var.xres_virtual + 7) & ~7;
822 writel(VIA_PITCH_ENABLE |
823 (((pitch *
824 info->var.bits_per_pixel >> 3) >> 3) |
825 (((pitch * info->
826 var.bits_per_pixel >> 3) >> 3) << 16)),
827 viaparinfo->io_virt + VIA_REG_PITCH);
828 /* BitBlt Destination Address */
829 writel(((rect->dy << 16) | rect->dx),
830 viaparinfo->io_virt + VIA_REG_DSTPOS);
831 /* Dimension: width & height */
832 writel((((rect->height - 1) << 16) | (rect->width - 1)),
833 viaparinfo->io_virt + VIA_REG_DIMENSION);
834 /* Forground color or Destination color */
835 writel(col, viaparinfo->io_virt + VIA_REG_FGCOLOR);
836 /* GE Command */
837 writel((0x01 | 0x2000 | (rop << 24)),
838 viaparinfo->io_virt + VIA_REG_GECMD);
839 790
791 DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n");
792 if (viapar->shared->hw_bitblt(viapar->io_virt, VIA_BITBLT_FILL,
793 rect->width, rect->height, info->var.bits_per_pixel,
794 viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy,
795 NULL, 0, 0, 0, 0, fg_color, 0, rop))
796 cfb_fillrect(info, rect);
840} 797}
841 798
842static void viafb_copyarea(struct fb_info *info, 799static void viafb_copyarea(struct fb_info *info,
843 const struct fb_copyarea *area) 800 const struct fb_copyarea *area)
844{ 801{
845 u32 dy = area->dy, sy = area->sy, direction = 0x0; 802 struct viafb_par *viapar = info->par;
846 u32 sx = area->sx, dx = area->dx, width = area->width;
847 int pitch;
848 803
849 DEBUG_MSG(KERN_INFO "viafb_copyarea!!\n"); 804 if (!viapar->shared->hw_bitblt) {
850
851 if (!viafb_accel) {
852 cfb_copyarea(info, area); 805 cfb_copyarea(info, area);
853 return; 806 return;
854 } 807 }
@@ -856,113 +809,48 @@ static void viafb_copyarea(struct fb_info *info,
856 if (!area->width || !area->height) 809 if (!area->width || !area->height)
857 return; 810 return;
858 811
859 if (sy < dy) { 812 DEBUG_MSG(KERN_DEBUG "viafb 2D engine: copyarea\n");
860 dy += area->height - 1; 813 if (viapar->shared->hw_bitblt(viapar->io_virt, VIA_BITBLT_COLOR,
861 sy += area->height - 1; 814 area->width, area->height, info->var.bits_per_pixel,
862 direction |= 0x4000; 815 viapar->vram_addr, info->fix.line_length, area->dx, area->dy,
863 } 816 NULL, viapar->vram_addr, info->fix.line_length,
864 817 area->sx, area->sy, 0, 0, 0))
865 if (sx < dx) { 818 cfb_copyarea(info, area);
866 dx += width - 1;
867 sx += width - 1;
868 direction |= 0x8000;
869 }
870
871 /* Source Base Address */
872 writel((info->fix.smem_start - viafbinfo->fix.smem_start) >> 3,
873 viaparinfo->io_virt + VIA_REG_SRCBASE);
874 /* Destination Base Address */
875 writel((info->fix.smem_start - viafbinfo->fix.smem_start) >> 3,
876 viaparinfo->io_virt + VIA_REG_DSTBASE);
877 /* Pitch */
878 pitch = (info->var.xres_virtual + 7) & ~7;
879 /* VIA_PITCH_ENABLE can be omitted now. */
880 writel(VIA_PITCH_ENABLE |
881 (((pitch *
882 info->var.bits_per_pixel >> 3) >> 3) | (((pitch *
883 info->var.
884 bits_per_pixel
885 >> 3) >> 3)
886 << 16)),
887 viaparinfo->io_virt + VIA_REG_PITCH);
888 /* BitBlt Source Address */
889 writel(((sy << 16) | sx), viaparinfo->io_virt + VIA_REG_SRCPOS);
890 /* BitBlt Destination Address */
891 writel(((dy << 16) | dx), viaparinfo->io_virt + VIA_REG_DSTPOS);
892 /* Dimension: width & height */
893 writel((((area->height - 1) << 16) | (area->width - 1)),
894 viaparinfo->io_virt + VIA_REG_DIMENSION);
895 /* GE Command */
896 writel((0x01 | direction | (0xCC << 24)),
897 viaparinfo->io_virt + VIA_REG_GECMD);
898
899} 819}
900 820
901static void viafb_imageblit(struct fb_info *info, 821static void viafb_imageblit(struct fb_info *info,
902 const struct fb_image *image) 822 const struct fb_image *image)
903{ 823{
904 u32 size, bg_col = 0, fg_col = 0, *udata; 824 struct viafb_par *viapar = info->par;
905 int i; 825 u32 fg_color = 0, bg_color = 0;
906 int pitch; 826 u8 op;
907 827
908 if (!viafb_accel) { 828 if (!viapar->shared->hw_bitblt ||
829 (image->depth != 1 && image->depth != viapar->depth)) {
909 cfb_imageblit(info, image); 830 cfb_imageblit(info, image);
910 return; 831 return;
911 } 832 }
912 833
913 udata = (u32 *) image->data; 834 if (image->depth == 1) {
914 835 op = VIA_BITBLT_MONO;
915 switch (info->var.bits_per_pixel) { 836 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
916 case 8: 837 fg_color =
917 bg_col = image->bg_color; 838 ((u32 *)info->pseudo_palette)[image->fg_color];
918 fg_col = image->fg_color; 839 bg_color =
919 break; 840 ((u32 *)info->pseudo_palette)[image->bg_color];
920 case 16: 841 } else {
921 bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color]; 842 fg_color = image->fg_color;
922 fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color]; 843 bg_color = image->bg_color;
923 break; 844 }
924 case 32: 845 } else
925 bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color]; 846 op = VIA_BITBLT_COLOR;
926 fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color];
927 break;
928 }
929 size = image->width * image->height;
930
931 /* Source Base Address */
932 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
933 /* Destination Base Address */
934 writel((info->fix.smem_start - viafbinfo->fix.smem_start) >> 3,
935 viaparinfo->io_virt + VIA_REG_DSTBASE);
936 /* Pitch */
937 pitch = (info->var.xres_virtual + 7) & ~7;
938 writel(VIA_PITCH_ENABLE |
939 (((pitch *
940 info->var.bits_per_pixel >> 3) >> 3) | (((pitch *
941 info->var.
942 bits_per_pixel
943 >> 3) >> 3)
944 << 16)),
945 viaparinfo->io_virt + VIA_REG_PITCH);
946 /* BitBlt Source Address */
947 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
948 /* BitBlt Destination Address */
949 writel(((image->dy << 16) | image->dx),
950 viaparinfo->io_virt + VIA_REG_DSTPOS);
951 /* Dimension: width & height */
952 writel((((image->height - 1) << 16) | (image->width - 1)),
953 viaparinfo->io_virt + VIA_REG_DIMENSION);
954 /* fb color */
955 writel(fg_col, viaparinfo->io_virt + VIA_REG_FGCOLOR);
956 /* bg color */
957 writel(bg_col, viaparinfo->io_virt + VIA_REG_BGCOLOR);
958 /* GE Command */
959 writel(0xCC020142, viaparinfo->io_virt + VIA_REG_GECMD);
960
961 for (i = 0; i < size / 4; i++) {
962 writel(*udata, viaparinfo->io_virt + VIA_MMIO_BLTBASE);
963 udata++;
964 }
965 847
848 DEBUG_MSG(KERN_DEBUG "viafb 2D engine: imageblit\n");
849 if (viapar->shared->hw_bitblt(viapar->io_virt, op,
850 image->width, image->height, info->var.bits_per_pixel,
851 viapar->vram_addr, info->fix.line_length, image->dx, image->dy,
852 (u32 *)image->data, 0, 0, 0, 0, fg_color, bg_color, 0))
853 cfb_imageblit(info, image);
966} 854}
967 855
968static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) 856static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
@@ -1961,6 +1849,7 @@ static int __devinit via_pci_probe(void)
1961 1849
1962 viaparinfo = (struct viafb_par *)viafbinfo->par; 1850 viaparinfo = (struct viafb_par *)viafbinfo->par;
1963 viaparinfo->shared = viafbinfo->par + viafb_par_length; 1851 viaparinfo->shared = viafbinfo->par + viafb_par_length;
1852 viaparinfo->vram_addr = 0;
1964 viaparinfo->tmds_setting_info = &viaparinfo->shared->tmds_setting_info; 1853 viaparinfo->tmds_setting_info = &viaparinfo->shared->tmds_setting_info;
1965 viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info; 1854 viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info;
1966 viaparinfo->lvds_setting_info2 = 1855 viaparinfo->lvds_setting_info2 =
@@ -2007,7 +1896,7 @@ static int __devinit via_pci_probe(void)
2007 1896
2008 viafbinfo->pseudo_palette = pseudo_pal; 1897 viafbinfo->pseudo_palette = pseudo_pal;
2009 if (viafb_accel) { 1898 if (viafb_accel) {
2010 viafb_init_accel(); 1899 viafb_init_accel(viaparinfo->shared);
2011 viafb_init_2d_engine(); 1900 viafb_init_2d_engine();
2012 viafb_hw_cursor_init(); 1901 viafb_hw_cursor_init();
2013 } 1902 }
@@ -2110,6 +1999,7 @@ static int __devinit via_pci_probe(void)
2110 } 1999 }
2111 viaparinfo1 = viafbinfo1->par; 2000 viaparinfo1 = viafbinfo1->par;
2112 memcpy(viaparinfo1, viaparinfo, viafb_par_length); 2001 memcpy(viaparinfo1, viaparinfo, viafb_par_length);
2002 viaparinfo1->vram_addr = viafb_second_offset;
2113 viaparinfo1->memsize = viaparinfo->memsize - 2003 viaparinfo1->memsize = viaparinfo->memsize -
2114 viafb_second_offset; 2004 viafb_second_offset;
2115 viaparinfo->memsize = viafb_second_offset; 2005 viaparinfo->memsize = viafb_second_offset;
@@ -2157,12 +2047,16 @@ static int __devinit via_pci_probe(void)
2157 viafb_check_var(&default_var, viafbinfo1); 2047 viafb_check_var(&default_var, viafbinfo1);
2158 viafbinfo1->var = default_var; 2048 viafbinfo1->var = default_var;
2159 viafb_update_fix(viafbinfo1); 2049 viafb_update_fix(viafbinfo1);
2050 viaparinfo1->depth = fb_get_color_depth(&viafbinfo1->var,
2051 &viafbinfo1->fix);
2160 } 2052 }
2161 2053
2162 viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); 2054 viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
2163 viafb_check_var(&default_var, viafbinfo); 2055 viafb_check_var(&default_var, viafbinfo);
2164 viafbinfo->var = default_var; 2056 viafbinfo->var = default_var;
2165 viafb_update_fix(viafbinfo); 2057 viafb_update_fix(viafbinfo);
2058 viaparinfo->depth = fb_get_color_depth(&viafbinfo->var,
2059 &viafbinfo->fix);
2166 default_var.activate = FB_ACTIVATE_NOW; 2060 default_var.activate = FB_ACTIVATE_NOW;
2167 fb_alloc_cmap(&viafbinfo->cmap, 256, 0); 2061 fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
2168 2062
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index 1d1fe35feaa7..beb470392db1 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -49,9 +49,17 @@ struct viafb_shared {
49 struct lvds_setting_information lvds_setting_info; 49 struct lvds_setting_information lvds_setting_info;
50 struct lvds_setting_information lvds_setting_info2; 50 struct lvds_setting_information lvds_setting_info2;
51 struct chip_information chip_info; 51 struct chip_information chip_info;
52
53 /* hardware acceleration stuff */
54 int (*hw_bitblt)(void __iomem *engine, u8 op, u32 width, u32 height,
55 u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
56 u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
57 u32 fg_color, u32 bg_color, u8 fill_rop);
52}; 58};
53 59
54struct viafb_par { 60struct viafb_par {
61 u8 depth;
62 u32 vram_addr;
55 void __iomem *io_virt; /*iospace virtual memory address */ 63 void __iomem *io_virt; /*iospace virtual memory address */
56 unsigned int fbmem; /*framebuffer physical memory address */ 64 unsigned int fbmem; /*framebuffer physical memory address */
57 unsigned int memsize; /*size of fbmem */ 65 unsigned int memsize; /*size of fbmem */