⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disp_gu1.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 3 页
字号:
/*-----------------------------------------------------------------------------
 * DISP_GU1.C
 *
 * Version 2.1 - March 3, 2000
 *
 * This file contains routines for the first generation display controller.  
 *
 * History:
 *    Versions 0.1 through 2.1 by Brian Falardeau.
 *
 * Copyright (c) 1999-2000 National Semiconductor.
 *-----------------------------------------------------------------------------
 */

void gu1_enable_compression(void);      /* private routine definition */
void gu1_disable_compression(void);     /* private routine definition */
void gfx_reset_video(void);             /* private routine definition */

/*-----------------------------------------------------------------------------
 * WARNING!!!! INACCURATE DELAY MECHANISM
 *
 * In an effort to keep the code self contained and operating system 
 * independent, the delay loop just performs reads of a display controller
 * register.  This time will vary for faster processors.  The delay can always
 * be longer than intended, only effecting the time of the mode switch 
 * (obviously want it to still be under a second).  Problems with the hardware
 * only arise if the delay is not long enough.  
 *-----------------------------------------------------------------------------
 */
#if GFX_DISPLAY_DYNAMIC
void gu1_delay_milliseconds(unsigned long milliseconds)
#else
void gfx_delay_milliseconds(unsigned long milliseconds)
#endif
{
    /* ASSUME 300 MHz, 5 CLOCKS PER READ */

    #define READS_PER_MILLISECOND 60000L

    unsigned long loop;
    loop = milliseconds * READS_PER_MILLISECOND;
    while (loop-- > 0)
    {
        READ_REG32(DC_UNLOCK);
    }
}

/*-----------------------------------------------------------------------------
 * GFX_VIDEO_SHUTDOWN
 *
 * This routine disables the display controller output.
 *-----------------------------------------------------------------------------
 */
void gu1_video_shutdown(void)
{
    unsigned long unlock;
    unsigned long gcfg, tcfg;

    /* DISABLE COMPRESSION */

    gu1_disable_compression();

    /* ALSO DISABLE VIDEO */
    /* Use private "reset video" routine to do all that is needed. */
    /* SC1200, for example, also disables the alpha blending regions. */

    gfx_reset_video();

    /* UNLOCK THE DISPLAY CONTROLLER REGISTERS */

    unlock = READ_REG32(DC_UNLOCK);
    WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);

    /* READ THE CURRENT GX VALUES */

    gcfg = READ_REG32(DC_GENERAL_CFG);
    tcfg = READ_REG32(DC_TIMING_CFG);

    /* BLANK THE GX DISPLAY */

    tcfg &= ~(unsigned long)DC_TCFG_BLKE;
    WRITE_REG32(DC_TIMING_CFG, tcfg);
    gfx_delay_milliseconds(1); /* delay after TIMING_CFG */

    /* DISABLE THE TIMING GENERATOR */

    tcfg &= ~(unsigned long)DC_TCFG_TGEN;                         
    WRITE_REG32(DC_TIMING_CFG, tcfg);
    gfx_delay_milliseconds(1); /* delay after TIMING_CFG */ 

    /* DELAY: WAIT FOR PENDING MEMORY REQUESTS */ 
    /* This delay is used to make sure that all pending requests to the */ 
    /* memory controller have completed before disabling the FIFO load. */

    gfx_delay_milliseconds(10);

    /* DISABLE DISPLAY FIFO LOAD AND DISABLE COMPRESSION */

    gcfg &= ~(unsigned long)(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
    WRITE_REG32(DC_GENERAL_CFG, gcfg);
    WRITE_REG32(DC_UNLOCK, unlock);
    return;
}

/*-----------------------------------------------------------------------------
 * GFX_SET_SPECIFIED_MODE
 * This routine uses the parameters in the specified display mode structure
 * to program the display controller hardware.  
 *-----------------------------------------------------------------------------
 */
