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