2 Copyright 1999, Be Incorporated. All Rights Reserved.
3 This file may be used under the terms of the Be Sample Code License.
5 Other authors for NV driver:
7 Rudolf Cornelissen 9/2002-11/2005
10 #define MODULE_BIT 0x00400000
14 #define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC)
15 /* mode flags will be setup as status info by PROPOSEMODE! */
17 #define MODE_COUNT (sizeof (mode_list) / sizeof (display_mode))
19 /*some monitors only handle a fixed set of modes*/
20 #include "valid_mode_list"
22 /* Standard VESA modes,
23 * plus panel specific resolution modes which are internally modified during run-time depending on the requirements of the actual
24 * panel connected. The modes as listed here, should timing-wise be as compatible with analog (CRT) monitors as can be... */
25 static const display_mode mode_list
[] = {
26 /* 4:3 modes; 307.2k pixels */
27 { { 25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_CMAP8
, 640, 480, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */
28 { { 27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_CMAP8
, 640, 480, 0, 0, MODE_FLAGS
}, /* 640X480X60Hz */
29 { { 30500, 640, 672, 768, 864, 480, 517, 523, 588, 0}, B_CMAP8
, 640, 480, 0, 0, MODE_FLAGS
}, /* SVGA_640X480X60HzNI */
30 { { 31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, B_CMAP8
, 640, 480, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@70-72Hz_(640X480X8.Z1) */
31 { { 31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, B_CMAP8
, 640, 480, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@75Hz_(640X480X8.Z1) */
32 { { 36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_CMAP8
, 640, 480, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */
33 /* 4:3 modes; 480k pixels */
34 { { 36000, 800, 824, 896, 1024, 600, 601, 603, 625, 0}, B_CMAP8
, 800, 600, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@56Hz_(800X600) from Be, Inc. driver + XFree86 */
35 { { 38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_CMAP8
, 800, 600, 0, 0, MODE_FLAGS
}, /* SVGA_800X600X56HzNI */
36 { { 40000, 800, 840, 968, 1056, 600, 601, 605, 628, T_POSITIVE_SYNC
}, B_CMAP8
, 800, 600, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(800X600X8.Z1) + XFree86 */
37 { { 49500, 800, 816, 896, 1056, 600, 601, 604, 625, T_POSITIVE_SYNC
}, B_CMAP8
, 800, 600, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@75Hz_(800X600X8.Z1) + XFree86 */
38 { { 50000, 800, 856, 976, 1040, 600, 637, 643, 666, T_POSITIVE_SYNC
}, B_CMAP8
, 800, 600, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@70-72Hz_(800X600X8.Z1) + XFree86 */
39 { { 56250, 800, 832, 896, 1048, 600, 601, 604, 631, T_POSITIVE_SYNC
}, B_CMAP8
, 800, 600, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@85Hz_(800X600X8.Z1) + XFree86 */
40 /* 4:3 modes; 786.432k pixels */
41 { { 65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, B_CMAP8
, 1024, 768, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1024X768X8.Z1) + XFree86 */
42 { { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 0}, B_CMAP8
, 1024, 768, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@70-72Hz_(1024X768X8.Z1) + XFree86 */
43 { { 78750, 1024, 1040, 1136, 1312, 768, 769, 772, 800, T_POSITIVE_SYNC
}, B_CMAP8
, 1024, 768, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@75Hz_(1024X768X8.Z1) + XFree86 */
44 { { 94500, 1024, 1072, 1168, 1376, 768, 769, 772, 808, T_POSITIVE_SYNC
}, B_CMAP8
, 1024, 768, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@85Hz_(1024X768X8.Z1) + XFree86 */
45 /* 4:3 modes; 995.328k pixels */
46 { { 94200, 1152, 1184, 1280, 1472, 864, 865, 868, 914, T_POSITIVE_SYNC
}, B_CMAP8
, 1152, 864, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */
47 { { 97800, 1152, 1216, 1344, 1552, 864, 865, 868, 900, T_POSITIVE_SYNC
}, B_CMAP8
, 1152, 864, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */
48 { { 108000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, T_POSITIVE_SYNC
}, B_CMAP8
, 1152, 864, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@75Hz_(1152X864X8.Z1) + XFree86 */
49 { { 121500, 1152, 1216, 1344, 1568, 864, 865, 868, 911, T_POSITIVE_SYNC
}, B_CMAP8
, 1152, 864, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@85Hz_(1152X864X8.Z1) */
50 /* 5:4 modes; 1.311M pixels */
51 { { 108000, 1280, 1328, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC
}, B_CMAP8
, 1280, 1024, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1280X1024) from Be, Inc. driver + XFree86 */
52 { { 135000, 1280, 1296, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC
}, B_CMAP8
, 1280, 1024, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@75Hz_(1280X1024X8.Z1) + XFree86 */
53 { { 157500, 1280, 1344, 1504, 1728, 1024, 1025, 1028, 1072, T_POSITIVE_SYNC
}, B_CMAP8
, 1280, 1024, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@85Hz_(1280X1024X8.Z1) + XFree86 */
54 /* 4:3 panel mode; 1.47M pixels */
55 { { 122600, 1400, 1488, 1640, 1880, 1050, 1051, 1054, 1087, T_POSITIVE_SYNC
}, B_CMAP8
, 1400, 1050, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1400X1050) */
56 /* 4:3 modes; 1.92M pixels */
57 { { 162000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC
}, B_CMAP8
, 1600, 1200, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1600X1200X8.Z1) + XFree86 */
58 /* identical lines to above one, apart from refreshrate.. */
59 { { 175500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC
}, B_CMAP8
, 1600, 1200, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@65Hz_(1600X1200X8.Z1) + XFree86 */
60 { { 189000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC
}, B_CMAP8
, 1600, 1200, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@70Hz_(1600X1200X8.Z1) + XFree86 */
61 { { 202500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC
}, B_CMAP8
, 1600, 1200, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@75Hz_(1600X1200X8.Z1) + XFree86 */
62 { { 216000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC
}, B_CMAP8
, 1600, 1200, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@80Hz_(1600X1200X8.Z1) */
63 { { 229500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC
}, B_CMAP8
, 1600, 1200, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@85Hz_(1600X1200X8.Z1) + XFree86 */
64 /* end identical lines. */
65 /* 4:3 modes; 2.408M pixels */
66 { { 204750, 1792, 1920, 2120, 2448, 1344, 1345, 1348, 1394, B_POSITIVE_VSYNC
}, B_CMAP8
, 1792, 1344, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1792X1344) from Be, Inc. driver + XFree86 */
67 { { 261000, 1792, 1888, 2104, 2456, 1344, 1345, 1348, 1417, B_POSITIVE_VSYNC
}, B_CMAP8
, 1792, 1344, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@75Hz_(1792X1344) from Be, Inc. driver + XFree86 */
68 /* 4:3 modes; 2.584M pixels */
69 { { 218250, 1856, 1952, 2176, 2528, 1392, 1393, 1396, 1439, B_POSITIVE_VSYNC
}, B_CMAP8
, 1856, 1392, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1856X1392) from Be, Inc. driver + XFree86 */
70 { { 288000, 1856, 1984, 2208, 2560, 1392, 1393, 1396, 1500, B_POSITIVE_VSYNC
}, B_CMAP8
, 1856, 1392, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@75Hz_(1856X1392) from Be, Inc. driver + XFree86 */
71 /* 4:3 modes; 2.765M pixels */
72 { { 234000, 1920, 2048, 2256, 2600, 1440, 1441, 1444, 1500, B_POSITIVE_VSYNC
}, B_CMAP8
, 1920, 1440, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1920X1440) from Be, Inc. driver + XFree86 */
73 { { 297000, 1920, 2064, 2288, 2640, 1440, 1441, 1444, 1500, B_POSITIVE_VSYNC
}, B_CMAP8
, 1920, 1440, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@75Hz_(1920X1440) from Be, Inc. driver + XFree86 */
74 /* 4:3 modes; 3.146M pixels */
75 { { 266950, 2048, 2200, 2424, 2800, 1536, 1537, 1540, 1589, B_POSITIVE_VSYNC
}, B_CMAP8
, 2048, 1536, 0, 0, MODE_FLAGS
}, /* From XFree86 posting @60Hz + XFree86 */
76 /* 16:10 panel mode; 400k pixels */
77 { { 31300, 800, 848, 928, 1008, 500, 501, 504, 518, T_POSITIVE_SYNC
}, B_CMAP8
, 800, 500, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(800X500) */
78 /* 16:10 panel mode; 655.36k pixels */
79 { { 52800, 1024, 1072, 1176, 1328, 640, 641, 644, 663, T_POSITIVE_SYNC
}, B_CMAP8
, 1024, 640, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1024X640) */
80 /* 16:10 panel-TV mode; 983.04k pixels */
81 { { 80135, 1280, 1344, 1480, 1680, 768, 769, 772, 795, T_POSITIVE_SYNC
}, B_CMAP8
, 1280, 768, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1280X768) */
82 /* 16:10 panel mode; 1.024M pixels */
83 { { 83500, 1280, 1344, 1480, 1680, 800, 801, 804, 828, T_POSITIVE_SYNC
}, B_CMAP8
, 1280, 800, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1280X800) */
84 /* 16:10 panel mode; 1.296M pixels */
85 { { 106500, 1440, 1520, 1672, 1904, 900, 901, 904, 932, T_POSITIVE_SYNC
}, B_CMAP8
, 1440, 900, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1440X900) */
86 /* 16:10 panel mode; 1.764M pixels */
87 { { 147100, 1680, 1784, 1968, 2256, 1050, 1051, 1054, 1087, T_POSITIVE_SYNC
}, B_CMAP8
, 1680, 1050, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1680X1050) */
88 /* 16:10 panel mode; 2.304M pixels */
89 { { 193200, 1920, 2048, 2256, 2592, 1200, 1201, 1204, 1242, T_POSITIVE_SYNC
}, B_CMAP8
, 1920, 1200, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1920X1200) */
93 Check mode is between low and high limits
96 B_BAD_VALUE - mode can be made, but outside limits
97 B_ERROR - not possible
100 * BeOS (tested R5.0.3PE) is failing BWindowScreen.SetFrameBuffer() if PROPOSEMODE
101 * returns B_BAD_VALUE. It's called by the OS with target, low and high set to
102 * have the same settings for BWindowScreen!
103 * Which means we should not return B_BAD_VALUE on anything except for deviations on:
104 * display_mode.virtual_width;
105 * display_mode.virtual_height;
106 * display_mode.timing.h_display;
107 * display_mode.timing.v_display;
110 * The target mode should be modified to correspond to the mode as it can be made. */
111 status_t
PROPOSE_DISPLAY_MODE(display_mode
*target
, const display_mode
*low
, const display_mode
*high
)
113 status_t status
= B_OK
;
114 float pix_clock_found
, target_aspect
;
117 uint32 max_vclk
, row_bytes
, pointer_reservation
;
119 double target_refresh
= ((double)target
->timing
.pixel_clock
* 1000.0) /
121 (double)target
->timing
.h_total
*
122 (double)target
->timing
.v_total
125 want_same_width
= target
->timing
.h_display
== target
->virtual_width
,
126 want_same_height
= target
->timing
.v_display
== target
->virtual_height
;
128 LOG(1, ("PROPOSEMODE: (ENTER) requested virtual_width %d, virtual_height %d\n",
129 target
->virtual_width
, target
->virtual_height
));
132 if (VALID_REQUIRED is set)
134 if (find modes with same size)
136 pick one with nearest pixel clock
140 pick next largest with nearest pixel clock and modify visible portion as far as possible
144 #ifdef VALID_MODE_REQUIRED
147 int closest_mode_ptr
;
148 uint32 closest_mode_clock
;
150 LOG(1, ("PROPOSEMODE: valid mode required!\n"));
152 closest_mode_ptr
= 0xbad;
153 closest_mode_clock
= 0;
154 for (i
=0;i
<VALID_MODES
;i
++)
156 /*check size is ok and clock is better than any found before*/
158 target
->timing
.h_display
==valid_mode_list
[i
].h_display
&&
159 target
->timing
.v_display
==valid_mode_list
[i
].v_display
163 abs(valid_mode_list
[i
].pixel_clock
-target
->timing
.pixel_clock
)<
164 abs(closest_mode_clock
-target
->timing
.pixel_clock
)
167 closest_mode_clock
=valid_mode_list
[i
].pixel_clock
;
173 if (closest_mode_ptr
==0xbad)/*if no modes of correct size*/
175 LOG(4, ("PROPOSEMODE: no valid mode found, aborted.\n"));
180 target
->timing
=valid_mode_list
[closest_mode_ptr
];
181 target_refresh
= ((double)target
->timing
.pixel_clock
* 1000.0) / /*I require this refresh*/
182 ((double)target
->timing
.h_total
* (double)target
->timing
.v_total
);
187 /*find a nearby valid timing from that given*/
188 result
= head1_validate_timing
190 &target
->timing
.h_display
, &target
->timing
.h_sync_start
, &target
->timing
.h_sync_end
, &target
->timing
.h_total
,
191 &target
->timing
.v_display
, &target
->timing
.v_sync_start
, &target
->timing
.v_sync_end
, &target
->timing
.v_total
193 if (result
== B_ERROR
)
195 LOG(4, ("PROPOSEMODE: could not validate timing, aborted.\n"));
199 /* check if all connected output devices can display the requested mode's aspect: */
200 /* calculate display mode aspect */
201 target_aspect
= (target
->timing
.h_display
/ ((float)target
->timing
.v_display
));
203 * allow 0.10 difference so 5:4 aspect panels will be able to use 4:3 aspect modes! */
204 switch (si
->ps
.monitors
)
206 case 0x01: /* digital panel on head 1, nothing on head 2 */
207 if (si
->ps
.panel1_aspect
< (target_aspect
- 0.10))
209 LOG(4, ("PROPOSEMODE: connected panel1 is not widescreen type, aborted.\n"));
213 case 0x10: /* nothing on head 1, digital panel on head 2 */
214 if (si
->ps
.panel2_aspect
< (target_aspect
- 0.10))
216 LOG(4, ("PROPOSEMODE: connected panel2 is not widescreen type, aborted.\n"));
220 case 0x11: /* digital panels on both heads */
221 if ((si
->ps
.panel1_aspect
< (target_aspect
- 0.10)) ||
222 (si
->ps
.panel2_aspect
< (target_aspect
- 0.10)))
224 LOG(4, ("PROPOSEMODE: not all connected panels are widescreen type, aborted.\n"));
228 default: /* at least one analog monitor is connected, or nothing detected at all */
229 if (target_aspect
> 1.34)
231 LOG(4, ("PROPOSEMODE: not all output devices can display widescreen modes, aborted.\n"));
237 /* only export widescreen panel-TV modes when an exact resolution match exists,
238 * to prevent the modelist from becoming too crowded */
239 if (target_aspect
> 1.61)
241 status_t panel_TV_stat
= B_ERROR
;
243 if (si
->ps
.tmds1_active
)
245 if ((target
->timing
.h_display
== si
->ps
.p1_timing
.h_display
) &&
246 (target
->timing
.v_display
== si
->ps
.p1_timing
.v_display
))
248 panel_TV_stat
= B_OK
;
251 if (si
->ps
.tmds2_active
)
253 if ((target
->timing
.h_display
== si
->ps
.p2_timing
.h_display
) &&
254 (target
->timing
.v_display
== si
->ps
.p2_timing
.v_display
))
256 panel_TV_stat
= B_OK
;
259 if (panel_TV_stat
!= B_OK
)
261 LOG(4, ("PROPOSEMODE: WS panel_TV mode requested but no such TV here, aborted.\n"));
266 /* check if panel(s) can display the requested resolution (if connected) */
267 if (si
->ps
.tmds1_active
)
269 if ((target
->timing
.h_display
> si
->ps
.p1_timing
.h_display
) ||
270 (target
->timing
.v_display
> si
->ps
.p1_timing
.v_display
))
272 LOG(4, ("PROPOSEMODE: panel1 can't display requested resolution, aborted.\n"));
276 if (si
->ps
.tmds2_active
)
278 if ((target
->timing
.h_display
> si
->ps
.p2_timing
.h_display
) ||
279 (target
->timing
.v_display
> si
->ps
.p2_timing
.v_display
))
281 LOG(4, ("PROPOSEMODE: panel2 can't display requested resolution, aborted.\n"));
286 /* validate display vs. virtual */
287 if ((target
->timing
.h_display
> target
->virtual_width
) || want_same_width
)
288 target
->virtual_width
= target
->timing
.h_display
;
289 if ((target
->timing
.v_display
> target
->virtual_height
) || want_same_height
)
290 target
->virtual_height
= target
->timing
.v_display
;
292 /* nail virtual size and 'subsequently' calculate rowbytes */
293 result
= eng_general_validate_pic_size (target
, &row_bytes
, &acc_mode
);
294 if (result
== B_ERROR
)
296 LOG(4, ("PROPOSEMODE: could not validate virtual picture size, aborted.\n"));
300 /*check if virtual_width is still within the requested limits*/
301 if ((target
->virtual_width
< low
->virtual_width
) ||
302 (target
->virtual_width
> high
->virtual_width
))
304 status
= B_BAD_VALUE
;
305 LOG(4, ("PROPOSEMODE: WARNING: virtual_width deviates too much\n"));
308 /*check if timing found is within the requested horizontal limits*/
309 if ((target
->timing
.h_display
< low
->timing
.h_display
) ||
310 (target
->timing
.h_display
> high
->timing
.h_display
) ||
311 (target
->timing
.h_sync_start
< low
->timing
.h_sync_start
) ||
312 (target
->timing
.h_sync_start
> high
->timing
.h_sync_start
) ||
313 (target
->timing
.h_sync_end
< low
->timing
.h_sync_end
) ||
314 (target
->timing
.h_sync_end
> high
->timing
.h_sync_end
) ||
315 (target
->timing
.h_total
< low
->timing
.h_total
) ||
316 (target
->timing
.h_total
> high
->timing
.h_total
))
318 /* BWindowScreen workaround: we accept everything except h_display deviations */
319 if ((target
->timing
.h_display
< low
->timing
.h_display
) ||
320 (target
->timing
.h_display
> high
->timing
.h_display
))
322 status
= B_BAD_VALUE
;
324 LOG(4, ("PROPOSEMODE: WARNING: horizontal timing deviates too much\n"));
327 /*check if timing found is within the requested vertical limits*/
329 (target
->timing
.v_display
< low
->timing
.v_display
) ||
330 (target
->timing
.v_display
> high
->timing
.v_display
) ||
331 (target
->timing
.v_sync_start
< low
->timing
.v_sync_start
) ||
332 (target
->timing
.v_sync_start
> high
->timing
.v_sync_start
) ||
333 (target
->timing
.v_sync_end
< low
->timing
.v_sync_end
) ||
334 (target
->timing
.v_sync_end
> high
->timing
.v_sync_end
) ||
335 (target
->timing
.v_total
< low
->timing
.v_total
) ||
336 (target
->timing
.v_total
> high
->timing
.v_total
)
339 /* BWindowScreen workaround: we accept everything except v_display deviations */
340 if ((target
->timing
.v_display
< low
->timing
.v_display
) ||
341 (target
->timing
.v_display
> high
->timing
.v_display
))
343 status
= B_BAD_VALUE
;
345 LOG(4, ("PROPOSEMODE: WARNING: vertical timing deviates too much\n"));
348 /* adjust pixelclock for possible timing modifications done above */
349 target
->timing
.pixel_clock
= target_refresh
* ((double)target
->timing
.h_total
) * ((double)target
->timing
.v_total
) / 1000.0;
351 /* Now find the nearest valid pixelclock we actually can setup for the target mode,
352 * this also makes sure we don't generate more pixel bandwidth than the device can handle */
353 /* calculate settings, but do not actually test anything (that costs too much time!) */
354 result
= head1_pix_pll_find(*target
,&pix_clock_found
,&m
,&n
,&p
,0);
355 /* update the target mode */
356 target
->timing
.pixel_clock
= (pix_clock_found
* 1000);
358 /* note if we fell outside the limits */
359 if ((target
->timing
.pixel_clock
< low
->timing
.pixel_clock
) ||
360 (target
->timing
.pixel_clock
> high
->timing
.pixel_clock
)
363 /* BWindowScreen workaround: we accept deviations <= 1Mhz */
364 if ((target
->timing
.pixel_clock
< (low
->timing
.pixel_clock
- 1000)) ||
365 (target
->timing
.pixel_clock
> (high
->timing
.pixel_clock
+ 1000)))
367 status
= B_BAD_VALUE
;
369 LOG(4, ("PROPOSEMODE: WARNING: pixelclock deviates too much\n"));
372 /* checkout space needed for hardcursor (if any) */
373 pointer_reservation
= 0;
374 if (si
->settings
.hardcursor
) pointer_reservation
= 2048;
375 /* memory requirement for frame buffer */
376 if ((row_bytes
* target
->virtual_height
) >
377 (si
->ps
.memory_size
- pointer_reservation
))
379 target
->virtual_height
=
380 (si
->ps
.memory_size
- pointer_reservation
) / row_bytes
;
382 if (target
->virtual_height
< target
->timing
.v_display
)
384 LOG(4,("PROPOSEMODE: not enough memory for current mode, aborted.\n"));
387 LOG(4,("PROPOSEMODE: validated virtual_width %d, virtual_height %d pixels\n",
388 target
->virtual_width
, target
->virtual_height
));
390 if ((target
->virtual_height
< low
->virtual_height
) ||
391 (target
->virtual_height
> high
->virtual_height
))
393 status
= B_BAD_VALUE
;
394 LOG(4, ("PROPOSEMODE: WARNING: virtual_height deviates too much\n"));
397 /* setup status flags */
398 LOG(1, ("PROPOSEMODE: initial modeflags: $%08x\n", target
->flags
));
399 /* preset to singlehead card without TVout, no overlay support and no hardcursor.
400 * also advice system that app_server and acc engine may touch the framebuffer
401 * simultaneously (fixed). */
403 ~(DUALHEAD_CAPABLE
| TV_CAPABLE
| B_SUPPORTS_OVERLAYS
| B_HARDWARE_CURSOR
| B_IO_FB_NA
);
404 /* we always allow parallel access (fixed), the DAC is always in 'enhanced'
405 * mode (fixed), and all modes support DPMS (fixed);
406 * We support scrolling and panning in every mode, so we 'send a signal' to
407 * BWindowScreen.CanControlFrameBuffer() by setting B_SCROLL. */
408 /* BTW: B_PARALLEL_ACCESS in combination with a hardcursor enables
409 * BDirectWindow windowed modes. */
410 target
->flags
|= (B_PARALLEL_ACCESS
| B_8_BIT_DAC
| B_DPMS
| B_SCROLL
);
412 /* determine the 'would be' max. pixelclock for the second DAC for the current videomode if dualhead were activated */
413 switch (target
->space
)
416 max_vclk
= si
->ps
.max_dac2_clock_8
;
421 max_vclk
= si
->ps
.max_dac2_clock_16
;
425 max_vclk
= si
->ps
.max_dac2_clock_24
;
429 max_vclk
= si
->ps
.max_dac2_clock_32dh
;
433 /* use fail-safe value */
434 max_vclk
= si
->ps
.max_dac2_clock_32dh
;
439 /* set DUALHEAD_CAPABLE if suitable */
440 //fixme: update for independant secondary head use! (reserve fixed memory then)
441 if (si
->ps
.secondary_head
&& (target
->timing
.pixel_clock
<= (max_vclk
* 1000)))
443 switch (target
->flags
& DUALHEAD_BITS
)
446 case DUALHEAD_SWITCH
:
447 if (((si
->ps
.memory_size
- pointer_reservation
) >=
448 (row_bytes
* target
->virtual_height
)) &&
449 ((uint16
)(row_bytes
/ bpp
) >= (target
->timing
.h_display
* 2)))
451 target
->flags
|= DUALHEAD_CAPABLE
;
455 if ((si
->ps
.memory_size
- pointer_reservation
) >=
456 (row_bytes
* target
->virtual_height
))
458 target
->flags
|= DUALHEAD_CAPABLE
;
462 if ((si
->ps
.memory_size
- pointer_reservation
) >=
463 (row_bytes
* target
->virtual_height
* 2))
465 target
->flags
|= DUALHEAD_CAPABLE
;
471 /* set TV_CAPABLE if suitable: pixelclock is not important (defined by TVstandard) */
472 //fixme: modify for G100 and G200 TVout later on...
473 if (target
->flags
& DUALHEAD_CAPABLE
)
476 (target
->timing
.h_display
<= 1024) &&
477 (target
->timing
.v_display
<= 768))
479 target
->flags
|= TV_CAPABLE
;
483 /* set HARDWARE_CURSOR mode if suitable */
484 if (si
->settings
.hardcursor
)
485 target
->flags
|= B_HARDWARE_CURSOR
;
487 /* set SUPPORTS_OVERLAYS */
488 target
->flags
|= B_SUPPORTS_OVERLAYS
;
490 LOG(1, ("PROPOSEMODE: validated status modeflags: $%08x\n", target
->flags
));
492 /* overrule timing command flags to be (fixed) blank_pedestal = 0.0IRE,
493 * progressive scan (fixed), and sync_on_green not avaible. */
494 target
->timing
.flags
&= ~(B_BLANK_PEDESTAL
| B_TIMING_INTERLACED
| B_SYNC_ON_GREEN
);
495 /* The HSYNC and VSYNC command flags are actually executed by the driver. */
497 if (status
== B_OK
) LOG(4, ("PROPOSEMODE: completed successfully.\n"));
498 else LOG(4, ("PROPOSEMODE: mode can be made, but outside given limits.\n"));
502 /* Return the number of modes this device will return from GET_MODE_LIST().
503 This is precalculated in create_mode_list (called from InitAccelerant stuff)
505 uint32
ACCELERANT_MODE_COUNT(void)
507 LOG(1, ("ACCELERANT_MODE_COUNT: the modelist contains %d modes\n",si
->mode_count
));
509 return si
->mode_count
;
512 /* Copy the list of guaranteed supported video modes to the location provided.*/
513 status_t
GET_MODE_LIST(display_mode
*dm
)
515 LOG(1, ("GET_MODE_LIST: exporting the modelist created before.\n"));
517 memcpy(dm
, my_mode_list
, si
->mode_count
* sizeof(display_mode
));
521 /* Create a list of display_modes to pass back to the caller.*/
522 status_t
create_mode_list(void)
535 color_space spaces
[4] = {B_RGB32_LITTLE
,B_RGB16_LITTLE
,B_RGB15_LITTLE
,B_CMAP8
};
537 /* figure out how big the list could be, and adjust up to nearest multiple of B_PAGE_SIZE */
538 max_size
= (((MODE_COUNT
* 4) * sizeof(display_mode
)) + (B_PAGE_SIZE
-1)) & ~(B_PAGE_SIZE
-1);
539 /* create an area to hold the info */
540 si
->mode_area
= my_mode_list_area
=
541 create_area("NV accelerant mode info", (void **)&my_mode_list
, B_ANY_ADDRESS
, max_size
, B_NO_LOCK
, B_READ_AREA
| B_WRITE_AREA
);
542 if (my_mode_list_area
< B_OK
) return my_mode_list_area
;
544 /* walk through our predefined list and see which modes fit this device */
548 for (i
= 0; i
< MODE_COUNT
; i
++)
550 /* set ranges for acceptable values */
552 /* range is 6.25% of default clock: arbitrarily picked */
553 pix_clk_range
= low
.timing
.pixel_clock
>> 5;
554 low
.timing
.pixel_clock
-= pix_clk_range
;
555 high
.timing
.pixel_clock
+= pix_clk_range
;
556 /* 'some cards need wider virtual widths for certain modes':
557 * Not true. They might need a wider pitch, but this is _not_ reflected in
558 * virtual_width, but in fbc.bytes_per_row. */
559 //So disable next line:
560 //high.virtual_width = 4096;
561 /* do it once for each depth we want to support */
562 for (j
= 0; j
< (sizeof(spaces
) / sizeof(color_space
)); j
++)
564 /* set target values */
566 /* poke the specific space */
567 dst
->space
= low
.space
= high
.space
= spaces
[j
];
568 /* ask for a compatible mode */
569 /* We have to check for B_OK, because otherwise the pix_clk_range
570 * won't be taken into account!! */
572 //if (PROPOSE_DISPLAY_MODE(dst, &low, &high) != B_ERROR) {
574 if (PROPOSE_DISPLAY_MODE(dst
, &low
, &high
) == B_OK
) {
575 /* count it, and move on to next mode */
580 /* advance to next mode */