void gu1_set_specified_mode(DISPLAYMODE *pMode, int bpp)
{
    unsigned long unlock, value;
    unsigned long gcfg, tcfg, ocfg, dcfg, vcfg;
    unsigned long size, pitch;

    /* DISABLE COMPRESSION */

    gu1_disable_compression();

    /* ALSO DISABLE VIDEO */
    /* Use private "reset video" routine to do all that is needed. */
    /* SC1200, for example, also disables the alpha blending regions. */

    gfx_reset_video();

    /* UNLOCK THE DISPLAY CONTROLLER REGISTERS */

    unlock = READ_REG32(DC_UNLOCK);
    WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);

    /* READ THE CURRENT GX VALUES */

    gcfg = READ_REG32(DC_GENERAL_CFG);
    tcfg = READ_REG32(DC_TIMING_CFG);

    /* BLANK THE GX DISPLAY */

    tcfg &= ~(unsigned long)DC_TCFG_BLKE;
    WRITE_REG32(DC_TIMING_CFG, tcfg);
    gfx_delay_milliseconds(1); /* delay after TIMING_CFG */

    /* DISABLE THE TIMING GENERATOR */

    tcfg &= ~(unsigned long)DC_TCFG_TGEN;                         
    WRITE_REG32(DC_TIMING_CFG, tcfg);
    gfx_delay_milliseconds(1); /* delay after TIMING_CFG */ 

    /* DELAY: WAIT FOR PENDING MEMORY REQUESTS 
     * This delay is used to make sure that all pending requests to the 
     * memory controller have completed before disabling the FIFO load.
     */

    gfx_delay_milliseconds(10);

    /* DISABLE DISPLAY FIFO LOAD AND DISABLE COMPRESSION */

    gcfg &= ~(unsigned long)(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
    WRITE_REG32(DC_GENERAL_CFG, gcfg);

    /* CLEAR THE "DCLK_MUL" FIELD */ 

    gcfg &= ~(unsigned long)(DC_GCFG_DDCK | DC_GCFG_DPCK | DC_GCFG_DFCK);
    gcfg &= ~(unsigned long)DC_GCFG_DCLK_MASK;
    WRITE_REG32(DC_GENERAL_CFG, gcfg);

    /* SET THE DOT CLOCK FREQUENCY */
    /* Mask off the divide by two bit (bit 31) */

    gfx_set_clock_frequency(pMode->frequency & 0x7FFFFFFF);

    /* DELAY: WAIT FOR THE PLL TO SETTLE */
    /* This allows the dot clock frequency that was just set to settle. */

    gfx_delay_milliseconds(10);

    /* SET THE "DCLK_MUL" FIELD OF DC_GENERAL_CFG */
    /* The GX hardware divides the dot clock, so 2x really means that the */ 
    /* internal dot clock equals the external dot clock. */ 

    if (pMode->frequency & 0x80000000) gcfg |= 0x0040;
    else gcfg |= 0x0080;
    WRITE_REG32(DC_GENERAL_CFG, gcfg);
    
    /* DELAY: WAIT FOR THE ADL TO LOCK */
    /* This allows the clock generatation within GX to settle.  This is */
    /* needed since some of the register writes that follow require that */
    /* clock to be present. */

    gfx_delay_milliseconds(10);

    /* SET THE GX DISPLAY CONTROLLER PARAMETERS */

    WRITE_REG32(DC_FB_ST_OFFSET, 0);
    WRITE_REG32(DC_CB_ST_OFFSET, 0);
    WRITE_REG32(DC_CURS_ST_OFFSET, 0);

    /* SET LINE SIZE AND PITCH */

    size = pMode->hactive;
    if (bpp > 8) size <<= 1;
    if (size <= 1024) pitch = 1024;
    else pitch = 2048;
    WRITE_REG32(DC_LINE_DELTA, pitch >> 2);

    /* ADD 2 TO SIZE FOR POSSIBLE START ADDRESS ALIGNMENTS */

    WRITE_REG32(DC_BUF_SIZE, (size >> 3) + 2);

    /* COMBINE AND SET TIMING VALUES */

    value = (unsigned long) (pMode->hactive - 1) |
        (((unsigned long) (pMode->htotal - 1)) << 16);
    WRITE_REG32(DC_H_TIMING_1, value);
    value = (unsigned long) (pMode->hblankstart - 1) |
        (((unsigned long) (pMode->hblankend - 1)) << 16);
    WRITE_REG32(DC_H_TIMING_2, value);
    value = (unsigned long) (pMode->hsyncstart - 1) |
        (((unsigned long) (pMode->hsyncend - 1)) << 16);
    WRITE_REG32(DC_H_TIMING_3, value);
    WRITE_REG32(DC_FP_H_TIMING, value);
    value = (unsigned long) (pMode->vactive - 1) |
        (((unsigned long) (pMode->vtotal - 1)) << 16);
    WRITE_REG32(DC_V_TIMING_1, value);
    value = (unsigned long) (pMode->vblankstart - 1) |
        (((unsigned long) (pMode->vblankend - 1)) << 16);
    WRITE_REG32(DC_V_TIMING_2, value);
    value = (unsigned long) (pMode->vsyncstart - 1) |
        (((unsigned long) (pMode->vsyncend - 1)) << 16);
    WRITE_REG32(DC_V_TIMING_3, value);
    WRITE_REG32(DC_FP_V_TIMING, value);

    /* ALWAYS ENABLE "PANEL" DATA FROM MEDIAGX */
    /* That is really just the 18 BPP data bus to the companion chip */

    ocfg = DC_OCFG_PCKE | DC_OCFG_PDEL | DC_OCFG_PDEH;

    /* SET PIXEL FORMAT */

    if (bpp == 8) ocfg |= DC_OCFG_8BPP;
    else if (bpp == 15) ocfg |= DC_OCFG_555;

    /* ENABLE TIMING GENERATOR, SYNCS, AND FP DATA */

    tcfg = DC_TCFG_FPPE | DC_TCFG_HSYE | DC_TCFG_VSYE | DC_TCFG_BLKE |
        DC_TCFG_TGEN;

    /* SET FIFO PRIORITY, DCLK MULTIPLIER, AND FIFO ENABLE */
    /* Always 6/5 for FIFO, 2x for DCLK multiplier. */

    gcfg = 0x0006501;

    /* SET DOT CLOCK MULTIPLIER */
    /* Bit 31 of frequency indicates divide frequency by two */

    if (pMode->frequency & 0x80000000) gcfg |= 0x0040;
    else gcfg |= 0x0080;

    gcfg |= DC_GCFG_VRDY;

    WRITE_REG32(DC_OUTPUT_CFG, ocfg);
    WRITE_REG32(DC_TIMING_CFG, tcfg);
    gfx_delay_milliseconds(1); /* delay after TIMING_CFG */ 
    WRITE_REG32(DC_GENERAL_CFG, gcfg);

    /* DISABLE VIDEO OUTPUT FROM THE CS5530 */
    /* Same register in SC1400 */

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

    /* ENABLE DISPLAY OUTPUT FROM CX5530 */

    dcfg = 0x0029002F;

    /* SET APPROPRIATE SYNC POLARITIES */

    if (pMode->flags & GFX_MODE_NEG_HSYNC)
        dcfg |= 0x00000100;
    if (pMode->flags & GFX_MODE_NEG_VSYNC)
        dcfg |= 0x00000200;
    
    WRITE_VID32(CS5530_DISPLAY_CONFIG, dcfg);

    /* RESTORE VALUE OF DC_UNLOCK */

    WRITE_REG32(DC_UNLOCK, unlock);

    /* ALSO WRITE GP_BLIT_STATUS FOR PITCH AND 8/18 BPP */

    value = 0;
    if (bpp > 8) value |= BC_16BPP;
    if (pitch > 1024) value |= BC_FB_WIDTH_2048;
    WRITE_REG16(GP_BLIT_STATUS, (unsigned short) value);    
    return;

} /* end gfx_set_specified_mode() */

