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

📄 cim_vg.c

📁 LX 800 WindowsCE 6.0 BSP
💻 C
📖 第 1 页 / 共 5 页
字号:
        tv_mode.mode_height  = tv_mode.vactive;

		return vg_set_custom_mode (&tv_mode, bpp);
	}
	return CIM_STATUS_ERROR;
}

/*---------------------------------------------------------------------------
 * vg_set_custom_mode
 *
 * This routine sets a display mode.  The API is structured such that this routine
 * can be called from four sources:
 *   - vg_set_display_mode
 *   - vg_set_panel_mode
 *   - vg_set_tv_mode
 *   - directly by the user for a custom mode.
 *---------------------------------------------------------------------------*/

int vg_set_custom_mode (VG_DISPLAY_MODE *mode_params, int bpp)
{
	unsigned long config, misc, temp;
    unsigned long irq_ctl, genlk_ctl;
	unsigned long unlock, flags;
	unsigned long acfg, gcfg, dcfg;
	unsigned long size, line_size, pitch;
	unsigned long bpp_mask, dv_size;
	unsigned long hscale, vscale, starting_width;
    unsigned long starting_height, output_height;
    Q_WORD msr_value;

    /* DETERMINE DIMENSIONS FOR SCALING */
    /* Scaling is performed before flicker filtering and interlacing */

    output_height = mode_params->vactive;

    if (mode_params->flags & VG_MODEFLAG_INTERLACED)
    {
        /* EVEN AND ODD FIELDS ARE SEPARATE */
        /* The composite image height is the sum of the height of both fields */

        if ((mode_params->flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_FLICKER ||
            (mode_params->flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_ADDRESS)
        {
            output_height += mode_params->vactive_even;
        }

        /* LINE DOUBLING */
        /* The composite image height is the greater of the two field heights. */

        else if (mode_params->vactive_even > output_height)
            output_height = mode_params->vactive_even;
    }

	/* CHECK FOR VALID SCALING FACTOR */
	/* GeodeLX supports only 2:1 vertical downscale (before interlacing) and */
	/* 2:1 horizontal downscale.  The source width when scaling must be      */
    /* less than or equal to 1024 pixels.  The destination can be any size,  */
    /* except when flicker filtering is enabled.                             */

    irq_ctl = 0;
    if (mode_params->flags & VG_MODEFLAG_PANELOUT)
    {
        if (mode_params->src_width != mode_params->mode_width)
	    {
            starting_width = (mode_params->hactive * mode_params->src_width) / mode_params->mode_width;
		    hscale = (mode_params->src_width << 14) / (mode_params->mode_width - 1);
		    irq_ctl |= (DC3_IRQFILT_ALPHA_FILT_EN | DC3_IRQFILT_GFX_FILT_EN);
	    }
	    else
	    {
            starting_width = mode_params->hactive;
		    hscale = 0x4000;
	    }
	    if (mode_params->src_height != mode_params->mode_height)
	    {
            starting_height = (output_height * mode_params->src_height) / mode_params->mode_height;
		    vscale = (mode_params->src_height << 14) / (mode_params->mode_height - 1);
		    irq_ctl |= (DC3_IRQFILT_ALPHA_FILT_EN | DC3_IRQFILT_GFX_FILT_EN);
	    }
	    else
	    {
            starting_height = output_height;
		    vscale = 0x4000;
	    }
    }
    else
    {
        starting_width  = mode_params->src_width;
        starting_height = mode_params->src_height;
	    if (mode_params->src_width != mode_params->hactive)
	    {
		    hscale = (mode_params->src_width << 14) / (mode_params->hactive - 1);
		    irq_ctl |= (DC3_IRQFILT_ALPHA_FILT_EN | DC3_IRQFILT_GFX_FILT_EN);
	    }
	    else
	    {
		    hscale = 0x4000;
	    }
	    if (mode_params->src_height != output_height)
	    {
		    vscale = (mode_params->src_height << 14) / (output_height - 1);
		    irq_ctl |= (DC3_IRQFILT_ALPHA_FILT_EN | DC3_IRQFILT_GFX_FILT_EN);
	    }
	    else
	    {
		    vscale = 0x4000;
	    }
    }

    starting_width = (starting_width + 7) & 0xFFFF8;

    if (mode_params->hactive < (starting_width  >> 1) ||
        output_height < (starting_height >> 1)        ||
       (irq_ctl && (starting_width > 1024)))
    {
        return CIM_STATUS_INVALIDSCALE;
    }

    /* VERIFY INTERLACED SCALING */
    /* The output width must be less than or equal to 1024 pixels when the */
    /* flicker filter is enabled.  Also, scaling should be disabled when   */
    /* the interlacing mode is set to interlaced addressing.               */

    if (mode_params->flags & VG_MODEFLAG_INTERLACED)
    {
        if ((((mode_params->flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_FLICKER) &&
               (mode_params->hactive > 1024))                                                 ||
            (((mode_params->flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_ADDRESS) && irq_ctl))
        {
            return CIM_STATUS_INVALIDSCALE;
        }
    }
			
	/* CHECK FOR VALID BPP */
	
	switch (bpp)
	{
		case 8:  bpp_mask = DC3_DCFG_DISP_MODE_8BPP;  break;
	    case 24: bpp_mask = DC3_DCFG_DISP_MODE_24BPP; break;
		case 32: bpp_mask = DC3_DCFG_DISP_MODE_32BPP; break;
		case 12: bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_12BPP; break;
		case 15: bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_15BPP; break;
		case 16: bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_16BPP; break;
		default: return CIM_STATUS_INVALIDPARAMS;
	}

	vg3_bpp = bpp;

	/* CLEAR PANNING OFFSETS */

	vg3_delta_x = 0;
	vg3_delta_y = 0;

	/* SAVE PANEL PARAMETERS */

	if (mode_params->flags & VG_MODEFLAG_PANELOUT)
	{
		vg3_panel_enable = 1;
		vg3_panel_width  = mode_params->panel_width;
		vg3_panel_height = mode_params->panel_height;
		vg3_mode_width   = mode_params->mode_width;
		vg3_mode_height  = mode_params->mode_height;

        /* INVERT THE SHIFT CLOCK IF REQUESTED */
        /* Note that we avoid writing the power management register if */
        /* we can help it.                                             */

        temp = READ_VID32 (DF_POWER_MANAGEMENT);
        if ((mode_params->flags & VG_MODEFLAG_INVERT_SHFCLK) &&
           !(temp & DF_PM_INVERT_SHFCLK))
        {
            WRITE_VID32 (DF_POWER_MANAGEMENT, (temp | DF_PM_INVERT_SHFCLK));
        }
        else if (!(mode_params->flags & VG_MODEFLAG_INVERT_SHFCLK) &&
                  (temp & DF_PM_INVERT_SHFCLK))
        {
            WRITE_VID32 (DF_POWER_MANAGEMENT, (temp & ~DF_PM_INVERT_SHFCLK));
        }

        /* SET PANEL TIMING VALUES */

        if (!(mode_params->flags & VG_MODEFLAG_NOPANELTIMINGS))
        {
            unsigned long pmtim1, pmtim2, dith_ctl;

            if (mode_params->flags & VG_MODEFLAG_XVGA_TFT)
            {
                pmtim1   = DF_DEFAULT_XVGA_PMTIM1;
                pmtim2   = DF_DEFAULT_XVGA_PMTIM2;
                dith_ctl = DF_DEFAULT_DITHCTL;
                msr_value.low  = DF_DEFAULT_XVGA_PAD_SEL_LOW;
                msr_value.high = DF_DEFAULT_XVGA_PAD_SEL_HIGH;
            }
            else if (mode_params->flags & VG_MODEFLAG_CUSTOM_PANEL)
            {
                pmtim1   = mode_params->panel_tim1;
                pmtim2   = mode_params->panel_tim2;
                dith_ctl = mode_params->panel_dither_ctl;
                msr_value.low  = mode_params->panel_pad_sel_low;
                msr_value.high = mode_params->panel_pad_sel_high;
            }
            else
            {
                pmtim1   = DF_DEFAULT_TFT_PMTIM1;
                pmtim2   = DF_DEFAULT_TFT_PMTIM2;
                dith_ctl = DF_DEFAULT_DITHCTL;
                msr_value.low  = DF_DEFAULT_TFT_PAD_SEL_LOW;
                msr_value.high = DF_DEFAULT_TFT_PAD_SEL_HIGH;

            }
            WRITE_VID32 (DF_VIDEO_PANEL_TIM1, pmtim1);
            WRITE_VID32 (DF_VIDEO_PANEL_TIM2, pmtim2);
            WRITE_VID32 (DF_DITHER_CONTROL, dith_ctl);
            msr_write64 (MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, &msr_value);
        }

        /* SET APPROPRIATE PANEL OUTPUT MODE */

        msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);

        msr_value.low &= ~DF_CONFIG_OUTPUT_MASK;
        msr_value.low |=  DF_OUTPUT_PANEL;
        if (mode_params->flags & VG_MODEFLAG_CRT_AND_FP)
            msr_value.low |=  DF_SIMULTANEOUS_CRT_FP;
        else
            msr_value.low &= ~DF_SIMULTANEOUS_CRT_FP;

        msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);

	}
    else if (mode_params->flags & VG_MODEFLAG_TVOUT)
    {
        vg3_panel_enable = 0;

        /* SET APPROPRIATE TV OUTPUT MODE */

        msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);

        msr_value.low &= ~DF_CONFIG_OUTPUT_MASK;
        msr_value.low |=  DF_OUTPUT_PANEL;
        if (mode_params->flags & VG_MODEFLAG_CRT_AND_FP)
            msr_value.low |=  DF_SIMULTANEOUS_CRT_FP;
        else
            msr_value.low &= ~DF_SIMULTANEOUS_CRT_FP;

        msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);

        /* CONFIGURE PADS FOR VOP OUTPUT */
        /* Note that the VOP clock is currently always inverted. */

        msr_value.low  = DF_DEFAULT_TV_PAD_SEL_LOW;
        msr_value.high = DF_DEFAULT_TV_PAD_SEL_HIGH;
        msr_write64 (MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, &msr_value);
    }
	else
    {
		vg3_panel_enable = 0;

        /* SET OUTPUT TO CRT ONLY */

        msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
        msr_value.low &= ~DF_CONFIG_OUTPUT_MASK;
        msr_value.low |=  DF_OUTPUT_CRT;
        msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
    }

	/* SET UNLOCK VALUE */

	unlock = READ_REG32 (DC3_UNLOCK);
	WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);

    /*-------------------------------------------------------------------*/
    /* MAKE THE SYSTEM "SAFE"                                            */
    /* Before setting a mode, we first ensure that the system is in a    */
    /* benign quiescent state.  This involves disabling compression and  */
    /* all interrupt sources.  It also involves terminating all accesses */
    /* to memory, including video, FIFO load, VIP and the GP.            */
    /*-------------------------------------------------------------------*/

    /* DISABLE VGA */
    /* VGA *MUST* be turned off before TGEN is enabled.  If not, a condition */
    /* will result where VGA Enable is waiting for a VSync to be latched but */
    /* a VSync will not be generated until VGA is disabled.                  */
	
    temp = READ_REG32 (DC3_GENERAL_CFG) & ~DC3_GCFG_VGAE;
	
    /* DISABLE VIDEO (INCLUDING ALPHA WINDOWS) */

	WRITE_VID32 (DF_ALPHA_CONTROL_1, 0);
	WRITE_VID32 (DF_ALPHA_CONTROL_1 + 32, 0);
	WRITE_VID32 (DF_ALPHA_CONTROL_1 + 64, 0);
	
	WRITE_REG32 (DC3_GENERAL_CFG, (temp & ~DC3_GCFG_VIDE));
	temp = READ_VID32 (DF_VIDEO_CONFIG);
	WRITE_VID32 (DF_VIDEO_CONFIG, (temp & ~DF_VCFG_VID_EN));

    /* DISABLE VG INTERRUPTS */

    WRITE_REG32 (DC3_IRQ, DC3_IRQ_MASK | DC3_VSYNC_IRQ_MASK |
        DC3_IRQ_STATUS | DC3_VSYNC_IRQ_STATUS);

    /* DISABLE GENLOCK */

    genlk_ctl = READ_REG32 (DC3_GENLK_CTL);
    WRITE_REG32 (DC3_GENLK_CTL, (genlk_ctl & ~DC3_GC_GENLOCK_ENABLE));

    /* DISABLE VIP CAPTURE AND VIP INTERRUPTS */

    WRITE_VIP32 (VIP_CONTROL1, 0);
    WRITE_VIP32 (VIP_CONTROL2, 0);
    WRITE_VIP32 (VIP_INTERRUPT, VIP_ALL_INTERRUPTS | (VIP_ALL_INTERRUPTS >> 16));

    /* DISABLE COLOR KEYING */
    /* The color key mechanism should be disabled whenever a mode switch occurs. */

    temp = READ_REG32 (DC3_COLOR_KEY);
    WRITE_REG32 (DC3_COLOR_KEY, (temp & ~DC3_CLR_KEY_ENABLE));
	
    /* BLANK THE DISPLAY */
    /* Note that we never blank the panel.  Most flat panels have very long      */
    /* latency requirements when setting their power low.  Some panels require   */
    /* upwards of 500ms before VDD goes high again.  Needless to say, we are not */
    /* planning to take over one half a second inside this routine.              */

	misc   = READ_VID32 (DF_VID_MISC);
	config = READ_VID32 (DF_DISPLAY_CONFIG);
	
	WRITE_VID32 (DF_VID_MISC, (misc | DF_DAC_POWER_DOWN));
	WRITE_VID32 (DF_DISPLAY_CONFIG, (config & ~(DF_DCFG_DIS_EN   | DF_DCFG_HSYNC_EN |
		DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN)));

	/* DISABLE COMPRESSION  */

	gcfg = READ_REG32 (DC3_GENERAL_CFG);
	gcfg &= ~(DC3_GCFG_CMPE | DC3_GCFG_DECE);
	WRITE_REG32 (DC3_GENERAL_CFG, gcfg);

	/* DISABLE THE TIMING GENERATOR */

	dcfg = READ_REG32 (DC3_DISPLAY_CFG);
    dcfg &= ~DC3_DCFG_TGEN;
    WRITE_REG32 (DC3_DISPLAY_CFG, dcfg);
	
	/* WAIT FOR PENDING MEMORY REQUESTS */
	
	vg_delay_milliseconds(1);

    /* DISABLE DISPLAY FIFO LOAD */

    gcfg &= ~DC3_GCFG_DFLE;
    WRITE_REG32 (DC3_GENERAL_CFG, gcfg);
	gcfg = 0;
	dcfg = 0;

    /* WAIT FOR THE GP TO BE IDLE (JUST IN CASE) */

    while (((temp = READ_GP32 (GP3_BLT_STATUS)) & GP3_BS_BLT_BUSY) ||

⌨️ 快捷键说明

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