ngle_accel.c revision 9f844d85
1/* 2 * NGLE - hardware acceleration. 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: ngle_accel.c,v 1.4 2024/10/25 07:15:41 macallan Exp $ */ 25 26#include <sys/types.h> 27#include <dev/ic/stireg.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 44static inline void 45NGLEWrite4(NGLEPtr fPtr, int offset, uint32_t val) 46{ 47 volatile uint32_t *ptr = (uint32_t *)((uint8_t *)fPtr->regs + offset); 48 *ptr = val; 49} 50 51static inline void 52NGLEWrite1(NGLEPtr fPtr, int offset, uint8_t val) 53{ 54 volatile uint8_t *ptr = (uint8_t *)fPtr->regs + offset; 55 *ptr = val; 56} 57 58static inline uint32_t 59NGLERead4(NGLEPtr fPtr, int offset) 60{ 61 volatile uint32_t *ptr = (uint32_t *)((uint8_t *)fPtr->regs + offset); 62 return *ptr; 63} 64 65static inline uint8_t 66NGLERead1(NGLEPtr fPtr, int offset) 67{ 68 volatile uint8_t *ptr = (uint8_t *)fPtr->regs + offset; 69 return *ptr; 70} 71 72static void 73NGLEWaitMarker(ScreenPtr pScreen, int Marker) 74{ 75 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 76 NGLEPtr fPtr = NGLEPTR(pScrn); 77 uint8_t stat; 78 79 ENTER; 80 do { 81 stat = NGLERead1(fPtr, NGLE_REG_15b0); 82 if (stat == 0) 83 stat = NGLERead1(fPtr, NGLE_REG_15b0); 84 } while (stat != 0); 85 LEAVE; 86} 87 88static void 89NGLEWaitFifo(NGLEPtr fPtr, int slots) 90{ 91 uint32_t reg; 92 93 ENTER; 94 do { 95 reg = NGLERead4(fPtr, NGLE_REG_34); 96 } while (reg < slots); 97 LEAVE; 98} 99 100static Bool 101NGLEPrepareCopy_EG 102( 103 PixmapPtr pSrcPixmap, 104 PixmapPtr pDstPixmap, 105 int xdir, 106 int ydir, 107 int alu, 108 Pixel planemask 109) 110{ 111 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 112 NGLEPtr fPtr = NGLEPTR(pScrn); 113 int srcpitch = exaGetPixmapPitch(pSrcPixmap); 114 int srcoff = exaGetPixmapOffset(pSrcPixmap); 115 116 ENTER; 117 118 DBGMSG(X_ERROR, "%s %d %d\n", __func__, srcoff, srcpitch); 119 fPtr->offset = srcoff >> 11; 120 NGLEWaitMarker(pDstPixmap->drawable.pScreen, 0); 121 /* XXX HCRX needs ifferent values here */ 122 NGLEWrite4(fPtr, NGLE_REG_10, 123 BA(IndexedDcd, Otc04, Ots08, AddrLong, 0, BINapp0I, 0)); 124 NGLEWrite4(fPtr, NGLE_REG_14, 125 IBOvals(RopSrc, 0, BitmapExtent08, 0, DataDynamic, MaskOtc, 0, 0)); 126 NGLEWrite4(fPtr, NGLE_REG_13, planemask); 127 128 fPtr->hwmode = HW_BLIT; 129 130 LEAVE; 131 return TRUE; 132} 133 134static Bool 135NGLEPrepareCopy_HCRX 136( 137 PixmapPtr pSrcPixmap, 138 PixmapPtr pDstPixmap, 139 int xdir, 140 int ydir, 141 int alu, 142 Pixel planemask 143) 144{ 145 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 146 NGLEPtr fPtr = NGLEPTR(pScrn); 147 int srcpitch = exaGetPixmapPitch(pSrcPixmap); 148 int srcoff = exaGetPixmapOffset(pSrcPixmap); 149 150 ENTER; 151 152 DBGMSG(X_ERROR, "%s %d %d\n", __func__, srcoff, srcpitch); 153 fPtr->offset = srcoff / srcpitch; 154 NGLEWaitMarker(pDstPixmap->drawable.pScreen, 0); 155 NGLEWrite4(fPtr, NGLE_REG_10, 156 BA(FractDcd, Otc24, Ots08, AddrLong, 0, BINapp0F8, 0)); 157 NGLEWrite4(fPtr, NGLE_REG_14, 158 IBOvals(RopSrc, 0, BitmapExtent32, 0, DataDynamic, MaskOtc, 0, 0)); 159 NGLEWrite4(fPtr, NGLE_REG_13, planemask); 160 161 fPtr->hwmode = HW_BLIT; 162 163 LEAVE; 164 return TRUE; 165} 166 167static void 168NGLECopy 169( 170 PixmapPtr pDstPixmap, 171 int xs, 172 int ys, 173 int xd, 174 int yd, 175 int wi, 176 int he 177) 178{ 179 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 180 NGLEPtr fPtr = NGLEPTR(pScrn); 181 int dstpitch = exaGetPixmapPitch(pDstPixmap); 182 int dstoff = exaGetPixmapOffset(pDstPixmap); 183 184 ENTER; 185 NGLEWaitFifo(fPtr, 3); 186 NGLEWrite4(fPtr, NGLE_REG_24, (xs << 16) | (ys + fPtr->offset)); 187 NGLEWrite4(fPtr, NGLE_REG_7, (wi << 16) | he); 188 NGLEWrite4(fPtr, NGLE_REG_25, (xd << 16) | (yd + (dstoff / dstpitch))); 189 190 exaMarkSync(pDstPixmap->drawable.pScreen); 191 LEAVE; 192} 193 194static void 195NGLEDoneCopy(PixmapPtr pDstPixmap) 196{ 197 ENTER; 198 LEAVE; 199} 200 201static Bool 202NGLEPrepareSolid_EG( 203 PixmapPtr pPixmap, 204 int alu, 205 Pixel planemask, 206 Pixel fg) 207{ 208 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 209 NGLEPtr fPtr = NGLEPTR(pScrn); 210 211 ENTER; 212 NGLEWaitFifo(fPtr, 4); 213 /* plane mask */ 214 NGLEWrite4(fPtr, NGLE_REG_13, planemask); 215 /* bitmap op */ 216 NGLEWrite4(fPtr, NGLE_REG_14, 217 IBOvals(alu, 0, BitmapExtent08, 0, DataDynamic, MaskOtc, 1, 0)); 218 /* dst bitmap access */ 219 NGLEWrite4(fPtr, NGLE_REG_11, 220 BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0I, 0)); 221 NGLEWrite4(fPtr, NGLE_REG_35, fg); 222 fPtr->hwmode = HW_FILL; 223 224 LEAVE; 225 return TRUE; 226} 227 228static Bool 229NGLEPrepareSolid_HCRX( 230 PixmapPtr pPixmap, 231 int alu, 232 Pixel planemask, 233 Pixel fg) 234{ 235 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 236 NGLEPtr fPtr = NGLEPTR(pScrn); 237 238 ENTER; 239 NGLEWaitFifo(fPtr, 4); 240 /* plane mask */ 241 NGLEWrite4(fPtr, NGLE_REG_13, planemask); 242 /* bitmap op */ 243 NGLEWrite4(fPtr, NGLE_REG_14, 244 IBOvals(alu, 0, BitmapExtent32, 0, DataDynamic, MaskOtc, 1, 0)); 245 /* dst bitmap access */ 246 NGLEWrite4(fPtr, NGLE_REG_11, 247 BA(FractDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0F8, 0)); 248 NGLEWrite4(fPtr, NGLE_REG_35, fg); 249 fPtr->hwmode = HW_FILL; 250 251 LEAVE; 252 return TRUE; 253} 254 255static void 256NGLESolid( 257 PixmapPtr pPixmap, 258 int x1, 259 int y1, 260 int x2, 261 int y2) 262{ 263 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 264 NGLEPtr fPtr = NGLEPTR(pScrn); 265 int w = x2 - x1, h = y2 - y1; 266 int pitch = exaGetPixmapPitch(pPixmap); 267 int offset = exaGetPixmapOffset(pPixmap); 268 uint32_t mask; 269 int wi, rest; 270 271 ENTER; 272 273 y1 += offset >> 11; 274 275 /* 276 * XXX 277 * Turns out this thing always fills rectangles to the next 32 pixel 278 * boundary on te right. To get around this we split the rectangle 279 * into a multiples-of-32 part and the rest, so we can mask off the 280 * excess pixels. 281 */ 282 rest = w & 0x1f; 283 wi = w & 0xffffe0; 284 if (wi > 0) { 285 NGLEWaitFifo(fPtr, 3); 286 /* transfer data */ 287 NGLEWrite4(fPtr, NGLE_REG_8, 0xffffffff); 288 /* dst XY */ 289 NGLEWrite4(fPtr, NGLE_REG_6, (x1 << 16) | y1); 290 /* len XY start */ 291 NGLEWrite4(fPtr, NGLE_REG_9, (wi << 16) | h); 292 } 293 if (rest > 0) { 294 mask = 0xffffffff << (32 - w); 295 /* transfer data */ 296 NGLEWaitFifo(fPtr, 3); 297 NGLEWrite4(fPtr, NGLE_REG_8, mask); 298 /* dst XY */ 299 NGLEWrite4(fPtr, NGLE_REG_6, ((x1 + wi) << 16) | y1); 300 /* len XY start */ 301 NGLEWrite4(fPtr, NGLE_REG_9, (rest << 16) | h); 302 } 303 exaMarkSync(pPixmap->drawable.pScreen); 304 LEAVE; 305} 306 307Bool 308NGLEPrepareAccess_EG(PixmapPtr pPixmap, int index) 309{ 310 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 311 NGLEPtr fPtr = NGLEPTR(pScrn); 312 313 if (fPtr->hwmode == HW_FB) return TRUE; 314 315 NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 316 NGLEWrite4(fPtr, NGLE_REG_10, 317 BA(IndexedDcd, Otc04, Ots08, AddrByte, 0, BINapp0I, 0)); 318 NGLEWrite4(fPtr, NGLE_REG_14, 0x83000300); 319 NGLEWrite4(fPtr, NGLE_REG_13, 0xff); 320 NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 321 NGLEWrite1(fPtr, NGLE_REG_16b1, 1); 322 fPtr->hwmode = HW_FB; 323 return TRUE; 324} 325 326Bool 327NGLEPrepareAccess_HCRX(PixmapPtr pPixmap, int index) 328{ 329 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 330 NGLEPtr fPtr = NGLEPTR(pScrn); 331 332 if (fPtr->hwmode == HW_FB) return TRUE; 333 334 NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 335 NGLEWrite4(fPtr, NGLE_REG_10, 336 BA(FractDcd, Otc24, Ots08, AddrLong, 0, BINapp0F8, 0)); 337 NGLEWrite4(fPtr, NGLE_REG_14, 0x83000300); 338 NGLEWrite4(fPtr, NGLE_REG_13, 0xffffffff); 339 NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 340 NGLEWrite1(fPtr, NGLE_REG_16b1, 1); 341 fPtr->hwmode = HW_FB; 342 return TRUE; 343} 344Bool 345NGLEInitAccel(ScreenPtr pScreen) 346{ 347 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 348 NGLEPtr fPtr = NGLEPTR(pScrn); 349 ExaDriverPtr pExa; 350 int lines, bpp = pScrn->bitsPerPixel >> 3; 351 352 pExa = exaDriverAlloc(); 353 if (!pExa) 354 return FALSE; 355 356 fPtr->pExa = pExa; 357 358 pExa->exa_major = EXA_VERSION_MAJOR; 359 pExa->exa_minor = EXA_VERSION_MINOR; 360 361 pExa->memoryBase = fPtr->fbmem; 362 lines = fPtr->fbmem_len / fPtr->fbi.fbi_stride; 363 DBGMSG(X_ERROR, "lines %d\n", lines); 364 pExa->memorySize = fPtr->fbmem_len; 365 pExa->offScreenBase = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 366 pExa->pixmapOffsetAlign = fPtr->fbi.fbi_stride; 367 pExa->pixmapPitchAlign = fPtr->fbi.fbi_stride; 368 369 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_MIXED_PIXMAPS; 370 371 pExa->maxX = 2048; 372 pExa->maxY = 2048; 373 374 fPtr->hwmode = -1; 375 376 pExa->WaitMarker = NGLEWaitMarker; 377 pExa->Solid = NGLESolid; 378 pExa->DoneSolid = NGLEDoneCopy; 379 pExa->Copy = NGLECopy; 380 pExa->DoneCopy = NGLEDoneCopy; 381 switch (fPtr->gid) { 382 case STI_DD_EG: 383 pExa->PrepareCopy = NGLEPrepareCopy_EG; 384 pExa->PrepareSolid = NGLEPrepareSolid_EG; 385 pExa->PrepareAccess = NGLEPrepareAccess_EG; 386 break; 387 case STI_DD_HCRX: 388 pExa->PrepareCopy = NGLEPrepareCopy_HCRX; 389 pExa->PrepareSolid = NGLEPrepareSolid_HCRX; 390 pExa->PrepareAccess = NGLEPrepareAccess_HCRX; 391 break; 392 default: 393 xf86Msg(X_ERROR, 394 "unsupported dvice GID %08x\n", fPtr->gid); 395 return FALSE; 396 } 397 NGLEWaitMarker(pScreen, 0); 398 399 return exaDriverInit(pScreen, pExa); 400} 401