162306a36Sopenharmony_ci/*-*- linux-c -*-
262306a36Sopenharmony_ci *  linux/drivers/video/i810_accel.c -- Hardware Acceleration
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
562306a36Sopenharmony_ci *      All Rights Reserved
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *  This file is subject to the terms and conditions of the GNU General Public
862306a36Sopenharmony_ci *  License. See the file COPYING in the main directory of this archive for
962306a36Sopenharmony_ci *  more details.
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci#include <linux/kernel.h>
1262306a36Sopenharmony_ci#include <linux/string.h>
1362306a36Sopenharmony_ci#include <linux/fb.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include "i810_regs.h"
1662306a36Sopenharmony_ci#include "i810.h"
1762306a36Sopenharmony_ci#include "i810_main.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic u32 i810fb_rop[] = {
2062306a36Sopenharmony_ci	COLOR_COPY_ROP, /* ROP_COPY */
2162306a36Sopenharmony_ci	XOR_ROP         /* ROP_XOR  */
2262306a36Sopenharmony_ci};
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/* Macros */
2562306a36Sopenharmony_ci#define PUT_RING(n) {                                        \
2662306a36Sopenharmony_ci	i810_writel(par->cur_tail, par->iring.virtual, n);   \
2762306a36Sopenharmony_ci        par->cur_tail += 4;                                  \
2862306a36Sopenharmony_ci        par->cur_tail &= RING_SIZE_MASK;                     \
2962306a36Sopenharmony_ci}
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ciextern void flush_cache(void);
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/************************************************************/
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/* BLT Engine Routines */
3662306a36Sopenharmony_cistatic inline void i810_report_error(u8 __iomem *mmio)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	printk("IIR     : 0x%04x\n"
3962306a36Sopenharmony_ci	       "EIR     : 0x%04x\n"
4062306a36Sopenharmony_ci	       "PGTBL_ER: 0x%04x\n"
4162306a36Sopenharmony_ci	       "IPEIR   : 0x%04x\n"
4262306a36Sopenharmony_ci	       "IPEHR   : 0x%04x\n",
4362306a36Sopenharmony_ci	       i810_readw(IIR, mmio),
4462306a36Sopenharmony_ci	       i810_readb(EIR, mmio),
4562306a36Sopenharmony_ci	       i810_readl(PGTBL_ER, mmio),
4662306a36Sopenharmony_ci	       i810_readl(IPEIR, mmio),
4762306a36Sopenharmony_ci	       i810_readl(IPEHR, mmio));
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci/**
5162306a36Sopenharmony_ci * wait_for_space - check ring buffer free space
5262306a36Sopenharmony_ci * @space: amount of ringbuffer space needed in bytes
5362306a36Sopenharmony_ci * @par: pointer to i810fb_par structure
5462306a36Sopenharmony_ci *
5562306a36Sopenharmony_ci * DESCRIPTION:
5662306a36Sopenharmony_ci * The function waits until a free space from the ringbuffer
5762306a36Sopenharmony_ci * is available
5862306a36Sopenharmony_ci */
5962306a36Sopenharmony_cistatic inline int wait_for_space(struct fb_info *info, u32 space)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	struct i810fb_par *par = info->par;
6262306a36Sopenharmony_ci	u32 head, count = WAIT_COUNT, tail;
6362306a36Sopenharmony_ci	u8 __iomem *mmio = par->mmio_start_virtual;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	tail = par->cur_tail;
6662306a36Sopenharmony_ci	while (count--) {
6762306a36Sopenharmony_ci		head = i810_readl(IRING + 4, mmio) & RBUFFER_HEAD_MASK;
6862306a36Sopenharmony_ci		if ((tail == head) ||
6962306a36Sopenharmony_ci		    (tail > head &&
7062306a36Sopenharmony_ci		     (par->iring.size - tail + head) >= space) ||
7162306a36Sopenharmony_ci		    (tail < head && (head - tail) >= space)) {
7262306a36Sopenharmony_ci			return 0;
7362306a36Sopenharmony_ci		}
7462306a36Sopenharmony_ci	}
7562306a36Sopenharmony_ci	printk("ringbuffer lockup!!!\n");
7662306a36Sopenharmony_ci	i810_report_error(mmio);
7762306a36Sopenharmony_ci	par->dev_flags |= LOCKUP;
7862306a36Sopenharmony_ci	info->pixmap.scan_align = 1;
7962306a36Sopenharmony_ci	return 1;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci/**
8362306a36Sopenharmony_ci * wait_for_engine_idle - waits for all hardware engines to finish
8462306a36Sopenharmony_ci * @par: pointer to i810fb_par structure
8562306a36Sopenharmony_ci *
8662306a36Sopenharmony_ci * DESCRIPTION:
8762306a36Sopenharmony_ci * This waits for lring(0), iring(1), and batch(3), etc to finish and
8862306a36Sopenharmony_ci * waits until ringbuffer is empty.
8962306a36Sopenharmony_ci */
9062306a36Sopenharmony_cistatic inline int wait_for_engine_idle(struct fb_info *info)
9162306a36Sopenharmony_ci{
9262306a36Sopenharmony_ci	struct i810fb_par *par = info->par;
9362306a36Sopenharmony_ci	u8 __iomem *mmio = par->mmio_start_virtual;
9462306a36Sopenharmony_ci	int count = WAIT_COUNT;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	if (wait_for_space(info, par->iring.size)) /* flush */
9762306a36Sopenharmony_ci		return 1;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	while((i810_readw(INSTDONE, mmio) & 0x7B) != 0x7B && --count);
10062306a36Sopenharmony_ci	if (count) return 0;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	printk("accel engine lockup!!!\n");
10362306a36Sopenharmony_ci	printk("INSTDONE: 0x%04x\n", i810_readl(INSTDONE, mmio));
10462306a36Sopenharmony_ci	i810_report_error(mmio);
10562306a36Sopenharmony_ci	par->dev_flags |= LOCKUP;
10662306a36Sopenharmony_ci	info->pixmap.scan_align = 1;
10762306a36Sopenharmony_ci	return 1;
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci/* begin_iring - prepares the ringbuffer
11162306a36Sopenharmony_ci * @space: length of sequence in dwords
11262306a36Sopenharmony_ci * @par: pointer to i810fb_par structure
11362306a36Sopenharmony_ci *
11462306a36Sopenharmony_ci * DESCRIPTION:
11562306a36Sopenharmony_ci * Checks/waits for sufficient space in ringbuffer of size
11662306a36Sopenharmony_ci * space.  Returns the tail of the buffer
11762306a36Sopenharmony_ci */
11862306a36Sopenharmony_cistatic inline u32 begin_iring(struct fb_info *info, u32 space)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	struct i810fb_par *par = info->par;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	if (par->dev_flags & ALWAYS_SYNC)
12362306a36Sopenharmony_ci		wait_for_engine_idle(info);
12462306a36Sopenharmony_ci	return wait_for_space(info, space);
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci/**
12862306a36Sopenharmony_ci * end_iring - advances the buffer
12962306a36Sopenharmony_ci * @par: pointer to i810fb_par structure
13062306a36Sopenharmony_ci *
13162306a36Sopenharmony_ci * DESCRIPTION:
13262306a36Sopenharmony_ci * This advances the tail of the ringbuffer, effectively
13362306a36Sopenharmony_ci * beginning the execution of the graphics instruction sequence.
13462306a36Sopenharmony_ci */
13562306a36Sopenharmony_cistatic inline void end_iring(struct i810fb_par *par)
13662306a36Sopenharmony_ci{
13762306a36Sopenharmony_ci	u8 __iomem *mmio = par->mmio_start_virtual;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	i810_writel(IRING, mmio, par->cur_tail);
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci/**
14362306a36Sopenharmony_ci * source_copy_blit - BLIT transfer operation
14462306a36Sopenharmony_ci * @dwidth: width of rectangular graphics data
14562306a36Sopenharmony_ci * @dheight: height of rectangular graphics data
14662306a36Sopenharmony_ci * @dpitch: bytes per line of destination buffer
14762306a36Sopenharmony_ci * @xdir: direction of copy (left to right or right to left)
14862306a36Sopenharmony_ci * @src: address of first pixel to read from
14962306a36Sopenharmony_ci * @dest: address of first pixel to write to
15062306a36Sopenharmony_ci * @from: source address
15162306a36Sopenharmony_ci * @where: destination address
15262306a36Sopenharmony_ci * @rop: raster operation
15362306a36Sopenharmony_ci * @blit_bpp: pixel format which can be different from the
15462306a36Sopenharmony_ci *            framebuffer's pixelformat
15562306a36Sopenharmony_ci * @par: pointer to i810fb_par structure
15662306a36Sopenharmony_ci *
15762306a36Sopenharmony_ci * DESCRIPTION:
15862306a36Sopenharmony_ci * This is a BLIT operation typically used when doing
15962306a36Sopenharmony_ci * a 'Copy and Paste'
16062306a36Sopenharmony_ci */
16162306a36Sopenharmony_cistatic inline void source_copy_blit(int dwidth, int dheight, int dpitch,
16262306a36Sopenharmony_ci				    int xdir, int src, int dest, int rop,
16362306a36Sopenharmony_ci				    int blit_bpp, struct fb_info *info)
16462306a36Sopenharmony_ci{
16562306a36Sopenharmony_ci	struct i810fb_par *par = info->par;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	if (begin_iring(info, 24 + IRING_PAD)) return;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	PUT_RING(BLIT | SOURCE_COPY_BLIT | 4);
17062306a36Sopenharmony_ci	PUT_RING(xdir | rop << 16 | dpitch | DYN_COLOR_EN | blit_bpp);
17162306a36Sopenharmony_ci	PUT_RING(dheight << 16 | dwidth);
17262306a36Sopenharmony_ci	PUT_RING(dest);
17362306a36Sopenharmony_ci	PUT_RING(dpitch);
17462306a36Sopenharmony_ci	PUT_RING(src);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	end_iring(par);
17762306a36Sopenharmony_ci}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci/**
18062306a36Sopenharmony_ci * color_blit - solid color BLIT operation
18162306a36Sopenharmony_ci * @width: width of destination
18262306a36Sopenharmony_ci * @height: height of destination
18362306a36Sopenharmony_ci * @pitch: pixels per line of the buffer
18462306a36Sopenharmony_ci * @dest: address of first pixel to write to
18562306a36Sopenharmony_ci * @where: destination
18662306a36Sopenharmony_ci * @rop: raster operation
18762306a36Sopenharmony_ci * @what: color to transfer
18862306a36Sopenharmony_ci * @blit_bpp: pixel format which can be different from the
18962306a36Sopenharmony_ci *            framebuffer's pixelformat
19062306a36Sopenharmony_ci * @par: pointer to i810fb_par structure
19162306a36Sopenharmony_ci *
19262306a36Sopenharmony_ci * DESCRIPTION:
19362306a36Sopenharmony_ci * A BLIT operation which can be used for  color fill/rectangular fill
19462306a36Sopenharmony_ci */
19562306a36Sopenharmony_cistatic inline void color_blit(int width, int height, int pitch,  int dest,
19662306a36Sopenharmony_ci			      int rop, int what, int blit_bpp,
19762306a36Sopenharmony_ci			      struct fb_info *info)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	struct i810fb_par *par = info->par;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	if (begin_iring(info, 24 + IRING_PAD)) return;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	PUT_RING(BLIT | COLOR_BLT | 3);
20462306a36Sopenharmony_ci	PUT_RING(rop << 16 | pitch | SOLIDPATTERN | DYN_COLOR_EN | blit_bpp);
20562306a36Sopenharmony_ci	PUT_RING(height << 16 | width);
20662306a36Sopenharmony_ci	PUT_RING(dest);
20762306a36Sopenharmony_ci	PUT_RING(what);
20862306a36Sopenharmony_ci	PUT_RING(NOP);
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	end_iring(par);
21162306a36Sopenharmony_ci}
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci/**
21462306a36Sopenharmony_ci * mono_src_copy_imm_blit - color expand from system memory to framebuffer
21562306a36Sopenharmony_ci * @dwidth: width of destination
21662306a36Sopenharmony_ci * @dheight: height of destination
21762306a36Sopenharmony_ci * @dpitch: pixels per line of the buffer
21862306a36Sopenharmony_ci * @dsize: size of bitmap in double words
21962306a36Sopenharmony_ci * @dest: address of first byte of pixel;
22062306a36Sopenharmony_ci * @rop: raster operation
22162306a36Sopenharmony_ci * @blit_bpp: pixelformat to use which can be different from the
22262306a36Sopenharmony_ci *            framebuffer's pixelformat
22362306a36Sopenharmony_ci * @src: address of image data
22462306a36Sopenharmony_ci * @bg: backgound color
22562306a36Sopenharmony_ci * @fg: forground color
22662306a36Sopenharmony_ci * @par: pointer to i810fb_par structure
22762306a36Sopenharmony_ci *
22862306a36Sopenharmony_ci * DESCRIPTION:
22962306a36Sopenharmony_ci * A color expand operation where the  source data is placed in the
23062306a36Sopenharmony_ci * ringbuffer itself. Useful for drawing text.
23162306a36Sopenharmony_ci *
23262306a36Sopenharmony_ci * REQUIREMENT:
23362306a36Sopenharmony_ci * The end of a scanline must be padded to the next word.
23462306a36Sopenharmony_ci */
23562306a36Sopenharmony_cistatic inline void mono_src_copy_imm_blit(int dwidth, int dheight, int dpitch,
23662306a36Sopenharmony_ci					  int dsize, int blit_bpp, int rop,
23762306a36Sopenharmony_ci					  int dest, const u32 *src, int bg,
23862306a36Sopenharmony_ci					  int fg, struct fb_info *info)
23962306a36Sopenharmony_ci{
24062306a36Sopenharmony_ci	struct i810fb_par *par = info->par;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	if (begin_iring(info, 24 + (dsize << 2) + IRING_PAD)) return;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	PUT_RING(BLIT | MONO_SOURCE_COPY_IMMEDIATE | (4 + dsize));
24562306a36Sopenharmony_ci	PUT_RING(DYN_COLOR_EN | blit_bpp | rop << 16 | dpitch);
24662306a36Sopenharmony_ci	PUT_RING(dheight << 16 | dwidth);
24762306a36Sopenharmony_ci	PUT_RING(dest);
24862306a36Sopenharmony_ci	PUT_RING(bg);
24962306a36Sopenharmony_ci	PUT_RING(fg);
25062306a36Sopenharmony_ci	while (dsize--)
25162306a36Sopenharmony_ci		PUT_RING(*src++);
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	end_iring(par);
25462306a36Sopenharmony_ci}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cistatic inline void load_front(int offset, struct fb_info *info)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	struct i810fb_par *par = info->par;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	if (begin_iring(info, 8 + IRING_PAD)) return;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	PUT_RING(PARSER | FLUSH);
26362306a36Sopenharmony_ci	PUT_RING(NOP);
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	end_iring(par);
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	if (begin_iring(info, 8 + IRING_PAD)) return;
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	PUT_RING(PARSER | FRONT_BUFFER | ((par->pitch >> 3) << 8));
27062306a36Sopenharmony_ci	PUT_RING((par->fb.offset << 12) + offset);
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	end_iring(par);
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci/**
27662306a36Sopenharmony_ci * i810fb_iring_enable - enables/disables the ringbuffer
27762306a36Sopenharmony_ci * @mode: enable or disable
27862306a36Sopenharmony_ci * @par: pointer to i810fb_par structure
27962306a36Sopenharmony_ci *
28062306a36Sopenharmony_ci * DESCRIPTION:
28162306a36Sopenharmony_ci * Enables or disables the ringbuffer, effectively enabling or
28262306a36Sopenharmony_ci * disabling the instruction/acceleration engine.
28362306a36Sopenharmony_ci */
28462306a36Sopenharmony_cistatic inline void i810fb_iring_enable(struct i810fb_par *par, u32 mode)
28562306a36Sopenharmony_ci{
28662306a36Sopenharmony_ci	u32 tmp;
28762306a36Sopenharmony_ci	u8 __iomem *mmio = par->mmio_start_virtual;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	tmp = i810_readl(IRING + 12, mmio);
29062306a36Sopenharmony_ci	if (mode == OFF)
29162306a36Sopenharmony_ci		tmp &= ~1;
29262306a36Sopenharmony_ci	else
29362306a36Sopenharmony_ci		tmp |= 1;
29462306a36Sopenharmony_ci	flush_cache();
29562306a36Sopenharmony_ci	i810_writel(IRING + 12, mmio, tmp);
29662306a36Sopenharmony_ci}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_civoid i810fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
29962306a36Sopenharmony_ci{
30062306a36Sopenharmony_ci	struct i810fb_par *par = info->par;
30162306a36Sopenharmony_ci	u32 dx, dy, width, height, dest, rop = 0, color = 0;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
30462306a36Sopenharmony_ci	    par->depth == 4) {
30562306a36Sopenharmony_ci		cfb_fillrect(info, rect);
30662306a36Sopenharmony_ci		return;
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	if (par->depth == 1)
31062306a36Sopenharmony_ci		color = rect->color;
31162306a36Sopenharmony_ci	else
31262306a36Sopenharmony_ci		color = ((u32 *) (info->pseudo_palette))[rect->color];
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	rop = i810fb_rop[rect->rop];
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	dx = rect->dx * par->depth;
31762306a36Sopenharmony_ci	width = rect->width * par->depth;
31862306a36Sopenharmony_ci	dy = rect->dy;
31962306a36Sopenharmony_ci	height = rect->height;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	dest = info->fix.smem_start + (dy * info->fix.line_length) + dx;
32262306a36Sopenharmony_ci	color_blit(width, height, info->fix.line_length, dest, rop, color,
32362306a36Sopenharmony_ci		   par->blit_bpp, info);
32462306a36Sopenharmony_ci}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_civoid i810fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
32762306a36Sopenharmony_ci{
32862306a36Sopenharmony_ci	struct i810fb_par *par = info->par;
32962306a36Sopenharmony_ci	u32 sx, sy, dx, dy, pitch, width, height, src, dest, xdir;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
33262306a36Sopenharmony_ci	    par->depth == 4) {
33362306a36Sopenharmony_ci		cfb_copyarea(info, region);
33462306a36Sopenharmony_ci		return;
33562306a36Sopenharmony_ci	}
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	dx = region->dx * par->depth;
33862306a36Sopenharmony_ci	sx = region->sx * par->depth;
33962306a36Sopenharmony_ci	width = region->width * par->depth;
34062306a36Sopenharmony_ci	sy = region->sy;
34162306a36Sopenharmony_ci	dy = region->dy;
34262306a36Sopenharmony_ci	height = region->height;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	if (dx <= sx) {
34562306a36Sopenharmony_ci		xdir = INCREMENT;
34662306a36Sopenharmony_ci	}
34762306a36Sopenharmony_ci	else {
34862306a36Sopenharmony_ci		xdir = DECREMENT;
34962306a36Sopenharmony_ci		sx += width - 1;
35062306a36Sopenharmony_ci		dx += width - 1;
35162306a36Sopenharmony_ci	}
35262306a36Sopenharmony_ci	if (dy <= sy) {
35362306a36Sopenharmony_ci		pitch = info->fix.line_length;
35462306a36Sopenharmony_ci	}
35562306a36Sopenharmony_ci	else {
35662306a36Sopenharmony_ci		pitch = (-(info->fix.line_length)) & 0xFFFF;
35762306a36Sopenharmony_ci		sy += height - 1;
35862306a36Sopenharmony_ci		dy += height - 1;
35962306a36Sopenharmony_ci	}
36062306a36Sopenharmony_ci	src = info->fix.smem_start + (sy * info->fix.line_length) + sx;
36162306a36Sopenharmony_ci	dest = info->fix.smem_start + (dy * info->fix.line_length) + dx;
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	source_copy_blit(width, height, pitch, xdir, src, dest,
36462306a36Sopenharmony_ci			 PAT_COPY_ROP, par->blit_bpp, info);
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_civoid i810fb_imageblit(struct fb_info *info, const struct fb_image *image)
36862306a36Sopenharmony_ci{
36962306a36Sopenharmony_ci	struct i810fb_par *par = info->par;
37062306a36Sopenharmony_ci	u32 fg = 0, bg = 0, size, dst;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
37362306a36Sopenharmony_ci	    par->depth == 4 || image->depth != 1) {
37462306a36Sopenharmony_ci		cfb_imageblit(info, image);
37562306a36Sopenharmony_ci		return;
37662306a36Sopenharmony_ci	}
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	switch (info->var.bits_per_pixel) {
37962306a36Sopenharmony_ci	case 8:
38062306a36Sopenharmony_ci		fg = image->fg_color;
38162306a36Sopenharmony_ci		bg = image->bg_color;
38262306a36Sopenharmony_ci		break;
38362306a36Sopenharmony_ci	case 16:
38462306a36Sopenharmony_ci	case 24:
38562306a36Sopenharmony_ci		fg = ((u32 *)(info->pseudo_palette))[image->fg_color];
38662306a36Sopenharmony_ci		bg = ((u32 *)(info->pseudo_palette))[image->bg_color];
38762306a36Sopenharmony_ci		break;
38862306a36Sopenharmony_ci	}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	dst = info->fix.smem_start + (image->dy * info->fix.line_length) +
39162306a36Sopenharmony_ci		(image->dx * par->depth);
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	size = (image->width+7)/8 + 1;
39462306a36Sopenharmony_ci	size &= ~1;
39562306a36Sopenharmony_ci	size *= image->height;
39662306a36Sopenharmony_ci	size += 7;
39762306a36Sopenharmony_ci	size &= ~7;
39862306a36Sopenharmony_ci	mono_src_copy_imm_blit(image->width * par->depth,
39962306a36Sopenharmony_ci			       image->height, info->fix.line_length,
40062306a36Sopenharmony_ci			       size/4, par->blit_bpp,
40162306a36Sopenharmony_ci			       PAT_COPY_ROP, dst, (u32 *) image->data,
40262306a36Sopenharmony_ci			       bg, fg, info);
40362306a36Sopenharmony_ci}
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ciint i810fb_sync(struct fb_info *info)
40662306a36Sopenharmony_ci{
40762306a36Sopenharmony_ci	struct i810fb_par *par = info->par;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	if (!info->var.accel_flags || par->dev_flags & LOCKUP)
41062306a36Sopenharmony_ci		return 0;
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	return wait_for_engine_idle(info);
41362306a36Sopenharmony_ci}
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_civoid i810fb_load_front(u32 offset, struct fb_info *info)
41662306a36Sopenharmony_ci{
41762306a36Sopenharmony_ci	struct i810fb_par *par = info->par;
41862306a36Sopenharmony_ci	u8 __iomem *mmio = par->mmio_start_virtual;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	if (!info->var.accel_flags || par->dev_flags & LOCKUP)
42162306a36Sopenharmony_ci		i810_writel(DPLYBASE, mmio, par->fb.physical + offset);
42262306a36Sopenharmony_ci	else
42362306a36Sopenharmony_ci		load_front(offset, info);
42462306a36Sopenharmony_ci}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci/**
42762306a36Sopenharmony_ci * i810fb_init_ringbuffer - initialize the ringbuffer
42862306a36Sopenharmony_ci * @par: pointer to i810fb_par structure
42962306a36Sopenharmony_ci *
43062306a36Sopenharmony_ci * DESCRIPTION:
43162306a36Sopenharmony_ci * Initializes the ringbuffer by telling the device the
43262306a36Sopenharmony_ci * size and location of the ringbuffer.  It also sets
43362306a36Sopenharmony_ci * the head and tail pointers = 0
43462306a36Sopenharmony_ci */
43562306a36Sopenharmony_civoid i810fb_init_ringbuffer(struct fb_info *info)
43662306a36Sopenharmony_ci{
43762306a36Sopenharmony_ci	struct i810fb_par *par = info->par;
43862306a36Sopenharmony_ci	u32 tmp1, tmp2;
43962306a36Sopenharmony_ci	u8 __iomem *mmio = par->mmio_start_virtual;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	wait_for_engine_idle(info);
44262306a36Sopenharmony_ci	i810fb_iring_enable(par, OFF);
44362306a36Sopenharmony_ci	i810_writel(IRING, mmio, 0);
44462306a36Sopenharmony_ci	i810_writel(IRING + 4, mmio, 0);
44562306a36Sopenharmony_ci	par->cur_tail = 0;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	tmp2 = i810_readl(IRING + 8, mmio) & ~RBUFFER_START_MASK;
44862306a36Sopenharmony_ci	tmp1 = par->iring.physical;
44962306a36Sopenharmony_ci	i810_writel(IRING + 8, mmio, tmp2 | tmp1);
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	tmp1 = i810_readl(IRING + 12, mmio);
45262306a36Sopenharmony_ci	tmp1 &= ~RBUFFER_SIZE_MASK;
45362306a36Sopenharmony_ci	tmp2 = (par->iring.size - I810_PAGESIZE) & RBUFFER_SIZE_MASK;
45462306a36Sopenharmony_ci	i810_writel(IRING + 12, mmio, tmp1 | tmp2);
45562306a36Sopenharmony_ci	i810fb_iring_enable(par, ON);
45662306a36Sopenharmony_ci}
457