/*----------------------------------------------------------------------------
 * GFX_SET_DISPLAY_MODE
 *
 * This routine sets the specified display mode.
 *
 * Returns 1 if successful, 0 if mode could not be set.
 *----------------------------------------------------------------------------  
 */
#if GFX_DISPLAY_DYNAMIC
int gu1_set_display_mode(int xres, int yres, int bpp, int hz)
#else
int gfx_set_display_mode(int xres, int yres, int bpp, int hz)
#endif
{
    int mode;
    unsigned long hz_flag = 0, bpp_flag = 0;

    /* SET FLAGS TO MATCH REFRESH RATE */

    if (hz == 60) hz_flag = GFX_MODE_60HZ;
    if (hz == 75) hz_flag = GFX_MODE_75HZ;
    if (hz == 85) hz_flag = GFX_MODE_85HZ;

    /* SET BPP FLAGS TO LIMIT MODE SELECTION */

    bpp_flag = GFX_MODE_8BPP;
    if (bpp > 8) bpp_flag = GFX_MODE_16BPP;

    /* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */

    for (mode = 0; mode < NUM_DISPLAY_MODES; mode++) {
        if ((DisplayParams[mode].hactive == xres) &&
            (DisplayParams[mode].vactive == yres) &&
            (DisplayParams[mode].flags & hz_flag) &&
            (DisplayParams[mode].flags & bpp_flag)) {

            /* SET THE DISPLAY CONTROLLER FOR THE SELECTED MODE */

            gu1_set_specified_mode(&DisplayParams[mode], bpp);
            return(1);
            }
        } 
    return(0);
} 

