📄 cim_vip.c
字号:
}
/*---------------------------------------------------------------------------
* vip_set_capture_state
*
* This routine takes the current control word definition ( stored in locals )
* adds in the specified state, and writes the control word.
*---------------------------------------------------------------------------*/
int vip_set_capture_state (unsigned long state)
{
unsigned long vip_control1, vip_control3;
/* UPDATE THE CURRENT CAPTURE MODE */
vip_control1 = READ_VIP32 (VIP_CONTROL1);
vip_control3 = READ_VIP32 (VIP_CONTROL3);
vip_control1 &= ~VIP_CONTROL1_RUNMODE_MASK;
vip_control1 |= (state << VIP_CONTROL1_RUNMODE_SHIFT);
WRITE_VIP32 (VIP_CONTROL1, vip_control1);
if (state >= VIP_STARTCAPTUREATNEXTLINE)
{
/* WHACK VIP RESET */
/* The VIP can get confused when switching between capture settings, such as */
/* between linear and planar. We will thus whack VIP reset when enabling */
/* capture to ensure a pristine VIP state. */
WRITE_VIP32 (VIP_CONTROL1, vip_control1 | VIP_CONTROL1_RESET);
WRITE_VIP32 (VIP_CONTROL1, vip_control1 & ~VIP_CONTROL1_RESET);
WRITE_VIP32 (VIP_CONTROL3, vip_control3 | VIP_CONTROL3_FIFO_RESET);
}
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vip_terminate
*
* This routine stops VIP capture and resets the VIP internal state.
*---------------------------------------------------------------------------*/
int vip_terminate (void)
{
unsigned long timeout = 50000;
/* DISABLE AND CLEAR ALL VIP INTERRUPTS */
WRITE_VIP32 (VIP_INTERRUPT, VIP_ALL_INTERRUPTS | (VIP_ALL_INTERRUPTS >> 16));
/* DISABLE VIP CAPTURE */
/* We will try to let the VIP FIFO flush before shutting it down. */
WRITE_VIP32 (VIP_CONTROL1, 0);
while (timeout)
{
timeout--;
if (READ_VIP32 (VIP_STATUS) & VIP_STATUS_WRITES_COMPLETE)
break;
}
/* RESET THE HARDWARE REGISTERS */
/* Note that we enable VIP reset to allow clock gating to lower VIP */
/* power consumption. */
WRITE_VIP32 (VIP_CONTROL1, VIP_CONTROL1_RESET);
WRITE_VIP32 (VIP_CONTROL3, VIP_CONTROL3_FIFO_RESET);
WRITE_VIP32 (VIP_CONTROL2, 0);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vip_configure_fifo
*
* This routine sets the desired threshold or flush for the specified fifo.
*---------------------------------------------------------------------------*/
int vip_configure_fifo (unsigned long fifo_type, unsigned long fifo_size)
{
unsigned long vip_control1, vip_control2;
vip_control1 = READ_VIP32 (VIP_CONTROL1);
vip_control2 = READ_VIP32 (VIP_CONTROL2);
switch (fifo_type)
{
case VIP_VIDEOTHRESHOLD:
vip_control2 &= ~VIP_CONTROL2_VIDTH_MASK;
vip_control2 |= (fifo_size << VIP_CONTROL2_VIDTH_SHIFT) & VIP_CONTROL2_VIDTH_MASK;
break;
case VIP_ANCILLARYTHRESHOLD:
vip_control2 &= ~VIP_CONTROL2_ANCTH_MASK;
vip_control2 |= (fifo_size << VIP_CONTROL2_ANCTH_SHIFT) & VIP_CONTROL2_ANCTH_MASK;
break;
case VIP_VIDEOFLUSH:
vip_control1 &= ~VIP_CONTROL1_VID_FF_MASK;
vip_control1 |= ((fifo_size >> 2) << VIP_CONTROL1_VID_FF_SHIFT) & VIP_CONTROL1_VID_FF_MASK;
break;
case VIP_ANCILLARYFLUSH:
vip_control1 &= ~VIP_CONTROL1_ANC_FF_MASK;
vip_control1 |= ((fifo_size >> 2) << VIP_CONTROL1_ANC_FF_SHIFT) & VIP_CONTROL1_ANC_FF_MASK;
break;
default:
return CIM_STATUS_INVALIDPARAMS;
}
WRITE_VIP32 (VIP_CONTROL1, vip_control1);
WRITE_VIP32 (VIP_CONTROL2, vip_control2);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vip_set_interrupt_enable
*
* This routine accepts a mask of interrupts to be enabled/disabled and
* an enable flag.
*
* For each mask match, the interrupt will be enabled or disabled based on
* enable
*---------------------------------------------------------------------------*/
int vip_set_interrupt_enable (unsigned long mask, int enable)
{
/* CHECK IF ANY VALID INTERRUPTS ARE BEING CHANGED */
if (mask & VIP_ALL_INTERRUPTS)
{
unsigned long int_enable = READ_VIP32(VIP_INTERRUPT) & 0xFFFF;
/* SET OR CLEAR THE MASK BITS */
/* Note that the upper 16-bits of the register are 0 after this */
/* operation. This prevents us from indadvertently clearing a */
/* pending interrupt by enabling/disabling another one. */
if (enable) int_enable &= ~(mask >> 16);
else int_enable |= (mask >> 16);
WRITE_VIP32 (VIP_INTERRUPT, int_enable);
}
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vip_set_vsync_error
*
* This routine defines a region that is used to determine if the vsync is
* within an acceptable range. This definition is accomplished using
* a count and a vertical window. The count specifies the exact number
* of clocks expected for one field. The window parameters specify the number
* of clocks variation allowed before and after the expected vsync. For
* example, if vertical_count is 1000, window_before is 5 and window_after
* is 12, VSync will be considered valid if it occurs between 995 and 1012
* clocks after the last VSync. The total window size (window_before + window_after)
* cannot exceed 255.
*---------------------------------------------------------------------------*/
int vip_set_vsync_error (unsigned long vertical_count, unsigned long window_before,
unsigned long window_after, int enable)
{
unsigned long vip_control2 = READ_VIP32 (VIP_CONTROL2);
unsigned long temp;
if (enable)
{
/* CREATE THE VERTICAL WINDOW */
/* The VIP uses two counters. The first counter defines the minimum clock count */
/* before a valid VSync can occur. The second counter starts after the first */
/* completes and defines the acceptable region of variation. */
temp = ((window_before + window_after) << VIP_VSYNC_ERR_WINDOW_SHIFT) & VIP_VSYNC_ERR_WINDOW_MASK;
temp |= (vertical_count - window_before) & VIP_VSYNC_ERR_COUNT_MASK;
vip_control2 |= VIP_CONTROL2_VERTERROR_ENABLE;
WRITE_VIP32(VIP_VSYNC_ERR_COUNT, temp);
}
else
{
vip_control2 &= ~VIP_CONTROL2_VERTERROR_ENABLE;
}
WRITE_VIP32 (VIP_CONTROL2, vip_control2);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vip_max_address_enable
*
* This routine specifies the maximum address to which the the hardware should
* write during data storage. If this value is exceeded an error is generated,
* (this may be monitored using the appropriate interrupt flags - see
* vip_set_interrupt_enable)
*---------------------------------------------------------------------------*/
int vip_max_address_enable (unsigned long max_address, int enable)
{
unsigned long vip_control2 = READ_VIP32 (VIP_CONTROL2);
if (enable)
{
/* ENABLE THE CONTROL BIT */
vip_control2 |= VIP_CONTROL2_ADD_ERROR_ENABLE;
WRITE_VIP32(VIP_MAX_ADDRESS, max_address & VIP_MAXADDR_MASK);
}
else
{
/* DISABLE DETECTION */
vip_control2 &= ~VIP_CONTROL2_ADD_ERROR_ENABLE;
}
WRITE_VIP32 (VIP_CONTROL2, vip_control2);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vip_set_loopback_enable
*
* This routine enables/disables internal loopback functionality. When
* loopback is enabled, the VOP outputs are rerouted to the VIP inputs
* internal to the chip. No loopback connector is required.
*---------------------------------------------------------------------------*/
int vip_set_loopback_enable(int enable)
{
unsigned long vip_control2 = READ_VIP32 (VIP_CONTROL2);
if (enable) vip_control2 |= VIP_CONTROL2_LOOPBACK_ENABLE;
else vip_control2 &= ~VIP_CONTROL2_LOOPBACK_ENABLE;
WRITE_VIP32 (VIP_CONTROL2, vip_control2);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vip_configure_genlock
*
* This routine configures genlock functionality.
*---------------------------------------------------------------------------*/
int vip_configure_genlock (VIPGENLOCKBUFFER *buffer)
{
unsigned long vip_control1, vip_control2;
unsigned long unlock, genlk_ctl;
if (!buffer)
return CIM_STATUS_INVALIDPARAMS;
unlock = READ_REG32 (DC3_UNLOCK);
genlk_ctl = READ_REG32 (DC3_GENLK_CTL);
vip_control1 = READ_VIP32 (VIP_CONTROL1);
vip_control2 = READ_VIP32 (VIP_CONTROL2);
/* UPDATE VIDEO DETECTION */
/* These flags are used to indicate the ways in which the VIP signal can */
/* be considered 'lost'. */
vip_control1 &= ~VIP_CONTROL1_VDE_FF_MASK;
vip_control2 &= ~(VIP_CONTROL2_FIELD2VG_MASK | VIP_CONTROL2_SYNC2VG_MASK);
vip_control1 |= buffer->vip_signal_loss;
/* UPDATE FIELD AND VSYNC INFORMATION */
/* These flags control how and when the even/odd field and Vsync */
/* information is communicated to the VG. */
vip_control2 |= buffer->field_to_vg;
vip_control2 |= buffer->vsync_to_vg;
/* ENABLE OR DISABLE GENLOCK TIMEOUT */
/* Enabling genlock timeout allows the VG to revert to its own sync */
/* timings when the VIP input is lost. Note that the VIP will not */
/* know the signal is lost unless the appropriate error detection */
/* flags have been enabled inside vip_initialize. */
if (buffer->enable_timeout) genlk_ctl |= DC3_GC_GENLOCK_TO_ENABLE;
else genlk_ctl &= ~DC3_GC_GENLOCK_TO_ENABLE;
genlk_ctl &= ~DC3_GC_GENLOCK_SKEW_MASK;
genlk_ctl |= buffer->genlock_skew & DC3_GC_GENLOCK_SKEW_MASK;
WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
WRITE_REG32 (DC3_GENLK_CTL, genlk_ctl);
WRITE_VIP32 (VIP_CONTROL1, vip_control1);
WRITE_VIP32 (VIP_CONTROL2, vip_control2);
WRITE_REG32 (DC3_UNLOCK, unlock);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vip_set_genlock_enable
*
* This routine enables/disables genlock inside the VG.
*---------------------------------------------------------------------------*/
int vip_set_genlock_enable (int enable)
{
unsigned long unlock, temp;
unlock = READ_REG32 (DC3_UNLOCK);
temp = READ_REG32 (DC3_GENLK_CTL);
if (enable) temp |= DC3_GC_GENLOCK_ENABLE;
else temp &= ~DC3_GC_GENLOCK_ENABLE;
WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
WRITE_REG32 (DC3_GENLK_CTL, temp);
WRITE_REG32 (DC3_UNLOCK, unlock);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vip_set_power_characteristics
*
* This routine takes a VIPPOWERBUFFER structure, and selectively sets the
* GeodeLink power and/or Vip clock power states.
*---------------------------------------------------------------------------*/
int vip_set_power_characteristics (VIPPOWERBUFFER *buffer)
{
Q_WORD q_word;
if (!buffer)
return CIM_STATUS_INVALIDPARAMS;
q_word.low = q_word.high = 0;
/* ENABLE GEODELINK CLOCK GATING */
if (buffer->glink_clock_mode)
q_word.low |= VIP_MSR_POWER_GLINK;
/* ENABLE VIP CLOCK GATING */
if (buffer->vip_clock_mode)
q_word.low |= VIP_MSR_POWER_CLOCK;
/* WRITE THE NEW VALUE */
msr_write64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_PM, &q_word);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vip_set_priority_characteristics
*
* This routine programs the VIP GeodeLink priority characteristics
*---------------------------------------------------------------------------*/
int vip_set_priority_characteristics (VIPPRIORITYBUFFER *buffer)
{
Q_WORD q_word;
if (!buffer)
return CIM_STATUS_INVALIDPARAMS;
q_word.low = q_word.high = 0;
q_word.low |= (buffer->secondary << VIP_MSR_MCR_SECOND_PRIORITY_SHIFT) & VIP_MSR_MCR_SECOND_PRIORITY_MASK;
q_word.low |= (buffer->primary << VIP_MSR_MCR_PRIMARY_PRIORITY_SHIFT) & VIP_MSR_MCR_PRIMARY_PRIORITY_MASK;
q_word.low |= (buffer->pid << VIP_MSR_MCR_PID_SHIFT) & VIP_MSR_MCR_PID_MASK;
msr_write64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CONFIG, &q_word);
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vip_set_debug_characteristics
*
* This routine configures the debug data that is exposed over the diag bus.
*---------------------------------------------------------------------------*/
int vip_set_debug_characteristics (VIPDEBUGBUFFER *buffer)
{
Q_WORD q_word;
if (!buffer)
return CIM_STATUS_INVALIDPARAMS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -