summit_accel.c revision a6437d19
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.6 2025/01/26 05:38:38 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 inline void 59SummitWait(NGLEPtr fPtr) 60{ 61 int reg, count = 0;; 62 63 ENTER; 64 do { 65 reg = NGLERead4(fPtr, VISFX_STATUS); 66 count++; 67 } while ((reg & 0x01000000) != 0); 68 if (reg != 0) { 69 xf86Msg(X_ERROR, "%s status %08x\n", __func__, reg); 70 xf86Msg(X_ERROR, "fault %08x\n", NGLERead4(fPtr, 0x641040)); 71 } 72 DBGMSG(X_ERROR, "%s: %d\n", __func__, count); 73} 74 75static void 76SummitWaitMarker(ScreenPtr pScreen, int Marker) 77{ 78 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 79 NGLEPtr fPtr = NGLEPTR(pScrn); 80 int reg, count = 0; 81 82 ENTER; 83 do { 84 reg = NGLERead4(fPtr, VISFX_STATUS); 85 count++; 86 } while ((reg & 0x01000000) != 0); 87 if (reg != 0) { 88 xf86Msg(X_ERROR, "%s status %08x\n", __func__, reg); 89 xf86Msg(X_ERROR, "fault %08x\n", NGLERead4(fPtr, 0x641040)); 90 } 91 DBGMSG(X_ERROR, "%s: %d\n", __func__, count); 92} 93 94static void 95SummitWaitFifo(NGLEPtr fPtr, int count) 96{ 97 int reg; 98 do { 99 reg = NGLERead4(fPtr, VISFX_FIFO); 100 } while (reg < count); 101#ifdef DEBUG 102 if (reg != 0x800) xf86Msg(X_ERROR, "%s %x\n", __func__, reg); 103#endif 104} 105 106static Bool 107SummitPrepareCopy 108( 109 PixmapPtr pSrcPixmap, 110 PixmapPtr pDstPixmap, 111 int xdir, 112 int ydir, 113 int alu, 114 Pixel planemask 115) 116{ 117 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 118 NGLEPtr fPtr = NGLEPTR(pScrn); 119 int dstoff = exaGetPixmapOffset(pDstPixmap); 120 int srcoff = exaGetPixmapOffset(pSrcPixmap); 121 uint32_t sm, dm; 122 int y; 123 124 ENTER; 125 126 sm = dm = OTC01 | BIN8F | BUFFL; 127 DBGMSG(X_ERROR, "%s %d %d\n", __func__, srcoff, dstoff); 128 129 y = (srcoff >> 13); /* pitch is 8192 bytes in 24 bit */ 130 if (y >= fPtr->fbi.fbi_height) { 131 sm = OTC01 | BIN8F | BUFBL; 132 y -= fPtr->fbi.fbi_height; 133 } 134 fPtr->offset = y; 135 SUMMIT_READ_MODE(sm); 136 137 y = (dstoff >> 13); /* pitch is 8192 bytes in 24 bit */ 138 if (y >= fPtr->fbi.fbi_height) { 139 dm = OTC01 | BIN8F | BUFBL; 140 y -= fPtr->fbi.fbi_height; 141 } 142 fPtr->offsetd = y; 143 SUMMIT_WRITE_MODE(dm); 144 145 SummitWaitFifo(fPtr, 8); 146 if (alu == GXcopy) { 147 NGLEWrite4(fPtr, VISFX_FOE, 0); 148 } else { 149 NGLEWrite4(fPtr, VISFX_FOE, FOE_BLEND_ROP); 150 NGLEWrite4(fPtr, VISFX_IBO, alu); 151 } 152 NGLEWrite4(fPtr, VISFX_PLANE_MASK, planemask); 153 LEAVE; 154 return TRUE; 155} 156 157static void 158SummitCopy 159( 160 PixmapPtr pDstPixmap, 161 int xs, 162 int ys, 163 int xd, 164 int yd, 165 int wi, 166 int he 167) 168{ 169 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 170 NGLEPtr fPtr = NGLEPTR(pScrn); 171 172 ENTER; 173 SummitWaitFifo(fPtr, 8); 174 NGLEWrite4(fPtr, VISFX_COPY_SRC, (xs << 16) | (ys + fPtr->offset)); 175 NGLEWrite4(fPtr, VISFX_COPY_WH, (wi << 16) | he); 176 NGLEWrite4(fPtr, VISFX_COPY_DST, (xd << 16) | (yd + fPtr->offsetd)); 177 178 LEAVE; 179} 180 181static void 182SummitDoneCopy(PixmapPtr pDstPixmap) 183{ 184 ENTER; 185 LEAVE; 186} 187 188static Bool 189SummitPrepareSolid( 190 PixmapPtr pPixmap, 191 int alu, 192 Pixel planemask, 193 Pixel fg) 194{ 195 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 196 NGLEPtr fPtr = NGLEPTR(pScrn); 197 int ofs = exaGetPixmapOffset(pPixmap); 198 int y; 199 uint32_t wm = OTC32 | BIN8F | BUFFL | 0x8c0, rm = OTC01 | BIN8F | BUFFL; 200 201 ENTER; 202 y = (ofs >> 13); /* pitch is 8192 bytes in 24 bit */ 203 if (y >= fPtr->fbi.fbi_height) { 204 wm = OTC32 | BIN8F | BUFBL | 0x8c0; 205 rm = OTC01 | BIN8F | BUFBL; 206 y -= fPtr->fbi.fbi_height; 207 } 208 SUMMIT_READ_MODE(rm); 209 SUMMIT_WRITE_MODE(wm); 210 fPtr->offset = y; 211 SummitWaitFifo(fPtr, 10); 212 if (alu == GXcopy) { 213 NGLEWrite4(fPtr, VISFX_FOE, 0); 214 } else { 215 NGLEWrite4(fPtr, VISFX_FOE, FOE_BLEND_ROP); 216 NGLEWrite4(fPtr, VISFX_IBO, alu); 217 } 218 NGLEWrite4(fPtr, VISFX_FG_COLOUR, fg); 219 NGLEWrite4(fPtr, VISFX_PLANE_MASK, planemask); 220 LEAVE; 221 return TRUE; 222} 223 224static void 225SummitSolid( 226 PixmapPtr pPixmap, 227 int x1, 228 int y1, 229 int x2, 230 int y2) 231{ 232 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 233 NGLEPtr fPtr = NGLEPTR(pScrn); 234 int wi = x2 - x1, he = y2 - y1; 235 236 ENTER; 237 238 y1 += fPtr->offset; 239 240 SummitWaitFifo(fPtr, 6); 241 NGLEWrite4(fPtr, VISFX_START, (x1 << 16) | y1); 242 NGLEWrite4(fPtr, VISFX_SIZE, (wi << 16) | he); 243 244 LEAVE; 245} 246 247static Bool 248SummitUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 249 char *src, int src_pitch) 250{ 251 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 252 NGLEPtr fPtr = NGLEPTR(pScrn); 253 int ofs = exaGetPixmapOffset(pDst); 254 int i; 255 uint32_t *line, mode = OTC01 | BIN8F | BUFFL; 256 257 ENTER; 258 259 y += (ofs >> 13); /* pitch is 8192 bytes in 24 bit */ 260 if (y >= fPtr->fbi.fbi_height) { 261 mode = OTC01 | BIN8F | BUFBL; 262 y -= fPtr->fbi.fbi_height; 263 } 264 SUMMIT_WRITE_MODE(mode); 265 NGLEWrite4(fPtr, VISFX_PLANE_MASK, 0xffffffff); 266 NGLEWrite4(fPtr, VISFX_FOE, 0); 267 268 while (h--) { 269 /* 270 * it *should* be impossible to overrun the FIFO using BINC 271 * writes, but overruns are annoying if they do happen so be 272 * overly cautious and make sure there is at least some room 273 */ 274 SummitWaitFifo(fPtr, w + 1); 275 NGLEWrite4(fPtr, VISFX_VRAM_WRITE_DEST, (y << 16) | x); 276 line = (uint32_t *)src; 277 278 for (i = 0; i < w; i++) 279 NGLEWrite4(fPtr, VISFX_VRAM_WRITE_DATA_INCRX, line[i]); 280 src += src_pitch; 281 y++; 282 } 283 return TRUE; 284} 285 286static Bool 287SummitDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 288 char *dst, int dst_pitch) 289{ 290 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 291 NGLEPtr fPtr = NGLEPTR(pScrn); 292 uint8_t *src; 293 int ofs = exaGetPixmapOffset(pSrc); 294 uint32_t mode = OTC01 | BIN8F | BUFFL; 295 296 ENTER; 297 y += (ofs >> 13); 298 if (y >= fPtr->fbi.fbi_height) { 299 mode = OTC01 | BIN8F | BUFBL; 300 y -= fPtr->fbi.fbi_height; 301 } 302 SUMMIT_READ_MODE(mode); 303 SummitWait(fPtr); 304 NGLEWrite4(fPtr, VISFX_RPH, VISFX_RPH_LTR); 305 SummitWait(fPtr); 306 307 src = fPtr->fbmem; 308 src += (y << 13) + (x << 2); 309 310 while (h--) { 311 memcpy(dst, src, w << 2); 312 src += 8192; 313 dst += dst_pitch; 314 } 315 316 return TRUE; 317} 318 319Bool 320SummitPrepareAccess(PixmapPtr pPixmap, int index) 321{ 322 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 323 NGLEPtr fPtr = NGLEPTR(pScrn); 324 int ofs = exaGetPixmapOffset(pPixmap); 325 int y; 326 327 ENTER; 328 if (ofs == 0) { 329 /* accessing the visible framebuffer */ 330 SUMMIT_READ_MODE(OTC01 | BIN8F | BUFFL); 331 SUMMIT_WRITE_MODE(OTC01 | BIN8F | BUFFL); 332 } else { 333 SUMMIT_READ_MODE(OTC01 | BIN8F | BUFBL); 334 SUMMIT_WRITE_MODE(OTC01 | BIN8F | BUFBL); 335 y = ofs >> 13; 336 y -= fPtr->fbi.fbi_height; 337 pPixmap->devPrivate.ptr = fPtr->fbmem + (y << 13); 338 } 339 NGLEWrite4(fPtr, VISFX_FOE, 0); 340 //NGLEWrite4(fPtr, VISFX_CONTROL, 0x200); 341 SummitWait(fPtr); 342 LEAVE; 343 return TRUE; 344} 345 346void 347SummitFinishAccess(PixmapPtr pPixmap, int index) 348{ 349 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 350 NGLEPtr fPtr = NGLEPTR(pScrn); 351 352 ENTER; 353 //NGLEWrite4(fPtr, VISFX_CONTROL, 0); 354 LEAVE; 355} 356 357Bool 358SummitInitAccel(ScreenPtr pScreen) 359{ 360 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 361 NGLEPtr fPtr = NGLEPTR(pScrn); 362 ExaDriverPtr pExa; 363 int bpp = pScrn->bitsPerPixel >> 3; 364 365 pExa = exaDriverAlloc(); 366 if (!pExa) 367 return FALSE; 368 369 fPtr->pExa = pExa; 370 371 pExa->exa_major = EXA_VERSION_MAJOR; 372 pExa->exa_minor = EXA_VERSION_MINOR; 373 374 pExa->memoryBase = fPtr->fbmem; 375 pExa->memorySize = fPtr->fbi.fbi_stride * (fPtr->fbi.fbi_height * 2); 376 pExa->offScreenBase = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 377 pExa->pixmapOffsetAlign = fPtr->fbi.fbi_stride; 378 pExa->pixmapPitchAlign = fPtr->fbi.fbi_stride; 379 380 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_MIXED_PIXMAPS; 381 382 pExa->maxX = 2048; 383 pExa->maxY = 2048; 384 385 pExa->WaitMarker = SummitWaitMarker; 386 pExa->Solid = SummitSolid; 387 pExa->DoneSolid = SummitDoneCopy; 388 pExa->Copy = SummitCopy; 389 pExa->DoneCopy = SummitDoneCopy; 390 pExa->PrepareCopy = SummitPrepareCopy; 391 pExa->PrepareSolid = SummitPrepareSolid; 392 pExa->UploadToScreen = SummitUploadToScreen; 393 pExa->DownloadFromScreen = SummitDownloadFromScreen; 394 pExa->PrepareAccess = SummitPrepareAccess; 395 pExa->FinishAccess = SummitFinishAccess; 396 397 fPtr->read_mode = -1; 398 fPtr->write_mode = -1; 399 SUMMIT_READ_MODE(OTC01 | BIN8F | BUFFL); 400 SUMMIT_WRITE_MODE(OTC01 | BIN8F | BUFFL); 401 NGLEWrite4(fPtr, VISFX_FOE, FOE_BLEND_ROP); 402 NGLEWrite4(fPtr, VISFX_IBO, GXcopy); 403 NGLEWrite4(fPtr, VISFX_CONTROL, 0); 404 405 return exaDriverInit(pScreen, pExa); 406} 407