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// Memory Specifications from RAGE 128 Software Development Manual
22// (Technical Reference Manual P/N SDK-G04000 Rev 0.01), page 3-21.
23static R128_RAMSpec sRAMSpecs[] = {
24	{ 4, 4, 3, 3, 1, 3, 1, 16, 12, "128-bit SDR SGRAM 1:1" },
25	{ 4, 8, 3, 3, 1, 3, 1, 17, 13, "64-bit SDR SGRAM 1:1" },
26	{ 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SGRAM 2:1" },
27	{ 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SGRAM" },
28};
29
30
31
32static bool
33Rage128_GetColorSpaceParams(int colorSpace, uint8& bitsPerPixel, uint32& maxPixelClock)
34{
35	// Get parameters for a color space which is supported by the Rage128 chips.
36	// Argument maxPixelClock is in KHz.
37	// Return true if the color space is supported;  else return false.
38
39	switch (colorSpace) {
40		case B_RGB32:
41			bitsPerPixel = 32;
42			break;
43		case B_RGB16:
44			bitsPerPixel = 16;
45			break;
46		case B_RGB15:
47			bitsPerPixel = 15;
48			break;
49		case B_CMAP8:
50			bitsPerPixel = 8;
51			break;
52		default:
53			TRACE("Unsupported color space: 0x%X\n", colorSpace);
54			return false;
55	}
56
57	maxPixelClock = gInfo.sharedInfo->r128PLLParams.max_pll_freq * 10;
58	return true;
59}
60
61
62static void
63WaitForFifo(uint32 entries)
64{
65	// The FIFO has 64 slots.  This routines waits until at least `entries'
66	// of these slots are empty.
67
68	while (true) {
69		for (int i = 0; i < R128_TIMEOUT; i++) {
70			uint32 slots = INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK;
71			if (slots >= entries)
72				return;
73		}
74
75		TRACE("FIFO timed out: %d entries, stat=0x%08x, probe=0x%08x\n",
76			INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK,
77			INREG(R128_GUI_STAT),
78			INREG(R128_GUI_PROBE));
79		TRACE("FIFO timed out, resetting engine...\n");
80
81		Rage128_EngineReset();
82	}
83}
84
85
86static void
87WaitForIdle()
88{
89	// Wait for the graphics engine to be completely idle.  That is, the FIFO
90	// has drained, the Pixel Cache is flushed, and the engine is idle.  This
91	// is a standard "sync" function that will make the hardware "quiescent".
92
93	WaitForFifo(64);
94
95	while (true) {
96		for (uint32 i = 0; i < R128_TIMEOUT; i++) {
97			if ( ! (INREG(R128_GUI_STAT) & R128_GUI_ACTIVE)) {
98				Rage128_EngineFlush();
99				return ;
100			}
101		}
102
103		TRACE("Idle timed out: %d entries, stat=0x%08x, probe=0x%08x\n",
104				   INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK,
105				   INREG(R128_GUI_STAT),
106				   INREG(R128_GUI_PROBE));
107		TRACE("Idle timed out, resetting engine...\n");
108
109		Rage128_EngineReset();
110	}
111}
112
113
114status_t
115Rage128_Init(void)
116{
117	TRACE("Rage128_Init()\n");
118
119	SharedInfo& si = *gInfo.sharedInfo;
120
121	si.videoMemSize = INREG(R128_CONFIG_MEMSIZE);
122
123	si.cursorOffset = (si.videoMemSize - CURSOR_BYTES) & ~0xfff;	// align to 4k boundary
124	si.frameBufferOffset = 0;
125	si.maxFrameBufferSize = si.cursorOffset - si.frameBufferOffset;
126
127	TRACE("Video Memory size: %d MB  frameBufferOffset: 0x%x  cursorOffset: 0x%x\n",
128		si.videoMemSize / 1024 / 1024, si.frameBufferOffset, si.cursorOffset);
129
130	// Get the specifications of the memory used by the chip.
131
132	uint32 offset;
133
134	switch (INREG(R128_MEM_CNTL) & 0x3) {
135	case 0:					// SDR SGRAM 1:1
136		switch (si.deviceID) {
137		case 0x4C45:		// RAGE128 LE:
138		case 0x4C46:		// RAGE128 LF:
139		case 0x4D46:		// RAGE128 MF:
140		case 0x4D4C:		// RAGE128 ML:
141		case 0x5245:		// RAGE128 RE:
142		case 0x5246:		// RAGE128 RF:
143		case 0x5247:		// RAGE128 RG:
144		case 0x5446:		// RAGE128 TF:
145		case 0x544C:		// RAGE128 TL:
146		case 0x5452:		// RAGE128 TR:
147			offset = 0;		// 128-bit SDR SGRAM 1:1
148			break;
149		default:
150			offset = 1;		// 64-bit SDR SGRAM 1:1
151			break;
152		}
153		break;
154	case 1:
155		offset = 2;		// 64-bit SDR SGRAM 2:1
156		break;
157	case 2:
158		offset = 3;		// 64-bit DDR SGRAM
159		break;
160	default:
161		offset = 1;		// 64-bit SDR SGRAM 1:1
162		break;
163	}
164	si.r128MemSpec = sRAMSpecs[offset];
165	TRACE("RAM type: %s\n", si.r128MemSpec.name);
166
167	// Determine the type of display.
168
169	si.displayType = MT_VGA;
170
171	if (INREG(R128_FP_PANEL_CNTL) & R128_FP_DIGON)	// don't know if this is correct
172		si.displayType = MT_DVI;
173
174	if (si.chipType == RAGE128_MOBILITY && si.panelX > 0 && si.panelY > 0) {
175		if (INREG(R128_LVDS_GEN_CNTL) & R128_LVDS_ON)
176			si.displayType = MT_LAPTOP;	// laptop LCD display is on
177	}
178
179	// Set up the array of color spaces supported by the Rage128 chips.
180
181	si.colorSpaces[0] = B_CMAP8;
182	si.colorSpaces[1] = B_RGB15;
183	si.colorSpaces[2] = B_RGB16;
184	si.colorSpaces[3] = B_RGB32;
185	si.colorSpaceCount = 4;
186
187	// Setup the mode list.
188
189	return CreateModeList(IsModeUsable);
190}
191
192
193void
194Rage128_SetFunctionPointers(void)
195{
196	// Setting the function pointers must be done prior to first ModeInit call
197	// or any accel activity.
198
199	gInfo.WaitForFifo = WaitForFifo;
200	gInfo.WaitForIdle = WaitForIdle;
201
202	gInfo.DPMSCapabilities = Rage128_DPMSCapabilities;
203	gInfo.GetDPMSMode = Rage128_GetDPMSMode;
204	gInfo.SetDPMSMode = Rage128_SetDPMSMode;
205
206	gInfo.LoadCursorImage = Rage128_LoadCursorImage;
207	gInfo.SetCursorPosition = Rage128_SetCursorPosition;
208	gInfo.ShowCursor = Rage128_ShowCursor;
209
210	gInfo.FillRectangle = Rage128_FillRectangle;
211	gInfo.FillSpan = Rage128_FillSpan;
212	gInfo.InvertRectangle = Rage128_InvertRectangle;
213	gInfo.ScreenToScreenBlit = Rage128_ScreenToScreenBlit;
214
215	gInfo.AdjustFrame = Rage128_AdjustFrame;
216	gInfo.ChipInit = Rage128_Init;
217	gInfo.GetColorSpaceParams = Rage128_GetColorSpaceParams;
218	gInfo.SetDisplayMode = Rage128_SetDisplayMode;
219	gInfo.SetIndexedColors = Rage128_SetIndexedColors;
220}
221
222