igs_accel.c revision 2e72e74d
1/* 2 * IGS CyberPro - hardware acceleration. 3 * 4 * Copyright (C) 2009 Michael Lorenz 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * MICHAEL LORENZ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24/* $NetBSD: igs_accel.c,v 1.8 2011/12/14 23:58:54 macallan Exp $ */ 25 26#include <sys/types.h> 27 28/* all driver need this */ 29#include "xf86.h" 30#include "xf86_OSproc.h" 31#include "compiler.h" 32 33#include "igs.h" 34 35/*#define DEBUG*/ 36 37#ifdef DEBUG 38#define ENTER xf86Msg(X_ERROR, "%s\n", __func__) 39#define LEAVE xf86Msg(X_ERROR, "%s done\n", __func__) 40#else 41#define ENTER 42#define LEAVE 43#endif 44 45static inline void IgsWrite1(IgsPtr fPtr, int offset, uint8_t val) 46{ 47 *(fPtr->reg + offset) = val; 48} 49 50 51static inline void IgsWrite2(IgsPtr fPtr, int offset, uint16_t val) 52{ 53 *(volatile uint16_t *)(fPtr->reg + offset) = val; 54} 55 56static inline void IgsWrite4(IgsPtr fPtr, int offset, uint32_t val) 57{ 58 *(volatile uint32_t *)(fPtr->reg + offset) = val; 59} 60 61static inline uint8_t IgsRead1(IgsPtr fPtr, int offset) 62{ 63 return *(fPtr->reg + offset); 64} 65 66static inline uint16_t IgsRead2(IgsPtr fPtr, int offset) 67{ 68 return *(volatile uint16_t *)(fPtr->reg + offset); 69} 70 71static void 72IgsWaitMarker(ScreenPtr pScreen, int Marker) 73{ 74 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 75 IgsPtr fPtr = IGSPTR(pScrn); 76 int bail = 0x0fffffff; 77 78 ENTER; 79 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 80 while ((IgsRead1(fPtr, 81 IGS_COP_CTL_REG) & (IGS_COP_CTL_BUSY | IGS_COP_CTL_HFEMPTZ) != 0) 82 && (bail > 0)) { 83 bail--; 84 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 85 } 86 87 /* reset the coprocessor if we run into a timeout */ 88 if (bail == 0) { 89 xf86Msg(X_ERROR, "%s: timeout\n", __func__); 90 IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 91 } 92 LEAVE; 93} 94 95static void 96IgsWaitReady(IgsPtr fPtr) 97{ 98 int bail = 0x0fffffff; 99 100 ENTER; 101 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 102 while (((IgsRead1(fPtr, 103 IGS_COP_CTL_REG) & (IGS_COP_CTL_BUSY | IGS_COP_CTL_HFEMPTZ)) != 0) 104 && (bail > 0)) { 105 bail--; 106 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 107 } 108 109 /* reset the coprocessor if we run into a timeout */ 110 if (bail == 0) { 111 xf86Msg(X_ERROR, "%s: timeout\n", __func__); 112 IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 113 } 114 LEAVE; 115} 116 117static Bool 118IgsPrepareCopy 119( 120 PixmapPtr pSrcPixmap, 121 PixmapPtr pDstPixmap, 122 int xdir, 123 int ydir, 124 int alu, 125 Pixel planemask 126) 127{ 128 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 129 IgsPtr fPtr = IGSPTR(pScrn); 130 131 ENTER; 132 fPtr->cmd = IGS_COP_OP_PXBLT | IGS_COP_OP_FG_FROM_SRC | 133 IGS_COP_PPM_FIXED_FG; 134 if (xdir < 0) 135 fPtr->cmd |= IGS_COP_OCTANT_X_NEG; 136 if (ydir < 0) 137 fPtr->cmd |= IGS_COP_OCTANT_Y_NEG; 138 139 IgsWaitReady(fPtr); 140 IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 141 fPtr->srcoff = exaGetPixmapOffset(pSrcPixmap) >> fPtr->shift; 142 fPtr->srcpitch = exaGetPixmapPitch(pSrcPixmap) >> fPtr->shift; 143 144 IgsWrite2(fPtr, IGS_COP_SRC_MAP_WIDTH_REG, fPtr->srcpitch - 1); 145 IgsWrite2(fPtr, IGS_COP_DST_MAP_WIDTH_REG, 146 (exaGetPixmapPitch(pDstPixmap) >> fPtr->shift) - 1); 147 IgsWrite1(fPtr, IGS_COP_FG_MIX_REG, alu); 148 IgsWrite4(fPtr, IGS_PLANE_MASK_REG, planemask); 149 LEAVE; 150 return TRUE; 151} 152 153static void 154IgsCopy 155( 156 PixmapPtr pDstPixmap, 157 int srcX, 158 int srcY, 159 int dstX, 160 int dstY, 161 int w, 162 int h 163) 164{ 165 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 166 IgsPtr fPtr = IGSPTR(pScrn); 167 int dstpitch, dstoff; 168 169 if (fPtr->cmd & IGS_COP_OCTANT_X_NEG) { 170 srcX += (w - 1); 171 dstX += (w - 1); 172 } 173 174 if (fPtr->cmd & IGS_COP_OCTANT_Y_NEG) { 175 srcY += (h - 1); 176 dstY += (h - 1); 177 } 178 IgsWaitReady(fPtr); 179 IgsWrite4(fPtr, IGS_COP_SRC_START_REG, fPtr->srcoff + srcX + 180 fPtr->srcpitch * srcY); 181 dstpitch = exaGetPixmapPitch(pDstPixmap) >> fPtr->shift; 182 dstoff = exaGetPixmapOffset(pDstPixmap) >> fPtr->shift; 183 IgsWrite4(fPtr, IGS_COP_DST_START_REG, dstoff + dstX + 184 dstpitch * dstY); 185 IgsWrite2(fPtr, IGS_COP_WIDTH_REG, w - 1); 186 IgsWrite2(fPtr, IGS_COP_HEIGHT_REG, h - 1); 187 IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG, fPtr->cmd & 0xffff); 188 IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG + 2, (fPtr->cmd >> 16) & 0xffff); 189 exaMarkSync(pDstPixmap->drawable.pScreen); 190 LEAVE; 191} 192 193static void 194IgsDoneCopy(PixmapPtr pDstPixmap) 195{ 196 ENTER; 197 LEAVE; 198} 199 200static Bool 201IgsPrepareSolid( 202 PixmapPtr pPixmap, 203 int alu, 204 Pixel planemask, 205 Pixel fg) 206{ 207 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 208 IgsPtr fPtr = IGSPTR(pScrn); 209 210 ENTER; 211 fPtr->cmd = IGS_COP_OP_PXBLT | IGS_COP_PPM_FIXED_FG; 212 213 IgsWaitReady(fPtr); 214 215 IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 216 217 IgsWrite2(fPtr, IGS_COP_DST_MAP_WIDTH_REG, 218 (exaGetPixmapPitch(pPixmap) >> fPtr->shift) - 1); 219 IgsWrite1(fPtr, IGS_COP_FG_MIX_REG, alu); 220 IgsWrite4(fPtr, IGS_PLANE_MASK_REG, planemask); 221 IgsWrite4(fPtr, IGS_COP_FG_REG, fg); 222 LEAVE; 223 return TRUE; 224} 225 226static void 227IgsSolid( 228 PixmapPtr pPixmap, 229 int x1, 230 int y1, 231 int x2, 232 int y2) 233{ 234 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 235 IgsPtr fPtr = IGSPTR(pScrn); 236 int w = x2 - x1, h = y2 - y1, dstoff, dstpitch; 237 238 ENTER; 239 IgsWaitReady(fPtr); 240 dstpitch = exaGetPixmapPitch(pPixmap) >> fPtr->shift; 241 dstoff = exaGetPixmapOffset(pPixmap) >> fPtr->shift; 242 IgsWrite4(fPtr, IGS_COP_DST_START_REG, dstoff + x1 + 243 dstpitch * y1); 244 IgsWrite2(fPtr, IGS_COP_WIDTH_REG, w - 1); 245 IgsWrite2(fPtr, IGS_COP_HEIGHT_REG, h - 1); 246 IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG, fPtr->cmd & 0xffff); 247 IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG + 2, (fPtr->cmd >> 16) & 0xffff); 248 exaMarkSync(pPixmap->drawable.pScreen); 249} 250 251/* 252 * Memcpy-based UTS. 253 */ 254static Bool 255IgsUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 256 char *src, int src_pitch) 257{ 258 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 259 IgsPtr fPtr = IGSPTR(pScrn); 260 char *dst = fPtr->fbmem + exaGetPixmapOffset(pDst); 261 int dst_pitch = exaGetPixmapPitch(pDst); 262 263 int bpp = pDst->drawable.bitsPerPixel; 264 int cpp = (bpp + 7) >> 3; 265 int wBytes = w * cpp; 266 267 ENTER; 268 dst += (x * cpp) + (y * dst_pitch); 269 270 IgsWaitReady(fPtr); 271 272 while (h--) { 273 memcpy(dst, src, wBytes); 274 src += src_pitch; 275 dst += dst_pitch; 276 } 277 LEAVE; 278 return TRUE; 279} 280 281/* 282 * Memcpy-based DFS. 283 */ 284static Bool 285IgsDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 286 char *dst, int dst_pitch) 287{ 288 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 289 IgsPtr fPtr = IGSPTR(pScrn); 290 char *src = fPtr->fbmem + exaGetPixmapOffset(pSrc); 291 int src_pitch = exaGetPixmapPitch(pSrc); 292 293 int bpp = pSrc->drawable.bitsPerPixel; 294 int cpp = (bpp + 7) >> 3; 295 int wBytes = w * cpp; 296 297 ENTER; 298 src += (x * cpp) + (y * src_pitch); 299 300 IgsWaitReady(fPtr); 301 302 while (h--) { 303 memcpy(dst, src, wBytes); 304 src += src_pitch; 305 dst += dst_pitch; 306 } 307 LEAVE; 308 return TRUE; 309} 310 311#ifdef __arm__ 312static Bool 313IgsPrepareAccess(PixmapPtr pPix, int index) 314{ 315 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; 316 IgsPtr fPtr = IGSPTR(pScrn); 317 318 IgsWaitReady(fPtr); 319 return TRUE; 320} 321 322static void 323IgsFinishAccess(PixmapPtr pPix, int index) 324{ 325} 326#endif 327 328Bool 329IgsInitAccel(ScreenPtr pScreen) 330{ 331 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 332 IgsPtr fPtr = IGSPTR(pScrn); 333 ExaDriverPtr pExa; 334 335 pExa = exaDriverAlloc(); 336 if (!pExa) 337 return FALSE; 338 339 fPtr->pExa = pExa; 340 341 pExa->exa_major = EXA_VERSION_MAJOR; 342 pExa->exa_minor = EXA_VERSION_MINOR; 343 344 pExa->memoryBase = fPtr->fbmem; 345 pExa->memorySize = fPtr->fbmem_len; 346 pExa->offScreenBase = fPtr->linebytes * fPtr->info.height; 347 pExa->pixmapOffsetAlign = 4; 348 pExa->pixmapPitchAlign = 4; 349 350 pExa->flags = EXA_OFFSCREEN_PIXMAPS; 351 352 pExa->maxX = 2048; 353 pExa->maxY = 2048; 354 355 pExa->WaitMarker = IgsWaitMarker; 356 pExa->PrepareSolid = IgsPrepareSolid; 357 pExa->Solid = IgsSolid; 358 pExa->DoneSolid = IgsDoneCopy; 359 pExa->PrepareCopy = IgsPrepareCopy; 360 pExa->Copy = IgsCopy; 361 pExa->DoneCopy = IgsDoneCopy; 362 363 switch(fPtr->info.depth) { 364 case 8: 365 fPtr->shift = 0; 366 fPtr->mapfmt = IGS_COP_MAP_8BPP; 367 break; 368 case 16: 369 fPtr->shift = 1; 370 fPtr->mapfmt = IGS_COP_MAP_16BPP; 371 break; 372 case 24: 373 case 32: 374 fPtr->shift = 2; 375 fPtr->mapfmt = IGS_COP_MAP_32BPP; 376 break; 377 default: 378 ErrorF("Unsupported depth: %d\n", fPtr->info.depth); 379 } 380 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 381 382 /* EXA hits more optimized paths when it does not have to fallback 383 * because of missing UTS/DFS, hook memcpy-based UTS/DFS. 384 */ 385 pExa->UploadToScreen = IgsUploadToScreen; 386 pExa->DownloadFromScreen = IgsDownloadFromScreen; 387#ifdef __arm__ 388 pExa->PrepareAccess = IgsPrepareAccess; 389 pExa->FinishAccess = IgsFinishAccess; 390#endif 391 return exaDriverInit(pScreen, pExa); 392} 393