1/*
2	Haiku ATI video driver adapted from the X.org ATI driver.
3
4	Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
5						 Precision Insight, Inc., Cedar Park, Texas, and
6						 VA Linux Systems Inc., Fremont, California.
7
8	Copyright 2009 Haiku, Inc.  All rights reserved.
9	Distributed under the terms of the MIT license.
10
11	Authors:
12	Gerald Zajac 2009
13*/
14
15
16#include "accelerant.h"
17#include "rage128.h"
18
19
20
21
22void
23Rage128_EngineFlush()
24{
25	// Flush all dirty data in the Pixel Cache to memory.
26
27	OUTREGM(R128_PC_NGUI_CTLSTAT, R128_PC_FLUSH_ALL, R128_PC_FLUSH_ALL);
28
29	for (int i = 0; i < R128_TIMEOUT; i++) {
30		if ( ! (INREG(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY))
31			break;
32	}
33}
34
35
36void
37Rage128_EngineReset()
38{
39	// Reset graphics card to known state.
40
41	Rage128_EngineFlush();
42
43	uint32 clockCntlIndex = INREG(R128_CLOCK_CNTL_INDEX);
44	uint32 mclkCntl = GetPLLReg(R128_MCLK_CNTL);
45
46	SetPLLReg(R128_MCLK_CNTL, mclkCntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP);
47
48	uint32 genResetCntl = INREG(R128_GEN_RESET_CNTL);
49
50	OUTREG(R128_GEN_RESET_CNTL, genResetCntl | R128_SOFT_RESET_GUI);
51	INREG(R128_GEN_RESET_CNTL);
52	OUTREG(R128_GEN_RESET_CNTL, genResetCntl & ~R128_SOFT_RESET_GUI);
53	INREG(R128_GEN_RESET_CNTL);
54
55	SetPLLReg(R128_MCLK_CNTL, mclkCntl);
56	OUTREG(R128_CLOCK_CNTL_INDEX, clockCntlIndex);
57	OUTREG(R128_GEN_RESET_CNTL, genResetCntl);
58}
59
60
61void
62Rage128_EngineInit(const DisplayModeEx& mode)
63{
64	// Initialize the acceleration hardware.
65
66	SharedInfo& si = *gInfo.sharedInfo;
67
68	TRACE("Rage128_EngineInit()  bits/pixel: %d\n", mode.bitsPerPixel);
69
70	OUTREG(R128_SCALE_3D_CNTL, 0);
71	Rage128_EngineReset();
72
73	uint32 dataType = 0;
74
75	switch (mode.bitsPerPixel) {
76	case 8:
77		dataType = 2;
78		break;
79	case 15:
80		dataType = 3;
81		break;
82	case 16:
83		dataType = 4;
84		break;
85	case 32:
86		dataType = 6;
87		break;
88	default:
89		TRACE("Unsupported color depth: %d bits/pixel\n", mode.bitsPerPixel);
90	}
91
92	gInfo.WaitForFifo(2);
93	OUTREG(R128_DEFAULT_OFFSET, gInfo.sharedInfo->frameBufferOffset);
94	OUTREG(R128_DEFAULT_PITCH, mode.timing.h_display / 8);
95
96	gInfo.WaitForFifo(4);
97	OUTREG(R128_AUX_SC_CNTL, 0);
98	OUTREG(R128_DEFAULT_SC_BOTTOM_RIGHT, (R128_DEFAULT_SC_RIGHT_MAX
99										| R128_DEFAULT_SC_BOTTOM_MAX));
100	OUTREG(R128_SC_TOP_LEFT, 0);
101	OUTREG(R128_SC_BOTTOM_RIGHT, (R128_DEFAULT_SC_RIGHT_MAX
102								| R128_DEFAULT_SC_BOTTOM_MAX));
103
104	si.r128_dpGuiMasterCntl = ((dataType << R128_GMC_DST_DATATYPE_SHIFT)
105								| R128_GMC_CLR_CMP_CNTL_DIS
106								| R128_GMC_AUX_CLIP_DIS);
107	gInfo.WaitForFifo(1);
108	OUTREG(R128_DP_GUI_MASTER_CNTL, (si.r128_dpGuiMasterCntl
109									| R128_GMC_BRUSH_SOLID_COLOR
110									| R128_GMC_SRC_DATATYPE_COLOR));
111
112	gInfo.WaitForFifo(8);
113	OUTREG(R128_DST_BRES_ERR, 0);
114	OUTREG(R128_DST_BRES_INC, 0);
115	OUTREG(R128_DST_BRES_DEC, 0);
116	OUTREG(R128_DP_BRUSH_FRGD_CLR, 0xffffffff);
117	OUTREG(R128_DP_BRUSH_BKGD_CLR, 0x00000000);
118	OUTREG(R128_DP_SRC_FRGD_CLR, 0xffffffff);
119	OUTREG(R128_DP_SRC_BKGD_CLR, 0x00000000);
120	OUTREG(R128_DP_WRITE_MASK, 0xffffffff);
121
122	gInfo.WaitForFifo(1);
123	OUTREGM(R128_DP_DATATYPE, 0, R128_HOST_BIG_ENDIAN_EN);
124
125	gInfo.WaitForIdle();
126}
127
128
129void
130Rage128_FillRectangle(engine_token *et, uint32 color, fill_rect_params *pList, uint32 count)
131{
132	(void)et;		// avoid compiler warning for unused arg
133
134	gInfo.WaitForFifo(3);
135	OUTREG(R128_DP_GUI_MASTER_CNTL, (gInfo.sharedInfo->r128_dpGuiMasterCntl
136									| R128_GMC_BRUSH_SOLID_COLOR
137									| R128_GMC_SRC_DATATYPE_COLOR
138									| R128_ROP3_P));	// use GXcopy for rop
139
140	OUTREG(R128_DP_BRUSH_FRGD_CLR, color);
141	OUTREG(R128_DP_CNTL, R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM);
142
143	while (count--) {
144		int x = pList->left;
145		int y = pList->top;
146		int w = pList->right - x + 1;
147		int h = pList->bottom - y + 1;
148
149		gInfo.WaitForFifo(2);
150		OUTREG(R128_DST_Y_X, (y << 16) | x);
151		OUTREG(R128_DST_WIDTH_HEIGHT, (w << 16) | h);
152
153		pList++;
154	}
155}
156
157
158void
159Rage128_FillSpan(engine_token *et, uint32 color, uint16 *pList, uint32 count)
160{
161	(void)et;		// avoid compiler warning for unused arg
162
163	gInfo.WaitForFifo(2);
164	OUTREG(R128_DP_GUI_MASTER_CNTL, (gInfo.sharedInfo->r128_dpGuiMasterCntl
165									| R128_GMC_BRUSH_SOLID_COLOR
166									| R128_GMC_SRC_DATATYPE_COLOR
167									| R128_ROP3_P));	// use GXcopy for rop
168
169	OUTREG(R128_DP_BRUSH_FRGD_CLR, color);
170
171	while (count--) {
172		int y = *pList++;
173		int x = *pList++;
174		int w = *pList++ - x + 1;
175
176		if (w <= 0)
177			continue;	// discard span with zero or negative width
178
179		gInfo.WaitForFifo(2);
180		OUTREG(R128_DST_Y_X, (y << 16) | x);
181		OUTREG(R128_DST_WIDTH_HEIGHT, (w << 16) | 1);
182	}
183}
184
185
186void
187Rage128_InvertRectangle(engine_token *et, fill_rect_params *pList, uint32 count)
188{
189	(void)et;		// avoid compiler warning for unused arg
190
191	gInfo.WaitForFifo(2);
192	OUTREG(R128_DP_GUI_MASTER_CNTL, (gInfo.sharedInfo->r128_dpGuiMasterCntl
193									| R128_GMC_BRUSH_NONE
194									| R128_GMC_SRC_DATATYPE_COLOR
195									| R128_DP_SRC_SOURCE_MEMORY
196									| R128_ROP3_Dn));	// use GXinvert for rop
197
198	OUTREG(R128_DP_CNTL, R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM);
199
200	while (count--) {
201		int x = pList->left;
202		int y = pList->top;
203		int w = pList->right - x + 1;
204		int h = pList->bottom - y + 1;
205
206		gInfo.WaitForFifo(2);
207		OUTREG(R128_DST_Y_X, (y << 16) | x);
208		OUTREG(R128_DST_WIDTH_HEIGHT, (w << 16) | h);
209
210		pList++;
211	}
212}
213
214
215void
216Rage128_ScreenToScreenBlit(engine_token *et, blit_params *pList, uint32 count)
217{
218	(void)et;		// avoid compiler warning for unused arg
219
220	gInfo.WaitForFifo(1);
221	OUTREG(R128_DP_GUI_MASTER_CNTL, (gInfo.sharedInfo->r128_dpGuiMasterCntl
222									| R128_GMC_BRUSH_NONE
223									| R128_GMC_SRC_DATATYPE_COLOR
224									| R128_DP_SRC_SOURCE_MEMORY
225									| R128_ROP3_S));	// use GXcopy for rop
226
227	while (count--) {
228		int cmd = 0;
229		int src_x = pList->src_left;
230		int src_y = pList->src_top;
231		int dest_x = pList->dest_left;
232		int dest_y = pList->dest_top;
233		int width = pList->width;
234		int height = pList->height;
235
236		if (dest_x <= src_x) {
237			cmd |= R128_DST_X_LEFT_TO_RIGHT;
238		} else {
239			src_x += width;
240			dest_x += width;
241		}
242
243		if (dest_y <= src_y) {
244			cmd |= R128_DST_Y_TOP_TO_BOTTOM;
245		} else {
246			src_y += height;
247			dest_y += height;
248		}
249
250		gInfo.WaitForFifo(4);
251		OUTREG(R128_DP_CNTL, cmd);
252		OUTREG(R128_SRC_Y_X, (src_y << 16) | src_x);
253		OUTREG(R128_DST_Y_X, (dest_y << 16) | dest_x);
254		OUTREG(R128_DST_HEIGHT_WIDTH, ((height + 1) << 16) | (width + 1));
255
256		pList ++;
257	}
258}
259