summit_accel.c revision 97ec0dae
1/* 2 * hardware acceleration for Visualize FX 4 3 * 4 * Copyright (C) 2024 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: summit_accel.c,v 1.4 2025/01/15 08:21:06 macallan Exp $ */ 25 26#include <sys/types.h> 27#include <dev/ic/summitreg.h> 28 29 30#include "ngle.h" 31 32//#define DEBUG 33 34#ifdef DEBUG 35#define ENTER xf86Msg(X_ERROR, "%s\n", __func__) 36#define LEAVE xf86Msg(X_ERROR, "%s done\n", __func__) 37#define DBGMSG xf86Msg 38#else 39#define ENTER 40#define DBGMSG if (0) xf86Msg 41#define LEAVE 42#endif 43 44#define SUMMIT_READ_MODE(m) \ 45 if ((m) != fPtr->read_mode) { \ 46 SummitWait(fPtr); \ 47 NGLEWrite4(fPtr, VISFX_VRAM_READ_MODE, (m)); \ 48 fPtr->read_mode = (m); \ 49 } 50 51#define SUMMIT_WRITE_MODE(m) \ 52 if ((m) != fPtr->write_mode) { \ 53 SummitWait(fPtr); \ 54 NGLEWrite4(fPtr, VISFX_VRAM_WRITE_MODE, (m)); \ 55 fPtr->write_mode = (m); \ 56 } 57 58static void 59SummitWait(NGLEPtr fPtr) 60{ 61 int reg; 62 63 ENTER; 64 do { 65 reg = NGLERead4(fPtr, VISFX_STATUS); 66 } while ((reg & 0x01000000) != 0); 67 if (reg != 0) { 68 xf86Msg(X_ERROR, "%s status %08x\n", __func__, reg); 69 xf86Msg(X_ERROR, "fault %08x\n", NGLERead4(fPtr, 0x641040)); 70 } 71 LEAVE; 72} 73 74static void 75SummitWaitMarker(ScreenPtr pScreen, int Marker) 76{ 77 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 78 NGLEPtr fPtr = NGLEPTR(pScrn); 79 int reg; 80 81 ENTER; 82 do { 83 reg = NGLERead4(fPtr, VISFX_STATUS); 84 } while ((reg & 0x01000000) != 0); 85 if (reg != 0) { 86 xf86Msg(X_ERROR, "%s status %08x\n", __func__, reg); 87 xf86Msg(X_ERROR, "fault %08x\n", NGLERead4(fPtr, 0x641040)); 88 } 89 LEAVE; 90} 91 92static void 93SummitWaitFifo(NGLEPtr fPtr, int count) 94{ 95 int reg; 96 do { 97 reg = NGLERead4(fPtr, VISFX_FIFO); 98 } while (reg < count); 99#ifdef DEBUG 100 if (reg != 0x800) xf86Msg(X_ERROR, "%s %x\n", __func__, reg); 101#endif 102} 103 104static Bool 105SummitPrepareCopy 106( 107 PixmapPtr pSrcPixmap, 108 PixmapPtr pDstPixmap, 109 int xdir, 110 int ydir, 111 int alu, 112 Pixel planemask 113) 114{ 115 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 116 NGLEPtr fPtr = NGLEPTR(pScrn); 117 int dstoff = exaGetPixmapOffset(pDstPixmap); 118 int srcoff = exaGetPixmapOffset(pSrcPixmap); 119 uint32_t sm, dm; 120 int y; 121 122 ENTER; 123 124 sm = dm = OTC01 | BIN8F | BUFFL; 125 DBGMSG(X_ERROR, "%s %d %d\n", __func__, srcoff, dstoff); 126 127 y = (srcoff >> 13); /* pitch is 8192 bytes in 24 bit */ 128 if (y >= fPtr->fbi.fbi_height) { 129 sm = OTC01 | BIN8F | BUFBL; 130 y -= fPtr->fbi.fbi_height; 131 } 132 fPtr->offset = y; 133 SUMMIT_READ_MODE(sm); 134 135 y = (dstoff >> 13); /* pitch is 8192 bytes in 24 bit */ 136 if (y >= fPtr->fbi.fbi_height) { 137 dm = OTC01 | BIN8F | BUFBL; 138 y -= fPtr->fbi.fbi_height; 139 } 140 fPtr->offsetd = y; 141 SUMMIT_WRITE_MODE(dm); 142 143 SummitWaitFifo(fPtr, 6); 144 NGLEWrite4(fPtr, VISFX_IBO, alu); 145 NGLEWrite4(fPtr, VISFX_PLANE_MASK, planemask); 146 LEAVE; 147 return TRUE; 148} 149 150static void 151SummitCopy 152( 153 PixmapPtr pDstPixmap, 154 int xs, 155 int ys, 156 int xd, 157 int yd, 158 int wi, 159 int he 160) 161{ 162 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 163 NGLEPtr fPtr = NGLEPTR(pScrn); 164 165 ENTER; 166 SummitWaitFifo(fPtr, 8); 167 NGLEWrite4(fPtr, VISFX_COPY_SRC, (xs << 16) | (ys + fPtr->offset)); 168 NGLEWrite4(fPtr, VISFX_COPY_WH, (wi << 16) | he); 169 NGLEWrite4(fPtr, VISFX_COPY_DST, (xd << 16) | (yd + fPtr->offsetd)); 170 171 exaMarkSync(pDstPixmap->drawable.pScreen); 172 LEAVE; 173} 174 175static void 176SummitDoneCopy(PixmapPtr pDstPixmap) 177{ 178 ENTER; 179 LEAVE; 180} 181 182static Bool 183SummitPrepareSolid( 184 PixmapPtr pPixmap, 185 int alu, 186 Pixel planemask, 187 Pixel fg) 188{ 189 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 190 NGLEPtr fPtr = NGLEPTR(pScrn); 191 int ofs = exaGetPixmapOffset(pPixmap); 192 int y; 193 uint32_t wm = OTC32 | BIN8F | BUFFL | 0x8c0, rm = OTC01 | BIN8F | BUFFL; 194 195 ENTER; 196 y = (ofs >> 13); /* pitch is 8192 bytes in 24 bit */ 197 if (y >= fPtr->fbi.fbi_height) { 198 wm = OTC32 | BIN8F | BUFBL | 0x8c0; 199 rm = OTC01 | BIN8F | BUFBL; 200 y -= fPtr->fbi.fbi_height; 201 } 202 SUMMIT_READ_MODE(rm); 203 SUMMIT_WRITE_MODE(wm); 204 fPtr->offset = y; 205 SummitWaitFifo(fPtr, 6); 206 NGLEWrite4(fPtr, VISFX_IBO, alu); 207 NGLEWrite4(fPtr, VISFX_FG_COLOUR, fg); 208 NGLEWrite4(fPtr, VISFX_PLANE_MASK, planemask); 209 LEAVE; 210 return TRUE; 211} 212 213static void 214SummitSolid( 215 PixmapPtr pPixmap, 216 int x1, 217 int y1, 218 int x2, 219 int y2) 220{ 221 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 222 NGLEPtr fPtr = NGLEPTR(pScrn); 223 int wi = x2 - x1, he = y2 - y1; 224 225 ENTER; 226 227 y1 += fPtr->offset; 228 229 SummitWaitFifo(fPtr, 6); 230 NGLEWrite4(fPtr, VISFX_START, (x1 << 16) | y1); 231 NGLEWrite4(fPtr, VISFX_SIZE, (wi << 16) | he); 232 233 exaMarkSync(pPixmap->drawable.pScreen); 234 LEAVE; 235} 236 237static Bool 238SummitUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 239 char *src, int src_pitch) 240{ 241 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 242 NGLEPtr fPtr = NGLEPTR(pScrn); 243 int ofs = exaGetPixmapOffset(pDst); 244 int i; 245 uint32_t *line, mode = OTC01 | BIN8F | BUFFL; 246 247 ENTER; 248 249 y += (ofs >> 13); /* pitch is 8192 bytes in 24 bit */ 250 if (y >= fPtr->fbi.fbi_height) { 251 mode = OTC01 | BIN8F | BUFBL; 252 y -= fPtr->fbi.fbi_height; 253 } 254 SUMMIT_WRITE_MODE(mode); 255 NGLEWrite4(fPtr, VISFX_PLANE_MASK, 0xffffffff); 256 NGLEWrite4(fPtr, VISFX_IBO, GXcopy); 257 258 while (h--) { 259 SummitWaitFifo(fPtr, w + 1); 260 NGLEWrite4(fPtr, VISFX_VRAM_WRITE_DEST, (y << 16) | x); 261 line = (uint32_t *)src; 262 263 for (i = 0; i < w; i++) 264 NGLEWrite4(fPtr, VISFX_VRAM_WRITE_DATA_INCRX, line[i]); 265 src += src_pitch; 266 y++; 267 } 268 return TRUE; 269} 270 271static Bool 272SummitDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 273 char *dst, int dst_pitch) 274{ 275 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 276 NGLEPtr fPtr = NGLEPTR(pScrn); 277 uint8_t *src; 278 int ofs = exaGetPixmapOffset(pSrc); 279 uint32_t mode = OTC01 | BIN8F | BUFFL; 280 281 ENTER; 282 283 y += (ofs >> 13); 284 if (y >= fPtr->fbi.fbi_height) { 285 mode = OTC01 | BIN8F | BUFBL; 286 y -= fPtr->fbi.fbi_height; 287 } 288 SUMMIT_READ_MODE(mode); 289 SummitWait(fPtr); 290 291 src = fPtr->fbmem; 292 src += (y << 13) + (x << 2); 293 294 while (h--) { 295 memcpy(dst, src, w << 2); 296 src += 8192; 297 dst += dst_pitch; 298 } 299 300 return TRUE; 301} 302 303Bool 304SummitPrepareAccess(PixmapPtr pPixmap, int index) 305{ 306 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 307 NGLEPtr fPtr = NGLEPTR(pScrn); 308 int ofs = exaGetPixmapOffset(pPixmap); 309 310 ENTER; 311 /* 312 * XXX 313 * since we abuse the back buffer as off-screen storage we can't 314 * safely allow direct access to it - this will make X use 315 * {Up|Down}load{To|From}Screen() instead 316 */ 317 if (ofs > 0) return FALSE; 318 319 SUMMIT_READ_MODE(OTC01 | BIN8F | BUFFL); 320 SUMMIT_WRITE_MODE(OTC01 | BIN8F | BUFFL); 321 NGLEWrite4(fPtr, VISFX_FOE, 0); 322 //NGLEWrite4(fPtr, VISFX_CONTROL, 0x200); 323 SummitWait(fPtr); 324 LEAVE; 325 return TRUE; 326} 327 328void 329SummitFinishAccess(PixmapPtr pPixmap, int index) 330{ 331 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 332 NGLEPtr fPtr = NGLEPTR(pScrn); 333 334 ENTER; 335 NGLEWrite4(fPtr, VISFX_FOE, FOE_BLEND_ROP); 336 //NGLEWrite4(fPtr, VISFX_CONTROL, 0); 337 LEAVE; 338} 339 340Bool 341SummitInitAccel(ScreenPtr pScreen) 342{ 343 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 344 NGLEPtr fPtr = NGLEPTR(pScrn); 345 ExaDriverPtr pExa; 346 int bpp = pScrn->bitsPerPixel >> 3; 347 348 pExa = exaDriverAlloc(); 349 if (!pExa) 350 return FALSE; 351 352 fPtr->pExa = pExa; 353 354 pExa->exa_major = EXA_VERSION_MAJOR; 355 pExa->exa_minor = EXA_VERSION_MINOR; 356 357 pExa->memoryBase = fPtr->fbmem; 358 pExa->memorySize = fPtr->fbi.fbi_stride * (fPtr->fbi.fbi_height * 2); 359 pExa->offScreenBase = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 360 pExa->pixmapOffsetAlign = fPtr->fbi.fbi_stride; 361 pExa->pixmapPitchAlign = fPtr->fbi.fbi_stride; 362 363 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_MIXED_PIXMAPS; 364 365 pExa->maxX = 2048; 366 pExa->maxY = 2048; 367 368 pExa->WaitMarker = SummitWaitMarker; 369 pExa->Solid = SummitSolid; 370 pExa->DoneSolid = SummitDoneCopy; 371 pExa->Copy = SummitCopy; 372 pExa->DoneCopy = SummitDoneCopy; 373 pExa->PrepareCopy = SummitPrepareCopy; 374 pExa->PrepareSolid = SummitPrepareSolid; 375 pExa->UploadToScreen = SummitUploadToScreen; 376 pExa->DownloadFromScreen = SummitDownloadFromScreen; 377 pExa->PrepareAccess = SummitPrepareAccess; 378 pExa->FinishAccess = SummitFinishAccess; 379 380 fPtr->read_mode = -1; 381 fPtr->write_mode = -1; 382 SUMMIT_READ_MODE(OTC01 | BIN8F | BUFFL); 383 SUMMIT_WRITE_MODE(OTC01 | BIN8F | BUFFL); 384 NGLEWrite4(fPtr, VISFX_FOE, FOE_BLEND_ROP); 385 NGLEWrite4(fPtr, VISFX_IBO, GXcopy); 386 NGLEWrite4(fPtr, VISFX_CONTROL, 0); 387 388 return exaDriverInit(pScreen, pExa); 389} 390