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