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