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

📄 cim_vg.c

📁 LX 800 WindowsCE 6.0 BSP
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* We assume the input frequency is 48 MHz, which is represented   */
		/* in 16.16 fixed point as 0x300000. The PLL calculation is:       */
		/*                             n + 1                               */
		/*   Fout =  48.000   *    --------------                          */
		/*                         m + 1   *  p + 1                        */

        p =  msr_value.high & 0xF;
	    n = (msr_value.high >> 4)  & 0xFF;
	    m = (msr_value.high >> 12) & 0x7;
		current_display->frequency = (0x300000 * (n + 1)) / ((p + 1) * (m + 1));

		return CIM_STATUS_INEXACTMATCH;
	}

	current_display->frequency = CimarronPLLFrequencies[i].frequency;

	/* NOW SEARCH FOR AN IDENTICAL MODE */
	/* This is just to inform the user that an exact match was found.   */
	/* With an exact match, the user can use the refresh rate flag that */
	/* is returned in the VG_DISPLAY_MODE structure.                    */

	for (i = 0; i < NUM_CIMARRON_DISPLAY_MODES; i++)
	{
		if ((CimarronDisplayModes[i].flags & current_display->flags)             &&
			 CimarronDisplayModes[i].frequency   == current_display->frequency   &&
			 CimarronDisplayModes[i].hactive     == current_display->hactive     &&
			 CimarronDisplayModes[i].hblankstart == current_display->hblankstart &&
			 CimarronDisplayModes[i].hsyncstart  == current_display->hsyncstart  &&
			 CimarronDisplayModes[i].hsyncend    == current_display->hsyncend    &&
			 CimarronDisplayModes[i].hblankend   == current_display->hblankend   &&			
			 CimarronDisplayModes[i].htotal      == current_display->htotal      &&
			 CimarronDisplayModes[i].vactive     == current_display->vactive     &&
			 CimarronDisplayModes[i].vblankstart == current_display->vblankstart &&
			 CimarronDisplayModes[i].vsyncstart  == current_display->vsyncstart  &&
			 CimarronDisplayModes[i].vsyncend    == current_display->vsyncend    &&
			 CimarronDisplayModes[i].vblankend   == current_display->vblankend   &&			
			 CimarronDisplayModes[i].vtotal      == current_display->vtotal)
		{
			break;
		}
	}

	if (i == NUM_CIMARRON_DISPLAY_MODES)
		return CIM_STATUS_INEXACTMATCH;

	current_display->internal_flags |= (CimarronDisplayModes[i].internal_flags & VG_SUPPORTFLAG_HZMASK);
	return CIM_STATUS_OK;
}

/*---------------------------------------------------------------------------
 * vg_set_scaler_filter_coefficients
 *
 * This routine sets the vertical and horizontal filter coefficients for
 * graphics scaling.  If either of the input arrays is specified as NULL, a
 * set of default coeffecients will be used.
 *---------------------------------------------------------------------------*/

int vg_set_scaler_filter_coefficients (long h_taps[][5], long v_taps[][3])
{
	unsigned long irqfilt, i;
	unsigned long temp0, temp1;
    unsigned long lock;
	
	/* ENABLE ACCESS TO THE HORIZONTAL COEFFICIENTS */

	irqfilt  = READ_REG32 (DC3_IRQ_FILT_CTL);
	irqfilt |= DC3_IRQFILT_H_FILT_SEL;
	
    /* UNLOCK THE COEFFICIENT REGISTERS */

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

	/* WRITE COEFFICIENTS */
	/* Coefficient indexes do not auto-increment, so we must */
	/* write the address for every phase                     */

	for (i = 0; i < 256; i++)
	{
		WRITE_REG32 (DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i));

        if (!h_taps)
        {
            temp0 = CimarronHorizontalGraphicsFilter[i][0];
            temp1 = CimarronHorizontalGraphicsFilter[i][1];
        }
        else
        {
		    temp0 =  ((unsigned long)h_taps[i][0] & 0x3FF)        |
                    (((unsigned long)h_taps[i][1] & 0x3FF) << 10) |
                    (((unsigned long)h_taps[i][2] & 0x3FF) << 20);

		    temp1  = ((unsigned long)h_taps[i][3] & 0x3FF)        |
			        (((unsigned long)h_taps[i][4] & 0x3FF) << 10);
        }
        WRITE_REG32 (DC3_FILT_COEFF1, temp0);
        WRITE_REG32 (DC3_FILT_COEFF2, temp1);
	}

	/* ENABLE ACCESS TO THE VERTICAL COEFFICIENTS */

	irqfilt &= ~DC3_IRQFILT_H_FILT_SEL;

	/* WRITE COEFFICIENTS */

	for (i = 0; i < 256; i++)
	{
		WRITE_REG32 (DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i));

        if (!v_taps)
        {
            temp0 = CimarronVerticalGraphicsFilter[i];
        }
        else
        {
		    temp0 =  ((unsigned long)v_taps[i][0] & 0x3FF)        |
                    (((unsigned long)v_taps[i][1] & 0x3FF) << 10) |
                    (((unsigned long)v_taps[i][2] & 0x3FF) << 20);
        }

		WRITE_REG32 (DC3_FILT_COEFF1, temp0);
	}

    WRITE_REG32 (DC3_UNLOCK, lock);

	return CIM_STATUS_OK;
}

/*---------------------------------------------------------------------------
 * vg_configure_flicker_filter
 *
 * This routine updates the VG flicker filter settings when in an interlaced
 * mode.  Note that flicker filtering is enabled inside a mode set.  This routine
 * is provided to change from the default flicker filter setting of
 * 1/4, 1/2, 1/4.
 *---------------------------------------------------------------------------*/

int vg_configure_flicker_filter (unsigned long flicker_strength, int flicker_alpha)
{
    unsigned long unlock;
    unsigned long genlk_ctl;

    /* CHECK FOR VALID FLICKER SETTING */

    if (flicker_strength != VG_FLICKER_FILTER_NONE &&
        flicker_strength != VG_FLICKER_FILTER_1_16 &&
        flicker_strength != VG_FLICKER_FILTER_1_8  &&
        flicker_strength != VG_FLICKER_FILTER_1_4  &&
        flicker_strength != VG_FLICKER_FILTER_5_16)
    {
        return CIM_STATUS_INVALIDPARAMS;
    }

    unlock = READ_REG32 (DC3_UNLOCK);
    genlk_ctl  = READ_REG32 (DC3_GENLK_CTL) & ~(DC3_GC_FLICKER_FILTER_MASK | DC3_GC_ALPHA_FLICK_ENABLE);
    genlk_ctl |= flicker_strength;
    if (flicker_alpha)
        genlk_ctl |= DC3_GC_ALPHA_FLICK_ENABLE;

    WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
    WRITE_REG32 (DC3_GENLK_CTL, genlk_ctl);
    WRITE_REG32 (DC3_UNLOCK, unlock);

	return CIM_STATUS_OK;
}

/*---------------------------------------------------------------------------
 * vg_set_clock_frequency
 *
 * This routine sets the frequency of the dot clock.  The input to this routine
 * is a 16.16 fraction.  If an exact match is not found, this routine will program
 * the closest available frequency and return CIM_STATUS_INEXACTMATCH.
 *---------------------------------------------------------------------------*/

int vg_set_clock_frequency (unsigned long frequency, unsigned long pll_flags)
{
	Q_WORD msr_value;
	unsigned long timeout;
	unsigned long index = 0;
	unsigned long unlock, i;
    unsigned long pll_high, pll_low;
	long diff, min = 0;

	/* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY         */
	/* Search the table for the closest frequency (16.16 format). */
    /* This search is skipped if the user is manually specifying  */
    /* the MSR value.                                             */

    pll_low  = 0;
    if (!(pll_flags & VG_PLL_MANUAL))
    {
	    min = (long)CimarronPLLFrequencies[0].frequency - (long)frequency;
	    if (min < 0L)
		    min = -min;

	    for (i = 1; i < NUM_CIMARRON_PLL_FREQUENCIES; i++)
	    {
		    diff = (long)CimarronPLLFrequencies[i].frequency - (long)frequency;
		    if (diff < 0L)
			    diff = -diff;

		    if (diff < min)
		    {
			    min = diff;
			    index = i;
		    }
	    }

        pll_high = CimarronPLLFrequencies[index].pll_value & 0x00007FFF;
    }
    else
    {
        pll_high = frequency;
    }

    if (pll_flags & VG_PLL_DIVIDE_BY_2)
		pll_low |= GLCP_DOTPLL_HALFPIX;
	if (pll_flags & VG_PLL_DIVIDE_BY_4)
		pll_high |= GLCP_DOTPLL_DIV4;
    if (pll_flags & VG_PLL_BYPASS)
        pll_low |= GLCP_DOTPLL_BYPASS;
    if (pll_flags & VG_PLL_VIP_CLOCK)
        pll_high |= GLCP_DOTPLL_VIPCLK;

	/* VERIFY THAT WE ARE NOT WRITING WHAT IS ALREADY IN THE REGISTERS */
    /* The Dot PLL reset bit is tied to VDD for flat panels.  This can */
    /* cause a brief drop in flat panel power, which can cause serious */
    /* glitches on some panels.                                        */

	msr_read64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value);

    if ((msr_value.low & GLCP_DOTPLL_LOCK) &&
       ((msr_value.low & (GLCP_DOTPLL_HALFPIX | GLCP_DOTPLL_BYPASS)) == pll_low) &&
        (msr_value.high == pll_high))
    {
        return CIM_STATUS_OK;
    }

    /* PROGRAM THE SETTINGS WITH THE RESET BIT SET */
	/* Clear the bypass bit to ensure that the programmed */
	/* M, N and P values are being used.                  */

    msr_value.high = pll_high;
	msr_value.low &= ~(GLCP_DOTPLL_BYPASS | GLCP_DOTPLL_HALFPIX);
    msr_value.low |=  (pll_low | 0x00000001);
	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value);

    /* WAIT FOR THE LOCK BIT */
    /* The PLL spec states that the PLL may take up to 100 us to */
    /* properly lock.  Furthermore, the lock signal is not 100%  */
    /* reliable.  To address this, we add a hefty delay followed */
    /* by a polling loop that times out after a 1000 reads.      */

    unlock = READ_REG32 (DC3_UNLOCK);
    for (timeout = 0; timeout < 1280; timeout++)
        WRITE_REG32 (DC3_UNLOCK, unlock);

    for (timeout = 0; timeout < 1000; timeout++)
    {
        msr_read64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value);
        if (msr_value.low & GLCP_DOTPLL_LOCK)
            break;
    }

    /* CLEAR THE RESET BIT */

	msr_value.low &= 0xFFFFFFFE;
	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value);

	/* DID THE PLL SUCCESSFULLY LOCK? */

	if (!(msr_value.low & GLCP_DOTPLL_LOCK))
		return CIM_STATUS_NOLOCK;

	/* RETURN THE APPROPRIATE CODE */

	if (min == 0)
		return CIM_STATUS_OK;
	else
		return CIM_STATUS_INEXACTMATCH;
}

/*---------------------------------------------------------------------------
 * vg_set_border_color
 *
 * This routine sets the color used as the border in centered panel modes.
 *---------------------------------------------------------------------------*/

int vg_set_border_color (unsigned long border_color)
{
    unsigned long lock = READ_REG32 (DC3_UNLOCK);

    WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
	WRITE_REG32 (DC3_PAL_ADDRESS, 0x104);
	WRITE_REG32 (DC3_PAL_DATA, border_color);
    WRITE_REG32 (DC3_UNLOCK, lock);

	return CIM_STATUS_OK;
}

/*---------------------------------------------------------------------------
 * vg_set_cursor_enable
 *
 * This routine enables or disables the hardware cursor.  This routine should
 * only be called after the hardware cursor has been completely configured.
 *---------------------------------------------------------------------------*/

int vg_set_cursor_enable(int enable)
{
    unsigned long unlock, gcfg;
	
	/* SET OR CLEAR CURSOR ENABLE BIT */

	unlock = READ_REG32(DC3_UNLOCK);
	gcfg   = READ_REG32(DC3_GENERAL_CFG);
	if (enable) gcfg |=   DC3_GCFG_CURE;
	else        gcfg &= ~(DC3_GCFG_CURE);	

	/* WRITE NEW REGISTER VALUE */

	WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
	WRITE_REG32 (DC3_GENERAL_CFG, gcfg);
	WRITE_REG32 (DC3_UNLOCK, unlock);

	return CIM_STATUS_OK;
}

/*---------------------------------------------------------------------------
 * vg_set_mono_cursor_colors
 *
 * This routine sets the colors of the hardware monochrome cursor.
 *---------------------------------------------------------------------------*/

int vg_set_mono_cursor_colors (unsigned long bkcolor, unsigned long fgcolor)
{
    unsigned long lock = READ_REG32 (DC3_UNLOCK);

	/* SET CURSOR COLORS */

    WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
	WRITE_REG32 (DC3_PAL_ADDRESS, 0x100);
	WRITE_REG32 (DC3_PAL_DATA, bkcolor);
	WRITE_REG32 (DC3_PAL_DATA, fgcolor);
    WRITE_REG32 (DC3_UNLOCK, lock);

	return CIM_STATUS_OK;
}

/*---------------------------------------------------------------------------
 * vg_set_cursor_position
 *
 * This routine sets the position of the hardware cursor.  The cursor hotspots
 * and memory offset must have been specified in an earlier call to
 * a vg_set_cursor_

⌨️ 快捷键说明

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