vid_5530.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 867 行 · 第 1/2 页

C
867
字号
/*-----------------------------------------------------------------------------
 * VID_5530.C
 *
 * Version 2.0 - February 21, 2000
 *
 * This file contains routines to control the CS5530 video overlay hardware.
 *
 * History:
 *    Versions 0.1 through 2.0 by Brian Falardeau.
 *
 * Copyright (c) 1999-2000 National Semiconductor.
 *-----------------------------------------------------------------------------
 */

/*----------------------------------------------------------------------------
 * CS5530 PLL TABLE
 *----------------------------------------------------------------------------
 */
typedef struct tagCS5530PLLENTRY
{
    long frequency;                 /* 16.16 fixed point frequency */
    unsigned long pll_value;        /* associated register value */
} CS5530PLLENTRY;

CS5530PLLENTRY CS5530_PLLtable[] = {                                 
    { 0x00192CCC, 0x31C45801, }, /*  25.1750 */
    { 0x001C526E, 0x20E36802, }, /*  28.3220 */
    { 0x001F8000, 0x33915801, }, /*  31.5000 */
    { 0x00240000, 0x31EC4801, }, /*  36.0000 */
    { 0x00258000, 0x21E22801, }, /*  37.5000 */
    { 0x00280000, 0x33088801, }, /*  40.0000 */
    { 0x002CE666, 0x33E22801, }, /*  44.9000 */
    { 0x00318000, 0x336C4801, }, /*  49.5000 */
    { 0x00320000, 0x23088801, }, /*  50.0000 */
    { 0x00325999, 0x23088801, }, /*  50.3500 */
    { 0x00360000, 0x3708A801, }, /*  54.0000 */
    { 0x0038643F, 0x23E36802, }, /*  56.3916 */
    { 0x0038A4DD, 0x23E36802, }, /*  56.6444 */
    { 0x003B0000, 0x37C45801, }, /*  59.0000 */
    { 0x003F0000, 0x23EC4801, }, /*  63.0000 */
    { 0x00410000, 0x37911801, }, /*  65.0000 */
    { 0x00438000, 0x37963803, }, /*  67.5000 */
    { 0x0046CCCC, 0x37058803, }, /*  70.8000 */
    { 0x00480000, 0x3710C805, }, /*  72.0000 */
    { 0x004B0000, 0x37E22801, }, /*  75.0000 */
    { 0x004EC000, 0x27915801, }, /*  78.7500 */
    { 0x00500000, 0x37D8D802, }, /*  80.0000 */
    { 0x0059CCCC, 0x27588802, }, /*  89.8000 */
    { 0x005E8000, 0x27EC4802, }, /*  94.5000 */
    { 0x00630000, 0x27AC6803, }, /*  99.0000 */
    { 0x00640000, 0x27088801, }, /* 100.0000 */
    { 0x006C0000, 0x2710C805, }, /* 108.0000 */
    { 0x00708000, 0x27E36802, }, /* 112.5000 */
    { 0x00820000, 0x27C58803, }, /* 130.0000 */
    { 0x00870000, 0x27316803, }, /* 135.0000 */
    { 0x009D8000, 0x2F915801, }, /* 157.5000 */
    { 0x00A20000, 0x2F08A801, }, /* 162.0000 */
    { 0x00AF0000, 0x2FB11802, }, /* 175.0000 */
    { 0x00BD0000, 0x2FEC4802, }, /* 189.0000 */
    { 0x00CA0000, 0x2F963803, }, /* 202.0000 */
    { 0x00E80000, 0x2FB1B802, }, /* 232.0000 */
};

#define NUM_CS5530_FREQUENCIES sizeof(CS5530_PLLtable)/sizeof(CS5530PLLENTRY)

/*---------------------------------------------------------------------------
 * 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 cs5530_reset_video(void)
#else
void gfx_reset_video(void)
#endif
{
    gfx_set_video_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 cs5530_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 = CS5530_PLLtable[0].pll_value;
    min = (long) CS5530_PLLtable[0].frequency - frequency;
    if (min < 0L) min = -min;
    for (index = 1; index < NUM_CS5530_FREQUENCIES; index++)
    {
        diff = (long) CS5530_PLLtable[index].frequency - frequency;
        if (diff < 0L) diff = -diff;
        if (diff < min)
        {
            min = diff; 
            value = CS5530_PLLtable[index].pll_value;
        }
    }

    /* SET THE DOT CLOCK REGISTER */

    WRITE_VID32(CS5530_DOT_CLK_CONFIG, value);
    WRITE_VID32(CS5530_DOT_CLK_CONFIG, value | 0x80000100); /* set reset/bypass */
    gfx_delay_milliseconds(1); /* wait for PLL to settle */
    WRITE_VID32(CS5530_DOT_CLK_CONFIG, value & 0x7FFFFFFF); /* clear reset */
    WRITE_VID32(CS5530_DOT_CLK_CONFIG, value & 0x7FFFFEFF); /* clear bypass */
    return;
}

/*-----------------------------------------------------------------------------
 * gfx_set_video_enable
 *
 * This routine enables or disables the video overlay functionality.
 *-----------------------------------------------------------------------------
 */