DISPLAYMODE gfx_display_mode;

/*----------------------------------------------------------------------------
 * GFX_SET_DISPLAY_TIMINGS
 *
 * This routine sets the display controller mode using the specified timing
 * values (as opposed to using the tables internal to Durango).
 *
 * Always returns 0.
 *----------------------------------------------------------------------------  
 */
#if GFX_DISPLAY_DYNAMIC
int gu1_set_display_timings(unsigned short bpp, unsigned short flags, 
    unsigned short hactive, unsigned short hblankstart, 
    unsigned short hsyncstart, unsigned short hsyncend,
    unsigned short hblankend, unsigned short htotal,
    unsigned short vactive, unsigned short vblankstart, 
    unsigned short vsyncstart, unsigned short vsyncend,
    unsigned short vblankend, unsigned short vtotal,
    unsigned long frequency)
#else
int gfx_set_display_timings(unsigned short bpp, unsigned short flags, 
    unsigned short hactive, unsigned short hblankstart, 
    unsigned short hsyncstart, unsigned short hsyncend,
    unsigned short hblankend, unsigned short htotal,
    unsigned short vactive, unsigned short vblankstart, 
    unsigned short vsyncstart, unsigned short vsyncend,
    unsigned short vblankend, unsigned short vtotal,
    unsigned long frequency)
#endif
{
    /* SET MODE STRUCTURE WITH SPECIFIED VALUES */

    gfx_display_mode.flags = 0;
    if (flags & 1) gfx_display_mode.flags |= GFX_MODE_NEG_HSYNC;
    if (flags & 2) gfx_display_mode.flags |= GFX_MODE_NEG_VSYNC;
    gfx_display_mode.hactive = hactive;
    gfx_display_mode.hblankstart = hblankstart;
    gfx_display_mode.hsyncstart = hsyncstart;
    gfx_display_mode.hsyncend = hsyncend;
    gfx_display_mode.hblankend = hblankend;
    gfx_display_mode.htotal = htotal;
    gfx_display_mode.vactive = vactive;
    gfx_display_mode.vblankstart = vblankstart;
    gfx_display_mode.vsyncstart = vsyncstart;
    gfx_display_mode.vsyncend = vsyncend;
    gfx_display_mode.vblankend = vblankend;
    gfx_display_mode.vtotal = vtotal;
    gfx_display_mode.frequency = frequency;

    /* CALL ROUTINE TO SET MODE */

    gu1_set_specified_mode(&gfx_display_mode, bpp);
    return(0);
}

/*---------------------------------------------------------------------------
 * gfx_get_display_pitch
 *
 * This routine returns the current pitch of the frame buffer, in bytes.
 *---------------------------------------------------------------------------
 */
#if GFX_DISPLAY_DYNAMIC
unsigned short gu1_get_display_pitch(void)
#else
unsigned short gfx_get_display_pitch(void)
#endif
{
    unsigned long value;
    value = (READ_REG32(DC_LINE_DELTA) & 0x03FF) << 2;
    return((unsigned short) value);
}

/*---------------------------------------------------------------------------
 * gfx_set_display_pitch
 *
 * This routine sets the pitch of the frame buffer to the specified value.
 *---------------------------------------------------------------------------
 */
#if GFX_DISPLAY_DYNAMIC
void gu1_set_display_pitch(unsigned short pitch)
#else
void gfx_set_display_pitch(unsigned short pitch)
#endif
{
    unsigned long value, lock;
    value = (READ_REG32(DC_LINE_DELTA) & 0xFFFFF000);
    value |= (pitch >> 2);
    lock = READ_REG32(DC_UNLOCK);
    WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
    WRITE_REG32(DC_LINE_DELTA, value);
    WRITE_REG32(DC_UNLOCK, lock);

    /* ALSO UPDATE PITCH IN GRAPHICS ENGINE */

    value = (unsigned long) READ_REG16(GP_BLIT_STATUS);
    if (pitch > 1024) value |= BC_FB_WIDTH_2048;
    else value &= ~(BC_FB_WIDTH_2048);
    WRITE_REG16(GP_BLIT_STATUS, (unsigned short) value);    
    return;

⌨️ 快捷键说明

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