xref: /linux/drivers/video/fbdev/i810/i810_accel.c (revision e5451c8f8330e03ad3cfa16048b4daf961af434f)
1*f7018c21STomi Valkeinen /*-*- linux-c -*-
2*f7018c21STomi Valkeinen  *  linux/drivers/video/i810_accel.c -- Hardware Acceleration
3*f7018c21STomi Valkeinen  *
4*f7018c21STomi Valkeinen  *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
5*f7018c21STomi Valkeinen  *      All Rights Reserved
6*f7018c21STomi Valkeinen  *
7*f7018c21STomi Valkeinen  *  This file is subject to the terms and conditions of the GNU General Public
8*f7018c21STomi Valkeinen  *  License. See the file COPYING in the main directory of this archive for
9*f7018c21STomi Valkeinen  *  more details.
10*f7018c21STomi Valkeinen  */
11*f7018c21STomi Valkeinen #include <linux/kernel.h>
12*f7018c21STomi Valkeinen #include <linux/string.h>
13*f7018c21STomi Valkeinen #include <linux/fb.h>
14*f7018c21STomi Valkeinen 
15*f7018c21STomi Valkeinen #include "i810_regs.h"
16*f7018c21STomi Valkeinen #include "i810.h"
17*f7018c21STomi Valkeinen #include "i810_main.h"
18*f7018c21STomi Valkeinen 
19*f7018c21STomi Valkeinen static u32 i810fb_rop[] = {
20*f7018c21STomi Valkeinen 	COLOR_COPY_ROP, /* ROP_COPY */
21*f7018c21STomi Valkeinen 	XOR_ROP         /* ROP_XOR  */
22*f7018c21STomi Valkeinen };
23*f7018c21STomi Valkeinen 
24*f7018c21STomi Valkeinen /* Macros */
25*f7018c21STomi Valkeinen #define PUT_RING(n) {                                        \
26*f7018c21STomi Valkeinen 	i810_writel(par->cur_tail, par->iring.virtual, n);   \
27*f7018c21STomi Valkeinen         par->cur_tail += 4;                                  \
28*f7018c21STomi Valkeinen         par->cur_tail &= RING_SIZE_MASK;                     \
29*f7018c21STomi Valkeinen }
30*f7018c21STomi Valkeinen 
31*f7018c21STomi Valkeinen extern void flush_cache(void);
32*f7018c21STomi Valkeinen 
33*f7018c21STomi Valkeinen /************************************************************/
34*f7018c21STomi Valkeinen 
35*f7018c21STomi Valkeinen /* BLT Engine Routines */
i810_report_error(u8 __iomem * mmio)36*f7018c21STomi Valkeinen static inline void i810_report_error(u8 __iomem *mmio)
37*f7018c21STomi Valkeinen {
38*f7018c21STomi Valkeinen 	printk("IIR     : 0x%04x\n"
39*f7018c21STomi Valkeinen 	       "EIR     : 0x%04x\n"
40*f7018c21STomi Valkeinen 	       "PGTBL_ER: 0x%04x\n"
41*f7018c21STomi Valkeinen 	       "IPEIR   : 0x%04x\n"
42*f7018c21STomi Valkeinen 	       "IPEHR   : 0x%04x\n",
43*f7018c21STomi Valkeinen 	       i810_readw(IIR, mmio),
44*f7018c21STomi Valkeinen 	       i810_readb(EIR, mmio),
45*f7018c21STomi Valkeinen 	       i810_readl(PGTBL_ER, mmio),
46*f7018c21STomi Valkeinen 	       i810_readl(IPEIR, mmio),
47*f7018c21STomi Valkeinen 	       i810_readl(IPEHR, mmio));
48*f7018c21STomi Valkeinen }
49*f7018c21STomi Valkeinen 
50*f7018c21STomi Valkeinen /**
51*f7018c21STomi Valkeinen  * wait_for_space - check ring buffer free space
52*f7018c21STomi Valkeinen  * @space: amount of ringbuffer space needed in bytes
53*f7018c21STomi Valkeinen  * @par: pointer to i810fb_par structure
54*f7018c21STomi Valkeinen  *
55*f7018c21STomi Valkeinen  * DESCRIPTION:
56*f7018c21STomi Valkeinen  * The function waits until a free space from the ringbuffer
57*f7018c21STomi Valkeinen  * is available
58*f7018c21STomi Valkeinen  */
wait_for_space(struct fb_info * info,u32 space)59*f7018c21STomi Valkeinen static inline int wait_for_space(struct fb_info *info, u32 space)
60*f7018c21STomi Valkeinen {
61*f7018c21STomi Valkeinen 	struct i810fb_par *par = info->par;
62*f7018c21STomi Valkeinen 	u32 head, count = WAIT_COUNT, tail;
63*f7018c21STomi Valkeinen 	u8 __iomem *mmio = par->mmio_start_virtual;
64*f7018c21STomi Valkeinen 
65*f7018c21STomi Valkeinen 	tail = par->cur_tail;
66*f7018c21STomi Valkeinen 	while (count--) {
67*f7018c21STomi Valkeinen 		head = i810_readl(IRING + 4, mmio) & RBUFFER_HEAD_MASK;
68*f7018c21STomi Valkeinen 		if ((tail == head) ||
69*f7018c21STomi Valkeinen 		    (tail > head &&
70*f7018c21STomi Valkeinen 		     (par->iring.size - tail + head) >= space) ||
71*f7018c21STomi Valkeinen 		    (tail < head && (head - tail) >= space)) {
72*f7018c21STomi Valkeinen 			return 0;
73*f7018c21STomi Valkeinen 		}
74*f7018c21STomi Valkeinen 	}
75*f7018c21STomi Valkeinen 	printk("ringbuffer lockup!!!\n");
76*f7018c21STomi Valkeinen 	i810_report_error(mmio);
77*f7018c21STomi Valkeinen 	par->dev_flags |= LOCKUP;
78*f7018c21STomi Valkeinen 	info->pixmap.scan_align = 1;
79*f7018c21STomi Valkeinen 	return 1;
80*f7018c21STomi Valkeinen }
81*f7018c21STomi Valkeinen 
82*f7018c21STomi Valkeinen /**
83*f7018c21STomi Valkeinen  * wait_for_engine_idle - waits for all hardware engines to finish
84*f7018c21STomi Valkeinen  * @par: pointer to i810fb_par structure
85*f7018c21STomi Valkeinen  *
86*f7018c21STomi Valkeinen  * DESCRIPTION:
87*f7018c21STomi Valkeinen  * This waits for lring(0), iring(1), and batch(3), etc to finish and
88*f7018c21STomi Valkeinen  * waits until ringbuffer is empty.
89*f7018c21STomi Valkeinen  */
wait_for_engine_idle(struct fb_info * info)90*f7018c21STomi Valkeinen static inline int wait_for_engine_idle(struct fb_info *info)
91*f7018c21STomi Valkeinen {
92*f7018c21STomi Valkeinen 	struct i810fb_par *par = info->par;
93*f7018c21STomi Valkeinen 	u8 __iomem *mmio = par->mmio_start_virtual;
94*f7018c21STomi Valkeinen 	int count = WAIT_COUNT;
95*f7018c21STomi Valkeinen 
96*f7018c21STomi Valkeinen 	if (wait_for_space(info, par->iring.size)) /* flush */
97*f7018c21STomi Valkeinen 		return 1;
98*f7018c21STomi Valkeinen 
99*f7018c21STomi Valkeinen 	while((i810_readw(INSTDONE, mmio) & 0x7B) != 0x7B && --count);
100*f7018c21STomi Valkeinen 	if (count) return 0;
101*f7018c21STomi Valkeinen 
102*f7018c21STomi Valkeinen 	printk("accel engine lockup!!!\n");
103*f7018c21STomi Valkeinen 	printk("INSTDONE: 0x%04x\n", i810_readl(INSTDONE, mmio));
104*f7018c21STomi Valkeinen 	i810_report_error(mmio);
105*f7018c21STomi Valkeinen 	par->dev_flags |= LOCKUP;
106*f7018c21STomi Valkeinen 	info->pixmap.scan_align = 1;
107*f7018c21STomi Valkeinen 	return 1;
108*f7018c21STomi Valkeinen }
109*f7018c21STomi Valkeinen 
110*f7018c21STomi Valkeinen /* begin_iring - prepares the ringbuffer
111*f7018c21STomi Valkeinen  * @space: length of sequence in dwords
112*f7018c21STomi Valkeinen  * @par: pointer to i810fb_par structure
113*f7018c21STomi Valkeinen  *
114*f7018c21STomi Valkeinen  * DESCRIPTION:
115*f7018c21STomi Valkeinen  * Checks/waits for sufficient space in ringbuffer of size
116*f7018c21STomi Valkeinen  * space.  Returns the tail of the buffer
117*f7018c21STomi Valkeinen  */
begin_iring(struct fb_info * info,u32 space)118*f7018c21STomi Valkeinen static inline u32 begin_iring(struct fb_info *info, u32 space)
119*f7018c21STomi Valkeinen {
120*f7018c21STomi Valkeinen 	struct i810fb_par *par = info->par;
121*f7018c21STomi Valkeinen 
122*f7018c21STomi Valkeinen 	if (par->dev_flags & ALWAYS_SYNC)
123*f7018c21STomi Valkeinen 		wait_for_engine_idle(info);
124*f7018c21STomi Valkeinen 	return wait_for_space(info, space);
125*f7018c21STomi Valkeinen }
126*f7018c21STomi Valkeinen 
127*f7018c21STomi Valkeinen /**
128*f7018c21STomi Valkeinen  * end_iring - advances the buffer
129*f7018c21STomi Valkeinen  * @par: pointer to i810fb_par structure
130*f7018c21STomi Valkeinen  *
131*f7018c21STomi Valkeinen  * DESCRIPTION:
132*f7018c21STomi Valkeinen  * This advances the tail of the ringbuffer, effectively
133*f7018c21STomi Valkeinen  * beginning the execution of the graphics instruction sequence.
134*f7018c21STomi Valkeinen  */
end_iring(struct i810fb_par * par)135*f7018c21STomi Valkeinen static inline void end_iring(struct i810fb_par *par)
136*f7018c21STomi Valkeinen {
137*f7018c21STomi Valkeinen 	u8 __iomem *mmio = par->mmio_start_virtual;
138*f7018c21STomi Valkeinen 
139*f7018c21STomi Valkeinen 	i810_writel(IRING, mmio, par->cur_tail);
140*f7018c21STomi Valkeinen }
141*f7018c21STomi Valkeinen 
142*f7018c21STomi Valkeinen /**
143*f7018c21STomi Valkeinen  * source_copy_blit - BLIT transfer operation
144*f7018c21STomi Valkeinen  * @dwidth: width of rectangular graphics data
145*f7018c21STomi Valkeinen  * @dheight: height of rectangular graphics data
146*f7018c21STomi Valkeinen  * @dpitch: bytes per line of destination buffer
147*f7018c21STomi Valkeinen  * @xdir: direction of copy (left to right or right to left)
148*f7018c21STomi Valkeinen  * @src: address of first pixel to read from
149*f7018c21STomi Valkeinen  * @dest: address of first pixel to write to
150*f7018c21STomi Valkeinen  * @from: source address
151*f7018c21STomi Valkeinen  * @where: destination address
152*f7018c21STomi Valkeinen  * @rop: raster operation
153*f7018c21STomi Valkeinen  * @blit_bpp: pixel format which can be different from the
154*f7018c21STomi Valkeinen  *            framebuffer's pixelformat
155*f7018c21STomi Valkeinen  * @par: pointer to i810fb_par structure
156*f7018c21STomi Valkeinen  *
157*f7018c21STomi Valkeinen  * DESCRIPTION:
158*f7018c21STomi Valkeinen  * This is a BLIT operation typically used when doing
159*f7018c21STomi Valkeinen  * a 'Copy and Paste'
160*f7018c21STomi Valkeinen  */
source_copy_blit(int dwidth,int dheight,int dpitch,int xdir,int src,int dest,int rop,int blit_bpp,struct fb_info * info)161*f7018c21STomi Valkeinen static inline void source_copy_blit(int dwidth, int dheight, int dpitch,
162*f7018c21STomi Valkeinen 				    int xdir, int src, int dest, int rop,
163*f7018c21STomi Valkeinen 				    int blit_bpp, struct fb_info *info)
164*f7018c21STomi Valkeinen {
165*f7018c21STomi Valkeinen 	struct i810fb_par *par = info->par;
166*f7018c21STomi Valkeinen 
167*f7018c21STomi Valkeinen 	if (begin_iring(info, 24 + IRING_PAD)) return;
168*f7018c21STomi Valkeinen 
169*f7018c21STomi Valkeinen 	PUT_RING(BLIT | SOURCE_COPY_BLIT | 4);
170*f7018c21STomi Valkeinen 	PUT_RING(xdir | rop << 16 | dpitch | DYN_COLOR_EN | blit_bpp);
171*f7018c21STomi Valkeinen 	PUT_RING(dheight << 16 | dwidth);
172*f7018c21STomi Valkeinen 	PUT_RING(dest);
173*f7018c21STomi Valkeinen 	PUT_RING(dpitch);
174*f7018c21STomi Valkeinen 	PUT_RING(src);
175*f7018c21STomi Valkeinen 
176*f7018c21STomi Valkeinen 	end_iring(par);
177*f7018c21STomi Valkeinen }
178*f7018c21STomi Valkeinen 
179*f7018c21STomi Valkeinen /**
180*f7018c21STomi Valkeinen  * color_blit - solid color BLIT operation
181*f7018c21STomi Valkeinen  * @width: width of destination
182*f7018c21STomi Valkeinen  * @height: height of destination
183*f7018c21STomi Valkeinen  * @pitch: pixels per line of the buffer
184*f7018c21STomi Valkeinen  * @dest: address of first pixel to write to
185*f7018c21STomi Valkeinen  * @where: destination
186*f7018c21STomi Valkeinen  * @rop: raster operation
187*f7018c21STomi Valkeinen  * @what: color to transfer
188*f7018c21STomi Valkeinen  * @blit_bpp: pixel format which can be different from the
189*f7018c21STomi Valkeinen  *            framebuffer's pixelformat
190*f7018c21STomi Valkeinen  * @par: pointer to i810fb_par structure
191*f7018c21STomi Valkeinen  *
192*f7018c21STomi Valkeinen  * DESCRIPTION:
193*f7018c21STomi Valkeinen  * A BLIT operation which can be used for  color fill/rectangular fill
194*f7018c21STomi Valkeinen  */
color_blit(int width,int height,int pitch,int dest,int rop,int what,int blit_bpp,struct fb_info * info)195*f7018c21STomi Valkeinen static inline void color_blit(int width, int height, int pitch,  int dest,
196*f7018c21STomi Valkeinen 			      int rop, int what, int blit_bpp,
197*f7018c21STomi Valkeinen 			      struct fb_info *info)
198*f7018c21STomi Valkeinen {
199*f7018c21STomi Valkeinen 	struct i810fb_par *par = info->par;
200*f7018c21STomi Valkeinen 
201*f7018c21STomi Valkeinen 	if (begin_iring(info, 24 + IRING_PAD)) return;
202*f7018c21STomi Valkeinen 
203*f7018c21STomi Valkeinen 	PUT_RING(BLIT | COLOR_BLT | 3);
204*f7018c21STomi Valkeinen 	PUT_RING(rop << 16 | pitch | SOLIDPATTERN | DYN_COLOR_EN | blit_bpp);
205*f7018c21STomi Valkeinen 	PUT_RING(height << 16 | width);
206*f7018c21STomi Valkeinen 	PUT_RING(dest);
207*f7018c21STomi Valkeinen 	PUT_RING(what);
208*f7018c21STomi Valkeinen 	PUT_RING(NOP);
209*f7018c21STomi Valkeinen 
210*f7018c21STomi Valkeinen 	end_iring(par);
211*f7018c21STomi Valkeinen }
212*f7018c21STomi Valkeinen 
213*f7018c21STomi Valkeinen /**
214*f7018c21STomi Valkeinen  * mono_src_copy_imm_blit - color expand from system memory to framebuffer
215*f7018c21STomi Valkeinen  * @dwidth: width of destination
216*f7018c21STomi Valkeinen  * @dheight: height of destination
217*f7018c21STomi Valkeinen  * @dpitch: pixels per line of the buffer
218*f7018c21STomi Valkeinen  * @dsize: size of bitmap in double words
219*f7018c21STomi Valkeinen  * @dest: address of first byte of pixel;
220*f7018c21STomi Valkeinen  * @rop: raster operation
221*f7018c21STomi Valkeinen  * @blit_bpp: pixelformat to use which can be different from the
222*f7018c21STomi Valkeinen  *            framebuffer's pixelformat
223*f7018c21STomi Valkeinen  * @src: address of image data
224*f7018c21STomi Valkeinen  * @bg: backgound color
225*f7018c21STomi Valkeinen  * @fg: forground color
226*f7018c21STomi Valkeinen  * @par: pointer to i810fb_par structure
227*f7018c21STomi Valkeinen  *
228*f7018c21STomi Valkeinen  * DESCRIPTION:
229*f7018c21STomi Valkeinen  * A color expand operation where the  source data is placed in the
230*f7018c21STomi Valkeinen  * ringbuffer itself. Useful for drawing text.
231*f7018c21STomi Valkeinen  *
232*f7018c21STomi Valkeinen  * REQUIREMENT:
233*f7018c21STomi Valkeinen  * The end of a scanline must be padded to the next word.
234*f7018c21STomi Valkeinen  */
mono_src_copy_imm_blit(int dwidth,int dheight,int dpitch,int dsize,int blit_bpp,int rop,int dest,const u32 * src,int bg,int fg,struct fb_info * info)235*f7018c21STomi Valkeinen static inline void mono_src_copy_imm_blit(int dwidth, int dheight, int dpitch,
236*f7018c21STomi Valkeinen 					  int dsize, int blit_bpp, int rop,
237*f7018c21STomi Valkeinen 					  int dest, const u32 *src, int bg,
238*f7018c21STomi Valkeinen 					  int fg, struct fb_info *info)
239*f7018c21STomi Valkeinen {
240*f7018c21STomi Valkeinen 	struct i810fb_par *par = info->par;
241*f7018c21STomi Valkeinen 
242*f7018c21STomi Valkeinen 	if (begin_iring(info, 24 + (dsize << 2) + IRING_PAD)) return;
243*f7018c21STomi Valkeinen 
244*f7018c21STomi Valkeinen 	PUT_RING(BLIT | MONO_SOURCE_COPY_IMMEDIATE | (4 + dsize));
245*f7018c21STomi Valkeinen 	PUT_RING(DYN_COLOR_EN | blit_bpp | rop << 16 | dpitch);
246*f7018c21STomi Valkeinen 	PUT_RING(dheight << 16 | dwidth);
247*f7018c21STomi Valkeinen 	PUT_RING(dest);
248*f7018c21STomi Valkeinen 	PUT_RING(bg);
249*f7018c21STomi Valkeinen 	PUT_RING(fg);
250*f7018c21STomi Valkeinen 	while (dsize--)
251*f7018c21STomi Valkeinen 		PUT_RING(*src++);
252*f7018c21STomi Valkeinen 
253*f7018c21STomi Valkeinen 	end_iring(par);
254*f7018c21STomi Valkeinen }
255*f7018c21STomi Valkeinen 
load_front(int offset,struct fb_info * info)256*f7018c21STomi Valkeinen static inline void load_front(int offset, struct fb_info *info)
257*f7018c21STomi Valkeinen {
258*f7018c21STomi Valkeinen 	struct i810fb_par *par = info->par;
259*f7018c21STomi Valkeinen 
260*f7018c21STomi Valkeinen 	if (begin_iring(info, 8 + IRING_PAD)) return;
261*f7018c21STomi Valkeinen 
262*f7018c21STomi Valkeinen 	PUT_RING(PARSER | FLUSH);
263*f7018c21STomi Valkeinen 	PUT_RING(NOP);
264*f7018c21STomi Valkeinen 
265*f7018c21STomi Valkeinen 	end_iring(par);
266*f7018c21STomi Valkeinen 
267*f7018c21STomi Valkeinen 	if (begin_iring(info, 8 + IRING_PAD)) return;
268*f7018c21STomi Valkeinen 
269*f7018c21STomi Valkeinen 	PUT_RING(PARSER | FRONT_BUFFER | ((par->pitch >> 3) << 8));
270*f7018c21STomi Valkeinen 	PUT_RING((par->fb.offset << 12) + offset);
271*f7018c21STomi Valkeinen 
272*f7018c21STomi Valkeinen 	end_iring(par);
273*f7018c21STomi Valkeinen }
274*f7018c21STomi Valkeinen 
275*f7018c21STomi Valkeinen /**
276*f7018c21STomi Valkeinen  * i810fb_iring_enable - enables/disables the ringbuffer
277*f7018c21STomi Valkeinen  * @mode: enable or disable
278*f7018c21STomi Valkeinen  * @par: pointer to i810fb_par structure
279*f7018c21STomi Valkeinen  *
280*f7018c21STomi Valkeinen  * DESCRIPTION:
281*f7018c21STomi Valkeinen  * Enables or disables the ringbuffer, effectively enabling or
282*f7018c21STomi Valkeinen  * disabling the instruction/acceleration engine.
283*f7018c21STomi Valkeinen  */
i810fb_iring_enable(struct i810fb_par * par,u32 mode)284*f7018c21STomi Valkeinen static inline void i810fb_iring_enable(struct i810fb_par *par, u32 mode)
285*f7018c21STomi Valkeinen {
286*f7018c21STomi Valkeinen 	u32 tmp;
287*f7018c21STomi Valkeinen 	u8 __iomem *mmio = par->mmio_start_virtual;
288*f7018c21STomi Valkeinen 
289*f7018c21STomi Valkeinen 	tmp = i810_readl(IRING + 12, mmio);
290*f7018c21STomi Valkeinen 	if (mode == OFF)
291*f7018c21STomi Valkeinen 		tmp &= ~1;
292*f7018c21STomi Valkeinen 	else
293*f7018c21STomi Valkeinen 		tmp |= 1;
294*f7018c21STomi Valkeinen 	flush_cache();
295*f7018c21STomi Valkeinen 	i810_writel(IRING + 12, mmio, tmp);
296*f7018c21STomi Valkeinen }
297*f7018c21STomi Valkeinen 
i810fb_fillrect(struct fb_info * info,const struct fb_fillrect * rect)298*f7018c21STomi Valkeinen void i810fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
299*f7018c21STomi Valkeinen {
300*f7018c21STomi Valkeinen 	struct i810fb_par *par = info->par;
301*f7018c21STomi Valkeinen 	u32 dx, dy, width, height, dest, rop = 0, color = 0;
302*f7018c21STomi Valkeinen 
303*f7018c21STomi Valkeinen 	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
304*f7018c21STomi Valkeinen 	    par->depth == 4) {
305*f7018c21STomi Valkeinen 		cfb_fillrect(info, rect);
306*f7018c21STomi Valkeinen 		return;
307*f7018c21STomi Valkeinen 	}
308*f7018c21STomi Valkeinen 
309*f7018c21STomi Valkeinen 	if (par->depth == 1)
310*f7018c21STomi Valkeinen 		color = rect->color;
311*f7018c21STomi Valkeinen 	else
312*f7018c21STomi Valkeinen 		color = ((u32 *) (info->pseudo_palette))[rect->color];
313*f7018c21STomi Valkeinen 
314*f7018c21STomi Valkeinen 	rop = i810fb_rop[rect->rop];
315*f7018c21STomi Valkeinen 
316*f7018c21STomi Valkeinen 	dx = rect->dx * par->depth;
317*f7018c21STomi Valkeinen 	width = rect->width * par->depth;
318*f7018c21STomi Valkeinen 	dy = rect->dy;
319*f7018c21STomi Valkeinen 	height = rect->height;
320*f7018c21STomi Valkeinen 
321*f7018c21STomi Valkeinen 	dest = info->fix.smem_start + (dy * info->fix.line_length) + dx;
322*f7018c21STomi Valkeinen 	color_blit(width, height, info->fix.line_length, dest, rop, color,
323*f7018c21STomi Valkeinen 		   par->blit_bpp, info);
324*f7018c21STomi Valkeinen }
325*f7018c21STomi Valkeinen 
i810fb_copyarea(struct fb_info * info,const struct fb_copyarea * region)326*f7018c21STomi Valkeinen void i810fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
327*f7018c21STomi Valkeinen {
328*f7018c21STomi Valkeinen 	struct i810fb_par *par = info->par;
329*f7018c21STomi Valkeinen 	u32 sx, sy, dx, dy, pitch, width, height, src, dest, xdir;
330*f7018c21STomi Valkeinen 
331*f7018c21STomi Valkeinen 	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
332*f7018c21STomi Valkeinen 	    par->depth == 4) {
333*f7018c21STomi Valkeinen 		cfb_copyarea(info, region);
334*f7018c21STomi Valkeinen 		return;
335*f7018c21STomi Valkeinen 	}
336*f7018c21STomi Valkeinen 
337*f7018c21STomi Valkeinen 	dx = region->dx * par->depth;
338*f7018c21STomi Valkeinen 	sx = region->sx * par->depth;
339*f7018c21STomi Valkeinen 	width = region->width * par->depth;
340*f7018c21STomi Valkeinen 	sy = region->sy;
341*f7018c21STomi Valkeinen 	dy = region->dy;
342*f7018c21STomi Valkeinen 	height = region->height;
343*f7018c21STomi Valkeinen 
344*f7018c21STomi Valkeinen 	if (dx <= sx) {
345*f7018c21STomi Valkeinen 		xdir = INCREMENT;
346*f7018c21STomi Valkeinen 	}
347*f7018c21STomi Valkeinen 	else {
348*f7018c21STomi Valkeinen 		xdir = DECREMENT;
349*f7018c21STomi Valkeinen 		sx += width - 1;
350*f7018c21STomi Valkeinen 		dx += width - 1;
351*f7018c21STomi Valkeinen 	}
352*f7018c21STomi Valkeinen 	if (dy <= sy) {
353*f7018c21STomi Valkeinen 		pitch = info->fix.line_length;
354*f7018c21STomi Valkeinen 	}
355*f7018c21STomi Valkeinen 	else {
356*f7018c21STomi Valkeinen 		pitch = (-(info->fix.line_length)) & 0xFFFF;
357*f7018c21STomi Valkeinen 		sy += height - 1;
358*f7018c21STomi Valkeinen 		dy += height - 1;
359*f7018c21STomi Valkeinen 	}
360*f7018c21STomi Valkeinen 	src = info->fix.smem_start + (sy * info->fix.line_length) + sx;
361*f7018c21STomi Valkeinen 	dest = info->fix.smem_start + (dy * info->fix.line_length) + dx;
362*f7018c21STomi Valkeinen 
363*f7018c21STomi Valkeinen 	source_copy_blit(width, height, pitch, xdir, src, dest,
364*f7018c21STomi Valkeinen 			 PAT_COPY_ROP, par->blit_bpp, info);
365*f7018c21STomi Valkeinen }
366*f7018c21STomi Valkeinen 
i810fb_imageblit(struct fb_info * info,const struct fb_image * image)367*f7018c21STomi Valkeinen void i810fb_imageblit(struct fb_info *info, const struct fb_image *image)
368*f7018c21STomi Valkeinen {
369*f7018c21STomi Valkeinen 	struct i810fb_par *par = info->par;
370*f7018c21STomi Valkeinen 	u32 fg = 0, bg = 0, size, dst;
371*f7018c21STomi Valkeinen 
372*f7018c21STomi Valkeinen 	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
373*f7018c21STomi Valkeinen 	    par->depth == 4 || image->depth != 1) {
374*f7018c21STomi Valkeinen 		cfb_imageblit(info, image);
375*f7018c21STomi Valkeinen 		return;
376*f7018c21STomi Valkeinen 	}
377*f7018c21STomi Valkeinen 
378*f7018c21STomi Valkeinen 	switch (info->var.bits_per_pixel) {
379*f7018c21STomi Valkeinen 	case 8:
380*f7018c21STomi Valkeinen 		fg = image->fg_color;
381*f7018c21STomi Valkeinen 		bg = image->bg_color;
382*f7018c21STomi Valkeinen 		break;
383*f7018c21STomi Valkeinen 	case 16:
384*f7018c21STomi Valkeinen 	case 24:
385*f7018c21STomi Valkeinen 		fg = ((u32 *)(info->pseudo_palette))[image->fg_color];
386*f7018c21STomi Valkeinen 		bg = ((u32 *)(info->pseudo_palette))[image->bg_color];
387*f7018c21STomi Valkeinen 		break;
388*f7018c21STomi Valkeinen 	}
389*f7018c21STomi Valkeinen 
390*f7018c21STomi Valkeinen 	dst = info->fix.smem_start + (image->dy * info->fix.line_length) +
391*f7018c21STomi Valkeinen 		(image->dx * par->depth);
392*f7018c21STomi Valkeinen 
393*f7018c21STomi Valkeinen 	size = (image->width+7)/8 + 1;
394*f7018c21STomi Valkeinen 	size &= ~1;
395*f7018c21STomi Valkeinen 	size *= image->height;
396*f7018c21STomi Valkeinen 	size += 7;
397*f7018c21STomi Valkeinen 	size &= ~7;
398*f7018c21STomi Valkeinen 	mono_src_copy_imm_blit(image->width * par->depth,
399*f7018c21STomi Valkeinen 			       image->height, info->fix.line_length,
400*f7018c21STomi Valkeinen 			       size/4, par->blit_bpp,
401*f7018c21STomi Valkeinen 			       PAT_COPY_ROP, dst, (u32 *) image->data,
402*f7018c21STomi Valkeinen 			       bg, fg, info);
403*f7018c21STomi Valkeinen }
404*f7018c21STomi Valkeinen 
i810fb_sync(struct fb_info * info)405*f7018c21STomi Valkeinen int i810fb_sync(struct fb_info *info)
406*f7018c21STomi Valkeinen {
407*f7018c21STomi Valkeinen 	struct i810fb_par *par = info->par;
408*f7018c21STomi Valkeinen 
409*f7018c21STomi Valkeinen 	if (!info->var.accel_flags || par->dev_flags & LOCKUP)
410*f7018c21STomi Valkeinen 		return 0;
411*f7018c21STomi Valkeinen 
412*f7018c21STomi Valkeinen 	return wait_for_engine_idle(info);
413*f7018c21STomi Valkeinen }
414*f7018c21STomi Valkeinen 
i810fb_load_front(u32 offset,struct fb_info * info)415*f7018c21STomi Valkeinen void i810fb_load_front(u32 offset, struct fb_info *info)
416*f7018c21STomi Valkeinen {
417*f7018c21STomi Valkeinen 	struct i810fb_par *par = info->par;
418*f7018c21STomi Valkeinen 	u8 __iomem *mmio = par->mmio_start_virtual;
419*f7018c21STomi Valkeinen 
420*f7018c21STomi Valkeinen 	if (!info->var.accel_flags || par->dev_flags & LOCKUP)
421*f7018c21STomi Valkeinen 		i810_writel(DPLYBASE, mmio, par->fb.physical + offset);
422*f7018c21STomi Valkeinen 	else
423*f7018c21STomi Valkeinen 		load_front(offset, info);
424*f7018c21STomi Valkeinen }
425*f7018c21STomi Valkeinen 
426*f7018c21STomi Valkeinen /**
427*f7018c21STomi Valkeinen  * i810fb_init_ringbuffer - initialize the ringbuffer
428*f7018c21STomi Valkeinen  * @par: pointer to i810fb_par structure
429*f7018c21STomi Valkeinen  *
430*f7018c21STomi Valkeinen  * DESCRIPTION:
431*f7018c21STomi Valkeinen  * Initializes the ringbuffer by telling the device the
432*f7018c21STomi Valkeinen  * size and location of the ringbuffer.  It also sets
433*f7018c21STomi Valkeinen  * the head and tail pointers = 0
434*f7018c21STomi Valkeinen  */
i810fb_init_ringbuffer(struct fb_info * info)435*f7018c21STomi Valkeinen void i810fb_init_ringbuffer(struct fb_info *info)
436*f7018c21STomi Valkeinen {
437*f7018c21STomi Valkeinen 	struct i810fb_par *par = info->par;
438*f7018c21STomi Valkeinen 	u32 tmp1, tmp2;
439*f7018c21STomi Valkeinen 	u8 __iomem *mmio = par->mmio_start_virtual;
440*f7018c21STomi Valkeinen 
441*f7018c21STomi Valkeinen 	wait_for_engine_idle(info);
442*f7018c21STomi Valkeinen 	i810fb_iring_enable(par, OFF);
443*f7018c21STomi Valkeinen 	i810_writel(IRING, mmio, 0);
444*f7018c21STomi Valkeinen 	i810_writel(IRING + 4, mmio, 0);
445*f7018c21STomi Valkeinen 	par->cur_tail = 0;
446*f7018c21STomi Valkeinen 
447*f7018c21STomi Valkeinen 	tmp2 = i810_readl(IRING + 8, mmio) & ~RBUFFER_START_MASK;
448*f7018c21STomi Valkeinen 	tmp1 = par->iring.physical;
449*f7018c21STomi Valkeinen 	i810_writel(IRING + 8, mmio, tmp2 | tmp1);
450*f7018c21STomi Valkeinen 
451*f7018c21STomi Valkeinen 	tmp1 = i810_readl(IRING + 12, mmio);
452*f7018c21STomi Valkeinen 	tmp1 &= ~RBUFFER_SIZE_MASK;
453*f7018c21STomi Valkeinen 	tmp2 = (par->iring.size - I810_PAGESIZE) & RBUFFER_SIZE_MASK;
454*f7018c21STomi Valkeinen 	i810_writel(IRING + 12, mmio, tmp1 | tmp2);
455*f7018c21STomi Valkeinen 	i810fb_iring_enable(par, ON);
456*f7018c21STomi Valkeinen }
457