#if GFX_VIDEO_DYNAMIC
int cs5530_set_video_enable(int enable)
#else
int gfx_set_video_enable(int enable)
#endif
{
    unsigned long 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(CS5530_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 CS5530 BUS CONTROL PARAMETERS */
        /* Currently always high speed, 8-bit interface. */

        vcfg |= CS5530_VCFG_HIGH_SPD_INT;
        vcfg &= ~(CS5530_VCFG_EARLY_VID_RDY | CS5530_VCFG_16_BIT_EN);

        /* ENABLE CS5530 VIDEO OVERLAY */

        vcfg |= CS5530_VCFG_VID_EN;
        WRITE_VID32(CS5530_VIDEO_CONFIG, vcfg);
    }
    else
    {
        /* DISABLE CS5530 VIDEO OVERLAY */

        vcfg &= ~CS5530_VCFG_VID_EN;
        WRITE_VID32(CS5530_VIDEO_CONFIG, vcfg);

        /* DISABLE VIDEO OVERLAY FROM DISPLAY CONTROLLER */
        /* Use private routine to abstract the display controller. */

        gfx_set_display_video_enable(0);
    }
    return(0);
}

/*-----------------------------------------------------------------------------
 * gfx_set_video_format
 *
 * Currently only sets 4:2:0 format, Y1 V Y0 U.
 *-----------------------------------------------------------------------------
 */
#if GFX_VIDEO_DYNAMIC
int cs5530_set_video_format(unsigned long format)
#else
int gfx_set_video_format(unsigned long format)
#endif
{
    unsigned long vcfg = 0;

    /* SET THE CS5530 VIDEO INPUT FORMAT */

    vcfg = READ_VID32(CS5530_VIDEO_CONFIG);
    vcfg &= ~(CS5530_VCFG_VID_INP_FORMAT | CS5530_VCFG_4_2_0_MODE);
    vcfg &= ~(CS5530_VCFG_CSC_BYPASS);
    if (format < 4) vcfg |= (format << 2);
    else vcfg |= CS5530_VCFG_CSC_BYPASS;
    WRITE_VID32(CS5530_VIDEO_CONFIG, vcfg);
    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 cs5530_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 CS5530 VIDEO LINE SIZE */

    vcfg = READ_VID32(CS5530_VIDEO_CONFIG);
    vcfg &= ~(CS5530_VCFG_LINE_SIZE_LOWER_MASK | CS5530_VCFG_LINE_SIZE_UPPER);
    size = (width >> 1);
    vcfg |= (size & 0x00FF) << 8;
    if (size & 0x0100) vcfg |= CS5530_VCFG_LINE_SIZE_UPPER;
    WRITE_VID32(CS5530_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 cs5530_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 cs5530_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 CS5530 SCALE FACTORS */
    /* No downscaling in CS5530 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(CS5530_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 cs5530_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;
    }
    else 
    {
        /* CLIPPING ON LEFT */
        /* Adjust initial read for scale, checking for divide by zero */

        xstart = hadjust;
        initread = -x;
        if (gfx_vid_dstw) 
            initread = ((-x) * gfx_vid_srcw) / gfx_vid_dstw;
        else initread = 0;
    }
    
    /* CLIPPING ON RIGHT */

    xend = x + w;
    if (xend > gfx_get_hactive()) xend = gfx_get_hactive();
    xend += hadjust;

    /* CLIPPING ON TOP */

    offset = gfx_vid_offset;
    if (y >= 0) 
    {
        ystart = y + vadjust;
    }
    else 
    {
        ystart = vadjust;
        line_size = (READ_VID32(CS5530_VIDEO_CONFIG) >> 7) & 0x000001FE;
        if (READ_VID32(CS5530_VIDEO_CONFIG) & CS5530_VCFG_LINE_SIZE_UPPER)
            line_size += 512;
        if (gfx_vid_dsth)
            offset = gfx_vid_offset + (line_size << 1) * 
                (((-y) * gfx_vid_srch) / gfx_vid_dsth);
    }

    /* CLIPPING ON BOTTOM */

    yend = y + h;
    if (yend >= gfx_get_vactive()) yend = gfx_get_vactive();
    yend += vadjust;

    /* SET VIDEO BUFFER OFFSET IN DISPLAY CONTROLLER */
    /* Use private routine to abstract the display controller. */

    gfx_set_display_video_offset(offset);

    /* DISABLE REGISTER UPDATES */

    vcfg = READ_VID32(CS5530_VIDEO_CONFIG);
    vcfg &= ~CS5530_VCFG_VID_REG_UPDATE;
    WRITE_VID32(CS5530_VIDEO_CONFIG, vcfg);

    /* SET VIDEO POSITION */

    WRITE_VID32(CS5530_VIDEO_X_POS, (xend << 16) | xstart);
    WRITE_VID32(CS5530_VIDEO_Y_POS, (yend << 16) | ystart);

    /* SET INITIAL READ ADDRESS AND ENABLE REGISTER UPDATES */

    vcfg &= ~CS5530_VCFG_INIT_READ_MASK;
    vcfg |= (initread << 15) & CS5530_VCFG_INIT_READ_MASK;
    vcfg |= CS5530_VCFG_VID_REG_UPDATE;
    WRITE_VID32(CS5530_VIDEO_CONFIG, vcfg);
    return(0);
}

/*---------------------------------------------------------------------------
 * gfx_set_video_color_key
 * 
 * This routine specifies the color key value and mask for the video overlay
 * hardware.  To disable color key, the color and mask should both be set to 
 * zero.  The hardware uses the color key in the following equation:
 *
 * ((source data) & (color key mask)) == ((color key) & (color key mask))
 *
 * The source data can be either graphics data or video data.  The bluescreen
 * parameter is set to have the hardware compare video data and clear to
 * comapare graphics data.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?