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
16 #define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC)
17 /* mode flags will be setup as status info by PROPOSEMODE! */
19 #define MODE_COUNT (sizeof (mode_list) / sizeof (display_mode))
21 /*some monitors only handle a fixed set of modes*/
22 #include "valid_mode_list"
24 /* Standard VESA modes,
25 * plus panel specific resolution modes which are internally modified during run-time depending on the requirements of the actual
26 * panel connected. The modes as listed here, should timing-wise be as compatible with analog (CRT) monitors as can be... */
27 static const display_mode mode_list
[] = {
28 /* 4:3 modes; 307.2k pixels */
29 { { 25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_CMAP8
, 640, 480, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */
30 { { 27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_CMAP8
, 640, 480, 0, 0, MODE_FLAGS
}, /* 640X480X60Hz */
31 { { 30500, 640, 672, 768, 864, 480, 517, 523, 588, 0}, B_CMAP8
, 640, 480, 0, 0, MODE_FLAGS
}, /* SVGA_640X480X60HzNI */
32 { { 31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, B_CMAP8
, 640, 480, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@70-72Hz_(640X480X8.Z1) */
33 { { 31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, B_CMAP8
, 640, 480, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@75Hz_(640X480X8.Z1) */
34 { { 36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_CMAP8
, 640, 480, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */
35 /* 4:3 modes; 480k pixels */
36 { { 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 */
37 { { 38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_CMAP8
, 800, 600, 0, 0, MODE_FLAGS
}, /* SVGA_800X600X56HzNI */
38 { { 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 */
39 { { 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 */
40 { { 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 */
41 { { 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 */
42 /* 4:3 modes; 786.432k pixels */
43 { { 65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, B_CMAP8
, 1024, 768, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1024X768X8.Z1) + XFree86 */
44 { { 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 */
45 { { 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 */
46 { { 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 */
47 /* 4:3 modes; 995.328k pixels */
48 { { 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) */
49 { { 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) */
50 { { 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 */
51 { { 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) */
52 /* 5:4 modes; 1.311M pixels */
53 { { 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 */
54 { { 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 */
55 { { 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 */
56 /* 4:3 panel mode; 1.47M pixels */
57 { { 122600, 1400, 1488, 1640, 1880, 1050, 1051, 1054, 1087, T_POSITIVE_SYNC
}, B_CMAP8
, 1400, 1050, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1400X1050) */
58 /* 4:3 modes; 1.92M pixels */
59 { { 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 */
60 /* identical lines to above one, apart from refreshrate.. */
61 { { 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 */
62 { { 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 */
63 { { 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 */
64 { { 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) */
65 { { 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 */
66 /* end identical lines. */
67 /* 4:3 modes; 2.408M pixels */
68 { { 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 */
69 { { 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 */
70 /* 4:3 modes; 2.584M pixels */
71 { { 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 */
72 { { 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 */
73 /* 4:3 modes; 2.765M pixels */
74 { { 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 */
75 { { 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 */
76 /* 4:3 modes; 3.146M pixels */
77 { { 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 */
78 /* 16:10 panel mode; 400k pixels */
79 { { 31300, 800, 848, 928, 1008, 500, 501, 504, 518, T_POSITIVE_SYNC
}, B_CMAP8
, 800, 500, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(800X500) */
80 /* 16:10 panel mode; 655.36k pixels */
81 { { 52800, 1024, 1072, 1176, 1328, 640, 641, 644, 663, T_POSITIVE_SYNC
}, B_CMAP8
, 1024, 640, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1024X640) */
82 /* 16:10 panel-TV mode; 983.04k pixels */
83 { { 80135, 1280, 1344, 1480, 1680, 768, 769, 772, 795, T_POSITIVE_SYNC
}, B_CMAP8
, 1280, 768, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1280X768) */
84 /* 16:10 panel mode; 1.024M pixels */
85 { { 83500, 1280, 1344, 1480, 1680, 800, 801, 804, 828, T_POSITIVE_SYNC
}, B_CMAP8
, 1280, 800, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1280X800) */
86 /* 16:10 panel mode; 1.296M pixels */
87 { { 106500, 1440, 1520, 1672, 1904, 900, 901, 904, 932, T_POSITIVE_SYNC
}, B_CMAP8
, 1440, 900, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1440X900) */
88 /* 16:10 panel mode; 1.764M pixels */
89 { { 147100, 1680, 1784, 1968, 2256, 1050, 1051, 1054, 1087, T_POSITIVE_SYNC
}, B_CMAP8
, 1680, 1050, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1680X1050) */
90 /* 16:10 panel mode; 2.304M pixels */
91 { { 193200, 1920, 2048, 2256, 2592, 1200, 1201, 1204, 1242, T_POSITIVE_SYNC
}, B_CMAP8
, 1920, 1200, 0, 0, MODE_FLAGS
}, /* Vesa_Monitor_@60Hz_(1920X1200) */
95 Check mode is between low and high limits
98 B_BAD_VALUE - mode can be made, but outside limits
99 B_ERROR - not possible
102 * BeOS (tested R5.0.3PE) is failing BWindowScreen.SetFrameBuffer() if PROPOSEMODE
103 * returns B_BAD_VALUE. It's called by the OS with target, low and high set to
104 * have the same settings for BWindowScreen!
105 * Which means we should not return B_BAD_VALUE on anything except for deviations on:
106 * display_mode.virtual_width;
107 * display_mode.virtual_height;
108 * display_mode.timing.h_display;
109 * display_mode.timing.v_display;
112 * The target mode should be modified to correspond to the mode as it can be made. */
113 status_t
PROPOSE_DISPLAY_MODE(display_mode
*target
, const display_mode
*low
, const display_mode
*high
)
115 status_t status
= B_OK
;
116 float pix_clock_found
, target_aspect
;
119 uint32 max_vclk
, row_bytes
, pointer_reservation
;
121 double target_refresh
= ((double)target
->timing
.pixel_clock
* 1000.0) /
123 (double)target
->timing
.h_total
*
124 (double)target
->timing
.v_total
127 want_same_width
= target
->timing
.h_display
== target
->virtual_width
,
128 want_same_height
= target
->timing
.v_display
== target
->virtual_height
;
130 LOG(1, ("PROPOSEMODE: (ENTER) requested virtual_width %d, virtual_height %d\n",
131 target
->virtual_width
, target
->virtual_height
));
134 if (VALID_REQUIRED is set)
136 if (find modes with same size)
138 pick one with nearest pixel clock
142 pick next largest with nearest pixel clock and modify visible portion as far as possible
146 #ifdef VALID_MODE_REQUIRED
149 int closest_mode_ptr
;
150 uint32 closest_mode_clock
;
152 LOG(1, ("PROPOSEMODE: valid mode required!\n"));
154 closest_mode_ptr
= 0xbad;
155 closest_mode_clock
= 0;
156 for (i
=0;i
<VALID_MODES
;i
++)
158 /*check size is ok and clock is better than any found before*/
160 target
->timing
.h_display
==valid_mode_list
[i
].h_display
&&
161 target
->timing
.v_display
==valid_mode_list
[i
].v_display
165 abs(valid_mode_list
[i
].pixel_clock
-target
->timing
.pixel_clock
)<
166 abs(closest_mode_clock
-target
->timing
.pixel_clock
)
169 closest_mode_clock
=valid_mode_list
[i
].pixel_clock
;
175 if (closest_mode_ptr
==0xbad)/*if no modes of correct size*/
177 LOG(4, ("PROPOSEMODE: no valid mode found, aborted.\n"));
182 target
->timing
=valid_mode_list
[closest_mode_ptr
];
183 target_refresh
= ((double)target
->timing
.pixel_clock
* 1000.0) / /*I require this refresh*/
184 ((double)target
->timing
.h_total
* (double)target
->timing
.v_total
);
189 /*find a nearby valid timing from that given*/
190 result
= head1_validate_timing
192 &target
->timing
.h_display
, &target
->timing
.h_sync_start
, &target
->timing
.h_sync_end
, &target
->timing
.h_total
,
193 &target
->timing
.v_display
, &target
->timing
.v_sync_start
, &target
->timing
.v_sync_end
, &target
->timing
.v_total
195 if (result
== B_ERROR
)
197 LOG(4, ("PROPOSEMODE: could not validate timing, aborted.\n"));
201 /* check if all connected output devices can display the requested mode's aspect: */
202 /* calculate display mode aspect */
203 target_aspect
= (target
->timing
.h_display
/ ((float)target
->timing
.v_display
));
205 * allow 0.10 difference so 5:4 aspect panels will be able to use 4:3 aspect modes! */
206 switch (si
->ps
.monitors
)
208 case 0x01: /* digital panel on head 1, nothing on head 2 */
209 if (si
->ps
.panel1_aspect
< (target_aspect
- 0.10))
211 LOG(4, ("PROPOSEMODE: connected panel1 is not widescreen type, aborted.\n"));
215 case 0x10: /* nothing on head 1, digital panel on head 2 */
216 if (si
->ps
.panel2_aspect
< (target_aspect
- 0.10))
218 LOG(4, ("PROPOSEMODE: connected panel2 is not widescreen type, aborted.\n"));
222 case 0x11: /* digital panels on both heads */
223 if ((si
->ps
.panel1_aspect
< (target_aspect
- 0.10)) ||
224 (si
->ps
.panel2_aspect
< (target_aspect
- 0.10)))
226 LOG(4, ("PROPOSEMODE: not all connected panels are widescreen type, aborted.\n"));
230 default: /* at least one analog monitor is connected, or nothing detected at all */
231 if (target_aspect
> 1.34)
233 LOG(4, ("PROPOSEMODE: not all output devices can display widescreen modes, aborted.\n"));
239 /* only export widescreen panel-TV modes when an exact resolution match exists,
240 * to prevent the modelist from becoming too crowded */
241 if (target_aspect
> 1.61)
243 status_t panel_TV_stat
= B_ERROR
;
245 if (si
->ps
.tmds1_active
)
247 if ((target
->timing
.h_display
== si
->ps
.p1_timing
.h_display
) &&
248 (target
->timing
.v_display
== si
->ps
.p1_timing
.v_display
))
250 panel_TV_stat
= B_OK
;
253 if (si
->ps
.tmds2_active
)
255 if ((target
->timing
.h_display
== si
->ps
.p2_timing
.h_display
) &&
256 (target
->timing
.v_display
== si
->ps
.p2_timing
.v_display
))
258 panel_TV_stat
= B_OK
;
261 if (panel_TV_stat
!= B_OK
)
263 LOG(4, ("PROPOSEMODE: WS panel_TV mode requested but no such TV here, aborted.\n"));
268 /* check if panel(s) can display the requested resolution (if connected) */
269 if (si
->ps
.tmds1_active
)
271 if ((target
->timing
.h_display
> si
->ps
.p1_timing
.h_display
) ||
272 (target
->timing
.v_display
> si
->ps
.p1_timing
.v_display
))
274 LOG(4, ("PROPOSEMODE: panel1 can't display requested resolution, aborted.\n"));
278 if (si
->ps
.tmds2_active
)
280 if ((target
->timing
.h_display
> si
->ps
.p2_timing
.h_display
) ||
281 (target
->timing
.v_display
> si
->ps
.p2_timing
.v_display
))
283 LOG(4, ("PROPOSEMODE: panel2 can't display requested resolution, aborted.\n"));
288 /* validate display vs. virtual */
289 if ((target
->timing
.h_display
> target
->virtual_width
) || want_same_width
)
290 target
->virtual_width
= target
->timing
.h_display
;
291 if ((target
->timing
.v_display
> target
->virtual_height
) || want_same_height
)
292 target
->virtual_height
= target
->timing
.v_display
;
294 /* nail virtual size and 'subsequently' calculate rowbytes */
295 result
= eng_general_validate_pic_size (target
, &row_bytes
, &acc_mode
);
296 if (result
== B_ERROR
)
298 LOG(4, ("PROPOSEMODE: could not validate virtual picture size, aborted.\n"));
302 /*check if virtual_width is still within the requested limits*/
303 if ((target
->virtual_width
< low
->virtual_width
) ||
304 (target
->virtual_width
> high
->virtual_width
))
306 status
= B_BAD_VALUE
;
307 LOG(4, ("PROPOSEMODE: WARNING: virtual_width deviates too much\n"));
310 /*check if timing found is within the requested horizontal limits*/
311 if ((target
->timing
.h_display
< low
->timing
.h_display
) ||
312 (target
->timing
.h_display
> high
->timing
.h_display
) ||
313 (target
->timing
.h_sync_start
< low
->timing
.h_sync_start
) ||
314 (target
->timing
.h_sync_start
> high
->timing
.h_sync_start
) ||
315 (target
->timing
.h_sync_end
< low
->timing
.h_sync_end
) ||
316 (target
->timing
.h_sync_end
> high
->timing
.h_sync_end
) ||
317 (target
->timing
.h_total
< low
->timing
.h_total
) ||
318 (target
->timing
.h_total
> high
->timing
.h_total
))
320 /* BWindowScreen workaround: we accept everything except h_display deviations */
321 if ((target
->timing
.h_display
< low
->timing
.h_display
) ||
322 (target
->timing
.h_display
> high
->timing
.h_display
))
324 status
= B_BAD_VALUE
;
326 LOG(4, ("PROPOSEMODE: WARNING: horizontal timing deviates too much\n"));
329 /*check if timing found is within the requested vertical limits*/
331 (target
->timing
.v_display
< low
->timing
.v_display
) ||
332 (target
->timing
.v_display
> high
->timing
.v_display
) ||
333 (target
->timing
.v_sync_start
< low
->timing
.v_sync_start
) ||
334 (target
->timing
.v_sync_start
> high
->timing
.v_sync_start
) ||
335 (target
->timing
.v_sync_end
< low
->timing
.v_sync_end
) ||
336 (target
->timing
.v_sync_end
> high
->timing
.v_sync_end
) ||
337 (target
->timing
.v_total
< low
->timing
.v_total
) ||
338 (target
->timing
.v_total
> high
->timing
.v_total
)
341 /* BWindowScreen workaround: we accept everything except v_display deviations */
342 if ((target
->timing
.v_display
< low
->timing
.v_display
) ||
343 (target
->timing
.v_display
> high
->timing
.v_display
))
345 status
= B_BAD_VALUE
;
347 LOG(4, ("PROPOSEMODE: WARNING: vertical timing deviates too much\n"));
350 /* adjust pixelclock for possible timing modifications done above */
351 target
->timing
.pixel_clock
= target_refresh
* ((double)target
->timing
.h_total
) * ((double)target
->timing
.v_total
) / 1000.0;
353 /* Now find the nearest valid pixelclock we actually can setup for the target mode,
354 * this also makes sure we don't generate more pixel bandwidth than the device can handle */
355 /* calculate settings, but do not actually test anything (that costs too much time!) */
356 result
= head1_pix_pll_find(*target
,&pix_clock_found
,&m
,&n
,&p
,0);
357 /* update the target mode */
358 target
->timing
.pixel_clock
= (pix_clock_found
* 1000);
360 /* note if we fell outside the limits */
361 if ((target
->timing
.pixel_clock
< low
->timing
.pixel_clock
) ||
362 (target
->timing
.pixel_clock
> high
->timing
.pixel_clock
)
365 /* BWindowScreen workaround: we accept deviations <= 1Mhz */
366 if ((target
->timing
.pixel_clock
< (low
->timing
.pixel_clock
- 1000)) ||
367 (target
->timing
.pixel_clock
> (high
->timing
.pixel_clock
+ 1000)))
369 status
= B_BAD_VALUE
;
371 LOG(4, ("PROPOSEMODE: WARNING: pixelclock deviates too much\n"));
374 /* checkout space needed for hardcursor (if any) */
375 pointer_reservation
= 0;
376 if (si
->settings
.hardcursor
) pointer_reservation
= 2048;
377 /* memory requirement for frame buffer */
378 if ((row_bytes
* target
->virtual_height
) >
379 (si
->ps
.memory_size
- pointer_reservation
))
381 target
->virtual_height
=
382 (si
->ps
.memory_size
- pointer_reservation
) / row_bytes
;
384 if (target
->virtual_height
< target
->timing
.v_display
)
386 LOG(4,("PROPOSEMODE: not enough memory for current mode, aborted.\n"));
389 LOG(4,("PROPOSEMODE: validated virtual_width %d, virtual_height %d pixels\n",
390 target
->virtual_width
, target
->virtual_height
));
392 if ((target
->virtual_height
< low
->virtual_height
) ||
393 (target
->virtual_height
> high
->virtual_height
))
395 status
= B_BAD_VALUE
;
396 LOG(4, ("PROPOSEMODE: WARNING: virtual_height deviates too much\n"));
399 /* setup status flags */
400 LOG(1, ("PROPOSEMODE: initial modeflags: $%08x\n", target
->flags
));
401 /* preset to singlehead card without TVout, no overlay support and no hardcursor.
402 * also advice system that app_server and acc engine may touch the framebuffer
403 * simultaneously (fixed). */
405 ~(DUALHEAD_CAPABLE
| TV_CAPABLE
| B_SUPPORTS_OVERLAYS
| B_HARDWARE_CURSOR
| B_IO_FB_NA
);
406 /* we always allow parallel access (fixed), the DAC is always in 'enhanced'
407 * mode (fixed), and all modes support DPMS (fixed);
408 * We support scrolling and panning in every mode, so we 'send a signal' to
409 * BWindowScreen.CanControlFrameBuffer() by setting B_SCROLL. */
410 /* BTW: B_PARALLEL_ACCESS in combination with a hardcursor enables
411 * BDirectWindow windowed modes. */
412 target
->flags
|= (B_PARALLEL_ACCESS
| B_8_BIT_DAC
| B_DPMS
| B_SCROLL
);
414 /* determine the 'would be' max. pixelclock for the second DAC for the current videomode if dualhead were activated */
415 switch (target
->space
)
418 max_vclk
= si
->ps
.max_dac2_clock_8
;
423 max_vclk
= si
->ps
.max_dac2_clock_16
;
427 max_vclk
= si
->ps
.max_dac2_clock_24
;
431 max_vclk
= si
->ps
.max_dac2_clock_32dh
;
435 /* use fail-safe value */
436 max_vclk
= si
->ps
.max_dac2_clock_32dh
;
441 /* set DUALHEAD_CAPABLE if suitable */
442 //fixme: update for independant secondary head use! (reserve fixed memory then)
443 if (si
->ps
.secondary_head
&& (target
->timing
.pixel_clock
<= (max_vclk
* 1000)))
445 switch (target
->flags
& DUALHEAD_BITS
)
448 case DUALHEAD_SWITCH
:
449 if (((si
->ps
.memory_size
- pointer_reservation
) >=
450 (row_bytes
* target
->virtual_height
)) &&
451 ((uint16
)(row_bytes
/ bpp
) >= (target
->timing
.h_display
* 2)))
453 target
->flags
|= DUALHEAD_CAPABLE
;
457 if ((si
->ps
.memory_size
- pointer_reservation
) >=
458 (row_bytes
* target
->virtual_height
))
460 target
->flags
|= DUALHEAD_CAPABLE
;
464 if ((si
->ps
.memory_size
- pointer_reservation
) >=
465 (row_bytes
* target
->virtual_height
* 2))
467 target
->flags
|= DUALHEAD_CAPABLE
;
473 /* set TV_CAPABLE if suitable: pixelclock is not important (defined by TVstandard) */
474 //fixme: modify for G100 and G200 TVout later on...
475 if (target
->flags
& DUALHEAD_CAPABLE
)
478 (target
->timing
.h_display
<= 1024) &&
479 (target
->timing
.v_display
<= 768))
481 target
->flags
|= TV_CAPABLE
;
485 /* set HARDWARE_CURSOR mode if suitable */
486 if (si
->settings
.hardcursor
)
487 target
->flags
|= B_HARDWARE_CURSOR
;
489 /* set SUPPORTS_OVERLAYS */
490 target
->flags
|= B_SUPPORTS_OVERLAYS
;
492 LOG(1, ("PROPOSEMODE: validated status modeflags: $%08x\n", target
->flags
));
494 /* overrule timing command flags to be (fixed) blank_pedestal = 0.0IRE,
495 * progressive scan (fixed), and sync_on_green not avaible. */
496 target
->timing
.flags
&= ~(B_BLANK_PEDESTAL
| B_TIMING_INTERLACED
| B_SYNC_ON_GREEN
);
497 /* The HSYNC and VSYNC command flags are actually executed by the driver. */
499 if (status
== B_OK
) LOG(4, ("PROPOSEMODE: completed successfully.\n"));
500 else LOG(4, ("PROPOSEMODE: mode can be made, but outside given limits.\n"));
504 /* Return the number of modes this device will return from GET_MODE_LIST().
505 This is precalculated in create_mode_list (called from InitAccelerant stuff)
507 uint32
ACCELERANT_MODE_COUNT(void)
509 LOG(1, ("ACCELERANT_MODE_COUNT: the modelist contains %d modes\n",si
->mode_count
));
511 return si
->mode_count
;
514 /* Copy the list of guaranteed supported video modes to the location provided.*/
515 status_t
GET_MODE_LIST(display_mode
*dm
)
517 LOG(1, ("GET_MODE_LIST: exporting the modelist created before.\n"));
519 memcpy(dm
, my_mode_list
, si
->mode_count
* sizeof(display_mode
));
523 /* Create a list of display_modes to pass back to the caller.*/
524 status_t
create_mode_list(void)
537 color_space spaces
[4] = {B_RGB32_LITTLE
,B_RGB16_LITTLE
,B_RGB15_LITTLE
,B_CMAP8
};
539 /* figure out how big the list could be, and adjust up to nearest multiple of B_PAGE_SIZE */
540 max_size
= (((MODE_COUNT
* 4) * sizeof(display_mode
)) + (B_PAGE_SIZE
-1)) & ~(B_PAGE_SIZE
-1);
541 /* create an area to hold the info */
542 si
->mode_area
= my_mode_list_area
=
543 create_area("NV accelerant mode info", (void **)&my_mode_list
, B_ANY_ADDRESS
, max_size
, B_NO_LOCK
, B_READ_AREA
| B_WRITE_AREA
);
544 if (my_mode_list_area
< B_OK
) return my_mode_list_area
;
546 /* walk through our predefined list and see which modes fit this device */
550 for (i
= 0; i
< MODE_COUNT
; i
++)
552 /* set ranges for acceptable values */
554 /* range is 6.25% of default clock: arbitrarily picked */
555 pix_clk_range
= low
.timing
.pixel_clock
>> 5;
556 low
.timing
.pixel_clock
-= pix_clk_range
;
557 high
.timing
.pixel_clock
+= pix_clk_range
;
558 /* 'some cards need wider virtual widths for certain modes':
559 * Not true. They might need a wider pitch, but this is _not_ reflected in
560 * virtual_width, but in fbc.bytes_per_row. */
561 //So disable next line:
562 //high.virtual_width = 4096;
563 /* do it once for each depth we want to support */
564 for (j
= 0; j
< (sizeof(spaces
) / sizeof(color_space
)); j
++)
566 /* set target values */
568 /* poke the specific space */
569 dst
->space
= low
.space
= high
.space
= spaces
[j
];
570 /* ask for a compatible mode */
571 /* We have to check for B_OK, because otherwise the pix_clk_range
572 * won't be taken into account!! */
574 //if (PROPOSE_DISPLAY_MODE(dst, &low, &high) != B_ERROR) {
576 if (PROPOSE_DISPLAY_MODE(dst
, &low
, &high
) == B_OK
) {
577 /* count it, and move on to next mode */
582 /* advance to next mode */