📄 vid_1200.c
字号:
/*-----------------------------------------------------------------------------
* VID_1200.C
*
* Version 2.0 - February 21, 2000
*
* This file contains routines to control the SC1200 video overlay hardware.
*
* History:
* Versions 0.1 through 2.0 by Brian Falardeau.
*
* Copyright (c) 1999-2000 National Semiconductor.
*-----------------------------------------------------------------------------
*/
/* GLOBAL VARIABLES */
/* Needed to save intended color key values since the color key */
/* registers are required to truly disable the video window. */
unsigned long sc1200_color_key = 0;
unsigned long sc1200_color_mask = 0;
int sc1200_alpha_enable[3];
/*----------------------------------------------------------------------------
* SC1200 PLL TABLE
*----------------------------------------------------------------------------
*/
typedef struct tagSC1200PLL
{
long frequency; /* 16.16 fixed point frequency */
unsigned long clock_select; /* clock select register (0x2C) */
} SC1200PLL;
SC1200PLL gfx_sc1200_clock_table[] = {
{ 0x00192CCC, 0x00000000 }, /* 25.1750 */
{ 0x001F8000, 0x00010000 }, /* 31.5000 */
{ 0x00240000, 0x00020000 }, /* 36.0000 */
{ 0x00280000, 0x00030000 }, /* 40.0000 */
{ 0x00318000, 0x00050000 }, /* 49.5000 */
{ 0x00320000, 0x00040000 }, /* 50.0000 */
{ 0x00384000, 0x00060000 }, /* 56.2500 */
{ 0x00410000, 0x00080000 }, /* 65.0000 */
{ 0x004E8000, 0x000A0000 }, /* 78.5000 */
{ 0x005E8000, 0x000B0000 }, /* 94.5000 */
{ 0x006C0000, 0x000C0000 }, /* 108.0000 */
{ 0x00870000, 0x000D0000 }, /* 135.0000 */
};
#define NUM_SC1200_FREQUENCIES sizeof(gfx_sc1200_clock_table)/sizeof(SC1200PLL)
/*---------------------------------------------------------------------------
* gfx_reset_video (PRIVATE ROUTINE: NOT PART OF DURANGO API)
*
* This routine is used to disable all components of video overlay before
* performing a mode switch.
*---------------------------------------------------------------------------
*/
#if GFX_VIDEO_DYNAMIC
void sc1200_reset_video(void)
#else
void gfx_reset_video(void)
#endif
{
gfx_set_video_enable(0);
gfx_select_alpha_region(0);
gfx_set_alpha_enable(0);
gfx_select_alpha_region(1);
gfx_set_alpha_enable(0);
gfx_select_alpha_region(2);
gfx_set_alpha_enable(0);
}
/*---------------------------------------------------------------------------
* gfx_set_clock_frequency
*
* This routine sets the clock frequency, specified as a 16.16 fixed point
* value (0x00318000 = 49.5 MHz). It will set the closest frequency found
* in the lookup table.
*---------------------------------------------------------------------------
*/
#if GFX_VIDEO_DYNAMIC
void sc1200_set_clock_frequency(unsigned long frequency)
#else
void gfx_set_clock_frequency(unsigned long frequency)
#endif
{
int index;
unsigned long value;
long min, diff;
/* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */
/* Search the table for the closest frequency (16.16 format). */
value = gfx_sc1200_clock_table[0].clock_select;
min = (long) gfx_sc1200_clock_table[0].frequency - frequency;
if (min < 0L) min = -min;
for (index = 1; index < NUM_SC1200_FREQUENCIES; index++)
{
diff = (long) gfx_sc1200_clock_table[index].frequency - frequency;
if (diff < 0L) diff = -diff;
if (diff < min)
{
min = diff;
value = gfx_sc1200_clock_table[index].clock_select;
}
}
/* SET THE DOT CLOCK REGISTER */
WRITE_VID32(SC1200_VID_MISC, 0x00001000);
WRITE_VID32(SC1200_VID_CLOCK_SELECT, value);
return;
}
/*-----------------------------------------------------------------------------
* gfx_set_video_enable
*
* This routine enables or disables the video overlay functionality.
*-----------------------------------------------------------------------------
*/
#if GFX_VIDEO_DYNAMIC
int sc1200_set_video_enable(int enable)
#else
int gfx_set_video_enable(int enable)
#endif
{
int i;
unsigned long alpha, vcfg;
/* WAIT FOR VERTICAL BLANK TO START */
/* Otherwise a glitch can be observed. */
if (gfx_test_timing_active())
{
if (!gfx_test_vertical_active())
{
while(!gfx_test_vertical_active());
}
while(gfx_test_vertical_active());
}
vcfg = READ_VID32(SC1200_VIDEO_CONFIG);
if (enable)
{
/* ENABLE VIDEO OVERLAY FROM DISPLAY CONTROLLER */
/* Use private routine to abstract the display controller. */
gfx_set_display_video_enable(1);
/* SET SC1200 BUS CONTROL PARAMETERS */
/* Currently always high speed, 8-bit interface. */
vcfg |= SC1200_VCFG_HIGH_SPD_INT;
vcfg &= ~(SC1200_VCFG_EARLY_VID_RDY | SC1400_VCFG_16_BIT_EN);
/* ENABLE SC1200 VIDEO OVERLAY */
vcfg |= SC1200_VCFG_VID_EN;
WRITE_VID32(SC1200_VIDEO_CONFIG, vcfg);
/* RESTORE SC1200 COLOR KEY VALUE */
WRITE_VID32(SC1200_VIDEO_COLOR_KEY, sc1200_color_key);
WRITE_VID32(SC1200_VIDEO_COLOR_MASK, sc1200_color_mask);
/* RESTORE ALPHA ENABLE FOR ALL 3 REGIONS */
for (i = 0; i < 3; i++)
{
if (sc1200_alpha_enable[i])
{
alpha = READ_VID32(SC1200_ALPHA_CONTROL_1 + (i << 4));
alpha |= (1L << 16);
WRITE_VID32(SC1200_ALPHA_CONTROL_1 + (i << 4), alpha);
}
}
}
else
{
/* DISABLE VIDEO OVERLAY FROM DISPLAY CONTROLLER */
/* Use private routine to abstract the display controller. */
gfx_set_display_video_enable(0);
/* DISABLE SC1200 VIDEO OVERLAY */
/* Really only blanks video - hence use of color key. */
vcfg &= ~SC1200_VCFG_VID_EN;
WRITE_VID32(SC1200_VIDEO_CONFIG, vcfg);
/* USE COLOR KEY VALUE TO REALLY DISABLE WINDOW */
/* Key and mask set to 0xFFFFFF will disable window */
WRITE_VID32(SC1200_VIDEO_COLOR_KEY, 0xFFFFFF);
WRITE_VID32(SC1200_VIDEO_COLOR_MASK, 0xFFFFFF);
/* DISABLE ALL 3 ALPHA REGIONS */
for (i = 0; i < 3; i++)
{
alpha = READ_VID32(SC1200_ALPHA_CONTROL_1 + (i << 4));
alpha &= ~(1 << 16);
WRITE_VID32(SC1200_ALPHA_CONTROL_1 + (i << 4), alpha);
}
}
return(0);
}
/*-----------------------------------------------------------------------------
* gfx_set_video_format
*
* Currently only sets 4:2:2 format, Y1 V Y0 U.
*-----------------------------------------------------------------------------
*/
#if GFX_VIDEO_DYNAMIC
int sc1200_set_video_format(unsigned long format)
#else
int gfx_set_video_format(unsigned long format)
#endif
{
unsigned long ctrl, vcfg = 0;
/* SET THE SC1200 VIDEO INPUT FORMAT */
vcfg = READ_VID32(SC1200_VIDEO_CONFIG);
vcfg &= ~(SC1200_VCFG_VID_INP_FORMAT | SC1200_VCFG_4_2_0_MODE);
vcfg &= ~(SC1200_VCFG_CSC_BYPASS);
if (format < 4) vcfg |= (format << 2);
WRITE_VID32(SC1200_VIDEO_CONFIG, vcfg);
/* SET THE VIDEO COLOR SPACE CONVERSION BIT */
/* ### Currently always set for 4:2:2 YUV */
ctrl = READ_VID32(SC1200_VID_ALPHA_CONTROL);
ctrl |= (1 << 10); /* set bit 10 */
WRITE_VID32(SC1200_VID_ALPHA_CONTROL, ctrl);
return(0);
}
/*-----------------------------------------------------------------------------
* gfx_set_video_size
*
* This routine specifies the size of the source data. It is used only
* to determine how much data to transfer per frame, and is not used to
* calculate the scaling value (that is handled by a separate routine).
*-----------------------------------------------------------------------------
*/
#if GFX_VIDEO_DYNAMIC
int sc1200_set_video_size(unsigned short width, unsigned short height)
#else
int gfx_set_video_size(unsigned short width, unsigned short height)
#endif
{
unsigned long size, vcfg;
/* SET THE SC1200 VIDEO LINE SIZE */
vcfg = READ_VID32(SC1200_VIDEO_CONFIG);
vcfg &= ~(SC1200_VCFG_LINE_SIZE_LOWER_MASK | SC1200_VCFG_LINE_SIZE_UPPER);
size = (width >> 1);
vcfg |= (size & 0x00FF) << 8;
if (size & 0x0100) vcfg |= SC1200_VCFG_LINE_SIZE_UPPER;
WRITE_VID32(SC1200_VIDEO_CONFIG, vcfg);
/* SET TOTAL VIDEO BUFFER SIZE IN DISPLAY CONTROLLER */
/* Use private routine to abstract the display controller. */
gfx_set_display_video_size(width, height);
return(0);
}
/*-----------------------------------------------------------------------------
* gfx_set_video_offset
*
* This routine sets the starting offset for the video buffer when only
* one offset needs to be specified.
*-----------------------------------------------------------------------------
*/
#if GFX_VIDEO_DYNAMIC
int sc1200_set_video_offset(unsigned long offset)
#else
int gfx_set_video_offset(unsigned long offset)
#endif
{
/* SAVE VALUE FOR FUTURE CLIPPING OF THE TOP OF THE VIDEO WINDOW */
gfx_vid_offset = offset;
/* SET VIDEO BUFFER OFFSET IN DISPLAY CONTROLLER */
/* Use private routine to abstract the display controller. */
gfx_set_display_video_offset(offset);
return(0);
}
/*---------------------------------------------------------------------------
* gfx_set_video_scale
*
* This routine sets the scale factor for the video overlay window. The
* size of the source and destination regions are specified in pixels.
*---------------------------------------------------------------------------
*/
#if GFX_VIDEO_DYNAMIC
int sc1200_set_video_scale(unsigned short srcw, unsigned short srch,
unsigned short dstw, unsigned short dsth)
#else
int gfx_set_video_scale(unsigned short srcw, unsigned short srch,
unsigned short dstw, unsigned short dsth)
#endif
{
unsigned long xscale, yscale;
/* SAVE PARAMETERS */
/* These are needed for clipping the video window later. */
gfx_vid_srcw = srcw;
gfx_vid_srch = srch;
gfx_vid_dstw = dstw;
gfx_vid_dsth = dsth;
/* CALCULATE SC1200 SCALE FACTORS */
/* No downscaling in SC1200 so force to 1x if attempted. */
if (srcw < dstw) xscale = (0x2000 * (srcw - 1)) / (dstw - 1);
else xscale = 0x1FFF;
if (srch < dsth) yscale = (0x2000 * (srch - 1)) / (dsth - 1);
else yscale = 0x1FFF;
WRITE_VID32(SC1200_VIDEO_SCALE, (yscale << 16) | xscale);
/* CALL ROUTINE TO UPDATE WINDOW POSITION */
/* This is required because the scale values effect the number of */
/* source data pixels that need to be clipped, as well as the */
/* amount of data that needs to be transferred. */
gfx_set_video_window(gfx_vid_xpos, gfx_vid_ypos, gfx_vid_width,
gfx_vid_height);
return(0);
}
/*---------------------------------------------------------------------------
* gfx_set_video_window
*
* This routine sets the position and size of the video overlay window. The
* position is specified in screen relative coordinates, and may be negative.
* The size of destination region is specified in pixels. The line size
* indicates the number of bytes of source data per scanline.
*---------------------------------------------------------------------------
*/
#if GFX_VIDEO_DYNAMIC
int sc1200_set_video_window(short x, short y, unsigned short w,
unsigned short h)
#else
int gfx_set_video_window(short x, short y, unsigned short w,
unsigned short h)
#endif
{
unsigned long vcfg = 0;
unsigned long hadjust, vadjust;
unsigned long initread;
unsigned long xstart, ystart, xend, yend;
unsigned long offset, line_size;
/* SAVE PARAMETERS */
/* These are needed to call this routine if the scale value changes. */
gfx_vid_xpos = x;
gfx_vid_ypos = y;
gfx_vid_width = w;
gfx_vid_height = h;
/* GET ADJUSTMENT VALUES */
/* Use routines to abstract version of display controller. */
hadjust = gfx_get_htotal() - gfx_get_hsync_end() - 13;
vadjust = gfx_get_vtotal() - gfx_get_vsync_end() + 1;
if (x > 0)
{
/* NO CLIPPING ON LEFT */
xstart = x + hadjust;
initread = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -