168353368SRudolf Cornelissen /*
268353368SRudolf Cornelissen Copyright 1999, Be Incorporated. All Rights Reserved.
368353368SRudolf Cornelissen This file may be used under the terms of the Be Sample Code License.
468353368SRudolf Cornelissen
568353368SRudolf Cornelissen Other authors for NV driver:
668353368SRudolf Cornelissen Mark Watson,
768353368SRudolf Cornelissen Rudolf Cornelissen 9/2002-10/2004
868353368SRudolf Cornelissen */
968353368SRudolf Cornelissen
1068353368SRudolf Cornelissen #define MODULE_BIT 0x00400000
1168353368SRudolf Cornelissen
1268353368SRudolf Cornelissen #include "acc_std.h"
1368353368SRudolf Cornelissen
1468353368SRudolf Cornelissen #define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC)
1568353368SRudolf Cornelissen /* mode flags will be setup as status info by PROPOSEMODE! */
1668353368SRudolf Cornelissen #define MODE_FLAGS 0
1768353368SRudolf Cornelissen #define MODE_COUNT (sizeof (mode_list) / sizeof (display_mode))
1868353368SRudolf Cornelissen
1968353368SRudolf Cornelissen /*some monitors only handle a fixed set of modes*/
2068353368SRudolf Cornelissen #include "valid_mode_list"
2168353368SRudolf Cornelissen
2268353368SRudolf Cornelissen /* Standard VESA modes,
2368353368SRudolf Cornelissen * plus panel specific resolution modes which are internally modified during run-time depending on the requirements of the actual
2468353368SRudolf Cornelissen * panel connected. The modes as listed here, should timing-wise be as compatible with analog (CRT) monitors as can be... */
2568353368SRudolf Cornelissen static const display_mode mode_list[] = {
2668353368SRudolf Cornelissen /* 4:3 modes; 307.2k pixels */
2768353368SRudolf Cornelissen { { 25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */
2868353368SRudolf Cornelissen { { 27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* 640X480X60Hz */
2968353368SRudolf Cornelissen { { 30500, 640, 672, 768, 864, 480, 517, 523, 588, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* SVGA_640X480X60HzNI */
3068353368SRudolf Cornelissen { { 31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(640X480X8.Z1) */
3168353368SRudolf Cornelissen { { 31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(640X480X8.Z1) */
3268353368SRudolf Cornelissen { { 36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */
3368353368SRudolf Cornelissen /* 4:3 modes; 480k pixels */
3468353368SRudolf Cornelissen { { 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 */
3568353368SRudolf Cornelissen { { 38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* SVGA_800X600X56HzNI */
3668353368SRudolf Cornelissen { { 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 */
3768353368SRudolf Cornelissen { { 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 */
3868353368SRudolf Cornelissen { { 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 */
3968353368SRudolf Cornelissen { { 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 */
4068353368SRudolf Cornelissen /* 4:3 modes; 786.432k pixels */
4168353368SRudolf Cornelissen { { 65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1024X768X8.Z1) + XFree86 */
4268353368SRudolf Cornelissen { { 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 */
4368353368SRudolf Cornelissen { { 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 */
4468353368SRudolf Cornelissen { { 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 */
4568353368SRudolf Cornelissen /* 4:3 modes; 995.328k pixels */
4668353368SRudolf Cornelissen { { 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) */
4768353368SRudolf Cornelissen { { 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) */
4868353368SRudolf Cornelissen { { 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 */
4968353368SRudolf Cornelissen { { 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) */
5068353368SRudolf Cornelissen /* 5:4 modes; 1.311M pixels */
5168353368SRudolf Cornelissen { { 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 */
5268353368SRudolf Cornelissen { { 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 */
5368353368SRudolf Cornelissen { { 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 */
5468353368SRudolf Cornelissen /* 4:3 panel mode; 1.47M pixels */
5568353368SRudolf Cornelissen { { 122600, 1400, 1488, 1640, 1880, 1050, 1051, 1054, 1087, T_POSITIVE_SYNC}, B_CMAP8, 1400, 1050, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1400X1050) */
5668353368SRudolf Cornelissen /* 4:3 modes; 1.92M pixels */
5768353368SRudolf Cornelissen { { 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 */
5868353368SRudolf Cornelissen /* identical lines to above one, apart from refreshrate.. */
5968353368SRudolf Cornelissen { { 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 */
6068353368SRudolf Cornelissen { { 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 */
6168353368SRudolf Cornelissen { { 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 */
6268353368SRudolf Cornelissen { { 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) */
6368353368SRudolf Cornelissen { { 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 */
6468353368SRudolf Cornelissen /* end identical lines. */
6568353368SRudolf Cornelissen /* 4:3 modes; 2.408M pixels */
6668353368SRudolf Cornelissen { { 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 */
6768353368SRudolf Cornelissen { { 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 */
6868353368SRudolf Cornelissen /* 4:3 modes; 2.584M pixels */
6968353368SRudolf Cornelissen { { 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 */
7068353368SRudolf Cornelissen { { 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 */
7168353368SRudolf Cornelissen /* 4:3 modes; 2.765M pixels */
7268353368SRudolf Cornelissen { { 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 */
7368353368SRudolf Cornelissen { { 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 */
7468353368SRudolf Cornelissen /* 4:3 modes; 3.146M pixels */
7568353368SRudolf Cornelissen { { 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 */
7668353368SRudolf Cornelissen /* 16:10 panel mode; 400k pixels */
7768353368SRudolf Cornelissen { { 31300, 800, 848, 928, 1008, 500, 501, 504, 518, T_POSITIVE_SYNC}, B_CMAP8, 800, 500, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(800X500) */
7868353368SRudolf Cornelissen /* 16:10 panel mode; 655.36k pixels */
7968353368SRudolf Cornelissen { { 52800, 1024, 1072, 1176, 1328, 640, 641, 644, 663, T_POSITIVE_SYNC}, B_CMAP8, 1024, 640, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1024X640) */
8068353368SRudolf Cornelissen /* 16:10 panel-TV mode; 983.04k pixels */
8168353368SRudolf Cornelissen { { 80135, 1280, 1344, 1480, 1680, 768, 769, 772, 795, T_POSITIVE_SYNC}, B_CMAP8, 1280, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1280X768) */
8268353368SRudolf Cornelissen /* 16:10 panel mode; 1.024M pixels */
8368353368SRudolf Cornelissen { { 83500, 1280, 1344, 1480, 1680, 800, 801, 804, 828, T_POSITIVE_SYNC}, B_CMAP8, 1280, 800, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1280X800) */
8468353368SRudolf Cornelissen /* 16:10 panel mode; 1.296M pixels */
8568353368SRudolf Cornelissen { { 106500, 1440, 1520, 1672, 1904, 900, 901, 904, 932, T_POSITIVE_SYNC}, B_CMAP8, 1440, 900, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1440X900) */
8668353368SRudolf Cornelissen /* 16:10 panel mode; 1.764M pixels */
8768353368SRudolf Cornelissen { { 147100, 1680, 1784, 1968, 2256, 1050, 1051, 1054, 1087, T_POSITIVE_SYNC}, B_CMAP8, 1680, 1050, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1680X1050) */
8868353368SRudolf Cornelissen /* 16:10 panel mode; 2.304M pixels */
8968353368SRudolf Cornelissen { { 193200, 1920, 2048, 2256, 2592, 1200, 1201, 1204, 1242, T_POSITIVE_SYNC}, B_CMAP8, 1920, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1920X1200) */
9068353368SRudolf Cornelissen };
9168353368SRudolf Cornelissen
9268353368SRudolf Cornelissen /*
9368353368SRudolf Cornelissen Check mode is between low and high limits
9468353368SRudolf Cornelissen returns:
9568353368SRudolf Cornelissen B_OK - found one
9668353368SRudolf Cornelissen B_BAD_VALUE - mode can be made, but outside limits
9768353368SRudolf Cornelissen B_ERROR - not possible
9868353368SRudolf Cornelissen */
9968353368SRudolf Cornelissen /* BOUNDS WARNING:
10068353368SRudolf Cornelissen * BeOS (tested R5.0.3PE) is failing BWindowScreen.SetFrameBuffer() if PROPOSEMODE
10168353368SRudolf Cornelissen * returns B_BAD_VALUE. It's called by the OS with target, low and high set to
10268353368SRudolf Cornelissen * have the same settings for BWindowScreen!
10368353368SRudolf Cornelissen * Which means we should not return B_BAD_VALUE on anything except for deviations on:
10468353368SRudolf Cornelissen * display_mode.virtual_width;
10568353368SRudolf Cornelissen * display_mode.virtual_height;
10668353368SRudolf Cornelissen * display_mode.timing.h_display;
10768353368SRudolf Cornelissen * display_mode.timing.v_display;
10868353368SRudolf Cornelissen */
10968353368SRudolf Cornelissen /* Note:
11068353368SRudolf Cornelissen * The target mode should be modified to correspond to the mode as it can be made. */
PROPOSE_DISPLAY_MODE(display_mode * target,const display_mode * low,const display_mode * high)11168353368SRudolf Cornelissen status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const display_mode *high)
11268353368SRudolf Cornelissen {
11368353368SRudolf Cornelissen status_t status = B_OK;
11468353368SRudolf Cornelissen float pix_clock_found, target_aspect;
11568353368SRudolf Cornelissen uint8 m,n,p, bpp;
11668353368SRudolf Cornelissen status_t result;
11768353368SRudolf Cornelissen uint32 max_vclk, row_bytes, pointer_reservation;
11868353368SRudolf Cornelissen bool acc_mode;
11968353368SRudolf Cornelissen double target_refresh = ((double)target->timing.pixel_clock * 1000.0) /
12068353368SRudolf Cornelissen (
12168353368SRudolf Cornelissen (double)target->timing.h_total *
12268353368SRudolf Cornelissen (double)target->timing.v_total
12368353368SRudolf Cornelissen );
12468353368SRudolf Cornelissen bool
12568353368SRudolf Cornelissen want_same_width = target->timing.h_display == target->virtual_width,
12668353368SRudolf Cornelissen want_same_height = target->timing.v_display == target->virtual_height;
12768353368SRudolf Cornelissen
12868353368SRudolf Cornelissen LOG(1, ("PROPOSEMODE: (ENTER) requested virtual_width %d, virtual_height %d\n",
12968353368SRudolf Cornelissen target->virtual_width, target->virtual_height));
13068353368SRudolf Cornelissen
13168353368SRudolf Cornelissen /*check valid list:
13268353368SRudolf Cornelissen if (VALID_REQUIRED is set)
13368353368SRudolf Cornelissen {
13468353368SRudolf Cornelissen if (find modes with same size)
13568353368SRudolf Cornelissen {
13668353368SRudolf Cornelissen pick one with nearest pixel clock
13768353368SRudolf Cornelissen }
13868353368SRudolf Cornelissen else
13968353368SRudolf Cornelissen {
14068353368SRudolf Cornelissen pick next largest with nearest pixel clock and modify visible portion as far as possible
14168353368SRudolf Cornelissen }
14268353368SRudolf Cornelissen }
14368353368SRudolf Cornelissen */
14468353368SRudolf Cornelissen #ifdef VALID_MODE_REQUIRED
14568353368SRudolf Cornelissen {
14668353368SRudolf Cornelissen int i;
14768353368SRudolf Cornelissen int closest_mode_ptr;
14868353368SRudolf Cornelissen uint32 closest_mode_clock;
14968353368SRudolf Cornelissen
15068353368SRudolf Cornelissen LOG(1, ("PROPOSEMODE: valid mode required!\n"));
15168353368SRudolf Cornelissen
15268353368SRudolf Cornelissen closest_mode_ptr = 0xbad;
15368353368SRudolf Cornelissen closest_mode_clock = 0;
15468353368SRudolf Cornelissen for (i=0;i<VALID_MODES;i++)
15568353368SRudolf Cornelissen {
15668353368SRudolf Cornelissen /*check size is ok and clock is better than any found before*/
15768353368SRudolf Cornelissen if(
15868353368SRudolf Cornelissen target->timing.h_display==valid_mode_list[i].h_display &&
15968353368SRudolf Cornelissen target->timing.v_display==valid_mode_list[i].v_display
16068353368SRudolf Cornelissen )
16168353368SRudolf Cornelissen {
16268353368SRudolf Cornelissen if (
16368353368SRudolf Cornelissen abs(valid_mode_list[i].pixel_clock-target->timing.pixel_clock)<
16468353368SRudolf Cornelissen abs(closest_mode_clock-target->timing.pixel_clock)
16568353368SRudolf Cornelissen )
16668353368SRudolf Cornelissen {
16768353368SRudolf Cornelissen closest_mode_clock=valid_mode_list[i].pixel_clock;
16868353368SRudolf Cornelissen closest_mode_ptr=i;
16968353368SRudolf Cornelissen }
17068353368SRudolf Cornelissen }
17168353368SRudolf Cornelissen }
17268353368SRudolf Cornelissen
17368353368SRudolf Cornelissen if (closest_mode_ptr==0xbad)/*if no modes of correct size*/
17468353368SRudolf Cornelissen {
17568353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: no valid mode found, aborted.\n"));
17668353368SRudolf Cornelissen return B_ERROR;
17768353368SRudolf Cornelissen }
17868353368SRudolf Cornelissen else
17968353368SRudolf Cornelissen {
18068353368SRudolf Cornelissen target->timing=valid_mode_list[closest_mode_ptr];
18168353368SRudolf Cornelissen target_refresh = ((double)target->timing.pixel_clock * 1000.0) / /*I require this refresh*/
18268353368SRudolf Cornelissen ((double)target->timing.h_total * (double)target->timing.v_total);
18368353368SRudolf Cornelissen }
18468353368SRudolf Cornelissen }
18568353368SRudolf Cornelissen #endif
18668353368SRudolf Cornelissen
18768353368SRudolf Cornelissen /*find a nearby valid timing from that given*/
18868353368SRudolf Cornelissen result = head1_validate_timing
18968353368SRudolf Cornelissen (
19068353368SRudolf Cornelissen &target->timing.h_display, &target->timing.h_sync_start, &target->timing.h_sync_end, &target->timing.h_total,
19168353368SRudolf Cornelissen &target->timing.v_display, &target->timing.v_sync_start, &target->timing.v_sync_end, &target->timing.v_total
19268353368SRudolf Cornelissen );
19368353368SRudolf Cornelissen if (result == B_ERROR)
19468353368SRudolf Cornelissen {
19568353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: could not validate timing, aborted.\n"));
19668353368SRudolf Cornelissen return result;
19768353368SRudolf Cornelissen }
19868353368SRudolf Cornelissen
19968353368SRudolf Cornelissen /* check if all connected output devices can display the requested mode's aspect: */
20068353368SRudolf Cornelissen /* calculate display mode aspect */
20168353368SRudolf Cornelissen target_aspect = (target->timing.h_display / ((float)target->timing.v_display));
20268353368SRudolf Cornelissen /* NOTE:
20368353368SRudolf Cornelissen * allow 0.10 difference so 5:4 aspect panels will be able to use 4:3 aspect modes! */
20468353368SRudolf Cornelissen switch (si->ps.monitors)
20568353368SRudolf Cornelissen {
20668353368SRudolf Cornelissen case 0x01: /* digital panel on head 1, nothing on head 2 */
20768353368SRudolf Cornelissen if (si->ps.panel1_aspect < (target_aspect - 0.10))
20868353368SRudolf Cornelissen {
20968353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: connected panel1 is not widescreen type, aborted.\n"));
21068353368SRudolf Cornelissen return B_ERROR;
21168353368SRudolf Cornelissen }
21268353368SRudolf Cornelissen break;
21368353368SRudolf Cornelissen case 0x10: /* nothing on head 1, digital panel on head 2 */
21468353368SRudolf Cornelissen if (si->ps.panel2_aspect < (target_aspect - 0.10))
21568353368SRudolf Cornelissen {
21668353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: connected panel2 is not widescreen type, aborted.\n"));
21768353368SRudolf Cornelissen return B_ERROR;
21868353368SRudolf Cornelissen }
21968353368SRudolf Cornelissen break;
22068353368SRudolf Cornelissen case 0x11: /* digital panels on both heads */
22168353368SRudolf Cornelissen if ((si->ps.panel1_aspect < (target_aspect - 0.10)) ||
22268353368SRudolf Cornelissen (si->ps.panel2_aspect < (target_aspect - 0.10)))
22368353368SRudolf Cornelissen {
22468353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: not all connected panels are widescreen type, aborted.\n"));
22568353368SRudolf Cornelissen return B_ERROR;
22668353368SRudolf Cornelissen }
22768353368SRudolf Cornelissen break;
22868353368SRudolf Cornelissen default: /* at least one analog monitor is connected, or nothing detected at all */
22968353368SRudolf Cornelissen if (target_aspect > 1.34)
23068353368SRudolf Cornelissen {
23168353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: not all output devices can display widescreen modes, aborted.\n"));
23268353368SRudolf Cornelissen return B_ERROR;
23368353368SRudolf Cornelissen }
23468353368SRudolf Cornelissen break;
23568353368SRudolf Cornelissen }
23668353368SRudolf Cornelissen
23768353368SRudolf Cornelissen /* only export widescreen panel-TV modes when an exact resolution match exists,
23868353368SRudolf Cornelissen * to prevent the modelist from becoming too crowded */
23968353368SRudolf Cornelissen if (target_aspect > 1.61)
24068353368SRudolf Cornelissen {
24168353368SRudolf Cornelissen status_t panel_TV_stat = B_ERROR;
24268353368SRudolf Cornelissen
24368353368SRudolf Cornelissen if (si->ps.tmds1_active)
24468353368SRudolf Cornelissen {
24568353368SRudolf Cornelissen if ((target->timing.h_display == si->ps.p1_timing.h_display) &&
24668353368SRudolf Cornelissen (target->timing.v_display == si->ps.p1_timing.v_display))
24768353368SRudolf Cornelissen {
24868353368SRudolf Cornelissen panel_TV_stat = B_OK;
24968353368SRudolf Cornelissen }
25068353368SRudolf Cornelissen }
25168353368SRudolf Cornelissen if (si->ps.tmds2_active)
25268353368SRudolf Cornelissen {
25368353368SRudolf Cornelissen if ((target->timing.h_display == si->ps.p2_timing.h_display) &&
25468353368SRudolf Cornelissen (target->timing.v_display == si->ps.p2_timing.v_display))
25568353368SRudolf Cornelissen {
25668353368SRudolf Cornelissen panel_TV_stat = B_OK;
25768353368SRudolf Cornelissen }
25868353368SRudolf Cornelissen }
25968353368SRudolf Cornelissen if (panel_TV_stat != B_OK)
26068353368SRudolf Cornelissen {
26168353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: WS panel_TV mode requested but no such TV here, aborted.\n"));
26268353368SRudolf Cornelissen return B_ERROR;
26368353368SRudolf Cornelissen }
26468353368SRudolf Cornelissen }
26568353368SRudolf Cornelissen
26668353368SRudolf Cornelissen /* check if panel(s) can display the requested resolution (if connected) */
26768353368SRudolf Cornelissen if (si->ps.tmds1_active)
26868353368SRudolf Cornelissen {
26968353368SRudolf Cornelissen if ((target->timing.h_display > si->ps.p1_timing.h_display) ||
27068353368SRudolf Cornelissen (target->timing.v_display > si->ps.p1_timing.v_display))
27168353368SRudolf Cornelissen {
27268353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: panel1 can't display requested resolution, aborted.\n"));
27368353368SRudolf Cornelissen return B_ERROR;
27468353368SRudolf Cornelissen }
27568353368SRudolf Cornelissen }
27668353368SRudolf Cornelissen if (si->ps.tmds2_active)
27768353368SRudolf Cornelissen {
27868353368SRudolf Cornelissen if ((target->timing.h_display > si->ps.p2_timing.h_display) ||
27968353368SRudolf Cornelissen (target->timing.v_display > si->ps.p2_timing.v_display))
28068353368SRudolf Cornelissen {
28168353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: panel2 can't display requested resolution, aborted.\n"));
28268353368SRudolf Cornelissen return B_ERROR;
28368353368SRudolf Cornelissen }
28468353368SRudolf Cornelissen }
28568353368SRudolf Cornelissen
28668353368SRudolf Cornelissen /* validate display vs. virtual */
28768353368SRudolf Cornelissen if ((target->timing.h_display > target->virtual_width) || want_same_width)
28868353368SRudolf Cornelissen target->virtual_width = target->timing.h_display;
28968353368SRudolf Cornelissen if ((target->timing.v_display > target->virtual_height) || want_same_height)
29068353368SRudolf Cornelissen target->virtual_height = target->timing.v_display;
29168353368SRudolf Cornelissen
29268353368SRudolf Cornelissen /* nail virtual size and 'subsequently' calculate rowbytes */
293886dbf81SRudolf Cornelissen result = eng_general_validate_pic_size (target, &row_bytes, &acc_mode);
29468353368SRudolf Cornelissen if (result == B_ERROR)
29568353368SRudolf Cornelissen {
29668353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: could not validate virtual picture size, aborted.\n"));
29768353368SRudolf Cornelissen return result;
29868353368SRudolf Cornelissen }
29968353368SRudolf Cornelissen
30068353368SRudolf Cornelissen /*check if virtual_width is still within the requested limits*/
30168353368SRudolf Cornelissen if ((target->virtual_width < low->virtual_width) ||
30268353368SRudolf Cornelissen (target->virtual_width > high->virtual_width))
30368353368SRudolf Cornelissen {
30468353368SRudolf Cornelissen status = B_BAD_VALUE;
30568353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: WARNING: virtual_width deviates too much\n"));
30668353368SRudolf Cornelissen }
30768353368SRudolf Cornelissen
30868353368SRudolf Cornelissen /*check if timing found is within the requested horizontal limits*/
30968353368SRudolf Cornelissen if ((target->timing.h_display < low->timing.h_display) ||
31068353368SRudolf Cornelissen (target->timing.h_display > high->timing.h_display) ||
31168353368SRudolf Cornelissen (target->timing.h_sync_start < low->timing.h_sync_start) ||
31268353368SRudolf Cornelissen (target->timing.h_sync_start > high->timing.h_sync_start) ||
31368353368SRudolf Cornelissen (target->timing.h_sync_end < low->timing.h_sync_end) ||
31468353368SRudolf Cornelissen (target->timing.h_sync_end > high->timing.h_sync_end) ||
31568353368SRudolf Cornelissen (target->timing.h_total < low->timing.h_total) ||
31668353368SRudolf Cornelissen (target->timing.h_total > high->timing.h_total))
31768353368SRudolf Cornelissen {
31868353368SRudolf Cornelissen /* BWindowScreen workaround: we accept everything except h_display deviations */
31968353368SRudolf Cornelissen if ((target->timing.h_display < low->timing.h_display) ||
32068353368SRudolf Cornelissen (target->timing.h_display > high->timing.h_display))
32168353368SRudolf Cornelissen {
32268353368SRudolf Cornelissen status = B_BAD_VALUE;
32368353368SRudolf Cornelissen }
32468353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: WARNING: horizontal timing deviates too much\n"));
32568353368SRudolf Cornelissen }
32668353368SRudolf Cornelissen
32768353368SRudolf Cornelissen /*check if timing found is within the requested vertical limits*/
32868353368SRudolf Cornelissen if (
32968353368SRudolf Cornelissen (target->timing.v_display < low->timing.v_display) ||
33068353368SRudolf Cornelissen (target->timing.v_display > high->timing.v_display) ||
33168353368SRudolf Cornelissen (target->timing.v_sync_start < low->timing.v_sync_start) ||
33268353368SRudolf Cornelissen (target->timing.v_sync_start > high->timing.v_sync_start) ||
33368353368SRudolf Cornelissen (target->timing.v_sync_end < low->timing.v_sync_end) ||
33468353368SRudolf Cornelissen (target->timing.v_sync_end > high->timing.v_sync_end) ||
33568353368SRudolf Cornelissen (target->timing.v_total < low->timing.v_total) ||
33668353368SRudolf Cornelissen (target->timing.v_total > high->timing.v_total)
33768353368SRudolf Cornelissen )
33868353368SRudolf Cornelissen {
33968353368SRudolf Cornelissen /* BWindowScreen workaround: we accept everything except v_display deviations */
34068353368SRudolf Cornelissen if ((target->timing.v_display < low->timing.v_display) ||
34168353368SRudolf Cornelissen (target->timing.v_display > high->timing.v_display))
34268353368SRudolf Cornelissen {
34368353368SRudolf Cornelissen status = B_BAD_VALUE;
34468353368SRudolf Cornelissen }
34568353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: WARNING: vertical timing deviates too much\n"));
34668353368SRudolf Cornelissen }
34768353368SRudolf Cornelissen
34868353368SRudolf Cornelissen /* adjust pixelclock for possible timing modifications done above */
34968353368SRudolf Cornelissen target->timing.pixel_clock = target_refresh * ((double)target->timing.h_total) * ((double)target->timing.v_total) / 1000.0;
35068353368SRudolf Cornelissen
35168353368SRudolf Cornelissen /* Now find the nearest valid pixelclock we actually can setup for the target mode,
35268353368SRudolf Cornelissen * this also makes sure we don't generate more pixel bandwidth than the device can handle */
35368353368SRudolf Cornelissen /* calculate settings, but do not actually test anything (that costs too much time!) */
35468353368SRudolf Cornelissen result = head1_pix_pll_find(*target,&pix_clock_found,&m,&n,&p,0);
35568353368SRudolf Cornelissen /* update the target mode */
35668353368SRudolf Cornelissen target->timing.pixel_clock = (pix_clock_found * 1000);
35768353368SRudolf Cornelissen
35868353368SRudolf Cornelissen /* note if we fell outside the limits */
35968353368SRudolf Cornelissen if ((target->timing.pixel_clock < low->timing.pixel_clock) ||
36068353368SRudolf Cornelissen (target->timing.pixel_clock > high->timing.pixel_clock)
36168353368SRudolf Cornelissen )
36268353368SRudolf Cornelissen {
36368353368SRudolf Cornelissen /* BWindowScreen workaround: we accept deviations <= 1Mhz */
36468353368SRudolf Cornelissen if ((target->timing.pixel_clock < (low->timing.pixel_clock - 1000)) ||
36568353368SRudolf Cornelissen (target->timing.pixel_clock > (high->timing.pixel_clock + 1000)))
36668353368SRudolf Cornelissen {
36768353368SRudolf Cornelissen status = B_BAD_VALUE;
36868353368SRudolf Cornelissen }
36968353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: WARNING: pixelclock deviates too much\n"));
37068353368SRudolf Cornelissen }
37168353368SRudolf Cornelissen
37268353368SRudolf Cornelissen /* checkout space needed for hardcursor (if any) */
37368353368SRudolf Cornelissen pointer_reservation = 0;
37468353368SRudolf Cornelissen if (si->settings.hardcursor) pointer_reservation = 2048;
37568353368SRudolf Cornelissen /* memory requirement for frame buffer */
37668353368SRudolf Cornelissen if ((row_bytes * target->virtual_height) >
37768353368SRudolf Cornelissen (si->ps.memory_size - pointer_reservation))
37868353368SRudolf Cornelissen {
37968353368SRudolf Cornelissen target->virtual_height =
38068353368SRudolf Cornelissen (si->ps.memory_size - pointer_reservation) / row_bytes;
38168353368SRudolf Cornelissen }
38268353368SRudolf Cornelissen if (target->virtual_height < target->timing.v_display)
38368353368SRudolf Cornelissen {
38468353368SRudolf Cornelissen LOG(4,("PROPOSEMODE: not enough memory for current mode, aborted.\n"));
38568353368SRudolf Cornelissen return B_ERROR;
38668353368SRudolf Cornelissen }
38768353368SRudolf Cornelissen LOG(4,("PROPOSEMODE: validated virtual_width %d, virtual_height %d pixels\n",
38868353368SRudolf Cornelissen target->virtual_width, target->virtual_height));
38968353368SRudolf Cornelissen
39068353368SRudolf Cornelissen if ((target->virtual_height < low->virtual_height) ||
39168353368SRudolf Cornelissen (target->virtual_height > high->virtual_height))
39268353368SRudolf Cornelissen {
39368353368SRudolf Cornelissen status = B_BAD_VALUE;
39468353368SRudolf Cornelissen LOG(4, ("PROPOSEMODE: WARNING: virtual_height deviates too much\n"));
39568353368SRudolf Cornelissen }
39668353368SRudolf Cornelissen
39768353368SRudolf Cornelissen /* setup status flags */
39868353368SRudolf Cornelissen LOG(1, ("PROPOSEMODE: initial modeflags: $%08x\n", target->flags));
39968353368SRudolf Cornelissen /* preset to singlehead card without TVout, no overlay support and no hardcursor.
40068353368SRudolf Cornelissen * also advice system that app_server and acc engine may touch the framebuffer
40168353368SRudolf Cornelissen * simultaneously (fixed). */
40268353368SRudolf Cornelissen target->flags &=
40368353368SRudolf Cornelissen ~(DUALHEAD_CAPABLE | TV_CAPABLE | B_SUPPORTS_OVERLAYS | B_HARDWARE_CURSOR | B_IO_FB_NA);
40468353368SRudolf Cornelissen /* we always allow parallel access (fixed), the DAC is always in 'enhanced'
40568353368SRudolf Cornelissen * mode (fixed), and all modes support DPMS (fixed);
40668353368SRudolf Cornelissen * We support scrolling and panning in every mode, so we 'send a signal' to
40768353368SRudolf Cornelissen * BWindowScreen.CanControlFrameBuffer() by setting B_SCROLL. */
40868353368SRudolf Cornelissen /* BTW: B_PARALLEL_ACCESS in combination with a hardcursor enables
40968353368SRudolf Cornelissen * BDirectWindow windowed modes. */
41068353368SRudolf Cornelissen target->flags |= (B_PARALLEL_ACCESS | B_8_BIT_DAC | B_DPMS | B_SCROLL);
41168353368SRudolf Cornelissen
41268353368SRudolf Cornelissen /* determine the 'would be' max. pixelclock for the second DAC for the current videomode if dualhead were activated */
41368353368SRudolf Cornelissen switch (target->space)
41468353368SRudolf Cornelissen {
41568353368SRudolf Cornelissen case B_CMAP8:
41668353368SRudolf Cornelissen max_vclk = si->ps.max_dac2_clock_8;
41768353368SRudolf Cornelissen bpp = 1;
41868353368SRudolf Cornelissen break;
41968353368SRudolf Cornelissen case B_RGB15_LITTLE:
42068353368SRudolf Cornelissen case B_RGB16_LITTLE:
42168353368SRudolf Cornelissen max_vclk = si->ps.max_dac2_clock_16;
42268353368SRudolf Cornelissen bpp = 2;
42368353368SRudolf Cornelissen break;
42468353368SRudolf Cornelissen case B_RGB24_LITTLE:
42568353368SRudolf Cornelissen max_vclk = si->ps.max_dac2_clock_24;
42668353368SRudolf Cornelissen bpp = 3;
42768353368SRudolf Cornelissen break;
42868353368SRudolf Cornelissen case B_RGB32_LITTLE:
42968353368SRudolf Cornelissen max_vclk = si->ps.max_dac2_clock_32dh;
43068353368SRudolf Cornelissen bpp = 4;
43168353368SRudolf Cornelissen break;
43268353368SRudolf Cornelissen default:
43368353368SRudolf Cornelissen /* use fail-safe value */
43468353368SRudolf Cornelissen max_vclk = si->ps.max_dac2_clock_32dh;
43568353368SRudolf Cornelissen bpp = 4;
43668353368SRudolf Cornelissen break;
43768353368SRudolf Cornelissen }
43868353368SRudolf Cornelissen
43968353368SRudolf Cornelissen /* set DUALHEAD_CAPABLE if suitable */
44068353368SRudolf Cornelissen //fixme: update for independant secondary head use! (reserve fixed memory then)
44168353368SRudolf Cornelissen if (si->ps.secondary_head && (target->timing.pixel_clock <= (max_vclk * 1000)))
44268353368SRudolf Cornelissen {
44368353368SRudolf Cornelissen switch (target->flags & DUALHEAD_BITS)
44468353368SRudolf Cornelissen {
44568353368SRudolf Cornelissen case DUALHEAD_ON:
44668353368SRudolf Cornelissen case DUALHEAD_SWITCH:
44768353368SRudolf Cornelissen if (((si->ps.memory_size - pointer_reservation) >=
44868353368SRudolf Cornelissen (row_bytes * target->virtual_height)) &&
44968353368SRudolf Cornelissen ((uint16)(row_bytes / bpp) >= (target->timing.h_display * 2)))
45068353368SRudolf Cornelissen {
45168353368SRudolf Cornelissen target->flags |= DUALHEAD_CAPABLE;
45268353368SRudolf Cornelissen }
45368353368SRudolf Cornelissen break;
45468353368SRudolf Cornelissen case DUALHEAD_CLONE:
45568353368SRudolf Cornelissen if ((si->ps.memory_size - pointer_reservation) >=
45668353368SRudolf Cornelissen (row_bytes * target->virtual_height))
45768353368SRudolf Cornelissen {
45868353368SRudolf Cornelissen target->flags |= DUALHEAD_CAPABLE;
45968353368SRudolf Cornelissen }
46068353368SRudolf Cornelissen break;
46168353368SRudolf Cornelissen case DUALHEAD_OFF:
46268353368SRudolf Cornelissen if ((si->ps.memory_size - pointer_reservation) >=
46368353368SRudolf Cornelissen (row_bytes * target->virtual_height * 2))
46468353368SRudolf Cornelissen {
46568353368SRudolf Cornelissen target->flags |= DUALHEAD_CAPABLE;
46668353368SRudolf Cornelissen }
46768353368SRudolf Cornelissen break;
46868353368SRudolf Cornelissen }
46968353368SRudolf Cornelissen }
47068353368SRudolf Cornelissen
47168353368SRudolf Cornelissen /* set TV_CAPABLE if suitable: pixelclock is not important (defined by TVstandard) */
47268353368SRudolf Cornelissen //fixme: modify for G100 and G200 TVout later on...
47368353368SRudolf Cornelissen if (target->flags & DUALHEAD_CAPABLE)
47468353368SRudolf Cornelissen {
47568353368SRudolf Cornelissen if (si->ps.tvout &&
47668353368SRudolf Cornelissen (target->timing.h_display <= 1024) &&
47768353368SRudolf Cornelissen (target->timing.v_display <= 768))
47868353368SRudolf Cornelissen {
47968353368SRudolf Cornelissen target->flags |= TV_CAPABLE;
48068353368SRudolf Cornelissen }
48168353368SRudolf Cornelissen }
48268353368SRudolf Cornelissen
48368353368SRudolf Cornelissen /* set HARDWARE_CURSOR mode if suitable */
48468353368SRudolf Cornelissen if (si->settings.hardcursor)
48568353368SRudolf Cornelissen target->flags |= B_HARDWARE_CURSOR;
48668353368SRudolf Cornelissen
48768353368SRudolf Cornelissen /* set SUPPORTS_OVERLAYS */
48868353368SRudolf Cornelissen target->flags |= B_SUPPORTS_OVERLAYS;
48968353368SRudolf Cornelissen
49068353368SRudolf Cornelissen LOG(1, ("PROPOSEMODE: validated status modeflags: $%08x\n", target->flags));
49168353368SRudolf Cornelissen
49268353368SRudolf Cornelissen /* overrule timing command flags to be (fixed) blank_pedestal = 0.0IRE,
49368353368SRudolf Cornelissen * progressive scan (fixed), and sync_on_green not avaible. */
49468353368SRudolf Cornelissen target->timing.flags &= ~(B_BLANK_PEDESTAL | B_TIMING_INTERLACED | B_SYNC_ON_GREEN);
49568353368SRudolf Cornelissen /* The HSYNC and VSYNC command flags are actually executed by the driver. */
49668353368SRudolf Cornelissen
49768353368SRudolf Cornelissen if (status == B_OK) LOG(4, ("PROPOSEMODE: completed successfully.\n"));
49868353368SRudolf Cornelissen else LOG(4, ("PROPOSEMODE: mode can be made, but outside given limits.\n"));
49968353368SRudolf Cornelissen return status;
50068353368SRudolf Cornelissen }
50168353368SRudolf Cornelissen
50268353368SRudolf Cornelissen /* Return the number of modes this device will return from GET_MODE_LIST().
50368353368SRudolf Cornelissen This is precalculated in create_mode_list (called from InitAccelerant stuff)
50468353368SRudolf Cornelissen */
ACCELERANT_MODE_COUNT(void)50568353368SRudolf Cornelissen uint32 ACCELERANT_MODE_COUNT(void)
50668353368SRudolf Cornelissen {
50768353368SRudolf Cornelissen LOG(1, ("ACCELERANT_MODE_COUNT: the modelist contains %d modes\n",si->mode_count));
50868353368SRudolf Cornelissen
50968353368SRudolf Cornelissen return si->mode_count;
51068353368SRudolf Cornelissen }
51168353368SRudolf Cornelissen
51268353368SRudolf Cornelissen /* Copy the list of guaranteed supported video modes to the location provided.*/
GET_MODE_LIST(display_mode * dm)51368353368SRudolf Cornelissen status_t GET_MODE_LIST(display_mode *dm)
51468353368SRudolf Cornelissen {
51568353368SRudolf Cornelissen LOG(1, ("GET_MODE_LIST: exporting the modelist created before.\n"));
51668353368SRudolf Cornelissen
51768353368SRudolf Cornelissen memcpy(dm, my_mode_list, si->mode_count * sizeof(display_mode));
51868353368SRudolf Cornelissen return B_OK;
51968353368SRudolf Cornelissen }
52068353368SRudolf Cornelissen
52168353368SRudolf Cornelissen /* Create a list of display_modes to pass back to the caller.*/
create_mode_list(void)52268353368SRudolf Cornelissen status_t create_mode_list(void)
52368353368SRudolf Cornelissen {
52468353368SRudolf Cornelissen size_t max_size;
52568353368SRudolf Cornelissen uint32
52668353368SRudolf Cornelissen i, j,
52768353368SRudolf Cornelissen pix_clk_range;
52868353368SRudolf Cornelissen const display_mode
52968353368SRudolf Cornelissen *src;
53068353368SRudolf Cornelissen display_mode
53168353368SRudolf Cornelissen *dst,
53268353368SRudolf Cornelissen low,
53368353368SRudolf Cornelissen high;
53468353368SRudolf Cornelissen
53568353368SRudolf Cornelissen color_space spaces[4] = {B_RGB32_LITTLE,B_RGB16_LITTLE,B_RGB15_LITTLE,B_CMAP8};
53668353368SRudolf Cornelissen
53768353368SRudolf Cornelissen /* figure out how big the list could be, and adjust up to nearest multiple of B_PAGE_SIZE */
53868353368SRudolf Cornelissen max_size = (((MODE_COUNT * 4) * sizeof(display_mode)) + (B_PAGE_SIZE-1)) & ~(B_PAGE_SIZE-1);
53968353368SRudolf Cornelissen /* create an area to hold the info */
54068353368SRudolf Cornelissen si->mode_area = my_mode_list_area =
541*eb2b3762SRudolf Cornelissen create_area("NV accelerant mode info", (void **)&my_mode_list, B_ANY_ADDRESS, max_size,
542*eb2b3762SRudolf Cornelissen B_NO_LOCK, B_READ_AREA | B_WRITE_AREA | B_CLONEABLE_AREA);
54368353368SRudolf Cornelissen if (my_mode_list_area < B_OK) return my_mode_list_area;
54468353368SRudolf Cornelissen
54568353368SRudolf Cornelissen /* walk through our predefined list and see which modes fit this device */
54668353368SRudolf Cornelissen src = mode_list;
54768353368SRudolf Cornelissen dst = my_mode_list;
54868353368SRudolf Cornelissen si->mode_count = 0;
54968353368SRudolf Cornelissen for (i = 0; i < MODE_COUNT; i++)
55068353368SRudolf Cornelissen {
55168353368SRudolf Cornelissen /* set ranges for acceptable values */
55268353368SRudolf Cornelissen low = high = *src;
55368353368SRudolf Cornelissen /* range is 6.25% of default clock: arbitrarily picked */
55468353368SRudolf Cornelissen pix_clk_range = low.timing.pixel_clock >> 5;
55568353368SRudolf Cornelissen low.timing.pixel_clock -= pix_clk_range;
55668353368SRudolf Cornelissen high.timing.pixel_clock += pix_clk_range;
55768353368SRudolf Cornelissen /* 'some cards need wider virtual widths for certain modes':
55868353368SRudolf Cornelissen * Not true. They might need a wider pitch, but this is _not_ reflected in
55968353368SRudolf Cornelissen * virtual_width, but in fbc.bytes_per_row. */
56068353368SRudolf Cornelissen //So disable next line:
56168353368SRudolf Cornelissen //high.virtual_width = 4096;
56268353368SRudolf Cornelissen /* do it once for each depth we want to support */
56368353368SRudolf Cornelissen for (j = 0; j < (sizeof(spaces) / sizeof(color_space)); j++)
56468353368SRudolf Cornelissen {
56568353368SRudolf Cornelissen /* set target values */
56668353368SRudolf Cornelissen *dst = *src;
56768353368SRudolf Cornelissen /* poke the specific space */
56868353368SRudolf Cornelissen dst->space = low.space = high.space = spaces[j];
56968353368SRudolf Cornelissen /* ask for a compatible mode */
57068353368SRudolf Cornelissen /* We have to check for B_OK, because otherwise the pix_clk_range
57168353368SRudolf Cornelissen * won't be taken into account!! */
57268353368SRudolf Cornelissen //So don't do this:
57368353368SRudolf Cornelissen //if (PROPOSE_DISPLAY_MODE(dst, &low, &high) != B_ERROR) {
57468353368SRudolf Cornelissen //Instead, do this:
57568353368SRudolf Cornelissen if (PROPOSE_DISPLAY_MODE(dst, &low, &high) == B_OK) {
57668353368SRudolf Cornelissen /* count it, and move on to next mode */
57768353368SRudolf Cornelissen dst++;
57868353368SRudolf Cornelissen si->mode_count++;
57968353368SRudolf Cornelissen }
58068353368SRudolf Cornelissen }
58168353368SRudolf Cornelissen /* advance to next mode */
58268353368SRudolf Cornelissen src++;
58368353368SRudolf Cornelissen }
58468353368SRudolf Cornelissen
58568353368SRudolf Cornelissen return B_OK;
58668353368SRudolf Cornelissen }
587