1/*
2	Haiku S3 Trio64 driver adapted from the X.org S3 driver.
3
4	Copyright 2001	Ani Joshi <ajoshi@unixbox.com>
5
6	Copyright 2008 Haiku, Inc.  All rights reserved.
7	Distributed under the terms of the MIT license.
8
9	Authors:
10	Gerald Zajac 2008
11*/
12
13
14#include "accel.h"
15#include "trio64.h"
16
17
18
19static void
20WaitQueue(uint32 slots )
21{
22	// Wait until the requested number of queue slots are available.
23
24	while (ReadReg16(GP_STAT) & (0x0100 >> slots)) {}
25}
26
27
28static void
29WaitIdle()
30{
31	// Wait until Graphics Processor is idle.
32
33	while (ReadReg16(GP_STAT) & GP_BUSY);
34}
35
36
37
38static bool
39Trio64_GetColorSpaceParams(int colorSpace, uint32& bitsPerPixel, uint32& maxPixelClock)
40{
41	// Get parameters for a color space which is supported by the Trio64 chips.
42	// Argument maxPixelClock is in KHz.
43	// Return true if the color space is supported;  else return false.
44
45	switch (colorSpace) {
46		case B_RGB16:
47			bitsPerPixel = 16;
48			maxPixelClock = 110000;
49			break;
50		case B_CMAP8:
51			bitsPerPixel = 8;
52			maxPixelClock = 180000;
53			break;
54		default:
55			TRACE("Unsupported color space: 0x%X\n", colorSpace);
56			return false;
57	}
58
59	return true;
60}
61
62
63static bool
64Trio64_IsModeUsable(const display_mode* mode)
65{
66	// Test if the display mode is usable by the current video chip.
67	// Return true if the mode is usable.
68
69	SharedInfo& si = *gInfo.sharedInfo;
70
71	if (si.chipType == S3_TRIO64 && mode->timing.h_display >= 1600)
72		return false;
73
74	return IsModeUsable(mode);
75}
76
77
78static status_t
79Trio64_Init(void)
80{
81	TRACE("Trio64_Init()\n");
82
83	SharedInfo& si = *gInfo.sharedInfo;
84
85	// Use PIO to enable VGA, enable color instead of monochrome, and
86	// enable MMIO.
87
88	WritePIO_8(VGA_ENABLE, ReadPIO_8(VGA_ENABLE) | 0x01);
89	WritePIO_8(MISC_OUT_W, ReadPIO_8(MISC_OUT_R) | 0x01);	// enable color
90
91	WritePIO_8(CRTC_INDEX, 0x53);
92	WritePIO_8(CRTC_DATA, ReadPIO_8(CRTC_DATA) | 0x8);		// enable MMIO
93
94	WriteCrtcReg(0x38, 0x48);		// unlock sys regs
95	WriteCrtcReg(0x39, 0xa5);		// unlock sys regs
96
97	WriteCrtcReg(0x40, 0x01, 0x01);
98	WriteCrtcReg(0x35, 0x00, 0x30);
99	WriteCrtcReg(0x33, 0x20, 0x72);
100
101	if (si.chipType == S3_TRIO64_V2) {
102		WriteCrtcReg(0x86, 0x80);
103		WriteCrtcReg(0x90, 0x00);
104	}
105
106	// Detect number of megabytes of installed ram.
107
108	static const uint8 ramSizes[] = { 4, 0, 3, 8, 2, 6, 1, 0 };
109	int ramSizeMB = ramSizes[(ReadCrtcReg(0x36) >> 5) & 0x7];
110
111	TRACE("memory size: %d MB\n", ramSizeMB);
112
113	if (ramSizeMB <= 0)
114		return B_ERROR;
115
116	si.videoMemSize = ramSizeMB * 1024 * 1024;
117	si.cursorOffset = si.videoMemSize - CURSOR_BYTES;	// put cursor at end of video memory
118	si.frameBufferOffset = 0;
119	si.maxFrameBufferSize = si.videoMemSize - CURSOR_BYTES;
120
121	// Detect current mclk.
122
123	WriteSeqReg(0x08, 0x06);		// unlock extended sequencer regs
124
125	uint8 m = ReadSeqReg(0x11) & 0x7f;
126	uint8 n = ReadSeqReg(0x10);
127	uint8 n1 = n & 0x1f;
128	uint8 n2 = (n >> 5) & 0x03;
129	si.mclk = ((1431818 * (m + 2)) / (n1 + 2) / (1 << n2) + 50) / 100;
130
131	TRACE("MCLK value: %1.3f MHz\n", si.mclk / 1000.0);
132
133	// Set up the array of color spaces supported by the Trio64 chips.
134
135	si.colorSpaces[0] = B_CMAP8;
136	si.colorSpaces[1] = B_RGB16;
137	si.colorSpaceCount = 2;
138
139	si.bDisableHdwCursor = false;	// allow use of hardware cursor
140	si.bDisableAccelDraw = false;	// allow use of accelerated drawing functions
141
142	// Setup the mode list.
143
144	return CreateModeList(Trio64_IsModeUsable, NULL);
145}
146
147
148void
149Trio64_SetFunctionPointers(void)
150{
151	// Setting the function pointers must be done prior to first ModeInit call
152	// or any accel activity.
153
154	gInfo.WaitQueue = WaitQueue;
155	gInfo.WaitIdleEmpty = WaitIdle;
156
157	gInfo.DPMSCapabilities = Trio64_DPMSCapabilities;
158	gInfo.GetDPMSMode = Trio64_GetDPMSMode;
159	gInfo.SetDPMSMode = Trio64_SetDPMSMode;
160
161	gInfo.LoadCursorImage = Trio64_LoadCursorImage;
162	gInfo.SetCursorPosition = Trio64_SetCursorPosition;
163	gInfo.ShowCursor = Trio64_ShowCursor;
164
165	// Note that the 2D accel functions set below do not work with all display
166	// modes;  thus, when a mode is set, the function setting the mode will
167	// adjust the pointers according to the mode that is set.
168
169	gInfo.FillRectangle = Trio64_FillRectangle;
170	gInfo.FillSpan = Trio64_FillSpan;
171	gInfo.InvertRectangle = Trio64_InvertRectangle;
172	gInfo.ScreenToScreenBlit = Trio64_ScreenToScreenBlit;
173
174	gInfo.AdjustFrame = Trio64_AdjustFrame;
175	gInfo.ChipInit = Trio64_Init;
176	gInfo.GetColorSpaceParams = Trio64_GetColorSpaceParams;
177	gInfo.SetDisplayMode = Trio64_SetDisplayMode;
178	gInfo.SetIndexedColors = Trio64_SetIndexedColors;
179}
180