1/*****************************************************************************\
2 * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
3 * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
4\*****************************************************************************/
5
6#include "setmode.h"
7
8
9/*
10 * ATTENTION: Currently we set the graphics modes by setting the registers
11 * with the beforehand dumped values of the corresponding registers. So not
12 * all graphics modes ET6x00 chips are capable of are accessible. So it would
13 * be great to implement the normal algorithm of run-time computing of the
14 * values to set the register.
15 */
16
17
18/*****************************************************************************/
19typedef struct {
20    uint32 VisScreenWidth;
21    uint32 VisScreenHeight;
22    uint8 BitsPerPlane;
23    uint8 NumberGreenBits;
24    uint16 Frequency;
25} VIDEO_MODE_INFORMATION;
26/*****************************************************************************/
27/*
28 * ATTENTION: Don't forget that CRTC indexed register 0x11
29 * bit[7] write-protects some registers.
30 */
31struct {
32    uint16 width, height, bpp, refreshRate;
33    uint8 clock0M, clock0N;
34    uint8 pci42; /* contains MCLK divider (MDIV) */
35    uint8 crtc[64];
36} clock0MN[] = {
37    {640, 480, 24, 75, 0x28, 0x22, 0x02,
38       {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
39        0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40        0xea, 0x0c, 0xdf, 0xf0, 0x60, 0xe7, 0x04, 0xab,
41        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
42        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
43        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
44        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
45        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
46    {640, 480, 24, 72, 0x56, 0x63, 0x00,
47       {0x63, 0x4f, 0x50, 0x86, 0x55, 0x9a, 0x06, 0x3e,
48        0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49        0xe8, 0x0b, 0xdf, 0xf0, 0x60, 0xe7, 0xff, 0xab,
50        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
51        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
52        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
53        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
54        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
55    {640, 480, 24, 60, 0x28, 0x22, 0x02,
56       {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
57        0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58        0xea, 0x0c, 0xdf, 0xf0, 0x60, 0xe7, 0x04, 0xab,
59        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
60        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
61        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
62        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
63        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
64
65    {640, 480, 16, 75, 0x56, 0x43, 0x01,
66       {0x64, 0x4f, 0x4f, 0x88, 0x54, 0x9c, 0xf2, 0x1f,
67        0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68        0xe0, 0x03, 0xdf, 0xa0, 0x60, 0xdf, 0xf3, 0xab,
69        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
70        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
71        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
72        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
73        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
74    {640, 480, 16, 72, 0x56, 0x43, 0x01,
75       {0x63, 0x4f, 0x50, 0x86, 0x55, 0x9a, 0x06, 0x3e,
76        0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77        0xe8, 0x0b, 0xdf, 0xa0, 0x60, 0xe7, 0xff, 0xab,
78        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
79        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
80        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
81        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
82        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
83    {640, 480, 16, 60, 0x28, 0x41, 0x01,
84       {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
85        0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86        0xea, 0x0c, 0xdf, 0xa0, 0x60, 0xe7, 0x04, 0xab,
87        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
88        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
89        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
90        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
91        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
92
93    {800, 600, 24, 75, 0x79, 0x49, 0x00,
94       {0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0,
95        0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96        0x58, 0x0c, 0x57, 0x2c, 0x60, 0x57, 0x73, 0xab,
97        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
98        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
99        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
100        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
101        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
102    {800, 600, 24, 72, 0x28, 0x41, 0x00,
103       {0x7d, 0x63, 0x63, 0x81, 0x6d, 0x1c, 0x98, 0xf0,
104        0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105        0x7c, 0x02, 0x57, 0x2c, 0x60, 0x57, 0x99, 0xab,
106        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
107        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
108        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
109        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
110        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
111    {800, 600, 24, 60, 0x79, 0x49, 0x00,
112       {0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0,
113        0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114        0x58, 0x0c, 0x57, 0x2c, 0x60, 0x57, 0x73, 0xab,
115        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
116        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
117        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
118        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
119        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
120
121    {800, 600, 16, 75, 0x51, 0x44, 0x00,
122       {0x7f, 0x63, 0x63, 0x83, 0x68, 0x12, 0x6f, 0xf0,
123        0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124        0x58, 0x0b, 0x57, 0xc8, 0x60, 0x57, 0x70, 0xab,
125        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
126        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
127        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
128        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
129        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
130    {800, 600, 16, 72, 0x28, 0x41, 0x00,
131       {0x7d, 0x63, 0x63, 0x81, 0x6d, 0x1c, 0x98, 0xf0,
132        0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133        0x7c, 0x02, 0x57, 0xc8, 0x60, 0x57, 0x99, 0xab,
134        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
135        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
136        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
137        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
138        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
139    {800, 600, 16, 60, 0x79, 0x49, 0x00,
140       {0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0,
141        0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142        0x58, 0x0c, 0x57, 0xc8, 0x60, 0x57, 0x73, 0xab,
143        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
144        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
145        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
146        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
147        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
148
149    {1024, 768, 16, 75, 0x1f, 0x21, 0x00,
150       {0x9f, 0x7f, 0x7f, 0x83, 0x84, 0x90, 0x1e, 0xf5,
151        0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152        0x00, 0x83, 0xff, 0x00, 0x60, 0xff, 0x1f, 0xab,
153        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
154        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
155        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
156        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
157        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
158    {1024, 768, 16, 70, 0x28, 0x22, 0x00,
159       {0x9f, 0x7f, 0x7f, 0x83, 0x84, 0x90, 0x1e, 0xf5,
160        0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161        0x00, 0x83, 0xff, 0x00, 0x60, 0xff, 0x1f, 0xab,
162        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
163        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
164        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
165        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
166        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
167    {1024, 768, 16, 60, 0x6b, 0x44, 0x00,
168       {0xa1, 0x7f, 0x80, 0x84, 0x88, 0x99, 0x26, 0xfd,
169        0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170        0x08, 0x0a, 0xff, 0x00, 0x60, 0x04, 0x22, 0xab,
171        0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
172        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
173        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
174        0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
175        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
176};
177
178#define CLOCK0MN (sizeof(clock0MN) / sizeof(clock0MN[0]))
179/*****************************************************************************/
180__inline void et6000EnableLinearMemoryMapping(uint16 pciConfigSpace)
181{
182    /*
183     * Relocate memory via PCI Base Address 0; don't enable MMU;
184     * enable memory mapped registers; enable system linear memory mapping.
185     */
186    ioSet8(pciConfigSpace+0x40, 0xf0, 0x0b);
187}
188/*****************************************************************************/
189static void setPCIConfigSpaceRegisters41to5E(uint16 pciConfigSpace,
190                                             VIDEO_MODE_INFORMATION *mi,
191                                             uint32 m)
192{
193uint8 pci415e[30] = {
194    0x3a, 0x00, 0x02, 0x15, 0x04, 0x40, 0x13, 0x00,
195    0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
196    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197    0x04, 0x00, 0x00, 0x00, 0x00, 0x00};
198uint8 i;
199
200    pci415e[1] = clock0MN[m].pci42;
201
202    for (i=0x41; i<0x5f; i++) {
203        if ((i==0x45) || ((i>0x47)&&(i<0x4e)) ||
204            (i==0x4e) || ((i>0x59)&&(i<0x5c)))
205            continue; /* Skip absent or read-only registers */
206        ioSet8(pciConfigSpace+i, 0x00, pci415e[i-0x41]);
207    }
208
209    if (mi->BitsPerPlane == 16) {
210        if (mi->NumberGreenBits == 5)
211            ioSet8(pciConfigSpace+0x58, 0xfd, 0x00); /* 16bpp is 5:5:5 */
212        else
213            ioSet8(pciConfigSpace+0x58, 0xfd, 0x02); /* 16bpp is 5:6:5 */
214    }
215}
216/*****************************************************************************/
217static void setMiscOutputRegister(VIDEO_MODE_INFORMATION *mi) {
218uint8 MiscOutputReg;
219    if (mi->VisScreenHeight  < 400)
220        MiscOutputReg = 0x80;           /* -vsync, +hsync */
221    else if (mi->VisScreenHeight < 480)
222        MiscOutputReg = 0x40;           /* +vsync, -hsync */
223    else if (mi->VisScreenHeight < 768)
224        MiscOutputReg = 0xc0;           /* -vsync, -hsync */
225    else
226        MiscOutputReg = 0x00;           /* +vsync, +hsync */
227    ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0x3f) | MiscOutputReg);
228
229    /* Enable host access to display memory, color mode */
230    ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0xfc) | 0x03);
231}
232/*****************************************************************************/
233static void setATC(uint8 bpp) {
234uint8 atc[7] = {0x21, 0x00, 0x30, 0x00, 0x00}, atc16 = 0x80;///
235///uint8 atc[7] = {0x01, 0x00, 0x0f, 0x00, 0x00}, atc16 = 0x80;///zzz
236uint8 i, atcIndexReg;
237volatile uint8 f;
238
239    f = ioGet8(0x3da); /* Set index/data flip-flop to index mode */
240    atcIndexReg = ioGet8(0x3c0) & 0xe0; /* Save bits[7:5] */
241
242    for (i = 0x10; i < 0x15; i++) {
243        f = ioGet8(0x3da); /* Set index/data flip-flop to index mode */
244        ioSet8(0x3c0, 0x00, i | atcIndexReg);
245        ioSet8(0x3c0, 0x00, atc[i-0x10]);
246    }
247
248    switch (bpp) {
249    case 24:
250        atc16 |= 0x20;
251        break;
252    case 16:
253        atc16 |= 0x10;
254        break;
255    }
256    f = ioGet8(0x3da); /* Set index/data flip-flop to index mode */
257    ioSet8(0x3c0, 0x00, 0x16 | atcIndexReg);
258    ioSet8(0x3c0, 0x00, atc16);
259}
260/*****************************************************************************/
261static void setTS(void) {
262uint8 ts[7] = {0x02, 0x01, 0x0f, 0x00, 0x0e, 0x00, 0x00};
263uint8 i;
264
265    for (i = 0; i < 7; i++) {
266        if (i == 5) continue; /* Skip absent register */
267        ioSet8(0x3c4, 0xf8, i);
268        ioSet8(0x3c5, 0x00, ts[i]);
269    }
270}
271/*****************************************************************************/
272static void setGDC(void) {
273uint8 gdc[9] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff};
274uint8 i;
275
276     for (i = 0; i < 9; i++) {
277        ioSet8(0x3ce, 0xf0, i);
278        ioSet8(0x3cf, 0x00, gdc[i]);
279    }
280}
281/*****************************************************************************/
282static void setClock0RegNum(uint8 regNum) {
283    /* Set bits[1:0] of the selected CLOCK0 PLL parameters register number */
284    ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0xf3) | ((regNum & 0x03) << 2));
285
286    /* Set bit[2] of the selected CLOCK0 PLL parameters register number */
287    ioSet8(0x3d4, 0xc0, 0x34);
288    ioSet8(0x3d5, 0xfd, (regNum & 0x04) << 1);
289}
290/*****************************************************************************/
291static void setPLL(uint16 pciConfigSpace,
292                   uint32 m) /* mode index */
293{
294uint8 regNum = 3;
295uint8 clock0M = 0, clock0N = 0;
296
297    clock0M = clock0MN[m].clock0M;
298    clock0N = clock0MN[m].clock0N;
299
300    setClock0RegNum(regNum);
301    ioSet8(pciConfigSpace+0x67, 0x00, regNum);
302    ioSet8(pciConfigSpace+0x68, 0x00, regNum);
303    ioSet8(pciConfigSpace+0x69, 0x00, clock0M);
304    ioSet8(pciConfigSpace+0x69, 0x00, clock0N);
305}
306/*****************************************************************************/
307static void setCRTC(uint32 m) /* mode index */
308{
309uint8 i;
310
311    /* Unlock the write protection of several registers */
312    ioSet8(0x3d4, 0xc0, 0x11);
313    ioSet8(0x3d5, 0x7f, 0x00);
314
315    for (i = 0; i < 64; i++) {
316        if (((i > 0x18) && (i < 0x33)) ||
317            ((i > 0x35) && (i < 0x3f)))
318            continue; /* Skip absent or read-only registers */
319        ioSet8(0x3d4, 0xc0, i);
320        ioSet8(0x3d5, 0x00, clock0MN[m].crtc[i]);
321    }
322}
323/*****************************************************************************/
324static uint32 et6000SetGraphicsMode(VIDEO_MODE_INFORMATION *mi,
325                            uint16 pciConfigSpace)
326{
327uint8 m;
328
329    for(m = 0; m < CLOCK0MN; m++) {
330        if ((clock0MN[m].width == mi->VisScreenWidth) &&
331            (clock0MN[m].height == mi->VisScreenHeight) &&
332            (clock0MN[m].bpp == mi->BitsPerPlane) &&
333            ((clock0MN[m].refreshRate-1 <= mi->Frequency) &&
334            (clock0MN[m].refreshRate+1 >= mi->Frequency)))
335        {
336            break;
337        }
338    }
339    if (m == CLOCK0MN)
340        return B_BAD_VALUE; /* Found no entry for requested mode */
341
342    et6000EnableLinearMemoryMapping(pciConfigSpace);
343    setMiscOutputRegister(mi);
344    ioSet8(0x3d8, 0x00, 0xa0); /* Set the KEY for color modes */
345    setPCIConfigSpaceRegisters41to5E(pciConfigSpace, mi, m);
346    ioSet8(0x3c6, 0x00, 0xff); /* Set pixel mask */
347    setATC(mi->BitsPerPlane);
348    setTS();
349    setGDC();
350    setCRTC(m);
351    setPLL(pciConfigSpace, m);
352
353    return B_OK;
354}
355/*****************************************************************************/
356status_t et6000SetMode(display_mode *mode, uint16 pciConfigSpace) {
357VIDEO_MODE_INFORMATION mi;
358
359    mi.VisScreenWidth = mode->virtual_width;
360    mi.VisScreenHeight = mode->virtual_height;
361
362    switch (mode->space) {
363        case B_RGB24_LITTLE:
364        case B_RGB24_BIG:
365            mi.BitsPerPlane = 24;
366            mi.NumberGreenBits = 8;
367            break;
368        case B_RGB16_LITTLE:
369        case B_RGB16_BIG:
370            mi.BitsPerPlane = 16;
371            mi.NumberGreenBits = 6;
372            break;
373        case B_RGB15_LITTLE:
374        case B_RGB15_BIG:
375            mi.BitsPerPlane = 16;
376            mi.NumberGreenBits = 5;
377            break;
378		default:
379			return B_BAD_VALUE;
380    }
381
382    mi.Frequency = (uint16) (mode->timing.pixel_clock * 1000
383        / (mode->timing.h_total * mode->timing.v_total));
384
385    return et6000SetGraphicsMode(&mi, pciConfigSpace);
386}
387/*****************************************************************************/
388status_t et6000ProposeMode(display_mode *mode, uint32 memSize) {
389uint8 m, bpp;
390uint16 refreshRate;
391
392    /* Framebuffer must not overlap with the memory mapped registers */
393    if (memSize > 0x3fe000)
394        memSize = 0x3fe000;
395
396    memSize -= ET6000_ACL_NEEDS_MEMORY;
397
398    switch (mode->space) {
399        case B_RGB24_LITTLE:
400        case B_RGB24_BIG:
401            bpp = 24;
402            break;
403        case B_RGB16_LITTLE:
404        case B_RGB16_BIG:
405        case B_RGB15_LITTLE:
406        case B_RGB15_BIG:
407            bpp = 16;
408            break;
409		default:
410			return B_BAD_VALUE;
411    }
412
413    refreshRate = (uint16) (mode->timing.pixel_clock * 1000
414                  / (mode->timing.h_total * mode->timing.v_total));
415
416    for(m = 0; m < CLOCK0MN; m++) {
417        if ((clock0MN[m].width == mode->virtual_width) &&
418            (clock0MN[m].height == mode->virtual_height) &&
419            (clock0MN[m].bpp == bpp) &&
420            ((clock0MN[m].refreshRate-1 <= refreshRate) &&
421            (clock0MN[m].refreshRate+1 >= refreshRate)))
422        {
423            break;
424        }
425    }
426    if (m == CLOCK0MN)
427        return B_BAD_VALUE; /* Found no entry for requested mode */
428
429    if (mode->virtual_width * mode->virtual_height * bpp / 8 > memSize)
430        return B_BAD_VALUE; /* Not enough adapter onboard memory */
431
432    return B_OK;
433}
434/*****************************************************************************/
435