1727c6de2Smacallan/*
2727c6de2Smacallan * NGLE - hardware acceleration.
3727c6de2Smacallan *
4727c6de2Smacallan * Copyright (C) 2024 Michael Lorenz
5727c6de2Smacallan *
6727c6de2Smacallan * Permission is hereby granted, free of charge, to any person obtaining a copy
7727c6de2Smacallan * of this software and associated documentation files (the "Software"), to deal
8727c6de2Smacallan * in the Software without restriction, including without limitation the rights
9727c6de2Smacallan * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10727c6de2Smacallan * copies of the Software, and to permit persons to whom the Software is
11727c6de2Smacallan * furnished to do so, subject to the following conditions:
12727c6de2Smacallan *
13727c6de2Smacallan * The above copyright notice and this permission notice shall be included in
14727c6de2Smacallan * all copies or substantial portions of the Software.
15727c6de2Smacallan *
16727c6de2Smacallan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17727c6de2Smacallan * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18727c6de2Smacallan * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19727c6de2Smacallan * MICHAEL LORENZ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20727c6de2Smacallan * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21727c6de2Smacallan * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22727c6de2Smacallan */
23727c6de2Smacallan
24e4f83f77Smacallan/* $NetBSD: ngle_accel.c,v 1.7 2025/03/05 07:22:24 macallan Exp $ */
25727c6de2Smacallan
26727c6de2Smacallan#include <sys/types.h>
27727c6de2Smacallan#include <dev/ic/stireg.h>
28727c6de2Smacallan
29727c6de2Smacallan
30727c6de2Smacallan#include "ngle.h"
31727c6de2Smacallan
32727c6de2Smacallan//#define DEBUG
33727c6de2Smacallan
34727c6de2Smacallan#ifdef DEBUG
35727c6de2Smacallan#define ENTER xf86Msg(X_ERROR, "%s\n", __func__)
36727c6de2Smacallan#define LEAVE xf86Msg(X_ERROR, "%s done\n", __func__)
37727c6de2Smacallan#define DBGMSG xf86Msg
38727c6de2Smacallan#else
39727c6de2Smacallan#define ENTER
40727c6de2Smacallan#define DBGMSG if (0) xf86Msg
41727c6de2Smacallan#define LEAVE
42727c6de2Smacallan#endif
43727c6de2Smacallan
44727c6de2Smacallanstatic void
45727c6de2SmacallanNGLEWaitMarker(ScreenPtr pScreen, int Marker)
46727c6de2Smacallan{
47727c6de2Smacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
48727c6de2Smacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
49727c6de2Smacallan	uint8_t stat;
50727c6de2Smacallan
51727c6de2Smacallan	ENTER;
52727c6de2Smacallan	do {
53727c6de2Smacallan		stat = NGLERead1(fPtr, NGLE_REG_15b0);
54727c6de2Smacallan		if (stat == 0)
55727c6de2Smacallan			stat = NGLERead1(fPtr, NGLE_REG_15b0);
56727c6de2Smacallan	} while (stat != 0);
57727c6de2Smacallan	LEAVE;
58727c6de2Smacallan}
59727c6de2Smacallan
60727c6de2Smacallanstatic void
61727c6de2SmacallanNGLEWaitFifo(NGLEPtr fPtr, int slots)
62727c6de2Smacallan{
63727c6de2Smacallan	uint32_t reg;
64727c6de2Smacallan
65727c6de2Smacallan	ENTER;
66727c6de2Smacallan	do {
67727c6de2Smacallan		reg = NGLERead4(fPtr, NGLE_REG_34);
68727c6de2Smacallan	} while (reg < slots);
69727c6de2Smacallan	LEAVE;
70727c6de2Smacallan}
71727c6de2Smacallan
72727c6de2Smacallanstatic Bool
73ce159321SmacallanNGLEPrepareCopy_EG
74727c6de2Smacallan(
75727c6de2Smacallan    PixmapPtr pSrcPixmap,
76727c6de2Smacallan    PixmapPtr pDstPixmap,
77727c6de2Smacallan    int       xdir,
78727c6de2Smacallan    int       ydir,
79727c6de2Smacallan    int       alu,
80727c6de2Smacallan    Pixel     planemask
81727c6de2Smacallan)
82727c6de2Smacallan{
83727c6de2Smacallan	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
84727c6de2Smacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
85727c6de2Smacallan	int srcpitch = exaGetPixmapPitch(pSrcPixmap);
86727c6de2Smacallan	int srcoff = exaGetPixmapOffset(pSrcPixmap);
87727c6de2Smacallan
88727c6de2Smacallan	ENTER;
89727c6de2Smacallan
90727c6de2Smacallan	DBGMSG(X_ERROR, "%s %d %d\n", __func__, srcoff, srcpitch);
919f844d85Smacallan	fPtr->offset = srcoff >> 11;
92727c6de2Smacallan	NGLEWaitMarker(pDstPixmap->drawable.pScreen, 0);
93727c6de2Smacallan	NGLEWrite4(fPtr, NGLE_REG_10,
94727c6de2Smacallan	    BA(IndexedDcd, Otc04, Ots08, AddrLong, 0, BINapp0I, 0));
959f844d85Smacallan	NGLEWrite4(fPtr, NGLE_REG_14,
96852b373fSmacallan	    IBOvals(RopSrc, 0, BitmapExtent08, 1, DataDynamic, MaskOtc, 0, 0));
97727c6de2Smacallan	NGLEWrite4(fPtr, NGLE_REG_13, planemask);
98727c6de2Smacallan
99727c6de2Smacallan	fPtr->hwmode = HW_BLIT;
100727c6de2Smacallan
101727c6de2Smacallan	LEAVE;
102727c6de2Smacallan	return TRUE;
103727c6de2Smacallan}
104727c6de2Smacallan
105ce159321Smacallanstatic Bool
106ce159321SmacallanNGLEPrepareCopy_HCRX
107ce159321Smacallan(
108ce159321Smacallan    PixmapPtr pSrcPixmap,
109ce159321Smacallan    PixmapPtr pDstPixmap,
110ce159321Smacallan    int       xdir,
111ce159321Smacallan    int       ydir,
112ce159321Smacallan    int       alu,
113ce159321Smacallan    Pixel     planemask
114ce159321Smacallan)
115ce159321Smacallan{
116ce159321Smacallan	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
117ce159321Smacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
118ce159321Smacallan	int srcpitch = exaGetPixmapPitch(pSrcPixmap);
119ce159321Smacallan	int srcoff = exaGetPixmapOffset(pSrcPixmap);
120ce159321Smacallan
121ce159321Smacallan	ENTER;
122ce159321Smacallan
123ce159321Smacallan	DBGMSG(X_ERROR, "%s %d %d\n", __func__, srcoff, srcpitch);
124ce159321Smacallan	fPtr->offset = srcoff / srcpitch;
125ce159321Smacallan	NGLEWaitMarker(pDstPixmap->drawable.pScreen, 0);
126ce159321Smacallan	NGLEWrite4(fPtr, NGLE_REG_10,
127ce159321Smacallan	    BA(FractDcd, Otc24, Ots08, AddrLong, 0, BINapp0F8, 0));
1289f844d85Smacallan	NGLEWrite4(fPtr, NGLE_REG_14,
1299f844d85Smacallan	    IBOvals(RopSrc, 0, BitmapExtent32, 0, DataDynamic, MaskOtc, 0, 0));
130ce159321Smacallan	NGLEWrite4(fPtr, NGLE_REG_13, planemask);
131ce159321Smacallan
132ce159321Smacallan	fPtr->hwmode = HW_BLIT;
133ce159321Smacallan
134ce159321Smacallan	LEAVE;
135ce159321Smacallan	return TRUE;
136ce159321Smacallan}
137ce159321Smacallan
138727c6de2Smacallanstatic void
139727c6de2SmacallanNGLECopy
140727c6de2Smacallan(
141727c6de2Smacallan    PixmapPtr pDstPixmap,
142727c6de2Smacallan    int       xs,
143727c6de2Smacallan    int       ys,
144727c6de2Smacallan    int       xd,
145727c6de2Smacallan    int       yd,
146727c6de2Smacallan    int       wi,
147727c6de2Smacallan    int       he
148727c6de2Smacallan)
149727c6de2Smacallan{
150727c6de2Smacallan	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
151727c6de2Smacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
152727c6de2Smacallan	int dstpitch = exaGetPixmapPitch(pDstPixmap);
153727c6de2Smacallan	int dstoff = exaGetPixmapOffset(pDstPixmap);
154727c6de2Smacallan
155727c6de2Smacallan	ENTER;
156727c6de2Smacallan	NGLEWaitFifo(fPtr, 3);
157727c6de2Smacallan	NGLEWrite4(fPtr, NGLE_REG_24, (xs << 16) | (ys + fPtr->offset));
158727c6de2Smacallan	NGLEWrite4(fPtr, NGLE_REG_7, (wi << 16) | he);
159727c6de2Smacallan	NGLEWrite4(fPtr, NGLE_REG_25, (xd << 16) | (yd + (dstoff / dstpitch)));
160727c6de2Smacallan
161727c6de2Smacallan	exaMarkSync(pDstPixmap->drawable.pScreen);
162727c6de2Smacallan	LEAVE;
163727c6de2Smacallan}
164727c6de2Smacallan
165727c6de2Smacallanstatic void
166727c6de2SmacallanNGLEDoneCopy(PixmapPtr pDstPixmap)
167727c6de2Smacallan{
168727c6de2Smacallan    ENTER;
169727c6de2Smacallan    LEAVE;
170727c6de2Smacallan}
171727c6de2Smacallan
172727c6de2Smacallanstatic Bool
173ce159321SmacallanNGLEPrepareSolid_EG(
174727c6de2Smacallan    PixmapPtr pPixmap,
175727c6de2Smacallan    int alu,
176727c6de2Smacallan    Pixel planemask,
177727c6de2Smacallan    Pixel fg)
178727c6de2Smacallan{
179727c6de2Smacallan	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
180727c6de2Smacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
181727c6de2Smacallan
182727c6de2Smacallan	ENTER;
183727c6de2Smacallan	NGLEWaitFifo(fPtr, 4);
184727c6de2Smacallan	/* plane mask */
185727c6de2Smacallan	NGLEWrite4(fPtr, NGLE_REG_13, planemask);
186727c6de2Smacallan	/* bitmap op */
187727c6de2Smacallan	NGLEWrite4(fPtr, NGLE_REG_14,
188e4f83f77Smacallan	    IBOvals(alu, 0, BitmapExtent08, 1, DataDynamic, MaskOtc, 1, 0));
189727c6de2Smacallan	/* dst bitmap access */
190727c6de2Smacallan	NGLEWrite4(fPtr, NGLE_REG_11,
191727c6de2Smacallan	    BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0I, 0));
192727c6de2Smacallan    	NGLEWrite4(fPtr, NGLE_REG_35, fg);
193727c6de2Smacallan	fPtr->hwmode = HW_FILL;
194727c6de2Smacallan
195727c6de2Smacallan	LEAVE;
196727c6de2Smacallan	return TRUE;
197727c6de2Smacallan}
198727c6de2Smacallan
199ce159321Smacallanstatic Bool
200ce159321SmacallanNGLEPrepareSolid_HCRX(
201ce159321Smacallan    PixmapPtr pPixmap,
202ce159321Smacallan    int alu,
203ce159321Smacallan    Pixel planemask,
204ce159321Smacallan    Pixel fg)
205ce159321Smacallan{
206ce159321Smacallan	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
207ce159321Smacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
208ce159321Smacallan
209ce159321Smacallan	ENTER;
210ce159321Smacallan	NGLEWaitFifo(fPtr, 4);
211ce159321Smacallan	/* plane mask */
212ce159321Smacallan	NGLEWrite4(fPtr, NGLE_REG_13, planemask);
213ce159321Smacallan	/* bitmap op */
214ce159321Smacallan	NGLEWrite4(fPtr, NGLE_REG_14,
215e4f83f77Smacallan	    IBOvals(alu, 0, BitmapExtent32, 1, DataDynamic, MaskOtc, 1, 0));
216ce159321Smacallan	/* dst bitmap access */
217ce159321Smacallan	NGLEWrite4(fPtr, NGLE_REG_11,
218ce159321Smacallan	    BA(FractDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0F8, 0));
219ce159321Smacallan    	NGLEWrite4(fPtr, NGLE_REG_35, fg);
220ce159321Smacallan	fPtr->hwmode = HW_FILL;
221ce159321Smacallan
222ce159321Smacallan	LEAVE;
223ce159321Smacallan	return TRUE;
224ce159321Smacallan}
225ce159321Smacallan
226727c6de2Smacallanstatic void
227727c6de2SmacallanNGLESolid(
228727c6de2Smacallan    PixmapPtr pPixmap,
229727c6de2Smacallan    int x1,
230727c6de2Smacallan    int y1,
231727c6de2Smacallan    int x2,
232727c6de2Smacallan    int y2)
233727c6de2Smacallan{
234727c6de2Smacallan	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
235727c6de2Smacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
236727c6de2Smacallan	int w = x2 - x1, h = y2 - y1;
237727c6de2Smacallan	int pitch = exaGetPixmapPitch(pPixmap);
238727c6de2Smacallan	int offset = exaGetPixmapOffset(pPixmap);
239727c6de2Smacallan	uint32_t mask;
240727c6de2Smacallan	int wi, rest;
241727c6de2Smacallan
242727c6de2Smacallan	ENTER;
243727c6de2Smacallan
244852b373fSmacallan	y1 += offset / pitch;
245727c6de2Smacallan
246e4f83f77Smacallan	NGLEWaitFifo(fPtr, 3);
247e4f83f77Smacallan	/* transfer data */
248e4f83f77Smacallan	NGLEWrite4(fPtr, NGLE_REG_8, 0xffffffff);
249e4f83f77Smacallan	/* dst XY */
250e4f83f77Smacallan	NGLEWrite4(fPtr, NGLE_REG_6, (x1 << 16) | y1);
251e4f83f77Smacallan	/* len XY start */
252e4f83f77Smacallan	NGLEWrite4(fPtr, NGLE_REG_9, (w << 16) | h);
253e4f83f77Smacallan
254727c6de2Smacallan	exaMarkSync(pPixmap->drawable.pScreen);
255727c6de2Smacallan	LEAVE;
256727c6de2Smacallan}
257727c6de2Smacallan
258727c6de2SmacallanBool
259ce159321SmacallanNGLEPrepareAccess_EG(PixmapPtr pPixmap, int index)
260727c6de2Smacallan{
261727c6de2Smacallan	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
262727c6de2Smacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
263727c6de2Smacallan
264727c6de2Smacallan	if (fPtr->hwmode == HW_FB) return TRUE;
265727c6de2Smacallan
266727c6de2Smacallan	NGLEWaitMarker(pPixmap->drawable.pScreen, 0);
267ce159321Smacallan	NGLEWrite4(fPtr, NGLE_REG_10,
268ce159321Smacallan	    BA(IndexedDcd, Otc04, Ots08, AddrByte, 0, BINapp0I, 0));
269727c6de2Smacallan	NGLEWrite4(fPtr, NGLE_REG_14, 0x83000300);
270727c6de2Smacallan	NGLEWrite4(fPtr, NGLE_REG_13, 0xff);
271727c6de2Smacallan	NGLEWaitMarker(pPixmap->drawable.pScreen, 0);
272727c6de2Smacallan	NGLEWrite1(fPtr, NGLE_REG_16b1, 1);
273727c6de2Smacallan	fPtr->hwmode = HW_FB;
274727c6de2Smacallan	return TRUE;
275727c6de2Smacallan}
276727c6de2Smacallan
277ce159321SmacallanBool
278ce159321SmacallanNGLEPrepareAccess_HCRX(PixmapPtr pPixmap, int index)
279ce159321Smacallan{
280ce159321Smacallan	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
281ce159321Smacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
282ce159321Smacallan
283ce159321Smacallan	if (fPtr->hwmode == HW_FB) return TRUE;
284ce159321Smacallan
285ce159321Smacallan	NGLEWaitMarker(pPixmap->drawable.pScreen, 0);
286ce159321Smacallan	NGLEWrite4(fPtr, NGLE_REG_10,
287ce159321Smacallan	    BA(FractDcd, Otc24, Ots08, AddrLong, 0, BINapp0F8, 0));
288ce159321Smacallan	NGLEWrite4(fPtr, NGLE_REG_14, 0x83000300);
289ce159321Smacallan	NGLEWrite4(fPtr, NGLE_REG_13, 0xffffffff);
290ce159321Smacallan	NGLEWaitMarker(pPixmap->drawable.pScreen, 0);
291ce159321Smacallan	NGLEWrite1(fPtr, NGLE_REG_16b1, 1);
292ce159321Smacallan	fPtr->hwmode = HW_FB;
293ce159321Smacallan	return TRUE;
294ce159321Smacallan}
295727c6de2SmacallanBool
296727c6de2SmacallanNGLEInitAccel(ScreenPtr pScreen)
297727c6de2Smacallan{
298727c6de2Smacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
299727c6de2Smacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
300727c6de2Smacallan	ExaDriverPtr pExa;
301727c6de2Smacallan	int lines, bpp = pScrn->bitsPerPixel >> 3;
302727c6de2Smacallan
303727c6de2Smacallan	pExa = exaDriverAlloc();
304727c6de2Smacallan	if (!pExa)
305727c6de2Smacallan		return FALSE;
306727c6de2Smacallan
307727c6de2Smacallan	fPtr->pExa = pExa;
308727c6de2Smacallan
309727c6de2Smacallan	pExa->exa_major = EXA_VERSION_MAJOR;
310727c6de2Smacallan	pExa->exa_minor = EXA_VERSION_MINOR;
311727c6de2Smacallan
312727c6de2Smacallan	pExa->memoryBase = fPtr->fbmem;
313727c6de2Smacallan	lines = fPtr->fbmem_len / fPtr->fbi.fbi_stride;
314727c6de2Smacallan	DBGMSG(X_ERROR, "lines %d\n", lines);
315727c6de2Smacallan	pExa->memorySize = fPtr->fbmem_len;
316727c6de2Smacallan	pExa->offScreenBase = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height;
317727c6de2Smacallan	pExa->pixmapOffsetAlign = fPtr->fbi.fbi_stride;
318727c6de2Smacallan	pExa->pixmapPitchAlign = fPtr->fbi.fbi_stride;
319727c6de2Smacallan
320727c6de2Smacallan	pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_MIXED_PIXMAPS;
321727c6de2Smacallan
322727c6de2Smacallan	pExa->maxX = 2048;
323727c6de2Smacallan	pExa->maxY = 2048;
324727c6de2Smacallan
325727c6de2Smacallan	fPtr->hwmode = -1;
326727c6de2Smacallan
327727c6de2Smacallan	pExa->WaitMarker = NGLEWaitMarker;
328727c6de2Smacallan	pExa->Solid = NGLESolid;
329727c6de2Smacallan	pExa->DoneSolid = NGLEDoneCopy;
330727c6de2Smacallan	pExa->Copy = NGLECopy;
331727c6de2Smacallan	pExa->DoneCopy = NGLEDoneCopy;
332ce159321Smacallan	switch (fPtr->gid) {
333ce159321Smacallan		case STI_DD_EG:
334ce159321Smacallan			pExa->PrepareCopy = NGLEPrepareCopy_EG;
335ce159321Smacallan			pExa->PrepareSolid = NGLEPrepareSolid_EG;
336ce159321Smacallan			pExa->PrepareAccess = NGLEPrepareAccess_EG;
337ce159321Smacallan			break;
338ce159321Smacallan		case STI_DD_HCRX:
339ce159321Smacallan			pExa->PrepareCopy = NGLEPrepareCopy_HCRX;
340ce159321Smacallan			pExa->PrepareSolid = NGLEPrepareSolid_HCRX;
341ce159321Smacallan			pExa->PrepareAccess = NGLEPrepareAccess_HCRX;
342ce159321Smacallan			break;
343ce159321Smacallan		default:
344ce159321Smacallan			xf86Msg(X_ERROR,
345852b373fSmacallan			    "unsupported device GID %08x\n", fPtr->gid);
346ce159321Smacallan			return FALSE;
347ce159321Smacallan	}
348727c6de2Smacallan	NGLEWaitMarker(pScreen, 0);
349727c6de2Smacallan
350727c6de2Smacallan	return exaDriverInit(pScreen, pExa);
351727c6de2Smacallan}
352