1/*
2	Haiku ATI video driver adapted from the X.org ATI driver.
3
4	Copyright 1992,1993,1994,1995,1996,1997 by Kevin E. Martin, Chapel Hill, North Carolina.
5	Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
6
7	Copyright 2009 Haiku, Inc.  All rights reserved.
8	Distributed under the terms of the MIT license.
9
10	Authors:
11	Gerald Zajac 2009
12*/
13
14
15#include "accelerant.h"
16#include "mach64.h"
17
18
19
20void
21Mach64_EngineReset()
22{
23	// Reset engine and then enable it.
24
25	uint32 genTestCntl = INREG(GEN_TEST_CNTL) & ~GUI_ENGINE_ENABLE;
26	OUTREG(GEN_TEST_CNTL, genTestCntl);
27	OUTREG(GEN_TEST_CNTL, genTestCntl | GUI_ENGINE_ENABLE);
28
29	// Ensure engine is not locked up by clearing any FIFO errors.
30
31	OUTREG(BUS_CNTL, INREG(BUS_CNTL) | BUS_HOST_ERR_ACK | BUS_FIFO_ERR_ACK);
32}
33
34
35void
36Mach64_EngineInit(const DisplayModeEx& mode)
37{
38	// Initialize the drawing environment and clear the display.
39
40	Mach64_EngineReset();
41
42	gInfo.WaitForIdle();
43
44	OUTREG(MEM_VGA_WP_SEL, 0x00010000);
45	OUTREG(MEM_VGA_RP_SEL, 0x00010000);
46
47	uint32 dpPixWidth = 0;
48	uint32 dpChainMask = 0;
49
50	switch (mode.bitsPerPixel) {
51	case 8:
52		dpPixWidth = HOST_8BPP | SRC_8BPP | DST_8BPP;
53		dpChainMask = DP_CHAIN_8BPP;
54		break;
55	case 15:
56		dpPixWidth = HOST_15BPP | SRC_15BPP | DST_15BPP;
57		dpChainMask = DP_CHAIN_15BPP;
58		break;
59	case 16:
60		dpPixWidth = HOST_16BPP | SRC_16BPP | DST_16BPP;
61		dpChainMask = DP_CHAIN_16BPP;
62		break;
63	case 32:
64		dpPixWidth = HOST_32BPP | SRC_32BPP | DST_32BPP;
65		dpChainMask = DP_CHAIN_32BPP;
66		break;
67	}
68
69	dpPixWidth |= BYTE_ORDER_LSB_TO_MSB;	// set for little-endian byte order
70
71	gInfo.WaitForFifo(3);
72	OUTREG(DP_PIX_WIDTH, dpPixWidth);
73	OUTREG(DP_CHAIN_MASK, dpChainMask);
74
75	OUTREG(CONTEXT_MASK, 0xffffffff);
76
77	gInfo.WaitForFifo(7);
78	OUTREG(DST_OFF_PITCH, (mode.timing.h_display / 8) << 22);
79	OUTREG(DST_Y_X, 0);
80	OUTREG(DST_HEIGHT, 0);
81	OUTREG(DST_BRES_ERR, 0);
82	OUTREG(DST_BRES_INC, 0);
83	OUTREG(DST_BRES_DEC, 0);
84	OUTREG(DST_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM | DST_LAST_PEL);
85
86	gInfo.WaitForFifo(6);
87	OUTREG(SRC_OFF_PITCH, (mode.timing.h_display / 8) << 22);
88	OUTREG(SRC_Y_X, 0);
89	OUTREG(SRC_HEIGHT1_WIDTH1, 0x10001);
90	OUTREG(SRC_Y_X_START, 0);
91	OUTREG(SRC_HEIGHT2_WIDTH2, 0x10001);
92	OUTREG(SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT);
93
94	gInfo.WaitForFifo(7);
95	OUTREGM(HOST_CNTL, 0, HOST_BYTE_ALIGN);
96	OUTREG(PAT_REG0, 0);
97	OUTREG(PAT_REG1, 0);
98	OUTREG(PAT_CNTL, 0);
99
100	OUTREG(SC_LEFT_RIGHT, ((mode.timing.h_display << 16) | 0 ));
101	OUTREG(SC_TOP_BOTTOM, ((mode.timing.v_display << 16) | 0 ));
102
103	gInfo.WaitForFifo(9);
104	OUTREG(DP_BKGD_CLR, 0);
105	OUTREG(DP_FRGD_CLR, 0xffffffff);
106	OUTREG(DP_WRITE_MASK, 0xffffffff);
107	OUTREG(DP_MIX, (MIX_SRC << 16) | MIX_DST);
108	OUTREG(DP_SRC, FRGD_SRC_FRGD_CLR);
109
110	OUTREG(CLR_CMP_CLR, 0);
111	OUTREG(CLR_CMP_MASK, 0xffffffff);
112	OUTREG(CLR_CMP_CNTL, 0);
113
114	gInfo.WaitForIdle();
115}
116
117
118void
119Mach64_FillRectangle(engine_token *et, uint32 color, fill_rect_params *pList, uint32 count)
120{
121	(void)et;		// avoid compiler warning for unused arg
122
123	gInfo.WaitForFifo(4);
124	OUTREG(DP_SRC, BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE);
125	OUTREG(DP_FRGD_CLR, color);
126	OUTREG(DP_MIX, (MIX_SRC << 16) | MIX_DST);
127	OUTREG(DST_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM | DST_LAST_PEL);
128
129	while (count--) {
130		int x = pList->left;
131		int y = pList->top;
132		int w = pList->right - x + 1;
133		int h = pList->bottom - y + 1;
134
135		gInfo.WaitForFifo(2);
136		OUTREG(DST_Y_X, (x << 16) | y);
137		OUTREG(DST_HEIGHT_WIDTH, (w << 16) | h);
138
139		pList++;
140	}
141}
142
143
144void
145Mach64_FillSpan(engine_token *et, uint32 color, uint16 *pList, uint32 count)
146{
147	(void)et;		// avoid compiler warning for unused arg
148
149	gInfo.WaitForFifo(4);
150	OUTREG(DP_SRC, BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE);
151	OUTREG(DP_FRGD_CLR, color);
152	OUTREG(DP_MIX, (MIX_SRC << 16) | MIX_DST);
153	OUTREG(DST_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM | DST_LAST_PEL);
154
155	while (count--) {
156		int y = *pList++;
157		int x = *pList++;
158		int w = *pList++ - x + 1;
159
160		if (w <= 0)
161			continue;	// discard span with zero or negative width
162
163		gInfo.WaitForFifo(2);
164		OUTREG(DST_Y_X, (x << 16) | y);
165		OUTREG(DST_HEIGHT_WIDTH, (w << 16) | 1);
166	}
167}
168
169
170void
171Mach64_InvertRectangle(engine_token *et, fill_rect_params *pList, uint32 count)
172{
173	(void)et;		// avoid compiler warning for unused arg
174
175	gInfo.WaitForFifo(3);
176	OUTREG(DP_SRC, BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE);
177	OUTREG(DP_MIX, MIX_NOT_DST << 16);
178	OUTREG(DST_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM | DST_LAST_PEL);
179
180	while (count--) {
181		int x = pList->left;
182		int y = pList->top;
183		int w = pList->right - x + 1;
184		int h = pList->bottom - y + 1;
185
186		gInfo.WaitForFifo(2);
187		OUTREG(DST_Y_X, (x << 16) | y);
188		OUTREG(DST_HEIGHT_WIDTH, (w << 16) | h);
189
190		pList++;
191	}
192}
193
194
195void
196Mach64_ScreenToScreenBlit(engine_token *et, blit_params *pList, uint32 count)
197{
198	(void)et;		// avoid compiler warning for unused arg
199
200	gInfo.WaitForFifo(2);
201	OUTREG(DP_SRC, FRGD_SRC_BLIT);
202	OUTREG(DP_MIX, MIX_SRC << 16);
203
204	while (count--) {
205		int cmd = DST_LAST_PEL;
206		int src_x = pList->src_left;
207		int src_y = pList->src_top;
208		int dest_x = pList->dest_left;
209		int dest_y = pList->dest_top;
210		int width = pList->width;
211		int height = pList->height;
212
213		if (dest_x <= src_x) {
214			cmd |= DST_X_LEFT_TO_RIGHT;
215		} else {
216			src_x += width;
217			dest_x += width;
218		}
219
220		if (dest_y <= src_y) {
221			cmd |= DST_Y_TOP_TO_BOTTOM;
222		} else {
223			src_y += height;
224			dest_y += height;
225		}
226
227		gInfo.WaitForFifo(5);
228		OUTREG(DST_CNTL, cmd);
229		OUTREG(SRC_Y_X, (src_x << 16) | src_y);
230		OUTREG(SRC_HEIGHT1_WIDTH1, ((width + 1) << 16) | (height + 1));
231		OUTREG(DST_Y_X, (dest_x << 16) | dest_y);
232		OUTREG(DST_HEIGHT_WIDTH, ((width + 1) << 16) | (height + 1));
233
234		pList ++;
235	}
236}
237