#define MODULE_BIT 0x00400000
#include "acc_std.h"
#define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC)
#define MODE_FLAGS 0
#define MODE_COUNT (sizeof (mode_list) / sizeof (display_mode))
static const display_mode mode_list[] = {
{ { 25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS},
{ { 27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS},
{ { 30500, 640, 672, 768, 864, 480, 517, 523, 588, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS},
{ { 31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS},
{ { 31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS},
{ { 36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS},
{ { 36000, 800, 824, 896, 1024, 600, 601, 603, 625, 0}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS},
{ { 38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS},
{ { 40000, 800, 840, 968, 1056, 600, 601, 605, 628, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS},
{ { 49500, 800, 816, 896, 1056, 600, 601, 604, 625, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS},
{ { 50000, 800, 856, 976, 1040, 600, 637, 643, 666, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS},
{ { 56250, 800, 832, 896, 1048, 600, 601, 604, 631, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS},
{ { 65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS},
{ { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS},
{ { 78750, 1024, 1040, 1136, 1312, 768, 769, 772, 800, T_POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS},
{ { 94500, 1024, 1072, 1168, 1376, 768, 769, 772, 808, T_POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS},
{ { 94200, 1152, 1184, 1280, 1472, 864, 865, 868, 914, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS},
{ { 97800, 1152, 1216, 1344, 1552, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS},
{ { 108000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS},
{ { 121500, 1152, 1216, 1344, 1568, 864, 865, 868, 911, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS},
{ { 108000, 1280, 1328, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS},
{ { 135000, 1280, 1296, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS},
{ { 157500, 1280, 1344, 1504, 1728, 1024, 1025, 1028, 1072, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS},
{ { 122600, 1400, 1488, 1640, 1880, 1050, 1051, 1054, 1087, T_POSITIVE_SYNC}, B_CMAP8, 1400, 1050, 0, 0, MODE_FLAGS},
{ { 162000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS},
{ { 175500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS},
{ { 189000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS},
{ { 202500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS},
{ { 216000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS},
{ { 229500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS},
{ { 204750, 1792, 1920, 2120, 2448, 1344, 1345, 1348, 1394, B_POSITIVE_VSYNC}, B_CMAP8, 1792, 1344, 0, 0, MODE_FLAGS},
{ { 261000, 1792, 1888, 2104, 2456, 1344, 1345, 1348, 1417, B_POSITIVE_VSYNC}, B_CMAP8, 1792, 1344, 0, 0, MODE_FLAGS},
{ { 218250, 1856, 1952, 2176, 2528, 1392, 1393, 1396, 1439, B_POSITIVE_VSYNC}, B_CMAP8, 1856, 1392, 0, 0, MODE_FLAGS},
{ { 288000, 1856, 1984, 2208, 2560, 1392, 1393, 1396, 1500, B_POSITIVE_VSYNC}, B_CMAP8, 1856, 1392, 0, 0, MODE_FLAGS},
{ { 234000, 1920, 2048, 2256, 2600, 1440, 1441, 1444, 1500, B_POSITIVE_VSYNC}, B_CMAP8, 1920, 1440, 0, 0, MODE_FLAGS},
{ { 297000, 1920, 2064, 2288, 2640, 1440, 1441, 1444, 1500, B_POSITIVE_VSYNC}, B_CMAP8, 1920, 1440, 0, 0, MODE_FLAGS},
{ { 266950, 2048, 2200, 2424, 2800, 1536, 1537, 1540, 1589, B_POSITIVE_VSYNC}, B_CMAP8, 2048, 1536, 0, 0, MODE_FLAGS},
{ { 31300, 800, 848, 928, 1008, 500, 501, 504, 518, T_POSITIVE_SYNC}, B_CMAP8, 800, 500, 0, 0, MODE_FLAGS},
{ { 52800, 1024, 1072, 1176, 1328, 640, 641, 644, 663, T_POSITIVE_SYNC}, B_CMAP8, 1024, 640, 0, 0, MODE_FLAGS},
{ { 80135, 1280, 1344, 1480, 1680, 768, 769, 772, 795, T_POSITIVE_SYNC}, B_CMAP8, 1280, 768, 0, 0, MODE_FLAGS},
{ { 83500, 1280, 1344, 1480, 1680, 800, 801, 804, 828, T_POSITIVE_SYNC}, B_CMAP8, 1280, 800, 0, 0, MODE_FLAGS},
{ { 106500, 1440, 1520, 1672, 1904, 900, 901, 904, 932, T_POSITIVE_SYNC}, B_CMAP8, 1440, 900, 0, 0, MODE_FLAGS},
{ { 147100, 1680, 1784, 1968, 2256, 1050, 1051, 1054, 1087, T_POSITIVE_SYNC}, B_CMAP8, 1680, 1050, 0, 0, MODE_FLAGS},
{ { 193160, 1920, 2048, 2256, 2592, 1200, 1201, 1204, 1242, T_POSITIVE_SYNC}, B_CMAP8, 1920, 1200, 0, 0, MODE_FLAGS},
{ { 74520, 1280, 1368, 1424, 1656, 720, 724, 730, 750, T_POSITIVE_SYNC}, B_CMAP8, 1280, 720, 0, 0, MODE_FLAGS},
{ { 85500, 1368, 1440, 1576, 1792, 768, 771, 774, 798, T_POSITIVE_SYNC}, B_CMAP8, 1368, 768, 0, 0, MODE_FLAGS},
{ { 148500, 1920, 2008, 2052, 2200, 1080, 1084, 1089, 1125, T_POSITIVE_SYNC}, B_CMAP8, 1920, 1080, 0, 0, MODE_FLAGS},
};
static void Haiku_DetectTranslateMultiMode(display_mode *mode)
{
mode->flags &= ~DUALHEAD_BITS;
if( mode->virtual_width == 2 * mode->timing.h_display ) {
LOG(4, ("Haiku: horizontal combine mode\n"));
if (si->Haiku_switch_head)
mode->flags |= DUALHEAD_SWITCH;
else
mode->flags |= DUALHEAD_ON;
} else if( mode->virtual_height == 2 * mode->timing.v_display ) {
LOG(4, ("Haiku: vertical combine mode not supported\n"));
} else {
mode->flags |= DUALHEAD_CLONE;
}
}
static status_t Haiku_CheckMultiMonTunnel(display_mode *mode, const display_mode *low, const display_mode *high, bool *isTunneled )
{
if( (mode->timing.flags & RADEON_MODE_MULTIMON_REQUEST) != 0 &&
(mode->timing.flags & RADEON_MODE_MULTIMON_REPLY) == 0 )
{
mode->timing.flags &= ~RADEON_MODE_MULTIMON_REQUEST;
mode->timing.flags |= RADEON_MODE_MULTIMON_REPLY;
*isTunneled = true;
return B_OK;
}
if( mode->space != 0 || low->space != 0 || high->space != 0
|| low->virtual_width != 0xffff || low->virtual_height != 0xffff
|| high->virtual_width != 0 || high->virtual_height != 0
|| mode->timing.pixel_clock != 0
|| low->timing.pixel_clock != 'TKTK' || high->timing.pixel_clock != 'KTKT' )
{
*isTunneled = false;
return B_OK;
}
*isTunneled = true;
if (!si->haiku_prefs_used)
LOG(4, ("PROPOSEMODE: Haiku screenprefs tunnel detected.\n"));
si->haiku_prefs_used = true;
switch( mode->h_display_start ) {
case ms_swap:
switch( mode->v_display_start ) {
case 0:
if (si->Haiku_switch_head)
mode->timing.flags = 1;
else
mode->timing.flags = 0;
LOG(4, ("Haiku: tunnel access target=swap, command=get, value=%u\n", mode->timing.flags));
return B_OK;
case 1:
si->Haiku_switch_head = mode->timing.flags != 0;
LOG(4, ("Haiku: tunnel access target=swap, command=set, value=%u\n", mode->timing.flags));
SET_DISPLAY_MODE(&si->dm);
return B_OK;
}
break;
case ms_use_laptop_panel:
LOG(4, ("Haiku: tunnel access target=usepanel, command=%s, value=%u\n",
(mode->v_display_start == 1) ? "set" : "get", mode->timing.flags));
return B_ERROR;
break;
case ms_tv_standard:
LOG(4, ("Haiku: tunnel access target=tvstandard, command=%s, value=%u\n",
(mode->v_display_start == 1) ? "set" : "get", mode->timing.flags));
return B_ERROR;
break;
}
LOG(4, ("Haiku: unhandled tunnel access target=$%x, command=%u, value=%u\n",
mode->h_display_start, mode->v_display_start, mode->timing.flags));
return B_ERROR;
}
status_t
PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const display_mode *high)
{
status_t status = B_OK;
float pix_clock_found, target_aspect;
uint8 m,n,p, bpp;
status_t result;
uint32 max_vclk, row_bytes, mem_reservation;
bool acc_mode;
double target_refresh = ((double)target->timing.pixel_clock * 1000.0)
/ ((double)target->timing.h_total * (double)target->timing.v_total);
bool want_same_width = target->timing.h_display == target->virtual_width;
bool want_same_height = target->timing.v_display == target->virtual_height;
bool isTunneled = false;
result = Haiku_CheckMultiMonTunnel(target, low, high, &isTunneled);
if (isTunneled)
return result;
if (si->haiku_prefs_used) {
Haiku_DetectTranslateMultiMode(target);
}
LOG(1, ("PROPOSEMODE: (ENTER) requested virtual_width %d, virtual_height %d\n",
target->virtual_width, target->virtual_height));
result = head1_validate_timing(&target->timing.h_display,
&target->timing.h_sync_start, &target->timing.h_sync_end,
&target->timing.h_total, &target->timing.v_display,
&target->timing.v_sync_start, &target->timing.v_sync_end,
&target->timing.v_total);
if (result == B_ERROR) {
LOG(4, ("PROPOSEMODE: could not validate timing, aborted.\n"));
return result;
}
if (!si->ps.tvout
|| !(BT_check_tvmode(*target) && (target->flags & TV_BITS))) {
target_aspect = (target->timing.h_display / ((float)target->timing.v_display));
switch (si->ps.monitors) {
case 0:
if (target_aspect > 1.34 && !si->settings.force_ws) {
LOG(4, ("PROPOSEMODE: not all output devices can display widescreen modes, aborted.\n"));
return B_ERROR;
}
break;
case CRTC1_TMDS:
case CRTC1_VGA:
if (si->ps.crtc1_screen.aspect < (target_aspect - 0.10)) {
LOG(4, ("PROPOSEMODE: screen at crtc1 is not widescreen (enough) type, aborted.\n"));
return B_ERROR;
}
break;
case CRTC2_TMDS:
case CRTC2_VGA:
if (si->ps.crtc2_screen.aspect < (target_aspect - 0.10)) {
LOG(4, ("PROPOSEMODE: screen at crtc2 is not widescreen (enough) type, aborted.\n"));
return B_ERROR;
}
break;
case CRTC1_TMDS | CRTC2_TMDS:
case CRTC1_VGA | CRTC2_VGA:
case CRTC1_TMDS | CRTC2_VGA:
case CRTC1_VGA | CRTC2_TMDS:
default:
if ((si->ps.crtc1_screen.aspect < (target_aspect - 0.10)) ||
(si->ps.crtc2_screen.aspect < (target_aspect - 0.10))) {
LOG(4, ("PROPOSEMODE: not all connected screens are widescreen (enough) type, aborted.\n"));
return B_ERROR;
}
break;
}
}
if (si->settings.check_edid) {
if (si->ps.crtc1_screen.have_native_edid) {
if ((target->timing.h_display - 2) > si->ps.crtc1_screen.timing.h_display
|| target->timing.v_display > si->ps.crtc1_screen.timing.v_display) {
LOG(4, ("PROPOSEMODE: screen at crtc1 can't display requested resolution, aborted.\n"));
return B_ERROR;
}
}
if (si->ps.crtc2_screen.have_native_edid) {
if ((target->timing.h_display - 2) > si->ps.crtc2_screen.timing.h_display
|| target->timing.v_display > si->ps.crtc2_screen.timing.v_display) {
LOG(4, ("PROPOSEMODE: screen at crtc2 can't display requested resolution, aborted.\n"));
return B_ERROR;
}
}
}
if (target->timing.h_display > target->virtual_width || want_same_width)
target->virtual_width = target->timing.h_display;
if (target->timing.v_display > target->virtual_height || want_same_height)
target->virtual_height = target->timing.v_display;
result = nv_general_validate_pic_size(target, &row_bytes, &acc_mode);
if (result == B_ERROR) {
LOG(4, ("PROPOSEMODE: could not validate virtual picture size, aborted.\n"));
return result;
}
if (target->virtual_width < low->virtual_width
|| target->virtual_width > high->virtual_width) {
status = B_BAD_VALUE;
LOG(4, ("PROPOSEMODE: WARNING: virtual_width deviates too much\n"));
}
if (target->timing.h_display < low->timing.h_display
|| target->timing.h_display > high->timing.h_display
|| target->timing.h_sync_start < low->timing.h_sync_start
|| target->timing.h_sync_start > high->timing.h_sync_start
|| target->timing.h_sync_end < low->timing.h_sync_end
|| target->timing.h_sync_end > high->timing.h_sync_end
|| target->timing.h_total < low->timing.h_total
|| target->timing.h_total > high->timing.h_total) {
if (target->timing.h_display < low->timing.h_display
|| target->timing.h_display > high->timing.h_display)
status = B_BAD_VALUE;
LOG(4, ("PROPOSEMODE: WARNING: horizontal timing deviates too much\n"));
}
if (target->timing.v_display < low->timing.v_display
|| target->timing.v_display > high->timing.v_display
|| target->timing.v_sync_start < low->timing.v_sync_start
|| target->timing.v_sync_start > high->timing.v_sync_start
|| target->timing.v_sync_end < low->timing.v_sync_end
|| target->timing.v_sync_end > high->timing.v_sync_end
|| target->timing.v_total < low->timing.v_total
|| target->timing.v_total > high->timing.v_total) {
if (target->timing.v_display < low->timing.v_display
|| target->timing.v_display > high->timing.v_display)
status = B_BAD_VALUE;
LOG(4, ("PROPOSEMODE: WARNING: vertical timing deviates too much\n"));
}
target->timing.pixel_clock = target_refresh * ((double)target->timing.h_total)
* ((double)target->timing.v_total) / 1000.0;
result = head1_pix_pll_find(*target, &pix_clock_found, &m, &n, &p, 0);
target->timing.pixel_clock = pix_clock_found * 1000;
if (target->timing.pixel_clock < low->timing.pixel_clock
|| target->timing.pixel_clock > high->timing.pixel_clock) {
if (target->timing.pixel_clock < low->timing.pixel_clock - 1000
|| target->timing.pixel_clock > high->timing.pixel_clock + 1000)
status = B_BAD_VALUE;
LOG(4, ("PROPOSEMODE: WARNING: pixelclock deviates too much\n"));
}
mem_reservation = 0;
if (si->settings.hardcursor)
mem_reservation = 2048;
if (si->ps.card_arch < NV40A)
mem_reservation += PRE_NV40_OFFSET;
else
mem_reservation += NV40_PLUS_OFFSET;
if (row_bytes * target->virtual_height > si->ps.memory_size - mem_reservation) {
target->virtual_height = (si->ps.memory_size - mem_reservation) / row_bytes;
}
if (target->virtual_height < target->timing.v_display) {
LOG(4,("PROPOSEMODE: not enough memory for current mode, aborted.\n"));
return B_ERROR;
}
LOG(4,("PROPOSEMODE: validated virtual_width %d, virtual_height %d pixels\n",
target->virtual_width, target->virtual_height));
if (target->virtual_height < low->virtual_height
|| target->virtual_height > high->virtual_height) {
status = B_BAD_VALUE;
LOG(4, ("PROPOSEMODE: WARNING: virtual_height deviates too much\n"));
}
LOG(1, ("PROPOSEMODE: initial modeflags: $%08x\n", target->flags));
target->flags &=
~(DUALHEAD_CAPABLE | TV_CAPABLE | B_SUPPORTS_OVERLAYS | B_HARDWARE_CURSOR | B_IO_FB_NA);
target->flags |= (B_PARALLEL_ACCESS | B_8_BIT_DAC | B_DPMS | B_SCROLL);
switch (target->space) {
case B_CMAP8:
max_vclk = si->ps.max_dac2_clock_8;
bpp = 1;
break;
case B_RGB15_LITTLE:
case B_RGB16_LITTLE:
max_vclk = si->ps.max_dac2_clock_16;
bpp = 2;
break;
case B_RGB24_LITTLE:
max_vclk = si->ps.max_dac2_clock_24;
bpp = 3;
break;
case B_RGB32_LITTLE:
max_vclk = si->ps.max_dac2_clock_32dh;
bpp = 4;
break;
default:
max_vclk = si->ps.max_dac2_clock_32dh;
bpp = 4;
break;
}
if (si->ps.secondary_head && target->timing.pixel_clock <= (max_vclk * 1000)) {
switch (target->flags & DUALHEAD_BITS) {
case DUALHEAD_ON:
case DUALHEAD_SWITCH:
if (si->ps.memory_size - mem_reservation
>= row_bytes * target->virtual_height
&& (uint16)(row_bytes / bpp) >= target->timing.h_display * 2)
target->flags |= DUALHEAD_CAPABLE;
break;
case DUALHEAD_CLONE:
if (si->ps.memory_size - mem_reservation
>= row_bytes * target->virtual_height)
target->flags |= DUALHEAD_CAPABLE;
break;
case DUALHEAD_OFF:
if (si->ps.memory_size - mem_reservation
>= row_bytes * target->virtual_height * 2)
target->flags |= DUALHEAD_CAPABLE;
break;
}
}
if (!(target->flags & DUALHEAD_CAPABLE))
target->flags &= ~DUALHEAD_BITS;
if (si->ps.tvout && BT_check_tvmode(*target))
target->flags |= TV_CAPABLE;
if (!(target->flags & TV_CAPABLE))
target->flags &= ~TV_BITS;
if (target->flags & TV_BITS) {
if (!si->ps.secondary_head)
target->flags |= TV_PRIMARY;
else if ((target->flags & DUALHEAD_BITS) == DUALHEAD_OFF)
target->flags |= TV_PRIMARY;
} else
target->flags &= ~TV_PRIMARY;
if (si->settings.hardcursor)
target->flags |= B_HARDWARE_CURSOR;
if (si->ps.card_type <= NV40 || si->ps.card_type == NV45)
target->flags |= B_SUPPORTS_OVERLAYS;
LOG(1, ("PROPOSEMODE: validated modeflags: $%08x\n", target->flags));
target->timing.flags &= ~(B_BLANK_PEDESTAL | B_TIMING_INTERLACED | B_SYNC_ON_GREEN);
if (status == B_OK)
LOG(4, ("PROPOSEMODE: completed successfully.\n"));
else
LOG(4, ("PROPOSEMODE: mode can be made, but outside given limits.\n"));
return status;
}
uint32
ACCELERANT_MODE_COUNT(void)
{
LOG(1, ("ACCELERANT_MODE_COUNT: the modelist contains %d modes\n",si->mode_count));
return si->mode_count;
}
status_t
GET_MODE_LIST(display_mode *dm)
{
LOG(1, ("GET_MODE_LIST: exporting the modelist created before.\n"));
memcpy(dm, my_mode_list, si->mode_count * sizeof(display_mode));
return B_OK;
}
static void checkAndAddMode(const display_mode *src, display_mode *dst)
{
uint32 j, pix_clk_range;
display_mode low, high;
color_space spaces[4] = {B_RGB32_LITTLE, B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8};
low = high = *src;
pix_clk_range = low.timing.pixel_clock >> 5;
low.timing.pixel_clock -= pix_clk_range;
high.timing.pixel_clock += pix_clk_range;
for (j = 0; j < (sizeof(spaces) / sizeof(color_space)); j++) {
dst[si->mode_count] = *src;
dst[si->mode_count].space = low.space = high.space = spaces[j];
if (PROPOSE_DISPLAY_MODE(&dst[si->mode_count], &low, &high) == B_OK) {
si->mode_count++;
}
}
}
status_t
create_mode_list(void)
{
size_t max_size;
uint32 i;
const display_mode *src;
display_mode *dst;
display_mode custom_mode;
max_size = (((MODE_COUNT * 4 * 3) * sizeof(display_mode)) + (B_PAGE_SIZE-1)) & ~(B_PAGE_SIZE-1);
si->mode_area = my_mode_list_area = create_area("NV accelerant mode info",
(void **)&my_mode_list, B_ANY_ADDRESS, max_size, B_NO_LOCK,
B_READ_AREA | B_WRITE_AREA | B_CLONEABLE_AREA);
if (my_mode_list_area < B_OK)
return my_mode_list_area;
src = mode_list;
dst = my_mode_list;
si->mode_count = 0;
for (i = 0; i < MODE_COUNT; i++) {
custom_mode = *src;
custom_mode.flags |= DUALHEAD_CLONE;
checkAndAddMode(&custom_mode, dst);
custom_mode = *src;
custom_mode.virtual_width *= 2;
custom_mode.flags |= DUALHEAD_ON;
checkAndAddMode(&custom_mode, dst);
src++;
}
return B_OK;
}