📄 cim_df.c
字号:
/*
* <LIC_AMD_STD>
* Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
* </LIC_AMD_STD>
*
* <CTL_AMD_STD>
* </CTL_AMD_STD>
*
* <DOC_AMD_STD>
* Cimarron display filter routines. These routines program the video hardware.
* </DOC_AMD_STD>
*
*/
/*---------------------------------------------------------------------------
* df_set_crt_enable
*
* This routine enables or disables CRT output.
*---------------------------------------------------------------------------*/
int df_set_crt_enable (int crt_output)
{
unsigned long config, misc;
config = READ_VID32 (DF_DISPLAY_CONFIG);
misc = READ_VID32 (DF_VID_MISC);
switch (crt_output)
{
/* DISABLE DISPLAY */
case DF_CRT_DISABLE:
config &= ~(DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN |
DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN);
misc |= DF_DAC_POWER_DOWN;
break;
/* ENABLE THE DISPLAY */
case DF_CRT_ENABLE:
config |= (DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN |
DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN);
misc &= ~(DF_DAC_POWER_DOWN | DF_ANALOG_POWER_DOWN);
break;
/* HSYNC:OFF VSYNC:ON */
case DF_CRT_STANDBY:
config = (config & ~(DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN | DF_DCFG_DAC_BL_EN)) |
DF_DCFG_VSYNC_EN;
misc |= DF_DAC_POWER_DOWN;
break;
/* HSYNC:ON VSYNC:OFF */
case DF_CRT_SUSPEND:
config = (config & ~(DF_DCFG_DIS_EN | DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN)) |
DF_DCFG_HSYNC_EN;
misc |= DF_DAC_POWER_DOWN;
break;
default:
return CIM_STATUS_INVALIDPARAMS;
}
WRITE_VID32 (DF_DISPLAY_CONFIG, config);
WRITE_VID32 (DF_VID_MISC, misc);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* df_set_panel_enable
*
* This routine enables or disables panel output.
*---------------------------------------------------------------------------*/
int df_set_panel_enable (int enable)
{
unsigned long pm;
pm = READ_VID32 (DF_POWER_MANAGEMENT);
if (enable) pm |= DF_PM_PANEL_ON;
else pm &= ~DF_PM_PANEL_ON;
WRITE_VID32 (DF_POWER_MANAGEMENT, pm);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* df_configure_video_source
*
* This routine initializes all aspects of the source buffer for a video overlay.
*---------------------------------------------------------------------------*/
int df_configure_video_source (DF_VIDEO_SOURCE_PARAMS *video_source_odd,
DF_VIDEO_SOURCE_PARAMS *video_source_even)
{
unsigned long pitch, ctrl, vcfg;
unsigned long lock, vg_line, gcfg;
unsigned long width, size, scale;
unsigned long misc;
lock = READ_REG32 (DC3_UNLOCK);
vg_line = READ_REG32 (DC3_LINE_SIZE);
gcfg = READ_REG32 (DC3_GENERAL_CFG);
vcfg = READ_VID32 (DF_VIDEO_CONFIG);
ctrl = READ_VID32 (DF_VID_ALPHA_CONTROL);
scale = READ_VID32 (DF_VIDEO_SCALER);
/* STORE THE DESIRED SCALING PROCEDURE */
/* Cimarron supports two modes when programming the scale and position */
/* of the video window. The first mode is designed to implicitly apply */
/* the graphics scale to any video operations. The second applys the */
/* video unchanged, allowing complete control by the user. To allow */
/* visibility between modules, the current mode is stored in a spare */
/* bit in the DF miscellaneous register. */
misc = READ_VID32 (DF_VID_MISC);
if (video_source_odd->flags & DF_SOURCEFLAG_IMPLICITSCALING)
misc |= DF_USER_IMPLICIT_SCALING;
else
misc &= DF_USER_IMPLICIT_SCALING;
WRITE_VID32 (DF_VID_MISC, misc);
/* PARAMETER - VIDEO PITCH */
pitch = (video_source_odd->y_pitch >> 3) | ((video_source_odd->uv_pitch >> 3) << 16);
/* PARAMETER - VIDEO FORMAT */
gcfg &= ~DC3_GCFG_YUV_420;
vcfg &= ~(DF_VCFG_VID_INP_FORMAT | DF_VCFG_4_2_0_MODE);
ctrl &= ~(DF_VIDEO_INPUT_IS_RGB | DF_CSC_VIDEO_YUV_TO_RGB | DF_HD_VIDEO |
DF_YUV_CSC_EN);
/* SELECT PIXEL ORDERING */
switch (video_source_odd->video_format & 3)
{
case 0: vcfg |= DF_VCFG_UYVY_FORMAT; break;
case 1: vcfg |= DF_VCFG_Y2YU_FORMAT; break;
case 2: vcfg |= DF_VCFG_YUYV_FORMAT; break;
case 3: vcfg |= DF_VCFG_YVYU_FORMAT; break;
}
/* SELECT SOURCE FORMAT (4:2:2, 4:2:0, RGB) */
switch (video_source_odd->video_format >> 2)
{
case 0: ctrl |= DF_CSC_VIDEO_YUV_TO_RGB; break;
case 1: ctrl |= DF_CSC_VIDEO_YUV_TO_RGB;
vcfg |= DF_VCFG_4_2_0_MODE;
gcfg |= DC3_GCFG_YUV_420;
break;
case 2: ctrl |= DF_VIDEO_INPUT_IS_RGB; break;
default: return CIM_STATUS_INVALIDPARAMS;
}
/* ALIGN TO APPROPRIATE OUTPUT COLOR SPACE */
/* We have assumed until this point that the output color space is RGB */
/* and the input (if YUV) is always SDTV video. */
if (video_source_odd->flags & DF_SOURCEFLAG_HDTVSOURCE)
ctrl |= DF_HD_VIDEO;
if (ctrl & DF_CSC_GRAPHICS_RGB_TO_YUV)
{
/* YUV OUTPUT - DISABLE YUV->RGB AND ENABLE YUV->YUV */
ctrl &= ~DF_CSC_VIDEO_YUV_TO_RGB;
if ((!(ctrl & DF_HD_VIDEO) && (ctrl & DF_HD_GRAPHICS)) ||
((ctrl & DF_HD_VIDEO) && !(ctrl & DF_HD_GRAPHICS)))
{
ctrl |= DF_YUV_CSC_EN;
}
}
/* PARAMETER - DISPLAY FILTER BUFFER SIZE */
/* The line size in the video generator must be 32-byte aligned. */
/* However, smaller alignments are managed by setting the */
/* appropriate pitch and clipping the video window. */
vcfg &= ~(DF_VCFG_LINE_SIZE_LOWER_MASK | DF_VCFG_LINE_SIZE_BIT8 |
DF_VCFG_LINE_SIZE_BIT9);
size = ((video_source_odd->width >> 1) + 7) & 0xFFF8;
vcfg |= (size & 0x00FF) << 8;
if (size & 0x0100) vcfg |= DF_VCFG_LINE_SIZE_BIT8;
if (size & 0x0200) vcfg |= DF_VCFG_LINE_SIZE_BIT9;
scale = (scale & ~0x7FF) | video_source_odd->height;
/* PARAMETER - VIDEO GENERATOR BUFFER SIZE */
vg_line &= ~DC3_LINE_SIZE_VLS_MASK;
if (gcfg & DC3_GCFG_YUV_420)
width = ((video_source_odd->width >> 1) + 7) & 0xFFF8;
else
width = ((video_source_odd->width << 1) + 31) & 0xFFE0;
vg_line |= (width >> 3) << DC3_LINE_SIZE_VB_SHIFT;
/* WRITE ALL PARAMETERS AT ONCE */
WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
WRITE_VID32 (DF_VIDEO_CONFIG, vcfg);
WRITE_VID32 (DF_VID_ALPHA_CONTROL, ctrl);
WRITE_VID32 (DF_VIDEO_SCALER, scale);
WRITE_REG32 (DC3_GENERAL_CFG, gcfg);
WRITE_REG32 (DC3_LINE_SIZE, vg_line);
WRITE_REG32 (DC3_VID_YUV_PITCH, pitch);
/* WRITE EVEN OR ODD BUFFER OFFSETS */
/* The even buffer is only valid inside an interlaced display. */
if (READ_REG32 (DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN)
{
WRITE_REG32 (DC3_VID_EVEN_Y_ST_OFFSET, video_source_even->y_offset);
WRITE_REG32 (DC3_VID_EVEN_U_ST_OFFSET, video_source_even->u_offset);
WRITE_REG32 (DC3_VID_EVEN_V_ST_OFFSET, video_source_even->v_offset);
}
WRITE_REG32 (DC3_VID_Y_ST_OFFSET, video_source_odd->y_offset);
WRITE_REG32 (DC3_VID_U_ST_OFFSET, video_source_odd->u_offset);
WRITE_REG32 (DC3_VID_V_ST_OFFSET, video_source_odd->v_offset);
WRITE_REG32 (DC3_UNLOCK, lock);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* df_set_video_offsets
*
* This routine sets the starting offset for the video buffer(s). The buffers
* can also be configured inside df_configure_video_source, but a separate
* routine is provided here to allow quick buffer flipping.
*---------------------------------------------------------------------------*/
int df_set_video_offsets (int even, unsigned long y_offset,
unsigned long u_offset, unsigned long v_offset)
{
unsigned long lock = READ_REG32 (DC3_UNLOCK);
WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
if (even)
{
WRITE_REG32 (DC3_VID_EVEN_Y_ST_OFFSET, y_offset);
WRITE_REG32 (DC3_VID_EVEN_U_ST_OFFSET, u_offset);
WRITE_REG32 (DC3_VID_EVEN_V_ST_OFFSET, v_offset);
}
else
{
WRITE_REG32 (DC3_VID_Y_ST_OFFSET, y_offset);
WRITE_REG32 (DC3_VID_U_ST_OFFSET, u_offset);
WRITE_REG32 (DC3_VID_V_ST_OFFSET, v_offset);
}
WRITE_REG32 (DC3_UNLOCK, lock);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* df_set_video_scale
*
* This routine programs the horizontal/vertical scale factors for video. To
* disable scaling/filtering, this routine should be called with identical source
* and destination dimensions.
*---------------------------------------------------------------------------*/
int df_set_video_scale (unsigned long src_width, unsigned long src_height,
unsigned long dst_width, unsigned long dst_height, unsigned long flags)
{
unsigned long temp, misc;
unsigned long scale, gfxscale;
unsigned long fbactive, src;
unsigned long size, downscale;
unsigned long vcfg, gcfg, unlock;
/* APPLY THE GRAPHICS SCALE */
/* When requested by the user, we will adjust the video scale by the */
/* current graphics scale factor. This allows video to be programmed */
/* in terms of the graphics source resolution. */
misc = READ_VID32 (DF_VID_MISC);
if (misc & DF_USER_IMPLICIT_SCALING)
{
gfxscale = READ_REG32 (DC3_GFX_SCALE);
fbactive = READ_REG32 (DC3_FB_ACTIVE);
/* REVERSE ENGINEER THE SCALE FACTOR */
/* The graphics scale factor is (source / (dst - 1)), so a little */
/* math is performed to reverse engineer the correct scale for */
/* video. */
/* */
/* F = (0x4000*S)/(D-1) -> (D/S) = (((0x4000*S)/F)+1)/S */
scale = gfxscale & 0xFFFF;
src = (fbactive >> 16) + 1;
if (scale != 0x4000)
{
dst_width = dst_width * (((0x4000 * src) / scale) + 1);
dst_width /= src;
}
scale = gfxscale >> 16;
src = (fbactive & 0xFFFF) + 1;
if (scale != 0x4000)
{
dst_height = dst_height * (((0x4000 * src) / scale) + 1);
dst_height /= src;
}
}
/* CHECK FOR VALID SCALING FACTOR */
/* The display filter/video generator can support up to 8:1 */
/* horizontal downscale and up to 4:1 vertical downscale. */
/* Scale factors above 4:1 horizontal and 2:1 horizontal */
/* will have a quality impact. However, at such large scale */
/* factors, it might not matter, */
if (((flags & DF_SCALEFLAG_CHANGEX) && dst_width < (src_width >> 3)) ||
((flags & DF_SCALEFLAG_CHANGEY) && dst_height < (src_height >> 2)))
{
return CIM_STATUS_INVALIDSCALE;
}
/* ENABLE OR DISABLE ADVANCED SCALING FEATURES */
/* Scaling above 2:1 vertical and 4:1 horizontal relies */
/* on mechanisms beside the line filter. */
if (flags & DF_SCALEFLAG_CHANGEX)
{
scale = READ_VID32 (DF_VIDEO_SCALER);
vcfg = READ_VID32 (DF_VIDEO_CONFIG);
vcfg &= ~(DF_VCFG_LINE_SIZE_LOWER_MASK | DF_VCFG_LINE_SIZE_BIT8 |
DF_VCFG_LINE_SIZE_BIT9);
if (dst_width < (src_width >> 2))
{
src_width >>= 1;
WRITE_VID32 (DF_VIDEO_SCALER, scale | DF_SCALE_DOUBLE_H_DOWNSCALE);
}
else
{
WRITE_VID32 (DF_VIDEO_SCALER, scale & ~DF_SCALE_DOUBLE_H_DOWNSCALE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -