igs_accel.c revision ca0efe20
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.10 2016/08/18 09:32:26 mrg Exp $ */ 25 26#include <sys/types.h> 27 28#include "igs.h" 29 30/*#define DEBUG*/ 31 32#ifdef DEBUG 33#define ENTER xf86Msg(X_ERROR, "%s\n", __func__) 34#define LEAVE xf86Msg(X_ERROR, "%s done\n", __func__) 35#else 36#define ENTER 37#define LEAVE 38#endif 39 40static inline void IgsWrite1(IgsPtr fPtr, int offset, uint8_t val) 41{ 42 *(fPtr->reg + offset) = val; 43} 44 45 46static inline void IgsWrite2(IgsPtr fPtr, int offset, uint16_t val) 47{ 48 *(volatile uint16_t *)(fPtr->reg + offset) = val; 49} 50 51static inline void IgsWrite4(IgsPtr fPtr, int offset, uint32_t val) 52{ 53 *(volatile uint32_t *)(fPtr->reg + offset) = val; 54} 55 56static inline uint8_t IgsRead1(IgsPtr fPtr, int offset) 57{ 58 return *(fPtr->reg + offset); 59} 60 61static inline uint16_t IgsRead2(IgsPtr fPtr, int offset) 62{ 63 return *(volatile uint16_t *)(fPtr->reg + offset); 64} 65 66static void 67IgsWaitMarker(ScreenPtr pScreen, int Marker) 68{ 69 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 70 IgsPtr fPtr = IGSPTR(pScrn); 71 int bail = 0x0fffffff; 72 73 ENTER; 74 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 75 while (((IgsRead1(fPtr, 76 IGS_COP_CTL_REG) & (IGS_COP_CTL_BUSY | IGS_COP_CTL_HFEMPTZ)) != 0) 77 && (bail > 0)) { 78 bail--; 79 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 80 } 81 82 /* reset the coprocessor if we run into a timeout */ 83 if (bail == 0) { 84 xf86Msg(X_ERROR, "%s: timeout\n", __func__); 85 IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 86 } 87 LEAVE; 88} 89 90static void 91IgsWaitReady(IgsPtr fPtr) 92{ 93 int bail = 0x0fffffff; 94 95 ENTER; 96 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 97 while (((IgsRead1(fPtr, 98 IGS_COP_CTL_REG) & (IGS_COP_CTL_BUSY | IGS_COP_CTL_HFEMPTZ)) != 0) 99 && (bail > 0)) { 100 bail--; 101 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 102 } 103 104 /* reset the coprocessor if we run into a timeout */ 105 if (bail == 0) { 106 xf86Msg(X_ERROR, "%s: timeout\n", __func__); 107 IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 108 } 109 LEAVE; 110} 111 112static Bool 113IgsPrepareCopy 114( 115 PixmapPtr pSrcPixmap, 116 PixmapPtr pDstPixmap, 117 int xdir, 118 int ydir, 119 int alu, 120 Pixel planemask 121) 122{ 123 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 124 IgsPtr fPtr = IGSPTR(pScrn); 125 126 ENTER; 127 fPtr->cmd = IGS_COP_OP_PXBLT | IGS_COP_OP_FG_FROM_SRC | 128 IGS_COP_PPM_FIXED_FG; 129 if (xdir < 0) 130 fPtr->cmd |= IGS_COP_OCTANT_X_NEG; 131 if (ydir < 0) 132 fPtr->cmd |= IGS_COP_OCTANT_Y_NEG; 133 134 IgsWaitReady(fPtr); 135 IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 136 fPtr->srcoff = exaGetPixmapOffset(pSrcPixmap) >> fPtr->shift; 137 fPtr->srcpitch = exaGetPixmapPitch(pSrcPixmap) >> fPtr->shift; 138 139 IgsWrite2(fPtr, IGS_COP_SRC_MAP_WIDTH_REG, fPtr->srcpitch - 1); 140 IgsWrite2(fPtr, IGS_COP_DST_MAP_WIDTH_REG, 141 (exaGetPixmapPitch(pDstPixmap) >> fPtr->shift) - 1); 142 IgsWrite1(fPtr, IGS_COP_FG_MIX_REG, alu); 143 IgsWrite4(fPtr, IGS_PLANE_MASK_REG, planemask); 144 LEAVE; 145 return TRUE; 146} 147 148static void 149IgsCopy 150( 151 PixmapPtr pDstPixmap, 152 int srcX, 153 int srcY, 154 int dstX, 155 int dstY, 156 int w, 157 int h 158) 159{ 160 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 161 IgsPtr fPtr = IGSPTR(pScrn); 162 int dstpitch, dstoff; 163 164 if (fPtr->cmd & IGS_COP_OCTANT_X_NEG) { 165 srcX += (w - 1); 166 dstX += (w - 1); 167 } 168 169 if (fPtr->cmd & IGS_COP_OCTANT_Y_NEG) { 170 srcY += (h - 1); 171 dstY += (h - 1); 172 } 173 IgsWaitReady(fPtr); 174 IgsWrite4(fPtr, IGS_COP_SRC_START_REG, fPtr->srcoff + srcX + 175 fPtr->srcpitch * srcY); 176 dstpitch = exaGetPixmapPitch(pDstPixmap) >> fPtr->shift; 177 dstoff = exaGetPixmapOffset(pDstPixmap) >> fPtr->shift; 178 IgsWrite4(fPtr, IGS_COP_DST_START_REG, dstoff + dstX + 179 dstpitch * dstY); 180 IgsWrite2(fPtr, IGS_COP_WIDTH_REG, w - 1); 181 IgsWrite2(fPtr, IGS_COP_HEIGHT_REG, h - 1); 182 IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG, fPtr->cmd & 0xffff); 183 IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG + 2, (fPtr->cmd >> 16) & 0xffff); 184 exaMarkSync(pDstPixmap->drawable.pScreen); 185 LEAVE; 186} 187 188static void 189IgsDoneCopy(PixmapPtr pDstPixmap) 190{ 191 ENTER; 192 LEAVE; 193} 194 195static Bool 196IgsPrepareSolid( 197 PixmapPtr pPixmap, 198 int alu, 199 Pixel planemask, 200 Pixel fg) 201{ 202 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 203 IgsPtr fPtr = IGSPTR(pScrn); 204 205 ENTER; 206 fPtr->cmd = IGS_COP_OP_PXBLT | IGS_COP_PPM_FIXED_FG; 207 208 IgsWaitReady(fPtr); 209 210 IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 211 212 IgsWrite2(fPtr, IGS_COP_DST_MAP_WIDTH_REG, 213 (exaGetPixmapPitch(pPixmap) >> fPtr->shift) - 1); 214 IgsWrite1(fPtr, IGS_COP_FG_MIX_REG, alu); 215 IgsWrite4(fPtr, IGS_PLANE_MASK_REG, planemask); 216 IgsWrite4(fPtr, IGS_COP_FG_REG, fg); 217 LEAVE; 218 return TRUE; 219} 220 221static void 222IgsSolid( 223 PixmapPtr pPixmap, 224 int x1, 225 int y1, 226 int x2, 227 int y2) 228{ 229 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 230 IgsPtr fPtr = IGSPTR(pScrn); 231 int w = x2 - x1, h = y2 - y1, dstoff, dstpitch; 232 233 ENTER; 234 IgsWaitReady(fPtr); 235 dstpitch = exaGetPixmapPitch(pPixmap) >> fPtr->shift; 236 dstoff = exaGetPixmapOffset(pPixmap) >> fPtr->shift; 237 IgsWrite4(fPtr, IGS_COP_DST_START_REG, dstoff + x1 + 238 dstpitch * y1); 239 IgsWrite2(fPtr, IGS_COP_WIDTH_REG, w - 1); 240 IgsWrite2(fPtr, IGS_COP_HEIGHT_REG, h - 1); 241 IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG, fPtr->cmd & 0xffff); 242 IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG + 2, (fPtr->cmd >> 16) & 0xffff); 243 exaMarkSync(pPixmap->drawable.pScreen); 244} 245 246/* 247 * Memcpy-based UTS. 248 */ 249static Bool 250IgsUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 251 char *src, int src_pitch) 252{ 253 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 254 IgsPtr fPtr = IGSPTR(pScrn); 255 unsigned char *dst = fPtr->fbmem + exaGetPixmapOffset(pDst); 256 int dst_pitch = exaGetPixmapPitch(pDst); 257 258 int bpp = pDst->drawable.bitsPerPixel; 259 int cpp = (bpp + 7) >> 3; 260 int wBytes = w * cpp; 261 262 ENTER; 263 dst += (x * cpp) + (y * dst_pitch); 264 265 IgsWaitReady(fPtr); 266 267 while (h--) { 268 memcpy(dst, src, wBytes); 269 src += src_pitch; 270 dst += dst_pitch; 271 } 272 LEAVE; 273 return TRUE; 274} 275 276/* 277 * Memcpy-based DFS. 278 */ 279static Bool 280IgsDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 281 char *dst, int dst_pitch) 282{ 283 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 284 IgsPtr fPtr = IGSPTR(pScrn); 285 unsigned char *src = fPtr->fbmem + exaGetPixmapOffset(pSrc); 286 int src_pitch = exaGetPixmapPitch(pSrc); 287 288 int bpp = pSrc->drawable.bitsPerPixel; 289 int cpp = (bpp + 7) >> 3; 290 int wBytes = w * cpp; 291 292 ENTER; 293 src += (x * cpp) + (y * src_pitch); 294 295 IgsWaitReady(fPtr); 296 297 while (h--) { 298 memcpy(dst, src, wBytes); 299 src += src_pitch; 300 dst += dst_pitch; 301 } 302 LEAVE; 303 return TRUE; 304} 305 306#ifdef __arm__ 307static Bool 308IgsPrepareAccess(PixmapPtr pPix, int index) 309{ 310 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; 311 IgsPtr fPtr = IGSPTR(pScrn); 312 313 IgsWaitReady(fPtr); 314 return TRUE; 315} 316 317static void 318IgsFinishAccess(PixmapPtr pPix, int index) 319{ 320} 321#endif 322 323Bool 324IgsInitAccel(ScreenPtr pScreen) 325{ 326 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 327 IgsPtr fPtr = IGSPTR(pScrn); 328 ExaDriverPtr pExa; 329 330 pExa = exaDriverAlloc(); 331 if (!pExa) 332 return FALSE; 333 334 fPtr->pExa = pExa; 335 336 pExa->exa_major = EXA_VERSION_MAJOR; 337 pExa->exa_minor = EXA_VERSION_MINOR; 338 339 pExa->memoryBase = fPtr->fbmem; 340 pExa->memorySize = fPtr->fbmem_len; 341 pExa->offScreenBase = fPtr->linebytes * fPtr->info.height; 342 pExa->pixmapOffsetAlign = 4; 343 pExa->pixmapPitchAlign = 4; 344 345 pExa->flags = EXA_OFFSCREEN_PIXMAPS | 346 EXA_SUPPORTS_OFFSCREEN_OVERLAPS | 347 EXA_MIXED_PIXMAPS; 348 349 pExa->maxX = 2048; 350 pExa->maxY = 2048; 351 352 pExa->WaitMarker = IgsWaitMarker; 353 pExa->PrepareSolid = IgsPrepareSolid; 354 pExa->Solid = IgsSolid; 355 pExa->DoneSolid = IgsDoneCopy; 356 pExa->PrepareCopy = IgsPrepareCopy; 357 pExa->Copy = IgsCopy; 358 pExa->DoneCopy = IgsDoneCopy; 359 360 switch(fPtr->info.depth) { 361 case 8: 362 fPtr->shift = 0; 363 fPtr->mapfmt = IGS_COP_MAP_8BPP; 364 break; 365 case 16: 366 fPtr->shift = 1; 367 fPtr->mapfmt = IGS_COP_MAP_16BPP; 368 break; 369 case 24: 370 case 32: 371 fPtr->shift = 2; 372 fPtr->mapfmt = IGS_COP_MAP_32BPP; 373 break; 374 default: 375 ErrorF("Unsupported depth: %d\n", fPtr->info.depth); 376 } 377 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 378 379 /* EXA hits more optimized paths when it does not have to fallback 380 * because of missing UTS/DFS, hook memcpy-based UTS/DFS. 381 */ 382 pExa->UploadToScreen = IgsUploadToScreen; 383 pExa->DownloadFromScreen = IgsDownloadFromScreen; 384#ifdef __arm__ 385 pExa->PrepareAccess = IgsPrepareAccess; 386 pExa->FinishAccess = IgsFinishAccess; 387#endif 388 return exaDriverInit(pScreen, pExa); 389} 390