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