📄 cim_vip.c
字号:
/*
* <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 VIP configuration routines.
* </DOC_AMD_STD>
*
*/
/*---------------------------------------------------------------------------
* vip_initialize
*
* This routine initializes the internal module state and prepares the
* module for subsequent VIP orientated activities.
*---------------------------------------------------------------------------*/
int vip_initialize(VIPSETMODEBUFFER *buffer)
{
unsigned long vip_control1, vip_control2, vip_control3;
if (!buffer)
return CIM_STATUS_INVALIDPARAMS;
vip_control1 = 0;
vip_control2 = 0;
vip_control3 = 0;
/* CONFIGURE CONTROL WORDS BASED ON MODE STRUCTURE */
/* Note that some of the input parameters match the register fields */
/* they represent. */
/* STREAM ENABLES */
vip_control1 |= buffer->stream_enables;
/* VIP CAPTURE MODE */
vip_control1 |= buffer->operating_mode;
/* HANDLE PLANAR CAPTURE */
if (buffer->flags & VIP_MODEFLAG_PLANARCAPTURE)
{
vip_control1 |= VIP_CONTROL1_PLANAR;
if (buffer->planar_capture == VIP_420CAPTURE_EVERYLINE)
{
vip_control1 |= VIP_CONTROL1_DISABLE_DECIMATION;
}
else if (buffer->planar_capture == VIP_420CAPTURE_ALTERNATINGFIELDS)
{
if (buffer->flags & VIP_MODEFLAG_PROGRESSIVE)
return CIM_STATUS_INVALIDPARAMS;
vip_control1 |= VIP_CONTROL1_DISABLE_DECIMATION;
vip_control3 |= VIP_CONTROL3_DECIMATE_EVEN;
}
else if (buffer->planar_capture != VIP_420CAPTURE_ALTERNATINGLINES)
return CIM_STATUS_INVALIDPARAMS;
/* CONFIGURE THE VIDEO FIFO THRESHOLD BASED ON THE FIFO DEPTH */
vip_control2 |= VIP_CONTROL2_DEFAULT_VIDTH_420 << VIP_CONTROL2_VIDTH_SHIFT;
}
else
{
vip_control2 |= VIP_CONTROL2_DEFAULT_VIDTH_422 << VIP_CONTROL2_VIDTH_SHIFT;
}
/* CONFIGURE DEFAULT ANCILARRY THRESHOLD AND VIDEO FLUSH VALUES */
vip_control2 |= VIP_CONTROL2_DEFAULT_ANCTH << VIP_CONTROL2_ANCTH_SHIFT;
vip_control1 |= VIP_CONTROL1_DEFAULT_ANC_FF << VIP_CONTROL1_ANC_FF_SHIFT;
vip_control1 |= VIP_CONTROL1_DEFAULT_VID_FF << VIP_CONTROL1_VID_FF_SHIFT;
/* PROGRAM VIP OPTIONS */
/* The options are sanitized based on the current configuration. */
if (buffer->flags & VIP_MODEFLAG_PROGRESSIVE)
vip_control1 |= VIP_CONTROL1_NON_INTERLACED;
else
{
if (buffer->flags & VIP_MODEFLAG_TOGGLEEACHFIELD)
vip_control3 |= VIP_CONTROL3_BASE_UPDATE;
if (buffer->flags & VIP_MODEFLAG_INVERTPOLARITY)
vip_control2 |= VIP_CONTROL2_INVERT_POLARITY;
}
if ((buffer->operating_mode == VIP_MODE_MSG ||
buffer->operating_mode == VIP_MODE_DATA) &&
(buffer->flags & VIP_MODEFLAG_FLIPMESSAGEWHENFULL))
{
vip_control1 |= VIP_CONTROL1_MSG_STRM_CTRL;
}
else if (buffer->operating_mode == VIP_MODE_VIP2_8BIT ||
buffer->operating_mode == VIP_MODE_VIP2_16BIT)
{
if (buffer->flags & VIP_MODEFLAG_ENABLEREPEATFLAG)
vip_control2 |= VIP_CONTROL2_REPEAT_ENABLE;
if (buffer->flags & VIP_MODEFLAG_INVERTTASKPOLARITY)
vip_control3 |= VIP_CONTROL3_TASK_POLARITY;
}
if (buffer->flags & VIP_MODEFLAG_DISABLEZERODETECT)
vip_control1 |= VIP_CONTROL1_DISABLE_ZERO_DETECT;
if (buffer->flags & VIP_MODEFLAG_10BITANCILLARY)
vip_control2 |= VIP_CONTROL2_ANC10;
/* WRITE THE CONTROL REGISTERS */
/* The control registers are kept 'live' to allow separate instances of */
/* Cimarron to control the VIP hardware. */
WRITE_VIP32 (VIP_CONTROL1, vip_control1);
WRITE_VIP32 (VIP_CONTROL2, vip_control2);
WRITE_VIP32 (VIP_CONTROL3, vip_control3);
/* CONFIGURE 601 PARAMETERS */
if (buffer->operating_mode == VIP_MODE_8BIT601 ||
buffer->operating_mode == VIP_MODE_16BIT601)
{
vip_update_601_params (&buffer->vip601_settings);
}
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vip_update_601_params
*
* This routine configures all aspects of 601 VIP data capture, including
* start and stop timings and input polarities.
*---------------------------------------------------------------------------*/
int vip_update_601_params (VIP_601PARAMS *buffer)
{
unsigned long vip_control3, vip_control1;
if (!buffer)
return CIM_STATUS_INVALIDPARAMS;
vip_control1 = READ_VIP32 (VIP_CONTROL3);
vip_control3 = READ_VIP32 (VIP_CONTROL3);
if (buffer->flags & VIP_MODEFLAG_VSYNCACTIVEHIGH) vip_control3 |= VIP_CONTROL3_VSYNC_POLARITY;
else vip_control3 &= ~VIP_CONTROL3_VSYNC_POLARITY;
if (buffer->flags & VIP_MODEFLAG_HSYNCACTIVEHIGH) vip_control3 |= VIP_CONTROL3_HSYNC_POLARITY;
else vip_control3 &= ~VIP_CONTROL3_HSYNC_POLARITY;
WRITE_VIP32 (VIP_CONTROL3, vip_control3);
WRITE_VIP32 (VIP_601_HORZ_START, buffer->horz_start);
WRITE_VIP32 (VIP_601_VBI_START, buffer->vbi_start);
WRITE_VIP32 (VIP_601_VBI_END, buffer->vbi_start + buffer->vbi_height - 1);
WRITE_VIP32 (VIP_601_EVEN_START_STOP,
buffer->vert_start_even | ((buffer->vert_start_even + buffer->even_height - 1) << 16));
WRITE_VIP32 (VIP_601_ODD_START_STOP,
buffer->vert_start_odd | ((buffer->vert_start_odd + buffer->odd_height - 1) << 16));
WRITE_VIP32 (VIP_ODD_FIELD_DETECT,
buffer->odd_detect_start | (buffer->odd_detect_end << 16));
/* SPECIAL CASE FOR HORIZONTAL DATA */
/* 601 horizontal parameters are based on the number of clocks and not the */
/* number of pixels. */
if ((vip_control1 & VIP_CONTROL1_MODE_MASK) == VIP_MODE_16BIT601)
WRITE_VIP32 (VIP_601_HORZ_END, buffer->horz_start + (buffer->width << 1) + 3);
else
WRITE_VIP32 (VIP_601_HORZ_END, buffer->horz_start + buffer->width + 3);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vip_configure_capture_buffers
*
* This routine configures the base offsets for video, ancillary or message
* mode capture. The input structure can also contain multiple offsets, such
* that the calling application can avoid updating the structure for each flip.
*
* The new buffer addresses are written to the hardware registers although
* they may not be latched immediately. Calling vip_is_buffer_update_latched
* allows the determination of whether the update has occured.
*
* Review the Cimarron VIP API documentation to determine which buffer addresses are
* latched immediately.
*---------------------------------------------------------------------------*/
int vip_configure_capture_buffers (int buffer_type, VIPINPUTBUFFER *buffer)
{
VIPINPUTBUFFER_ADDR *offsets;
unsigned long cur_buffer = buffer->current_buffer;
if (!buffer)
return CIM_STATUS_INVALIDPARAMS;
if (buffer_type == VIP_BUFFER_A || buffer_type == VIP_BUFFER_601)
{
offsets = &buffer->offsets[VIP_BUFFER_TASK_A];
/* SET VIDEO PITCH */
WRITE_VIP32 (VIP_TASKA_VID_PITCH, offsets->y_pitch | (offsets->uv_pitch << 16));
/* SET BASE OFFSETS */
if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
{
WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->even_base[cur_buffer]);
WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->odd_base[cur_buffer]);
if (buffer->flags & VIP_INPUTFLAG_VBI)
{
WRITE_VIP32 (VIP_TASKA_VBI_ODD_BASE, offsets->vbi_even_base);
WRITE_VIP32 (VIP_TASKA_VBI_EVEN_BASE, offsets->vbi_odd_base);
}
}
else
{
WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->odd_base[cur_buffer]);
WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->even_base[cur_buffer]);
if (buffer->flags & VIP_INPUTFLAG_VBI)
{
WRITE_VIP32 (VIP_TASKA_VBI_ODD_BASE, offsets->vbi_odd_base);
WRITE_VIP32 (VIP_TASKA_VBI_EVEN_BASE, offsets->vbi_even_base);
}
}
/* SET 4:2:0 OFFSETS */
if (buffer->flags & VIP_INPUTFLAG_PLANAR)
{
WRITE_VIP32 (VIP_TASKA_U_OFFSET, offsets->odd_uoffset);
WRITE_VIP32 (VIP_TASKA_V_OFFSET, offsets->odd_voffset);
WRITE_VIP32 (VIP_TASKA_U_EVEN_OFFSET, offsets->even_uoffset);
WRITE_VIP32 (VIP_TASKA_V_EVEN_OFFSET, offsets->even_voffset);
}
}
else if (buffer_type == VIP_BUFFER_B)
{
offsets = &buffer->offsets[VIP_BUFFER_TASK_B];
/* SET VIDEO PITCH */
WRITE_VIP32 (VIP_TASKB_VID_PITCH, offsets->y_pitch | (offsets->uv_pitch << 16));
/* SET BASE OFFSETS */
if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
{
WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->even_base[cur_buffer]);
WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->odd_base[cur_buffer]);
if (buffer->flags & VIP_INPUTFLAG_VBI)
{
WRITE_VIP32 (VIP_TASKB_VBI_ODD_BASE, offsets->vbi_even_base);
WRITE_VIP32 (VIP_TASKB_VBI_EVEN_BASE, offsets->vbi_odd_base);
}
}
else
{
WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->odd_base[cur_buffer]);
WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->even_base[cur_buffer]);
if (buffer->flags & VIP_INPUTFLAG_VBI)
{
WRITE_VIP32 (VIP_TASKB_VBI_ODD_BASE, offsets->vbi_odd_base);
WRITE_VIP32 (VIP_TASKB_VBI_EVEN_BASE, offsets->vbi_even_base);
}
}
/* SET 4:2:0 OFFSETS */
if (buffer->flags & VIP_INPUTFLAG_PLANAR)
{
WRITE_VIP32 (VIP_TASKB_U_OFFSET, offsets->odd_uoffset);
WRITE_VIP32 (VIP_TASKB_V_OFFSET, offsets->odd_voffset);
}
}
else if (buffer_type == VIP_BUFFER_ANC || buffer_type == VIP_BUFFER_MSG)
{
WRITE_VIP32(VIP_ANC_MSG1_BASE, buffer->ancillaryData.msg1_base);
WRITE_VIP32(VIP_ANC_MSG2_BASE, buffer->ancillaryData.msg2_base);
WRITE_VIP32(VIP_ANC_MSG_SIZE, buffer->ancillaryData.msg_size);
}
else
{
return CIM_STATUS_INVALIDPARAMS;
}
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vip_toggle_vip_video_offsets
*
* This routine updates the offsets for video capture. It is a simplified
* version of vip_configure_capture_buffers that is designed to be called from
* interrupt service routines or other buffer flipping applications that
* require low latency.
*---------------------------------------------------------------------------*/
int vip_toggle_video_offsets (int buffer_type, VIPINPUTBUFFER *buffer)
{
unsigned long cur_buffer = buffer->current_buffer;
VIPINPUTBUFFER_ADDR *offsets;
if (buffer_type == VIP_BUFFER_A)
{
offsets = &buffer->offsets[VIP_BUFFER_TASK_A];
/* SET BASE OFFSETS */
if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
{
WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->even_base[cur_buffer]);
WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->odd_base[cur_buffer]);
}
else
{
WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->odd_base[cur_buffer]);
WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->even_base[cur_buffer]);
}
}
else if (buffer_type == VIP_BUFFER_B)
{
offsets = &buffer->offsets[VIP_BUFFER_TASK_B];
/* SET BASE OFFSETS */
if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
{
WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->even_base[cur_buffer]);
WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->odd_base[cur_buffer]);
}
else
{
WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->odd_base[cur_buffer]);
WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->even_base[cur_buffer]);
}
}
else if (buffer_type == VIP_BUFFER_A_ODD)
{
offsets = &buffer->offsets[VIP_BUFFER_TASK_A];
/* SET BASE OFFSETS */
if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->even_base[cur_buffer]);
else
WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->odd_base[cur_buffer]);
}
else if (buffer_type == VIP_BUFFER_A_EVEN)
{
offsets = &buffer->offsets[VIP_BUFFER_TASK_A];
/* SET BASE OFFSETS */
if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->odd_base[cur_buffer]);
else
WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->even_base[cur_buffer]);
}
else if (buffer_type == VIP_BUFFER_B_ODD)
{
offsets = &buffer->offsets[VIP_BUFFER_TASK_B];
/* SET BASE OFFSETS */
if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->even_base[cur_buffer]);
else
WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->odd_base[cur_buffer]);
}
else if (buffer_type == VIP_BUFFER_B_EVEN)
{
offsets = &buffer->offsets[VIP_BUFFER_TASK_B];
/* SET BASE OFFSETS */
if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->odd_base[cur_buffer]);
else
WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->even_base[cur_buffer]);
}
else
return CIM_STATUS_INVALIDPARAMS;
return CIM_STATUS_OK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -