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