📄 cim_df.c
字号:
}
/* PROGRAM A NEW LINE SIZE */
/* The line size must be updated when using the Double Horizontal */
/* Downscale (DHD) bit. This is because the amount of VFIFO space */
/* consumed is effectively half in this mode. */
size = ((src_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;
WRITE_VID32 (DF_VIDEO_CONFIG, vcfg);
WRITE_VID32 (DF_VIDEO_XSCALE, ((0x10000 * src_width) / dst_width));
}
if (flags & DF_SCALEFLAG_CHANGEY)
{
unlock = READ_REG32 (DC3_UNLOCK);
gcfg = READ_REG32 (DC3_GENERAL_CFG) & ~DC3_GCFG_VDSE;
WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
if (dst_height < (src_height >> 1))
{
gcfg |= DC3_GCFG_VDSE;
downscale = READ_REG32 (DC3_VID_DS_DELTA) & ~DC3_DS_DELTA_MASK;
if (dst_height == (src_height >> 2))
downscale |= (0x3FFF << 18);
else
downscale |= (((src_height >> 1) << 14) / dst_height) << 18;
WRITE_REG32 (DC3_VID_DS_DELTA, downscale);
WRITE_VID32 (DF_VIDEO_YSCALE, 0x20000);
}
else
{
WRITE_VID32 (DF_VIDEO_YSCALE, ((0x10000 * src_height) / dst_height));
}
WRITE_REG32 (DC3_GENERAL_CFG, gcfg);
WRITE_REG32 (DC3_UNLOCK, unlock);
}
/* CHECK IF SCALING IS DISABLED */
/* If no scaling occurs, we disable the hardware filter. */
temp = READ_VID32 (DF_VIDEO_CONFIG);
if ((READ_VID32 (DF_VIDEO_XSCALE) == 0x10000) &&
(READ_VID32 (DF_VIDEO_YSCALE) == 0x10000))
{
WRITE_VID32 (DF_VIDEO_CONFIG, (temp | DF_VCFG_SC_BYP));
}
else
WRITE_VID32 (DF_VIDEO_CONFIG, (temp & ~DF_VCFG_SC_BYP));
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* df_set_video_position
*
* This routine programs the position of the video window on the display.
* An indent parameter is also passed to this program to prevent artifacts
* when the video window is moved beyond the left edge of the screen.
*---------------------------------------------------------------------------*/
int df_set_video_position (DF_VIDEO_POSITION *video_window)
{
unsigned long vblankstart_even, vblankend_even, vsyncend_even, vtotal_even, vactive_even;
unsigned long hblankstart, hblankend, hsyncend, htotal, hactive;
unsigned long vblankstart, vblankend, vsyncend, vtotal, vactive;
unsigned long width, height, height_even;
unsigned long adjust, border_x, border_y, border_y_even;
unsigned long xstart, xend;
unsigned long ystart, yend;
unsigned long ckey_x, ckey_y;
unsigned long x_copy, y_copy;
unsigned long width_copy, height_copy;
unsigned long vcfg, initread;
unsigned long xscale, dst_clip;
unsigned long ypos, ypos_even;
unsigned long y, gfxscale;
unsigned long misc, fbactive;
unsigned long scale, src;
unsigned long irq_ctl;
unsigned long unlock;
hsyncend = ((READ_REG32 (DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1;
vsyncend = ((READ_REG32 (DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1;
vblankend = ((READ_REG32 (DC3_V_BLANK_TIMING) >> 16) & 0xFFF) + 1;
hblankend = ((READ_REG32 (DC3_H_BLANK_TIMING) >> 16) & 0xFFF) + 1;
htotal = ((READ_REG32 (DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
vtotal = ((READ_REG32 (DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
vblankstart = (READ_REG32 (DC3_V_BLANK_TIMING) & 0xFFF) + 1;
hblankstart = (READ_REG32 (DC3_H_BLANK_TIMING) & 0xFFF) + 1;
hactive = (READ_REG32 (DC3_H_ACTIVE_TIMING) & 0xFFF) + 1;
vactive = (READ_REG32 (DC3_V_ACTIVE_TIMING) & 0xFFF) + 1;
unlock = READ_REG32 (DC3_UNLOCK);
/* INCLUDE BORDER IF REQUESTED */
if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
{
border_x = htotal - hblankend;
border_y = vtotal - vblankend;
hactive = hblankstart + htotal - hblankend;
vactive = vblankstart + vtotal - vblankend;
}
else
{
border_x = border_y = 0;
}
/* APPLY THE GRAPHICS SCALE */
/* Do not alter the input data. */
width_copy = video_window->width;
height_copy = video_window->height;
x_copy = video_window->x;
y_copy = video_window->y;
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 */
scale = gfxscale & 0xFFFF;
src = (fbactive >> 16) + 1;
if (scale != 0x4000)
{
width_copy = width_copy * (((0x4000 * src) / scale) + 1);
width_copy /= src;
x_copy = x_copy * (((0x4000 * src) / scale) + 1);
x_copy /= src;
}
scale = gfxscale >> 16;
src = (fbactive & 0xFFFF) + 1;
if (scale != 0x4000)
{
height_copy = height_copy * (((0x4000 * src) / scale) + 1);
height_copy /= src;
y_copy = y_copy * (((0x4000 * src) / scale) + 1);
y_copy /= src;
}
}
/* HANDLE INTERLACING */
/* When the output is interlaced, we must set the position and height */
/* on the fields and not on the composite image. */
if ((irq_ctl = READ_REG32 (DC3_IRQ_FILT_CTL)) & DC3_IRQFILT_INTL_EN)
{
vsyncend_even = ((READ_REG32 (DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1;
vtotal_even = ((READ_REG32 (DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1;
vblankend_even = ((READ_REG32 (DC3_V_BLANK_EVEN) >> 16) & 0xFFF) + 1;
vactive_even = (READ_REG32 (DC3_V_ACTIVE_EVEN) & 0xFFF) + 1;
vblankstart_even = (READ_REG32 (DC3_V_BLANK_EVEN) & 0xFFF) + 1;
if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
{
border_y_even = vtotal_even- vblankend_even;
vactive_even = vblankstart_even + vtotal_even - vblankend_even;
}
else
border_y_even = 0;
/* THE ODD FIELD MUST ALWAYS PRECEDE THE EVEN FIELD */
/* This implies that we can never start video on an odd y position */
/* in the composite image. This is required because the only way to */
/* accomplish an odd y start would be to switch the buffer offsets, */
/* which could have serious repercussions for genlocked VIP. */
y = y_copy >> 1;
/* CALCULATE Y POSITION FOR ODD FIELD */
/* Clip the video window to the odd field timings. Note that the */
/* height in the odd field may be greater if the video height is */
/* odd. */
height = (height_copy + 1) >> 1;
if ((y + height) > vactive)
height = vactive - y;
ystart = y + vtotal_even - vsyncend_even + 1;
if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
ystart -= border_y_even;
yend = ystart + height;
ypos = (yend << 16) | ystart;
/* CALCULATE Y POSITION FOR EVEN FIELD */
height_even = height_copy >> 1;
if ((y + height_even) > vactive_even)
height_even = vactive_even - y;
ystart = y + vtotal - vsyncend + 1;
if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
ystart -= border_y;
yend = ystart + height_even;
ypos_even = (yend << 16) | ystart;
/* CALCULATE ACTUAL FRAME BUFFER HEIGHT */
/* The y position and height are used to determine the actual */
/* placement of the color key region. The region will either be */
/* the sum of the even and odd fields (for interlaced addressing */
/* or flicker filtering) or it will be the union of the two (for */
/* line doubling). We must also adjust the region such that the */
/* origin (0, 0) is centered on the beginning of graphics data. */
/* This is only a problem if video is being displayed over the */
/* overscan area. */
if ((READ_REG32 (DC3_GENLK_CTL) & DC3_GC_FLICKER_FILTER_ENABLE) ||
(irq_ctl & DC3_IRQFILT_INTL_ADDR))
{
y <<= 1;
height += height_even;
adjust = border_y + border_y_even;
}
else
{
adjust = border_y;
if (height_even > height)
height = height_even;
}
if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
{
if (y > adjust)
{
y -= adjust;
adjust = 0;
}
else
{
adjust -= y;
if (height > adjust)
height -= adjust;
else
height = 0;
}
}
}
else
{
y = y_copy;
height = height_copy;
if ((y + height) > vactive)
height = vactive - y;
ystart = y + vtotal - vsyncend + 1;
if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
ystart -= border_y;
yend = ystart + height;
ypos = (yend << 16) | ystart;
ypos_even = 0;
}
/* HORIZONTAL POSITION */
/* The horizontal values are identical for the even and odd field. */
width = width_copy;
xstart = x_copy + htotal - hsyncend - 14;
if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
xstart -= border_x;
/* RIGHT CLIPPING */
if ((x_copy + width) > hactive)
width = hactive - x_copy;
xend = xstart + width;
/* CALCULATE LEFT CLIPPING PARAMETER */
/* The value passed in can be interpreted as destination pixels, in which */
/* case the video scale is factored in, or as source pixels, in which case */
/* the value is written directly. Also, the display filter's initial read */
/* address value is only programmable on 4-pixel increments. However, we */
/* can achieve an arbitrary left clip by adjusting the xstart value, as */
/* there is a 14-clock delay in which to play. Also, according to the */
/* designers, 4:2:0 and 4:2:2 behave identically when setting the initial */
/* read address. The addition of scaling further complicates the */
/* algorithm. When setting the initial read address, it is in terms of */
/* source pixels, while adjusting the xstart value is in destination pixels */
/* We may thus not be able to achieve a perfect clipping fit for scaled */
/* video. We compensate by including two clipping parameters in our */
/* structure. This allows us the user additional control and it allows us */
/* to accurately convey to the user the state of clipping on the machine. */
initread = video_window->left_clip;
dst_clip = 0;
if (!(video_window->flags & DF_POSFLAG_DIRECTCLIP))
{
xscale = READ_VID32 (DF_VIDEO_XSCALE) & 0xFFFFF;
initread = (initread * xscale) / 0x10000;
if (xscale)
dst_clip = ((initread & 3) * 0x10000) / xscale;
}
else
dst_clip = video_window->dst_clip;
/* LIMIT THE CLIP */
/* We technically have a 14 pixel window in which to play. However, taking */
/* the entire 14 pixels makes the video timing a little hairy... Also note */
/* that we cannot do this when performing panel centering, as the video */
/* would then exceed the mode size. */
if (dst_clip > 4)
dst_clip = 4;
if (READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_DCEN)
dst_clip = 0;
xstart -= dst_clip;
vcfg = READ_VID32 (DF_VIDEO_CONFIG);
vcfg &= ~DF_VCFG_INIT_READ_MASK;
vcfg |= (initread >> 2) << 16;
/* SET COLOR KEY REGION */
/* We are assuming that color keying will never be desired outside */
/* of the video region. We adjust the color key region for graphics */
/* scaling. */
gfxscale = READ_REG32 (DC3_GFX_SCALE);
ckey_x = ((x_copy * (gfxscale & 0xFFFF)) / 0x4000) |
((((x_copy + width) * (gfxscale & 0xFFFF)) / 0x4000) << 16);
ckey_y = ((y * (gfxscale >> 16)) / 0x4000) |
((((y + height) * (gfxscale >> 16)) / 0x4000) << 16);
/* WRITE ALL PARAMETERS AT ONCE */
WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
WRITE_REG32 (DC3_CLR_KEY_X, ckey_x);
WRITE_REG32 (DC3_CLR_KEY_Y, ckey_y);
WRITE_VID32 (DF_VIDEO_X_POS, (xend << 16) | xstart);
WRITE_VID32 (DF_VIDEO_Y_POS, ypos);
WRITE_VID32 (DF_VID_YPOS_EVEN, ypos_even);
WRITE_VID32 (DF_VIDEO_CONFIG, vcfg);
WRITE_REG32 (DC3_UNLOCK, unlock);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* df_set_video_filter_coefficients
*
* This routine sets the horizontal and vertical filter coefficients for video
* scaling. These coefficients are used for upscaling and downscaling video.
* If the phase256 parameter is 1, the coefficient arrays are used as single
* arrays of 256 phases for both vertical and horizontal scaling. If the
* phase256 parameter is clear, the coefficient arrays are used as two 128-phase
* arrays. The first 128 entries represent the phases for vertical scaling.
* The last 128 entries represent the phases for horizontal scaling.
*---------------------------------------------------------------------------*/
int df_set_video_filter_coefficients (long taps[][4], int phase256)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -