Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / kdrive / src / kmode.c
CommitLineData
a09e091a
JB
1/*
2 * Copyright 1999 SuSE, Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of SuSE not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. SuSE makes no representations about the
11 * suitability of this software for any purpose. It is provided "as is"
12 * without express or implied warranty.
13 *
14 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
16 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
18 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
19 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *
21 * Author: Keith Packard, SuSE, Inc.
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <kdrive-config.h>
26#endif
27#include "kdrive.h"
28
29const KdMonitorTiming kdMonitorTimings[] = {
30 /* H V Hz KHz */
31 /* FP BP BLANK POLARITY */
32
33 /* IPAQ modeline:
34 *
35 * Modeline "320x240" 5.7222 320 337 340 352 240 241 244 254"
36 */
37 {320, 240, 64, 16256,
38 17, 12, 32, KdSyncNegative,
39 1, 11, 14, KdSyncNegative,
40 },
41
42 /* Other VESA modes */
43 {640, 350, 85, 31500, /* VESA */
44 32, 96, 192, KdSyncPositive, /* 26.413 */
45 32, 60, 95, KdSyncNegative, /* 59.354 */
46 },
47 {640, 400, 60, 31500, /* VESA */
48 32, 96, 192, KdSyncNegative, /* 26.413 */
49 1, 41, 45, KdSyncPositive, /* 59.354 */
50 },
51 {720, 400, 85, 35500, /* VESA */
52 36, 108, 216, KdSyncNegative, /* 37.927 */
53 1, 42, 46, KdSyncPositive, /* 85.039 */
54 },
55
56 /* Modeline "720x576" 29.000 720 736 800 880 576 577 580 625 */
57 {
58 720, 576, 52, 32954, /* PAL Video */
59 16, 80, 160, KdSyncPositive, /* 32.954 */
60 1, 45, 49, KdSyncPositive, /* 52.727 */
61 },
62
63 /* 640x480 modes */
64 {640, 480, 85, 36000, /* VESA */
65 56, 80, 192, KdSyncNegative, /* 43.269 */
66 1, 25, 29, KdSyncNegative, /* 85.008 */
67 },
68 {640, 480, 75, 31500, /* VESA */
69 16, 120, 200, KdSyncNegative, /* 37.500 */
70 1, 16, 20, KdSyncNegative, /* 75.000 */
71 },
72 {640, 480, 72, 31500, /* VESA */
73 16, 120, 176, KdSyncNegative, /* 37.861 */
74 1, 20, 24, KdSyncNegative, /* 72.809 */
75 },
76 {640, 480, 60, 25175, /* VESA */
77 16, 48, 160, KdSyncNegative, /* 31.469 */
78 10, 33, 45, KdSyncNegative, /* 59.940 */
79 },
80
81 /* 800x600 modes */
82 {800, 600, 85, 56250, /* VESA */
83 32, 152, 248, KdSyncPositive, /* 53.674 */
84 1, 27, 31, KdSyncPositive, /* 85.061 */
85 },
86 {800, 600, 75, 49500, /* VESA */
87 16, 160, 256, KdSyncPositive, /* 46.875 */
88 1, 21, 25, KdSyncPositive, /* 75.000 */
89 },
90 /* DEFAULT */
91#define MONITOR_TIMING_DEFAULT 9
92 {800, 600, 72, 50000, /* VESA */
93 56, 64, 240, KdSyncPositive, /* 48.077 */
94 37, 23, 66, KdSyncPositive, /* 72.188 */
95 },
96 {800, 600, 60, 40000, /* VESA */
97 40, 88, 256, KdSyncPositive, /* 37.879 */
98 1, 23, 28, KdSyncPositive, /* 60.317 */
99 },
100 {800, 600, 56, 36000, /* VESA */
101 24, 128, 224, KdSyncPositive, /* 35.156 */
102 1, 22, 25, KdSyncPositive, /* 56.250 */
103 },
104
105 /* 1024x768 modes */
106 {1024, 768, 85, 94500, /* VESA */
107 48, 208, 352, KdSyncPositive, /* 68.677 */
108 1, 36, 40, KdSyncPositive, /* 84.997 */
109 },
110 {1024, 768, 75, 78750, /* VESA */
111 16, 176, 288, KdSyncPositive, /* 60.023 */
112 1, 28, 32, KdSyncPositive, /* 75.029 */
113 },
114 {1024, 768, 70, 75000, /* VESA */
115 24, 144, 304, KdSyncNegative, /* 56.476 */
116 3, 29, 38, KdSyncNegative, /* 70.069 */
117 },
118 {1024, 768, 60, 65000, /* VESA */
119 24, 160, 320, KdSyncNegative, /* 48.363 */
120 3, 29, 38, KdSyncNegative, /* 60.004 */
121 },
122
123 /* 1152x864 mode */
124 {1152, 864, 75, 108000, /* VESA */
125 64, 256, 448, KdSyncPositive, /* 67.500 */
126 1, 32, 36, KdSyncPositive, /* 75.000 */
127 },
128
129 /* 1152x900 modes */
130 {1152, 900, 85, 122500, /* ADDED */
131 48, 208, 384, KdSyncPositive, /* 79.753 */
132 1, 32, 38, KdSyncPositive, /* 85.024 */
133 },
134 {1152, 900, 75, 108250, /* ADDED */
135 32, 208, 384, KdSyncPositive, /* 70.475 */
136 1, 32, 38, KdSyncPositive, /* 75.133 */
137 },
138 {1152, 900, 70, 100250, /* ADDED */
139 32, 208, 384, KdSyncPositive, /* 65.267 */
140 2, 32, 38, KdSyncPositive, /* 69.581 */
141 },
142 {1152, 900, 66, 95000, /* ADDED */
143 32, 208, 384, KdSyncPositive, /* 61.849 */
144 1, 32, 38, KdSyncPositive, /* 65.937 */
145 },
146
147 /* 1280x854 modes */
148 {1280, 854, 103, 12500, /* ADDED */
149 56, 16, 128, KdSyncPositive, /* 102.554 */
150 1, 216, 12, KdSyncPositive,
151 },
152
153 /* 1280x960 modes */
154 {1280, 960, 85, 148500, /* VESA */
155 64, 224, 448, KdSyncPositive, /* 85.938 */
156 1, 47, 51, KdSyncPositive, /* 85.002 */
157 },
158 {1280, 960, 60, 108000, /* VESA */
159 96, 312, 520, KdSyncPositive, /* 60.000 */
160 1, 36, 40, KdSyncPositive, /* 60.000 */
161 },
162
163 /* 1280x1024 modes */
164 {1280, 1024, 85, 157500, /* VESA */
165 64, 224, 448, KdSyncPositive, /* 91.146 */
166 1, 44, 48, KdSyncPositive, /* 85.024 */
167 },
168 {1280, 1024, 75, 135000, /* VESA */
169 16, 248, 408, KdSyncPositive, /* 79.976 */
170 1, 38, 42, KdSyncPositive, /* 75.025 */
171 },
172 {1280, 1024, 60, 108000, /* VESA */
173 48, 248, 408, KdSyncPositive, /* 63.981 */
174 1, 38, 42, KdSyncPositive, /* 60.020 */
175 },
176
177 /* 1600x1200 modes */
178 {1600, 1200, 85, 229500, /* VESA */
179 64, 304, 560, KdSyncPositive, /* 106.250 */
180 1, 46, 50, KdSyncPositive, /* 85.000 */
181 },
182 {1600, 1200, 75, 202500, /* VESA */
183 64, 304, 560, KdSyncPositive, /* 93.750 */
184 1, 46, 50, KdSyncPositive, /* 75.000 */
185 },
186 {1600, 1200, 70, 189000, /* VESA */
187 64, 304, 560, KdSyncPositive, /* 87.500 */
188 1, 46, 50, KdSyncPositive, /* 70.000 */
189 },
190 {1600, 1200, 65, 175500, /* VESA */
191 64, 304, 560, KdSyncPositive, /* 81.250 */
192 1, 46, 50, KdSyncPositive, /* 65.000 */
193 },
194 {1600, 1200, 60, 162000, /* VESA */
195 64, 304, 560, KdSyncPositive, /* 75.000 */
196 1, 46, 50, KdSyncPositive, /* 60.000 */
197 },
198
199 /* 1792x1344 modes */
200 {1792, 1344, 85, 301500, /* ADDED */
201 96, 352, 672, KdSyncNegative, /* 122.362 */
202 1, 92, 96, KdSyncPositive, /* 84.974 */
203 },
204 {1792, 1344, 75, 261000, /* VESA */
205 96, 352, 664, KdSyncNegative, /* 106.270 */
206 1, 69, 73, KdSyncPositive, /* 74.997 */
207 },
208 {1792, 1344, 60, 204750, /* VESA */
209 128, 328, 656, KdSyncNegative, /* 83.640 */
210 1, 46, 50, KdSyncPositive, /* 60.000 */
211 },
212
213#if 0
214 {1800, 1012, 75},
215 {1906, 1072, 68},
216#endif
217
218 /* 1856x1392 modes */
219 {1856, 1392, 85, 330500, /* ADDED */
220 160, 352, 736, KdSyncNegative, /* 127.508 */
221 1, 104, 108, KdSyncPositive, /* 85.001 */
222 },
223 {1856, 1392, 75, 288000, /* VESA */
224 128, 352, 704, KdSyncNegative, /* 112.500 */
225 1, 104, 108, KdSyncPositive, /* 75.000 */
226 },
227 {1856, 1392, 60, 218250, /* VESA */
228 96, 352, 672, KdSyncNegative, /* 86.333 */
229 1, 43, 47, KdSyncPositive, /* 59.995 */
230 },
231
232 /* 1920x1440 modes */
233 {1920, 1440, 85, 341750, /* ADDED */
234 160, 352, 760, KdSyncNegative, /* 127.512 */
235 1, 56, 60, KdSyncPositive, /* 85.012 */
236 },
237 {1920, 1440, 75, 297000, /* VESA */
238 144, 352, 720, KdSyncNegative, /* 112.500 */
239 1, 56, 60, KdSyncPositive, /* 75.000 */
240 },
241 {1920, 1440, 60, 234000, /* VESA */
242 128, 244, 680, KdSyncNegative, /* 90.000 */
243 1, 56, 60, KdSyncPositive, /* 60.000 */
244 },
245};
246
247#define NUM_MONITOR_TIMINGS (sizeof kdMonitorTimings/sizeof kdMonitorTimings[0])
248
249const int kdNumMonitorTimings = NUM_MONITOR_TIMINGS;
250
251const KdMonitorTiming *
252KdFindMode(KdScreenInfo * screen,
253 Bool (*supported) (KdScreenInfo *, const KdMonitorTiming *))
254{
255 int i;
256 const KdMonitorTiming *t;
257
258 for (i = 0, t = kdMonitorTimings; i < NUM_MONITOR_TIMINGS; i++, t++) {
259 if ((*supported) (screen, t) &&
260 t->horizontal == screen->width &&
261 t->vertical == screen->height &&
262 (!screen->rate || t->rate <= screen->rate)) {
263 return t;
264 }
265 }
266 ErrorF("Warning: mode not found, using default\n");
267 return &kdMonitorTimings[MONITOR_TIMING_DEFAULT];
268}
269
270static const KdMonitorTiming *
271kdFindPrevSize(const KdMonitorTiming * old)
272{
273 const KdMonitorTiming *new, *prev;
274
275 if (old == kdMonitorTimings)
276 return 0;
277 new = old;
278 /*
279 * Search for the previous size
280 */
281 while (new != kdMonitorTimings) {
282 new--;
283 if (new->horizontal != old->horizontal &&
284 new->vertical != old->vertical) {
285 break;
286 }
287 }
288 /*
289 * Match the refresh rate (<=)
290 */
291 while (new != kdMonitorTimings) {
292 prev = new - 1;
293 if (prev->horizontal == new->horizontal &&
294 prev->vertical == new->vertical && prev->rate > old->rate) {
295 break;
296 }
297 new--;
298 }
299 return new;
300}
301
302Bool
303KdTuneMode(KdScreenInfo * screen,
304 Bool (*usable) (KdScreenInfo *),
305 Bool (*supported) (KdScreenInfo *, const KdMonitorTiming *))
306{
307 const KdMonitorTiming *t;
308
309 while (!(*usable) (screen)) {
310 /*
311 * Fix requested depth and geometry until it works
312 */
313 if (screen->fb.depth > 16)
314 screen->fb.depth = 16;
315 else if (screen->fb.depth > 8)
316 screen->fb.depth = 8;
317 else {
318 t = kdFindPrevSize(KdFindMode(screen, supported));
319 if (!t)
320 return FALSE;
321 screen->width = t->horizontal;
322 screen->height = t->vertical;
323 screen->rate = t->rate;
324 }
325 }
326 return TRUE;
327}
328
329#ifdef RANDR
330Bool
331KdRandRGetInfo(ScreenPtr pScreen,
332 int randr,
333 Bool (*supported) (ScreenPtr pScreen, const KdMonitorTiming *))
334{
335 KdScreenPriv(pScreen);
336 KdScreenInfo *screen = pScreenPriv->screen;
337 int i;
338 const KdMonitorTiming *t;
339
340 for (i = 0, t = kdMonitorTimings; i < NUM_MONITOR_TIMINGS; i++, t++) {
341 if ((*supported) (pScreen, t)) {
342 RRScreenSizePtr pSize;
343
344 pSize = RRRegisterSize(pScreen,
345 t->horizontal,
346 t->vertical,
347 screen->width_mm, screen->height_mm);
348 if (!pSize)
349 return FALSE;
350 if (!RRRegisterRate(pScreen, pSize, t->rate))
351 return FALSE;
352 if (t->horizontal == screen->width &&
353 t->vertical == screen->height && t->rate == screen->rate)
354 RRSetCurrentConfig(pScreen, randr, t->rate, pSize);
355 }
356 }
357
358 return TRUE;
359}
360
361const KdMonitorTiming *
362KdRandRGetTiming(ScreenPtr pScreen,
363 Bool (*supported) (ScreenPtr pScreen,
364 const KdMonitorTiming *),
365 int rate, RRScreenSizePtr pSize)
366{
367 int i;
368 const KdMonitorTiming *t;
369
370 for (i = 0, t = kdMonitorTimings; i < NUM_MONITOR_TIMINGS; i++, t++) {
371 if (t->horizontal == pSize->width &&
372 t->vertical == pSize->height &&
373 t->rate == rate && (*supported) (pScreen, t))
374 return t;
375 }
376 return 0;
377}
378#endif