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