1/*
2 * SBus Weitek P9100 EXA support
3 */
4/*-
5 * Copyright (c) 2021 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Julian Coleman.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32/* $NetBSD: pnozz_exa.c,v 1.6 2023/11/05 17:06:14 jdc Exp $ */
33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
38#include "pnozz.h"
39#include "pnozz_regs.h"
40
41
42static CARD32 PnozzCopyROP[] = {
43	/*GXclear*/		0,
44	/*GXand*/		ROP_SRC & ROP_DST,
45	/*GXandReverse*/	ROP_SRC & (~ROP_DST),
46	/*GXcopy*/		ROP_SRC,
47	/*GXandInverted*/	(~ROP_SRC) & ROP_DST,
48	/*GXnoop*/		ROP_DST,
49	/*GXxor*/		ROP_SRC ^ ROP_DST,
50	/*GXor*/		ROP_SRC | ROP_DST,
51	/*GXnor*/		(~ROP_SRC) & (~ROP_DST),
52	/*GXequiv*/		(~ROP_SRC) ^ ROP_DST,
53	/*GXinvert*/		(~ROP_DST),
54	/*GXorReverse*/		ROP_SRC | (~ROP_DST),
55	/*GXcopyInverted*/	(~ROP_SRC),
56	/*GXorInverted*/	(~ROP_SRC) | ROP_DST,
57	/*GXnand*/		(~ROP_SRC) | (~ROP_DST),
58	/*GXset*/		ROP_SET
59};
60
61static CARD32 PnozzDrawROP[] = {
62	/*GXclear*/		0,
63	/*GXand*/		ROP_PAT & ROP_DST,
64	/*GXandReverse*/	ROP_PAT & (~ROP_DST),
65	/*GXcopy*/		ROP_PAT,
66	/*GXandInverted*/	(~ROP_PAT) & ROP_DST,
67	/*GXnoop*/		ROP_DST,
68	/*GXxor*/		ROP_PAT ^ ROP_DST,
69	/*GXor*/		ROP_PAT | ROP_DST,
70	/*GXnor*/		(~ROP_PAT) & (~ROP_DST),
71	/*GXequiv*/		(~ROP_PAT) ^ ROP_DST,
72	/*GXinvert*/		(~ROP_DST),
73	/*GXorReverse*/		ROP_PAT | (~ROP_DST),
74	/*GXcopyInverted*/	(~ROP_PAT),
75	/*GXorInverted*/	(~ROP_PAT) | ROP_DST,
76	/*GXnand*/		(~ROP_PAT) | (~ROP_DST),
77	/*GXset*/		ROP_PAT
78};
79
80#define waitReady(pPnozz) while((pnozz_read_4(pPnozz, ENGINE_STATUS) & \
81				(ENGINE_BUSY | BLITTER_BUSY)) !=0 )
82
83void PnozzInitEngine(PnozzPtr);
84void pnozz_write_colour(PnozzPtr pPnozz, int reg, CARD32 colour);
85
86extern CARD32 MaxClip, junk;
87
88static void
89PnozzWaitMarker(ScreenPtr pScreen, int Marker)
90{
91    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
92    PnozzPtr p = GET_PNOZZ_FROM_SCRN(pScrn);
93
94    waitReady(p);
95}
96
97static Bool
98PnozzPrepareCopy
99(
100    PixmapPtr pSrcPixmap,
101    PixmapPtr pDstPixmap,
102    int       xdir,
103    int       ydir,
104    int       alu,
105    Pixel     planemask
106)
107{
108    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
109    PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn);
110
111    waitReady(pPnozz);
112    pnozz_write_4(pPnozz, RASTER_OP, (PnozzCopyROP[alu] & 0xff));
113    pnozz_write_4(pPnozz, PLANE_MASK, planemask);
114    pPnozz->srcoff = exaGetPixmapOffset(pSrcPixmap) / pPnozz->width;
115
116    return TRUE;
117}
118
119static void
120PnozzCopy
121(
122    PixmapPtr pDstPixmap,
123    int       xSrc,
124    int       ySrc,
125    int       xDst,
126    int       yDst,
127    int       w,
128    int       h
129)
130{
131    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
132    PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn);
133    CARD32 src, dst, srcw, dstw;
134    int doff = exaGetPixmapOffset(pDstPixmap) / pPnozz->width;
135
136    src = (((xSrc << pPnozz->depthshift) & 0x1fff) << 16) |
137	((ySrc + pPnozz->srcoff) & 0x1fff);
138    dst = (((xDst << pPnozz->depthshift) & 0x1fff) << 16) |
139	((yDst + doff) & 0x1fff);
140    srcw = ((((xSrc + w) << pPnozz->depthshift) - 1) << 16) |
141        ((ySrc + pPnozz->srcoff + h - 1) & 0x1fff);
142    dstw = ((((xDst + w) << pPnozz->depthshift) - 1) << 16) |
143        ((yDst + doff + h - 1) & 0x1fff);
144
145    waitReady(pPnozz);
146
147    pnozz_write_4(pPnozz, ABS_XY0, src);
148    pnozz_write_4(pPnozz, ABS_XY1, srcw);
149    pnozz_write_4(pPnozz, ABS_XY2, dst);
150    pnozz_write_4(pPnozz, ABS_XY3, dstw);
151    junk = pnozz_read_4(pPnozz, COMMAND_BLIT);
152    exaMarkSync(pDstPixmap->drawable.pScreen);
153}
154
155static void
156PnozzDoneCopy(PixmapPtr pDstPixmap)
157{
158    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
159    PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn);
160
161    waitReady(pPnozz);
162}
163
164static Bool
165PnozzPrepareSolid(
166    PixmapPtr pPixmap,
167    int alu,
168    Pixel planemask,
169    Pixel fg)
170{
171    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
172    PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn);
173
174    waitReady(pPnozz);
175    pnozz_write_colour(pPnozz, FOREGROUND_COLOR, fg);
176    pnozz_write_4(pPnozz, RASTER_OP, PnozzDrawROP[alu] & 0xff);
177    pnozz_write_4(pPnozz, PLANE_MASK, planemask);
178    pnozz_write_4(pPnozz, COORD_INDEX, 0);
179
180    return TRUE;
181}
182
183static void
184PnozzSolid(
185    PixmapPtr pPixmap,
186    int x,
187    int y,
188    int x2,
189    int y2)
190{
191    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
192    PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn);
193    int w = x2 - x - 1;
194    int h = y2 - y - 1;
195
196    waitReady(pPnozz);
197    pnozz_write_4(pPnozz, RECT_RTW_XY, ((x & 0x1fff) << 16) |
198        (y & 0x1fff));
199    pnozz_write_4(pPnozz, RECT_RTP_XY, (((w & 0x1fff) << 16) |
200        (h & 0x1fff)));
201    junk = pnozz_read_4(pPnozz, COMMAND_QUAD);
202    exaMarkSync(pPixmap->drawable.pScreen);
203}
204
205int
206PnozzEXAInit(ScreenPtr pScreen)
207{
208    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
209    PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn);
210    ExaDriverPtr pExa;
211
212    PnozzInitEngine(pPnozz);
213
214    pExa = exaDriverAlloc();
215    if (!pExa)
216	return FALSE;
217
218    pPnozz->pExa = pExa;
219
220    pExa->exa_major = EXA_VERSION_MAJOR;
221    pExa->exa_minor = EXA_VERSION_MINOR;
222
223    pExa->memoryBase = pPnozz->fb;
224
225    /* round to multiple of pixmap pitch */
226    pExa->memorySize = (pPnozz->vidmem / pPnozz->width) * pPnozz->width;
227    pExa->offScreenBase = pPnozz->width * pPnozz->height;
228
229    /*
230     * our blitter can't deal with variable pitches
231     */
232    pExa->pixmapOffsetAlign = pPnozz->width;
233    pExa->pixmapPitchAlign = pPnozz->width;
234
235    pExa->flags = EXA_MIXED_PIXMAPS;
236
237    pExa->maxX = 4096;
238    pExa->maxY = 4096;
239
240    pExa->WaitMarker = PnozzWaitMarker;
241
242    pExa->PrepareSolid = PnozzPrepareSolid;
243    pExa->Solid = PnozzSolid;
244    pExa->DoneSolid = PnozzDoneCopy;
245
246    pExa->PrepareCopy = PnozzPrepareCopy;
247    pExa->Copy = PnozzCopy;
248    pExa->DoneCopy = PnozzDoneCopy;
249
250    return exaDriverInit(pScreen, pExa);;
251}
252