ngle_accel.c revision 852b373f
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.5 2024/10/25 09:20:37 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 NGLEWrite4(fPtr, NGLE_REG_10, 122 BA(IndexedDcd, Otc04, Ots08, AddrLong, 0, BINapp0I, 0)); 123 NGLEWrite4(fPtr, NGLE_REG_14, 124 IBOvals(RopSrc, 0, BitmapExtent08, 1, DataDynamic, MaskOtc, 0, 0)); 125 NGLEWrite4(fPtr, NGLE_REG_13, planemask); 126 127 fPtr->hwmode = HW_BLIT; 128 129 LEAVE; 130 return TRUE; 131} 132 133static Bool 134NGLEPrepareCopy_HCRX 135( 136 PixmapPtr pSrcPixmap, 137 PixmapPtr pDstPixmap, 138 int xdir, 139 int ydir, 140 int alu, 141 Pixel planemask 142) 143{ 144 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 145 NGLEPtr fPtr = NGLEPTR(pScrn); 146 int srcpitch = exaGetPixmapPitch(pSrcPixmap); 147 int srcoff = exaGetPixmapOffset(pSrcPixmap); 148 149 ENTER; 150 151 DBGMSG(X_ERROR, "%s %d %d\n", __func__, srcoff, srcpitch); 152 fPtr->offset = srcoff / srcpitch; 153 NGLEWaitMarker(pDstPixmap->drawable.pScreen, 0); 154 NGLEWrite4(fPtr, NGLE_REG_10, 155 BA(FractDcd, Otc24, Ots08, AddrLong, 0, BINapp0F8, 0)); 156 NGLEWrite4(fPtr, NGLE_REG_14, 157 IBOvals(RopSrc, 0, BitmapExtent32, 0, DataDynamic, MaskOtc, 0, 0)); 158 NGLEWrite4(fPtr, NGLE_REG_13, planemask); 159 160 fPtr->hwmode = HW_BLIT; 161 162 LEAVE; 163 return TRUE; 164} 165 166static void 167NGLECopy 168( 169 PixmapPtr pDstPixmap, 170 int xs, 171 int ys, 172 int xd, 173 int yd, 174 int wi, 175 int he 176) 177{ 178 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 179 NGLEPtr fPtr = NGLEPTR(pScrn); 180 int dstpitch = exaGetPixmapPitch(pDstPixmap); 181 int dstoff = exaGetPixmapOffset(pDstPixmap); 182 183 ENTER; 184 NGLEWaitFifo(fPtr, 3); 185 NGLEWrite4(fPtr, NGLE_REG_24, (xs << 16) | (ys + fPtr->offset)); 186 NGLEWrite4(fPtr, NGLE_REG_7, (wi << 16) | he); 187 NGLEWrite4(fPtr, NGLE_REG_25, (xd << 16) | (yd + (dstoff / dstpitch))); 188 189 exaMarkSync(pDstPixmap->drawable.pScreen); 190 LEAVE; 191} 192 193static void 194NGLEDoneCopy(PixmapPtr pDstPixmap) 195{ 196 ENTER; 197 LEAVE; 198} 199 200static Bool 201NGLEPrepareSolid_EG( 202 PixmapPtr pPixmap, 203 int alu, 204 Pixel planemask, 205 Pixel fg) 206{ 207 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 208 NGLEPtr fPtr = NGLEPTR(pScrn); 209 210 ENTER; 211 NGLEWaitFifo(fPtr, 4); 212 /* plane mask */ 213 NGLEWrite4(fPtr, NGLE_REG_13, planemask); 214 /* bitmap op */ 215 NGLEWrite4(fPtr, NGLE_REG_14, 216 IBOvals(alu, 0, BitmapExtent08, 0, DataDynamic, MaskOtc, 1, 0)); 217 /* dst bitmap access */ 218 NGLEWrite4(fPtr, NGLE_REG_11, 219 BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0I, 0)); 220 NGLEWrite4(fPtr, NGLE_REG_35, fg); 221 fPtr->hwmode = HW_FILL; 222 223 LEAVE; 224 return TRUE; 225} 226 227static Bool 228NGLEPrepareSolid_HCRX( 229 PixmapPtr pPixmap, 230 int alu, 231 Pixel planemask, 232 Pixel fg) 233{ 234 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 235 NGLEPtr fPtr = NGLEPTR(pScrn); 236 237 ENTER; 238 NGLEWaitFifo(fPtr, 4); 239 /* plane mask */ 240 NGLEWrite4(fPtr, NGLE_REG_13, planemask); 241 /* bitmap op */ 242 NGLEWrite4(fPtr, NGLE_REG_14, 243 IBOvals(alu, 0, BitmapExtent32, 0, DataDynamic, MaskOtc, 1, 0)); 244 /* dst bitmap access */ 245 NGLEWrite4(fPtr, NGLE_REG_11, 246 BA(FractDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0F8, 0)); 247 NGLEWrite4(fPtr, NGLE_REG_35, fg); 248 fPtr->hwmode = HW_FILL; 249 250 LEAVE; 251 return TRUE; 252} 253 254static void 255NGLESolid( 256 PixmapPtr pPixmap, 257 int x1, 258 int y1, 259 int x2, 260 int y2) 261{ 262 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 263 NGLEPtr fPtr = NGLEPTR(pScrn); 264 int w = x2 - x1, h = y2 - y1; 265 int pitch = exaGetPixmapPitch(pPixmap); 266 int offset = exaGetPixmapOffset(pPixmap); 267 uint32_t mask; 268 int wi, rest; 269 270 ENTER; 271 272 y1 += offset / pitch; 273 274 /* 275 * XXX 276 * Turns out this thing always fills rectangles to the next 32 pixel 277 * boundary on te right. To get around this we split the rectangle 278 * into a multiples-of-32 part and the rest, so we can mask off the 279 * excess pixels. 280 */ 281 rest = w & 0x1f; 282 wi = w & 0xffffe0; 283 if (wi > 0) { 284 NGLEWaitFifo(fPtr, 3); 285 /* transfer data */ 286 NGLEWrite4(fPtr, NGLE_REG_8, 0xffffffff); 287 /* dst XY */ 288 NGLEWrite4(fPtr, NGLE_REG_6, (x1 << 16) | y1); 289 /* len XY start */ 290 NGLEWrite4(fPtr, NGLE_REG_9, (wi << 16) | h); 291 } 292 if (rest > 0) { 293 mask = 0xffffffff << (32 - w); 294 /* transfer data */ 295 NGLEWaitFifo(fPtr, 3); 296 NGLEWrite4(fPtr, NGLE_REG_8, mask); 297 /* dst XY */ 298 NGLEWrite4(fPtr, NGLE_REG_6, ((x1 + wi) << 16) | y1); 299 /* len XY start */ 300 NGLEWrite4(fPtr, NGLE_REG_9, (rest << 16) | h); 301 } 302 exaMarkSync(pPixmap->drawable.pScreen); 303 LEAVE; 304} 305 306Bool 307NGLEPrepareAccess_EG(PixmapPtr pPixmap, int index) 308{ 309 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 310 NGLEPtr fPtr = NGLEPTR(pScrn); 311 312 if (fPtr->hwmode == HW_FB) return TRUE; 313 314 NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 315 NGLEWrite4(fPtr, NGLE_REG_10, 316 BA(IndexedDcd, Otc04, Ots08, AddrByte, 0, BINapp0I, 0)); 317 NGLEWrite4(fPtr, NGLE_REG_14, 0x83000300); 318 NGLEWrite4(fPtr, NGLE_REG_13, 0xff); 319 NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 320 NGLEWrite1(fPtr, NGLE_REG_16b1, 1); 321 fPtr->hwmode = HW_FB; 322 return TRUE; 323} 324 325Bool 326NGLEPrepareAccess_HCRX(PixmapPtr pPixmap, int index) 327{ 328 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 329 NGLEPtr fPtr = NGLEPTR(pScrn); 330 331 if (fPtr->hwmode == HW_FB) return TRUE; 332 333 NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 334 NGLEWrite4(fPtr, NGLE_REG_10, 335 BA(FractDcd, Otc24, Ots08, AddrLong, 0, BINapp0F8, 0)); 336 NGLEWrite4(fPtr, NGLE_REG_14, 0x83000300); 337 NGLEWrite4(fPtr, NGLE_REG_13, 0xffffffff); 338 NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 339 NGLEWrite1(fPtr, NGLE_REG_16b1, 1); 340 fPtr->hwmode = HW_FB; 341 return TRUE; 342} 343Bool 344NGLEInitAccel(ScreenPtr pScreen) 345{ 346 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 347 NGLEPtr fPtr = NGLEPTR(pScrn); 348 ExaDriverPtr pExa; 349 int lines, bpp = pScrn->bitsPerPixel >> 3; 350 351 pExa = exaDriverAlloc(); 352 if (!pExa) 353 return FALSE; 354 355 fPtr->pExa = pExa; 356 357 pExa->exa_major = EXA_VERSION_MAJOR; 358 pExa->exa_minor = EXA_VERSION_MINOR; 359 360 pExa->memoryBase = fPtr->fbmem; 361 lines = fPtr->fbmem_len / fPtr->fbi.fbi_stride; 362 DBGMSG(X_ERROR, "lines %d\n", lines); 363 pExa->memorySize = fPtr->fbmem_len; 364 pExa->offScreenBase = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 365 pExa->pixmapOffsetAlign = fPtr->fbi.fbi_stride; 366 pExa->pixmapPitchAlign = fPtr->fbi.fbi_stride; 367 368 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_MIXED_PIXMAPS; 369 370 pExa->maxX = 2048; 371 pExa->maxY = 2048; 372 373 fPtr->hwmode = -1; 374 375 pExa->WaitMarker = NGLEWaitMarker; 376 pExa->Solid = NGLESolid; 377 pExa->DoneSolid = NGLEDoneCopy; 378 pExa->Copy = NGLECopy; 379 pExa->DoneCopy = NGLEDoneCopy; 380 switch (fPtr->gid) { 381 case STI_DD_EG: 382 pExa->PrepareCopy = NGLEPrepareCopy_EG; 383 pExa->PrepareSolid = NGLEPrepareSolid_EG; 384 pExa->PrepareAccess = NGLEPrepareAccess_EG; 385 break; 386 case STI_DD_HCRX: 387 pExa->PrepareCopy = NGLEPrepareCopy_HCRX; 388 pExa->PrepareSolid = NGLEPrepareSolid_HCRX; 389 pExa->PrepareAccess = NGLEPrepareAccess_HCRX; 390 break; 391 default: 392 xf86Msg(X_ERROR, 393 "unsupported device GID %08x\n", fPtr->gid); 394 return FALSE; 395 } 396 NGLEWaitMarker(pScreen, 0); 397 398 return exaDriverInit(pScreen, pExa); 399} 400