📄 cim_vg.c
字号:
else if (query->hz == 60) hz_flag = VG_SUPPORTFLAG_60HZ;
else if (query->hz == 70) hz_flag = VG_SUPPORTFLAG_70HZ;
else if (query->hz == 72) hz_flag = VG_SUPPORTFLAG_72HZ;
else if (query->hz == 75) hz_flag = VG_SUPPORTFLAG_75HZ;
else if (query->hz == 85) hz_flag = VG_SUPPORTFLAG_85HZ;
else if (query->hz == 90) hz_flag = VG_SUPPORTFLAG_90HZ;
else if (query->hz == 100) hz_flag = VG_SUPPORTFLAG_100HZ;
else hz_flag = 0;
}
if (query->query_flags & VG_QUERYFLAG_BPP)
{
/* SET BPP FLAGS TO LIMIT MODE SELECTION */
if (query->bpp == 8) bpp_flag = VG_SUPPORTFLAG_8BPP;
else if (query->bpp == 12) bpp_flag = VG_SUPPORTFLAG_12BPP;
else if (query->bpp == 15) bpp_flag = VG_SUPPORTFLAG_15BPP;
else if (query->bpp == 16) bpp_flag = VG_SUPPORTFLAG_16BPP;
else if (query->bpp == 24) bpp_flag = VG_SUPPORTFLAG_24BPP;
else if (query->bpp == 32) bpp_flag = VG_SUPPORTFLAG_32BPP;
else bpp_flag = 0;
}
if (query->query_flags & VG_QUERYFLAG_ENCODER)
{
/* SET ENCODER FLAGS TO LIMIT MODE SELECTION */
if (query->encoder == VG_ENCODER_ADV7171) enc_flag = VG_SUPPORTFLAG_ADV7171;
else if (query->encoder == VG_ENCODER_SAA7127) enc_flag = VG_SUPPORTFLAG_SAA7127;
else if (query->encoder == VG_ENCODER_FS454) enc_flag = VG_SUPPORTFLAG_FS454;
else if (query->encoder == VG_ENCODER_ADV7300) enc_flag = VG_SUPPORTFLAG_ADV7300;
else enc_flag = 0;
}
if (query->query_flags & VG_QUERYFLAG_TVMODE)
{
/* SET ENCODER FLAGS TO LIMIT MODE SELECTION */
if (query->tvmode == VG_TVMODE_NTSC) tv_flag = VG_SUPPORTFLAG_NTSC;
else if (query->tvmode == VG_TVMODE_PAL) tv_flag = VG_SUPPORTFLAG_PAL;
else if (query->tvmode == VG_TVMODE_480P) tv_flag = VG_SUPPORTFLAG_480P;
else if (query->tvmode == VG_TVMODE_720P) tv_flag = VG_SUPPORTFLAG_720P;
else if (query->tvmode == VG_TVMODE_1080I) tv_flag = VG_SUPPORTFLAG_1080I;
else if (query->tvmode == VG_TVMODE_6X4_NTSC) tv_flag = VG_SUPPORTFLAG_6X4_NTSC;
else if (query->tvmode == VG_TVMODE_8X6_NTSC) tv_flag = VG_SUPPORTFLAG_8X6_NTSC;
else if (query->tvmode == VG_TVMODE_10X7_NTSC) tv_flag = VG_SUPPORTFLAG_10X7_NTSC;
else if (query->tvmode == VG_TVMODE_6X4_PAL) tv_flag = VG_SUPPORTFLAG_6X4_PAL;
else if (query->tvmode == VG_TVMODE_8X6_PAL) tv_flag = VG_SUPPORTFLAG_8X6_PAL;
else if (query->tvmode == VG_TVMODE_10X7_PAL) tv_flag = VG_SUPPORTFLAG_10X7_PAL;
else tv_flag = 0xFFFFFFFF;
}
/* SET APPROPRIATE TV AND VOP FLAGS */
if (query->query_flags & VG_QUERYFLAG_INTERLACED)
interlaced = query->interlaced ? VG_MODEFLAG_INTERLACED : 0;
if (query->query_flags & VG_QUERYFLAG_HALFCLOCK)
halfclock = query->halfclock ? VG_MODEFLAG_HALFCLOCK : 0;
/* CHECK FOR INVALID REQUEST */
if (!hz_flag || !bpp_flag || !enc_flag || tv_flag == 0xFFFFFFFF)
return -1;
/* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */
for (mode = 0; mode < NUM_CIMARRON_DISPLAY_MODES; mode++)
{
if ( (!(query->query_flags & VG_QUERYFLAG_PANEL) ||
(CimarronDisplayModes[mode].internal_flags & VG_SUPPORTFLAG_PANEL)) &&
(!(query->query_flags & VG_QUERYFLAG_TVOUT) ||
(CimarronDisplayModes[mode].internal_flags & VG_SUPPORTFLAG_TVOUT)) &&
(!(query->query_flags & VG_QUERYFLAG_INTERLACED) ||
(CimarronDisplayModes[mode].flags & VG_MODEFLAG_INTERLACED) == interlaced) &&
(!(query->query_flags & VG_QUERYFLAG_HALFCLOCK) ||
(CimarronDisplayModes[mode].flags & VG_MODEFLAG_HALFCLOCK) == halfclock) &&
(!(query->query_flags & VG_QUERYFLAG_PANELWIDTH) ||
(CimarronDisplayModes[mode].panel_width == query->panel_width)) &&
(!(query->query_flags & VG_QUERYFLAG_PANELHEIGHT) ||
(CimarronDisplayModes[mode].panel_height == query->panel_height)) &&
(!(query->query_flags & VG_QUERYFLAG_ACTIVEWIDTH) ||
(CimarronDisplayModes[mode].hactive == query->active_width)) &&
(!(query->query_flags & VG_QUERYFLAG_ACTIVEHEIGHT) ||
(CimarronDisplayModes[mode].vactive == query->active_height)) &&
(!(query->query_flags & VG_QUERYFLAG_TOTALWIDTH) ||
(CimarronDisplayModes[mode].htotal == query->total_width)) &&
(!(query->query_flags & VG_QUERYFLAG_TOTALHEIGHT) ||
(CimarronDisplayModes[mode].vtotal == query->total_height)) &&
(!(query->query_flags & VG_QUERYFLAG_BPP) ||
(CimarronDisplayModes[mode].internal_flags & bpp_flag)) &&
(!(query->query_flags & VG_QUERYFLAG_REFRESH) ||
(CimarronDisplayModes[mode].internal_flags & hz_flag)) &&
(!(query->query_flags & VG_QUERYFLAG_ENCODER) ||
(CimarronDisplayModes[mode].internal_flags & enc_flag)) &&
(!(query->query_flags & VG_QUERYFLAG_TVMODE) ||
((CimarronDisplayModes[mode].internal_flags & VG_SUPPORTFLAG_TVMODEMASK) == tv_flag)) &&
(!(query->query_flags & VG_QUERYFLAG_PIXELCLOCK) ||
(CimarronDisplayModes[mode].frequency == query->frequency)))
{
/* ALLOW SEARCHING BASED ON AN APPROXIMATE PIXEL CLOCK */
if (query->query_flags & VG_QUERYFLAG_PIXELCLOCK_APPROX)
{
diff = query->frequency - CimarronDisplayModes[mode].frequency;
if (diff < 0)
diff = -diff;
if (diff < minimum)
{
minimum = diff;
match = mode;
}
}
else
{
match = mode;
break;
}
}
}
/* RETURN DISPLAY MODE INDEX */
return match;
}
/*---------------------------------------------------------------------------
* vg_get_display_mode_information
*
* This routine retrieves all information for a display mode contained
* within Cimarron's mode tables.
*---------------------------------------------------------------------------*/
int vg_get_display_mode_information (unsigned int index, VG_DISPLAY_MODE *vg_mode)
{
if (index > NUM_CIMARRON_DISPLAY_MODES)
return CIM_STATUS_INVALIDPARAMS;
*vg_mode = CimarronDisplayModes[index];
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vg_get_display_mode_count
*
* This routine retrieves the count of all predefined Cimarron modes.
*---------------------------------------------------------------------------*/
int vg_get_display_mode_count (void)
{
return NUM_CIMARRON_DISPLAY_MODES;
}
/*---------------------------------------------------------------------------
* vg_get_current_display_mode
*
* This routine retrieves the settings for the current display. This includes
* any panel settings.
*---------------------------------------------------------------------------*/
int vg_get_current_display_mode (VG_DISPLAY_MODE *current_display, int *bpp)
{
Q_WORD msr_value;
unsigned long active, blank, sync;
unsigned long i, m, n, p;
unsigned long genlk, irq, temp;
unsigned long flags = 0;
unsigned long iflags = 0;
/* READ THE CURRENT HORIZONTAL DISPLAY TIMINGS */
active = READ_REG32 (DC3_H_ACTIVE_TIMING);
blank = READ_REG32 (DC3_H_BLANK_TIMING);
sync = READ_REG32 (DC3_H_SYNC_TIMING);
current_display->hactive = (active & 0xFFF) + 1;
current_display->hblankstart = (blank & 0xFFF) + 1;
current_display->hsyncstart = (sync & 0xFFF) + 1;
current_display->htotal = ((active >> 16) & 0xFFF) + 1;
current_display->hblankend = ((blank >> 16) & 0xFFF) + 1;
current_display->hsyncend = ((sync >> 16) & 0xFFF) + 1;
/* READ THE CURRENT VERTICAL DISPLAY TIMINGS */
active = READ_REG32 (DC3_V_ACTIVE_TIMING);
blank = READ_REG32 (DC3_V_BLANK_TIMING);
sync = READ_REG32 (DC3_V_SYNC_TIMING);
current_display->vactive = (active & 0x7FF) + 1;
current_display->vblankstart = (blank & 0x7FF) + 1;
current_display->vsyncstart = (sync & 0x7FF) + 1;
current_display->vtotal = ((active >> 16) & 0x7FF) + 1;
current_display->vblankend = ((blank >> 16) & 0x7FF) + 1;
current_display->vsyncend = ((sync >> 16) & 0x7FF) + 1;
/* READ THE CURRENT EVEN FIELD VERTICAL DISPLAY TIMINGS */
active = READ_REG32 (DC3_V_ACTIVE_EVEN);
blank = READ_REG32 (DC3_V_BLANK_EVEN);
sync = READ_REG32 (DC3_V_SYNC_EVEN);
current_display->vactive_even = (active & 0x7FF) + 1;
current_display->vblankstart_even = (blank & 0x7FF) + 1;
current_display->vsyncstart_even = (sync & 0x7FF) + 1;
current_display->vtotal_even = ((active >> 16) & 0x7FF) + 1;
current_display->vblankend_even = ((blank >> 16) & 0x7FF) + 1;
current_display->vsyncend_even = ((sync >> 16) & 0x7FF) + 1;
/* READ THE CURRENT SOURCE DIMENSIONS */
/* The DC3_FB_ACTIVE register is only used when scaling is enabled. */
/* As the goal of this routine is to return a structure that can be */
/* passed to vg_set_custom_mode to exactly recreate the current mode, */
/* we must check the status of the scaler/filter. */
genlk = READ_REG32 (DC3_GENLK_CTL);
irq = READ_REG32 (DC3_IRQ_FILT_CTL);
temp = READ_REG32 (DC3_FB_ACTIVE);
current_display->src_height = (temp & 0xFFFF) + 1;
current_display->src_width = ((temp >> 16) & 0xFFF8) + 8;
/* READ THE CURRENT PANEL CONFIGURATION */
/* We can only infer some of the panel settings based on hardware */
/* (like when panning). We will instead assume that the current */
/* mode was set using Cimarron and use the panel variables inside */
/* Cimarron when returning the current mode information. */
if (vg3_panel_enable)
{
Q_WORD msr_value;
flags |= VG_MODEFLAG_PANELOUT;
current_display->panel_width = vg3_panel_width;
current_display->panel_height = vg3_panel_height;
current_display->mode_width = vg3_mode_width;
current_display->mode_height = vg3_mode_height;
if (READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_DCEN)
flags |= VG_MODEFLAG_CENTERED;
msr_read64 (MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, &msr_value);
current_display->panel_tim1 = READ_VID32 (DF_VIDEO_PANEL_TIM1);
current_display->panel_tim2 = READ_VID32 (DF_VIDEO_PANEL_TIM2);
current_display->panel_dither_ctl = READ_VID32 (DF_DITHER_CONTROL);
current_display->panel_pad_sel_low = msr_value.low;
current_display->panel_pad_sel_high = msr_value.high;
}
/* SET MISCELLANEOUS MODE FLAGS */
/* INTERLACED */
if (irq & DC3_IRQFILT_INTL_EN)
{
flags |= VG_MODEFLAG_INTERLACED;
if (irq & DC3_IRQFILT_INTL_ADDR)
flags |= VG_MODEFLAG_INT_ADDRESS;
else if (genlk & DC3_GC_FLICKER_FILTER_ENABLE)
flags |= VG_MODEFLAG_INT_FLICKER;
else
flags |= VG_MODEFLAG_INT_LINEDOUBLE;
}
/* POLARITIES */
temp = READ_VID32 (DF_DISPLAY_CONFIG);
if (temp & DF_DCFG_CRT_HSYNC_POL)
flags |= VG_MODEFLAG_NEG_HSYNC;
if (temp & DF_DCFG_CRT_VSYNC_POL)
flags |= VG_MODEFLAG_NEG_VSYNC;
/* BPP */
temp = READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_DISP_MODE_MASK;
if (temp == DC3_DCFG_DISP_MODE_8BPP)
{
iflags |= VG_SUPPORTFLAG_8BPP;
*bpp = 8;
}
else if (temp == DC3_DCFG_DISP_MODE_24BPP)
{
iflags |= VG_SUPPORTFLAG_24BPP;
*bpp = 24;
}
else if (temp == DC3_DCFG_DISP_MODE_32BPP)
{
iflags |= VG_SUPPORTFLAG_32BPP;
*bpp = 32;
}
else if (temp == DC3_DCFG_DISP_MODE_16BPP)
{
temp = READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_16BPP_MODE_MASK;
if (temp == DC3_DCFG_16BPP)
{
iflags |= VG_SUPPORTFLAG_16BPP;
*bpp = 16;
}
else if (temp == DC3_DCFG_15BPP)
{
iflags |= VG_SUPPORTFLAG_15BPP;
*bpp = 15;
}
else if (temp == DC3_DCFG_12BPP)
{
iflags |= VG_SUPPORTFLAG_12BPP;
*bpp = 12;
}
}
/* TV RELATED FLAGS */
msr_read64 (MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, &msr_value);
if (msr_value.high & DF_INVERT_VOP_CLOCK)
flags |= VG_MODEFLAG_TVOUT;
/* LINEAR PITCH */
temp = (READ_REG32 (DC3_GFX_PITCH) & 0x0000FFFF) << 3;
if (temp != 1024 && temp != 2048 && temp != 4096 && temp != 8192)
flags |= VG_MODEFLAG_LINEARPITCH;
/* SIMULTANEOUS CRT/FP */
msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
if (msr_value.low & DF_SIMULTANEOUS_CRT_FP)
flags |= VG_MODEFLAG_CRT_AND_FP;
/* SET PLL-RELATED FLAGS */
msr_read64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value);
if (msr_value.high & GLCP_DOTPLL_DIV4)
flags |= VG_MODEFLAG_QVGA;
if (msr_value.low & GLCP_DOTPLL_HALFPIX)
flags |= VG_MODEFLAG_HALFCLOCK;
/* SAVE THE FLAGS IN THE MODE STRUCTURE */
current_display->internal_flags = iflags;
current_display->flags = flags;
/* READ PIXEL CLOCK FREQUENCY */
/* We first search for an exact match. If none is found, we try */
/* a fixed point calculation and return CIM_STATUS_INEXACTMATCH. */
for (i = 0; i < NUM_CIMARRON_PLL_FREQUENCIES; i++)
{
if (CimarronPLLFrequencies[i].pll_value == msr_value.high)
break;
}
if (i == NUM_CIMARRON_PLL_FREQUENCIES)
{
/* ATTEMPT 16.16 CALCULATION */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -