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

📄 cim_vop.c

📁 LX 800 WindowsCE 6.0 BSP
💻 C
📖 第 1 页 / 共 2 页
字号:
 /*
  * <LIC_AMD_STD>
  * Copyright (C) 2005 Advanced Micro Devices, Inc.  All Rights Reserved.
  * </LIC_AMD_STD>
  *
  * <CTL_AMD_STD>
  * </CTL_AMD_STD>
  *
  * <DOC_AMD_STD>
  * Cimarron VOP configuration routines.
  * </DOC_AMD_STD>
  *
  */

/*---------------------------------------------------------------------------
 * vop_set_vbi_window
 *
 * This routine configures the output position and location in memory of
 * VBI data.
 *---------------------------------------------------------------------------*/

int vop_set_vbi_window (VOPVBIWINDOWBUFFER *buffer)
{
    unsigned long unlock, temp;
    unsigned long hstart, hstop;
    unsigned long htotal, hsyncstart;

    if (!buffer)
        return CIM_STATUS_INVALIDPARAMS;	

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

    /* PROGRAM HORIZONTAL POSITION */
    /* The horizontal position is a little tricky.  The counter for the horizontal    */
    /* timings is reused for the VBI counter.  Consequently, the horizontal start     */
    /* and stop values are based off the beginning of active data.  However, the      */
    /* VG has a quirk.  If the counter start position is before the beginning of      */
    /* HSync, it applies to the previous line.  If the counter is after the           */
    /* beginning of HSync it applies to the current line.  So, for one line           */
    /* the real range can be thought of as HSync_start to (HSync_start + htotal - 1). */
    /* However, the counters must be between 0 and htotal - 1.  When placing VBI      */
    /* data before the start of active data, the horizontal end position will thus    */
    /* be *less* than the horizontal start.                                           */

    htotal     = ((READ_REG32 (DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
    hsyncstart =  (READ_REG32 (DC3_H_SYNC_TIMING) & 0xFFF) + 1;

    if (buffer->horz_from_hsync)
    {
        /* VERIFY THAT THE INPUT IS VALID */

        if (buffer->horz_start < 0 || (buffer->horz_start + buffer->vbi_width) > htotal)
            return CIM_STATUS_INVALIDPARAMS;

        hstart = buffer->horz_start + hsyncstart;
    }
    else
    {
        /* VERIFY THAT THE INPUT IS VALID */

        if (buffer->horz_start < ((long)hsyncstart - (long)htotal) ||
            buffer->horz_start > (long)hsyncstart ||
            buffer->vbi_width > htotal)
        {
            return CIM_STATUS_INVALIDPARAMS;
        }

        hstart = buffer->horz_start + htotal;
    }

    hstop = hstart + buffer->vbi_width;
    if (hstart > htotal) hstart -= htotal;
    if (hstop  > htotal) hstop  -= htotal;
    hstart--;
    hstop--;
	WRITE_REG32 (DC3_VBI_HOR, ((hstop << DC3_VBI_HOR_END_SHIFT) & DC3_VBI_HOR_END_MASK) |
        (hstart & DC3_VBI_HOR_START_MASK));
	
    /* WRITE LINE CAPTURE MASKS */

	WRITE_REG32 (DC3_VBI_LN_ODD, ((buffer->odd_line_offset << DC3_VBI_ODD_LINE_SHIFT) & DC3_VBI_ODD_LINE_MASK) |
        (buffer->odd_line_capture_mask & DC3_VBI_ODD_ENABLE_MASK));

    WRITE_REG32 (DC3_VBI_LN_EVEN, ((buffer->even_line_offset << DC3_VBI_EVEN_LINE_SHIFT) & DC3_VBI_EVEN_LINE_MASK) |
        (buffer->even_line_capture_mask & DC3_VBI_EVEN_ENABLE_MASK));

	/* PROGRAM SOURCE OFFSETS */
    /* Start with the even offsets.  Note that we always enable 16-bit VBI, as this */
    /* is the only way to get VBI data on each VOP clock.                           */

	temp  = READ_REG32 (DC3_VBI_EVEN_CTL) & ~DC3_VBI_EVEN_CTL_OFFSET_MASK;
    temp |= DC3_VBI_EVEN_CTL_ENABLE_16;
    if (buffer->enable_upscale)
        temp |= DC3_VBI_EVEN_CTL_UPSCALE;
	WRITE_REG32 (DC3_VBI_EVEN_CTL, temp | (buffer->even_address_offset & DC3_VBI_EVEN_CTL_OFFSET_MASK));
	
    /* ODD OFFSET */

	temp = READ_REG32 (DC3_VBI_ODD_CTL) & ~DC3_VBI_ODD_CTL_OFFSET_MASK;
	WRITE_REG32 (DC3_VBI_ODD_CTL, temp | (buffer->odd_address_offset & DC3_VBI_ODD_CTL_OFFSET_MASK));
	
    /* PITCH */

	temp = ((buffer->data_size >> 3) << 16) | ((buffer->data_pitch >> 3) & 0x0000FFFF);
	WRITE_REG32(DC3_VBI_PITCH, temp);
	
    WRITE_REG32 (DC3_UNLOCK, unlock);

	return CIM_STATUS_OK;
}

/*---------------------------------------------------------------------------
 * vop_enable_vbi_output
 *
 * This routine enables/disables VBI fetching inside the video generator.
 *---------------------------------------------------------------------------*/

int vop_enable_vbi_output (int enable)
{
	unsigned long unlock, temp;

    unlock = READ_REG32 (DC3_UNLOCK);
    temp   = READ_REG32 (DC3_VBI_EVEN_CTL);

	if (enable) temp |=  DC3_VBI_ENABLE;
	else        temp &= ~DC3_VBI_ENABLE;
	
    WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
	WRITE_REG32 (DC3_VBI_EVEN_CTL, temp);
    WRITE_REG32 (DC3_UNLOCK, unlock);

    return CIM_STATUS_OK;
}

/*---------------------------------------------------------------------------
 * vop_set_configuration
 *
 * This routine is passed a VOP_CONFIGURATION structure that contains all
 * the necessary information to configure VOP output.
 *---------------------------------------------------------------------------*/

int vop_set_configuration (VOPCONFIGURATIONBUFFER *config)
{
    unsigned long vop_config = 0;
    unsigned long alpha, control2;
    unsigned long unlock;
    unsigned long delta;
    Q_WORD msr_value;
    int rgb = 0;
		
    if (!config)
        return CIM_STATUS_INVALIDPARAMS;

    unlock = READ_REG32 (DC3_UNLOCK);
    delta  = READ_REG32 (DC3_VID_DS_DELTA) & DC3_DS_DELTA_MASK;

    /* OVERRIDE THE OUTPUT SETTINGS TO ENABLE VOP OUTPUT */

    if (config->mode != VOP_MODE_DISABLED)
    {
        msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
        msr_value.low &= ~DF_CONFIG_OUTPUT_MASK;
        msr_value.low |=  DF_OUTPUT_VOP;
        msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
    }

	/* SET THE UNIVERSAL VOP OPTIONS */

    if (config->flags & VOP_FLAG_SWAP_UV)   vop_config |= VOP_CONFIG_SWAPUV;
    if (config->flags & VOP_FLAG_SWAP_VBI)  vop_config |= VOP_CONFIG_SWAPVBI;

    /* SET THE MODE SPECIFIC PARAMETERS */

    if (config->mode == VOP_MODE_601)
    {
        vop_config |= config->vop601.flags;
        vop_config |= config->vop601.vsync_shift;
        vop_config |= VOP_CONFIG_ENABLE_601 | VOP_CONFIG_VIP2_0;

        switch (config->vop601.output_mode)
        {
            case VOP_601_YUV_16BIT:
                vop_config |= VOP_CONFIG_VIP2_16BIT;
                break;
            case VOP_601_YUV_4_4_4:
                vop_config |= VOP_CONFIG_DISABLE_DECIMATE;
                break;
            case VOP_601_RGB_8_8_8:
                vop_config |= VOP_CONFIG_DISABLE_DECIMATE | VOP_CONFIG_RGBMODE;
                rgb = 1;
                break;
        }

        if (config->vop601.vsync_shift == VOP_VSYNC_LATER_BY_X)
        {
            delta |= (config->vop601.vsync_shift_count & DC3_601_VSYNC_SHIFT_MASK);
            delta |= DC3_601_VSYNC_SHIFT_ENABLE;
        }
    }
    else
    {
        if (config->flags & VOP_FLAG_VBI)               vop_config |= VOP_CONFIG_VBI;
	    if (config->flags & VOP_FLAG_TASK)              vop_config |= VOP_CONFIG_TASK;
        if (config->flags & VOP_FLAG_SINGLECHIPCOMPAT)  vop_config |= VOP_CONFIG_SC_COMPATIBLE;
	    if (config->flags & VOP_FLAG_EXTENDEDSAV)       vop_config |= VOP_CONFIG_EXTENDED_SAV;

        switch (config->mode)
        {
            case VOP_MODE_DISABLED:
                vop_config |= VOP_CONFIG_DISABLED;
                break;
            case VOP_MODE_VIP11:
                vop_config |= VOP_CONFIG_VIP1_1;
                break;
            case VOP_MODE_CCIR656:
                vop_config |= VOP_CONFIG_CCIR656;
                break;
            case VOP_MODE_VIP20_8BIT:
                vop_config |= VOP_CONFIG_VIP2_0;
                break;
            case VOP_MODE_VIP20_16BIT:
                vop_config |= VOP_CONFIG_VIP2_0 | VOP_CONFIG_VIP2_16BIT;
                break;
        }
    }

    /* SET THE 4:4:4 TO 4:2:2 DECIMATION ALGORITHM */

	vop_config |= (config->conversion_mode);
	
    /* SET THE VSYNC OUT OPTIONS */

    control2  = READ_VIP32 (VIP_CONTROL2) & ~VIP_CONTROL2_SYNC2PIN_MASK;
    control2 |= config->vsync_out;
    WRITE_VIP32 (VIP_CONTROL2, control2);

    /* FORCE THE CORRECT VOP COLOR SPACE */
    /* The output of the mixer will be either RGB or YUV.  We must enable */
    /* or disable the VOP CSC based on the desired output format.         */

    alpha = READ_VID32 (DF_VID_ALPHA_CONTROL);
    if (!(alpha & DF_CSC_GRAPHICS_RGB_TO_YUV))
    {
        /* RGB OUTPUT FROM THE MIXER */

        if (!rgb) alpha |=  DF_CSC_VOP_RGB_TO_YUV;
        else      alpha &= ~DF_CSC_VOP_RGB_TO_YUV;
    }
    else
    {
        /* YUV OUTPUT FROM THE MIXER */
        /* As there is no YUV->RGB VOP conversion, we simply disable the */
        /* VOP CSC and trust that the user is competent.                 */

        alpha &= ~DF_CSC_VOP_RGB_TO_YUV;
    }

	/* AND WRITE THE CONFIGURATION */

    WRITE_VID32 (DF_VID_ALPHA_CONTROL, alpha);
	WRITE_VOP32(VOP_CONFIGURATION, vop_config);
    WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
    WRITE_REG32 (DC3_VID_DS_DELTA, delta);
    WRITE_REG32 (DC3_UNLOCK, unlock);
	
	return CIM_STATUS_OK;
}

/*---------------------------------------------------------------------------
 * vop_save_state
 *
 * This routine saves the necessary register contents in order to restore
 * at a later point to the same state.  Note that the capture state is
 * forced to OFF in this routine.
 *---------------------------------------------------------------------------*/

int vop_save_state (VOPSTATEBUFFER *save_buffer)
{
    if (!save_buffer)
        return CIM_STATUS_INVALIDPARAMS;

	save_buffer->config = READ_VOP32(VOP_CONFIGURATION);

⌨️ 快捷键说明

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