
Added initial support Xilinx Embedded Software. Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
1389 lines
39 KiB
C
Executable file
1389 lines
39 KiB
C
Executable file
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* Use of the Software is limited solely to applications:
|
|
* (a) running on a Xilinx device, or
|
|
* (b) that interact with a Xilinx device through a bus or interconnect.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
|
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
* Except as contained in this notice, the name of the Xilinx shall not be used
|
|
* in advertising or otherwise to promote the sale, use or other dealings in
|
|
* this Software without prior written authorization from Xilinx.
|
|
*
|
|
******************************************************************************/
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* @file xaxivdma.c
|
|
*
|
|
* Implementation of the driver API functions for the AXI Video DMA engine.
|
|
*
|
|
* <pre>
|
|
* MODIFICATION HISTORY:
|
|
*
|
|
* Ver Who Date Changes
|
|
* ----- ---- -------- -------------------------------------------------------
|
|
* 1.00a jz 08/16/10 First release
|
|
* 2.00a jz 12/10/10 Added support for direct register access mode, v3 core
|
|
* 2.01a jz 01/19/11 Added ability to re-assign BD addresses
|
|
* rkv 03/28/11 Added support for frame store register.
|
|
* 3.00a srt 08/26/11 Added support for Flush on Frame Sync and dynamic
|
|
* programming of Line Buffer Thresholds and added API
|
|
* XAxiVdma_SetLineBufThreshold.
|
|
* 4.00a srt 11/21/11 - XAxiVdma_CfgInitialize API is modified to use the
|
|
* EffectiveAddr.
|
|
* - Added APIs:
|
|
* XAxiVdma_FsyncSrcSelect()
|
|
* XAxiVdma_GenLockSourceSelect()
|
|
* 4.01a srt 06/13/12 - Added APIs:
|
|
* XAxiVdma_GetDmaChannelErrors()
|
|
* XAxiVdma_ClearDmaChannelErrors()
|
|
* 4.02a srt 09/25/12 - Fixed CR 678734
|
|
* XAxiVdma_SetFrmStore function changed to remove
|
|
* Reset logic after setting number of frame stores.
|
|
* 4.03a srt 01/18/13 - Updated logic of GenLockSourceSelect() & FsyncSrcSelect()
|
|
* APIs for newer versions of IP (CR: 691052).
|
|
* - Modified CfgInitialize() API to initialize
|
|
* StreamWidth parameters. (CR 691866)
|
|
* 4.04a srt 03/03/13 - Support for *_ENABLE_DEBUG_INFO_* debug configuration
|
|
* parameters (CR: 703738)
|
|
*
|
|
* </pre>
|
|
*
|
|
******************************************************************************/
|
|
|
|
/***************************** Include Files *********************************/
|
|
|
|
#include "xaxivdma.h"
|
|
#include "xaxivdma_i.h"
|
|
|
|
/************************** Constant Definitions *****************************/
|
|
/* The polling upon starting the hardware
|
|
*
|
|
* We have the assumption that reset is fast upon hardware start
|
|
*/
|
|
#define INITIALIZATION_POLLING 100000
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Get a channel
|
|
*
|
|
* @param InstancePtr is the DMA engine to work on
|
|
* @param Direction is the direction for the channel to get
|
|
*
|
|
* @return
|
|
* The pointer to the channel. Upon error, return NULL.
|
|
*
|
|
* @note
|
|
* Since this function is internally used, we assume Direction is valid
|
|
*****************************************************************************/
|
|
XAxiVdma_Channel *XAxiVdma_GetChannel(XAxiVdma *InstancePtr,
|
|
u16 Direction)
|
|
{
|
|
|
|
if (Direction == XAXIVDMA_READ) {
|
|
return &(InstancePtr->ReadChannel);
|
|
}
|
|
else if (Direction == XAXIVDMA_WRITE) {
|
|
return &(InstancePtr->WriteChannel);
|
|
}
|
|
else {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"Invalid direction %x\r\n", Direction);
|
|
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static int XAxiVdma_Major(XAxiVdma *InstancePtr) {
|
|
u32 Reg;
|
|
|
|
Reg = XAxiVdma_ReadReg(InstancePtr->BaseAddr, XAXIVDMA_VERSION_OFFSET);
|
|
|
|
return (int)((Reg & XAXIVDMA_VERSION_MAJOR_MASK) >>
|
|
XAXIVDMA_VERSION_MAJOR_SHIFT);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Initialize the driver with hardware configuration
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param CfgPtr is the pointer to the hardware configuration structure
|
|
* @param EffectiveAddr is the virtual address map for the device
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if everything goes fine
|
|
* - XST_FAILURE if reset the hardware failed, need system reset to recover
|
|
*
|
|
* @note
|
|
* If channel fails reset, then it will be set as invalid
|
|
*****************************************************************************/
|
|
int XAxiVdma_CfgInitialize(XAxiVdma *InstancePtr, XAxiVdma_Config *CfgPtr,
|
|
u32 EffectiveAddr)
|
|
{
|
|
XAxiVdma_Channel *RdChannel;
|
|
XAxiVdma_Channel *WrChannel;
|
|
int Polls;
|
|
|
|
/* Validate parameters */
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(CfgPtr != NULL);
|
|
|
|
/* Initially, no interrupt callback functions
|
|
*/
|
|
InstancePtr->ReadCallBack.CompletionCallBack = 0x0;
|
|
InstancePtr->ReadCallBack.ErrCallBack = 0x0;
|
|
InstancePtr->WriteCallBack.CompletionCallBack = 0x0;
|
|
InstancePtr->WriteCallBack.ErrCallBack = 0x0;
|
|
|
|
InstancePtr->BaseAddr = EffectiveAddr;
|
|
InstancePtr->MaxNumFrames = CfgPtr->MaxFrameStoreNum;
|
|
InstancePtr->HasMm2S = CfgPtr->HasMm2S;
|
|
InstancePtr->HasS2Mm = CfgPtr->HasS2Mm;
|
|
InstancePtr->UseFsync = CfgPtr->UseFsync;
|
|
InstancePtr->InternalGenLock = CfgPtr->InternalGenLock;
|
|
|
|
if (XAxiVdma_Major(InstancePtr) < 3) {
|
|
InstancePtr->HasSG = 1;
|
|
}
|
|
else {
|
|
InstancePtr->HasSG = CfgPtr->HasSG;
|
|
}
|
|
|
|
/* The channels are not valid until being initialized
|
|
*/
|
|
RdChannel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_READ);
|
|
RdChannel->IsValid = 0;
|
|
|
|
WrChannel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_WRITE);
|
|
WrChannel->IsValid = 0;
|
|
|
|
if (InstancePtr->HasMm2S) {
|
|
RdChannel->ChanBase = InstancePtr->BaseAddr + XAXIVDMA_TX_OFFSET;
|
|
RdChannel->InstanceBase = InstancePtr->BaseAddr;
|
|
RdChannel->HasSG = InstancePtr->HasSG;
|
|
RdChannel->IsRead = 1;
|
|
RdChannel->StartAddrBase = InstancePtr->BaseAddr +
|
|
XAXIVDMA_MM2S_ADDR_OFFSET;
|
|
|
|
RdChannel->NumFrames = CfgPtr->MaxFrameStoreNum;
|
|
|
|
/* Flush on Sync */
|
|
RdChannel->FlushonFsync = CfgPtr->FlushonFsync;
|
|
|
|
/* Dynamic Line Buffers Depth */
|
|
RdChannel->LineBufDepth = CfgPtr->Mm2SBufDepth;
|
|
if(RdChannel->LineBufDepth > 0) {
|
|
RdChannel->LineBufThreshold =
|
|
XAxiVdma_ReadReg(RdChannel->ChanBase,
|
|
XAXIVDMA_BUFTHRES_OFFSET);
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"Read Channel Buffer Threshold %d bytes\n\r",
|
|
RdChannel->LineBufThreshold);
|
|
}
|
|
RdChannel->HasDRE = CfgPtr->HasMm2SDRE;
|
|
RdChannel->WordLength = CfgPtr->Mm2SWordLen >> 3;
|
|
RdChannel->StreamWidth = CfgPtr->Mm2SStreamWidth >> 3;
|
|
|
|
/* Internal GenLock */
|
|
RdChannel->GenLock = CfgPtr->Mm2SGenLock;
|
|
|
|
/* Debug Info Parameter flags */
|
|
if (!CfgPtr->EnableAllDbgFeatures) {
|
|
if (CfgPtr->Mm2SThresRegEn) {
|
|
RdChannel->DbgFeatureFlags |=
|
|
XAXIVDMA_ENABLE_DBG_THRESHOLD_REG;
|
|
}
|
|
|
|
if (CfgPtr->Mm2SFrmStoreRegEn) {
|
|
RdChannel->DbgFeatureFlags |=
|
|
XAXIVDMA_ENABLE_DBG_FRMSTORE_REG;
|
|
}
|
|
|
|
if (CfgPtr->Mm2SDlyCntrEn) {
|
|
RdChannel->DbgFeatureFlags |=
|
|
XAXIVDMA_ENABLE_DBG_DLY_CNTR;
|
|
}
|
|
|
|
if (CfgPtr->Mm2SFrmCntrEn) {
|
|
RdChannel->DbgFeatureFlags |=
|
|
XAXIVDMA_ENABLE_DBG_FRM_CNTR;
|
|
}
|
|
|
|
} else {
|
|
RdChannel->DbgFeatureFlags =
|
|
XAXIVDMA_ENABLE_DBG_ALL_FEATURES;
|
|
}
|
|
|
|
XAxiVdma_ChannelInit(RdChannel);
|
|
|
|
XAxiVdma_ChannelReset(RdChannel);
|
|
|
|
/* At time of initialization, no transfers are going on,
|
|
* reset is expected to be quick
|
|
*/
|
|
Polls = INITIALIZATION_POLLING;
|
|
|
|
while (Polls && XAxiVdma_ChannelResetNotDone(RdChannel)) {
|
|
Polls -= 1;
|
|
}
|
|
|
|
if (!Polls) {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"Read channel reset failed %x\n\r",
|
|
(unsigned int)XAxiVdma_ChannelGetStatus(RdChannel));
|
|
|
|
return XST_FAILURE;
|
|
}
|
|
}
|
|
|
|
if (InstancePtr->HasS2Mm) {
|
|
WrChannel->ChanBase = InstancePtr->BaseAddr + XAXIVDMA_RX_OFFSET;
|
|
WrChannel->InstanceBase = InstancePtr->BaseAddr;
|
|
WrChannel->HasSG = InstancePtr->HasSG;
|
|
WrChannel->IsRead = 0;
|
|
WrChannel->StartAddrBase = InstancePtr->BaseAddr +
|
|
XAXIVDMA_S2MM_ADDR_OFFSET;
|
|
WrChannel->NumFrames = CfgPtr->MaxFrameStoreNum;
|
|
|
|
/* Flush on Sync */
|
|
WrChannel->FlushonFsync = CfgPtr->FlushonFsync;
|
|
|
|
/* Dynamic Line Buffers Depth */
|
|
WrChannel->LineBufDepth = CfgPtr->S2MmBufDepth;
|
|
if(WrChannel->LineBufDepth > 0) {
|
|
WrChannel->LineBufThreshold =
|
|
XAxiVdma_ReadReg(WrChannel->ChanBase,
|
|
XAXIVDMA_BUFTHRES_OFFSET);
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"Write Channel Buffer Threshold %d bytes\n\r",
|
|
WrChannel->LineBufThreshold);
|
|
}
|
|
WrChannel->HasDRE = CfgPtr->HasS2MmDRE;
|
|
WrChannel->WordLength = CfgPtr->S2MmWordLen >> 3;
|
|
WrChannel->StreamWidth = CfgPtr->S2MmStreamWidth >> 3;
|
|
|
|
/* Internal GenLock */
|
|
WrChannel->GenLock = CfgPtr->S2MmGenLock;
|
|
|
|
/* Frame Sync Source Selection*/
|
|
WrChannel->S2MmSOF = CfgPtr->S2MmSOF;
|
|
|
|
/* Debug Info Parameter flags */
|
|
if (!CfgPtr->EnableAllDbgFeatures) {
|
|
if (CfgPtr->S2MmThresRegEn) {
|
|
WrChannel->DbgFeatureFlags |=
|
|
XAXIVDMA_ENABLE_DBG_THRESHOLD_REG;
|
|
}
|
|
|
|
if (CfgPtr->S2MmFrmStoreRegEn) {
|
|
WrChannel->DbgFeatureFlags |=
|
|
XAXIVDMA_ENABLE_DBG_FRMSTORE_REG;
|
|
}
|
|
|
|
if (CfgPtr->S2MmDlyCntrEn) {
|
|
WrChannel->DbgFeatureFlags |=
|
|
XAXIVDMA_ENABLE_DBG_DLY_CNTR;
|
|
}
|
|
|
|
if (CfgPtr->S2MmFrmCntrEn) {
|
|
WrChannel->DbgFeatureFlags |=
|
|
XAXIVDMA_ENABLE_DBG_FRM_CNTR;
|
|
}
|
|
|
|
} else {
|
|
WrChannel->DbgFeatureFlags =
|
|
XAXIVDMA_ENABLE_DBG_ALL_FEATURES;
|
|
}
|
|
|
|
XAxiVdma_ChannelInit(WrChannel);
|
|
|
|
XAxiVdma_ChannelReset(WrChannel);
|
|
|
|
/* At time of initialization, no transfers are going on,
|
|
* reset is expected to be quick
|
|
*/
|
|
Polls = INITIALIZATION_POLLING;
|
|
|
|
while (Polls && XAxiVdma_ChannelResetNotDone(WrChannel)) {
|
|
Polls -= 1;
|
|
}
|
|
|
|
if (!Polls) {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"Write channel reset failed %x\n\r",
|
|
(unsigned int)XAxiVdma_ChannelGetStatus(WrChannel));
|
|
|
|
return XST_FAILURE;
|
|
}
|
|
}
|
|
|
|
InstancePtr->IsReady = XAXIVDMA_DEVICE_READY;
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* This function resets one DMA channel
|
|
*
|
|
* The registers will be default values after the reset
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE
|
|
*
|
|
* @return
|
|
* None
|
|
*
|
|
* @note
|
|
* Due to undeterminism of system delays, check the reset status through
|
|
* XAxiVdma_ResetNotDone(). If direction is invalid, do nothing.
|
|
*****************************************************************************/
|
|
void XAxiVdma_Reset(XAxiVdma *InstancePtr, u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (!Channel) {
|
|
return;
|
|
}
|
|
|
|
if (Channel->IsValid) {
|
|
XAxiVdma_ChannelReset(Channel);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* This function checks one DMA channel for reset completion
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE
|
|
*
|
|
* @return
|
|
* - 0 if reset is done
|
|
* - 1 if reset is ongoing
|
|
*
|
|
* @note
|
|
* We do not check for channel validity, because channel is marked as invalid
|
|
* before reset is done
|
|
*****************************************************************************/
|
|
int XAxiVdma_ResetNotDone(XAxiVdma *InstancePtr, u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
/* If dirction is invalid, reset is never done
|
|
*/
|
|
if (!Channel) {
|
|
return 1;
|
|
}
|
|
|
|
return XAxiVdma_ChannelResetNotDone(Channel);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Check whether a DMA channel is busy
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE
|
|
*
|
|
* @return
|
|
* - Non-zero if the channel is busy
|
|
* - Zero if the channel is idle
|
|
*
|
|
*****************************************************************************/
|
|
int XAxiVdma_IsBusy(XAxiVdma *InstancePtr, u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (!Channel) {
|
|
return 0;
|
|
}
|
|
|
|
if (Channel->IsValid) {
|
|
return XAxiVdma_ChannelIsBusy(Channel);
|
|
}
|
|
else {
|
|
/* An invalid channel is never busy
|
|
*/
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Get the current frame that hardware is working on
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE
|
|
*
|
|
* @return
|
|
* The current frame that the hardware is working on
|
|
*
|
|
* @note
|
|
* If returned frame number is out of range, then the channel is invalid
|
|
*****************************************************************************/
|
|
u32 XAxiVdma_CurrFrameStore(XAxiVdma *InstancePtr, u16 Direction)
|
|
{
|
|
u32 Rc;
|
|
|
|
Rc = XAxiVdma_ReadReg(InstancePtr->BaseAddr, XAXIVDMA_PARKPTR_OFFSET);
|
|
|
|
if (Direction == XAXIVDMA_READ) {
|
|
Rc &= XAXIVDMA_PARKPTR_READSTR_MASK;
|
|
return (Rc >> XAXIVDMA_READSTR_SHIFT);
|
|
}
|
|
else if (Direction == XAXIVDMA_WRITE) {
|
|
Rc &= XAXIVDMA_PARKPTR_WRTSTR_MASK;
|
|
return (Rc >> XAXIVDMA_WRTSTR_SHIFT);
|
|
}
|
|
else {
|
|
return 0xFFFFFFFF;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Get the version of the hardware
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
*
|
|
* @return
|
|
* The version of the hardware
|
|
*
|
|
*****************************************************************************/
|
|
u32 XAxiVdma_GetVersion(XAxiVdma *InstancePtr)
|
|
{
|
|
return XAxiVdma_ReadReg(InstancePtr->BaseAddr, XAXIVDMA_VERSION_OFFSET);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Get the status of a channel
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE
|
|
*
|
|
* @return
|
|
* The status of the channel
|
|
*
|
|
* @note
|
|
* An invalid return value indicates that channel is invalid
|
|
*****************************************************************************/
|
|
u32 XAxiVdma_GetStatus(XAxiVdma *InstancePtr, u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (!Channel) {
|
|
return 0xFFFFFFFF;
|
|
}
|
|
|
|
if (Channel->IsValid) {
|
|
return XAxiVdma_ChannelGetStatus(Channel);
|
|
}
|
|
else {
|
|
return 0xFFFFFFFF;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Configure Line Buffer Threshold
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param LineBufThreshold is the value to set threshold
|
|
* @param Direction is the DMA channel to work on
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if successful
|
|
* - XST_FAILURE otherwise
|
|
* - XST_NO_FEATURE if access to Threshold register is disabled
|
|
*****************************************************************************/
|
|
int XAxiVdma_SetLineBufThreshold(XAxiVdma *InstancePtr, int LineBufThreshold,
|
|
u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (!(Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_THRESHOLD_REG)) {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"Threshold Register is disabled\n\r");
|
|
return XST_NO_FEATURE;
|
|
}
|
|
|
|
if(Channel->LineBufThreshold) {
|
|
if((LineBufThreshold < Channel->LineBufDepth) &&
|
|
(LineBufThreshold % Channel->StreamWidth == 0)) {
|
|
XAxiVdma_WriteReg(Channel->ChanBase,
|
|
XAXIVDMA_BUFTHRES_OFFSET, LineBufThreshold);
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"Line Buffer Threshold set to %x\n\r",
|
|
XAxiVdma_ReadReg(Channel->ChanBase,
|
|
XAXIVDMA_BUFTHRES_OFFSET));
|
|
}
|
|
else {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"Invalid Line Buffer Threshold\n\r");
|
|
return XST_FAILURE;
|
|
}
|
|
}
|
|
else {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"Failed to set Threshold\n\r");
|
|
return XST_FAILURE;
|
|
}
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Configure Frame Sync Source and valid only when C_USE_FSYNC is enabled.
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param Source is the value to set the source of Frame Sync
|
|
* @param Direction is the DMA channel to work on
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if successful
|
|
* - XST_FAILURE if C_USE_FSYNC is disabled.
|
|
*
|
|
*****************************************************************************/
|
|
int XAxiVdma_FsyncSrcSelect(XAxiVdma *InstancePtr, u32 Source,
|
|
u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
u32 CrBits;
|
|
u32 UseFsync;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (Direction == XAXIVDMA_WRITE) {
|
|
UseFsync = ((InstancePtr->UseFsync == 1) ||
|
|
(InstancePtr->UseFsync == 3)) ? 1 : 0;
|
|
} else {
|
|
UseFsync = ((InstancePtr->UseFsync == 1) ||
|
|
(InstancePtr->UseFsync == 2)) ? 1 : 0;
|
|
}
|
|
|
|
if (UseFsync) {
|
|
CrBits = XAxiVdma_ReadReg(Channel->ChanBase,
|
|
XAXIVDMA_CR_OFFSET);
|
|
|
|
switch (Source) {
|
|
case XAXIVDMA_CHAN_FSYNC:
|
|
/* Same Channel Frame Sync */
|
|
CrBits &= ~(XAXIVDMA_CR_FSYNC_SRC_MASK);
|
|
break;
|
|
|
|
case XAXIVDMA_CHAN_OTHER_FSYNC:
|
|
/* The other Channel Frame Sync */
|
|
CrBits |= (XAXIVDMA_CR_FSYNC_SRC_MASK & ~(1 << 6));
|
|
break;
|
|
|
|
case XAXIVDMA_S2MM_TUSER_FSYNC:
|
|
/* S2MM TUser Sync */
|
|
if (Channel->S2MmSOF) {
|
|
CrBits |= (XAXIVDMA_CR_FSYNC_SRC_MASK
|
|
& ~(1 << 5));
|
|
}
|
|
else
|
|
return XST_FAILURE;
|
|
break;
|
|
}
|
|
|
|
XAxiVdma_WriteReg(Channel->ChanBase,
|
|
XAXIVDMA_CR_OFFSET, CrBits);
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"This bit is not valid for this configuration\n\r");
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Configure Gen Lock Source
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param Source is the value to set the source of Gen Lock
|
|
* @param Direction is the DMA channel to work on
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if successful
|
|
* - XST_FAILURE if the channel is in GenLock Master Mode.
|
|
* if C_INCLUDE_INTERNAL_GENLOCK is disabled.
|
|
*
|
|
*****************************************************************************/
|
|
int XAxiVdma_GenLockSourceSelect(XAxiVdma *InstancePtr, u32 Source,
|
|
u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel, *XChannel;
|
|
u32 CrBits;
|
|
|
|
if (InstancePtr->HasMm2S && InstancePtr->HasS2Mm &&
|
|
InstancePtr->InternalGenLock) {
|
|
if (Direction == XAXIVDMA_WRITE) {
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
XChannel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_READ);
|
|
} else {
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
XChannel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_WRITE);
|
|
}
|
|
|
|
if ((Channel->GenLock == XAXIVDMA_GENLOCK_MASTER &&
|
|
XChannel->GenLock == XAXIVDMA_GENLOCK_SLAVE) ||
|
|
(Channel->GenLock == XAXIVDMA_GENLOCK_SLAVE &&
|
|
XChannel->GenLock == XAXIVDMA_GENLOCK_MASTER) ||
|
|
(Channel->GenLock == XAXIVDMA_DYN_GENLOCK_MASTER &&
|
|
XChannel->GenLock == XAXIVDMA_DYN_GENLOCK_SLAVE) ||
|
|
(Channel->GenLock == XAXIVDMA_DYN_GENLOCK_SLAVE &&
|
|
XChannel->GenLock == XAXIVDMA_DYN_GENLOCK_MASTER)) {
|
|
|
|
CrBits = XAxiVdma_ReadReg(Channel->ChanBase,
|
|
XAXIVDMA_CR_OFFSET);
|
|
|
|
if (Source == XAXIVDMA_INTERNAL_GENLOCK)
|
|
CrBits |= XAXIVDMA_CR_GENLCK_SRC_MASK;
|
|
else if (Source == XAXIVDMA_EXTERNAL_GENLOCK)
|
|
CrBits &= ~XAXIVDMA_CR_GENLCK_SRC_MASK;
|
|
else {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"Invalid argument\n\r");
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
XAxiVdma_WriteReg(Channel->ChanBase,
|
|
XAXIVDMA_CR_OFFSET, CrBits);
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"This bit is not valid for this configuration\n\r");
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Start parking mode on a certain frame
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param FrameIndex is the frame to park on
|
|
* @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if everything is fine
|
|
* - XST_INVALID_PARAM if
|
|
* . channel is invalid
|
|
* . FrameIndex is invalid
|
|
* . Direction is invalid
|
|
*****************************************************************************/
|
|
int XAxiVdma_StartParking(XAxiVdma *InstancePtr, int FrameIndex,
|
|
u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
u32 FrmBits;
|
|
u32 RegValue;
|
|
int Status;
|
|
|
|
if (FrameIndex > XAXIVDMA_FRM_MAX) {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"Invalid frame to park on %d\r\n", FrameIndex);
|
|
|
|
return XST_INVALID_PARAM;
|
|
}
|
|
|
|
if (Direction == XAXIVDMA_READ) {
|
|
FrmBits = FrameIndex &
|
|
XAXIVDMA_PARKPTR_READREF_MASK;
|
|
|
|
RegValue = XAxiVdma_ReadReg(InstancePtr->BaseAddr,
|
|
XAXIVDMA_PARKPTR_OFFSET);
|
|
|
|
RegValue &= ~XAXIVDMA_PARKPTR_READREF_MASK;
|
|
|
|
RegValue |= FrmBits;
|
|
|
|
XAxiVdma_WriteReg(InstancePtr->BaseAddr,
|
|
XAXIVDMA_PARKPTR_OFFSET, RegValue);
|
|
}
|
|
else if (Direction == XAXIVDMA_WRITE) {
|
|
FrmBits = FrameIndex << XAXIVDMA_WRTREF_SHIFT;
|
|
|
|
FrmBits &= XAXIVDMA_PARKPTR_WRTREF_MASK;
|
|
|
|
RegValue = XAxiVdma_ReadReg(InstancePtr->BaseAddr,
|
|
XAXIVDMA_PARKPTR_OFFSET);
|
|
|
|
RegValue &= ~XAXIVDMA_PARKPTR_WRTREF_MASK;
|
|
|
|
RegValue |= FrmBits;
|
|
|
|
XAxiVdma_WriteReg(InstancePtr->BaseAddr,
|
|
XAXIVDMA_PARKPTR_OFFSET, RegValue);
|
|
}
|
|
else {
|
|
/* Invalid direction, do nothing
|
|
*/
|
|
return XST_INVALID_PARAM;
|
|
}
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (Channel->IsValid) {
|
|
Status = XAxiVdma_ChannelStartParking(Channel);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"Failed to start channel %x\r\n",
|
|
(unsigned int)Channel);
|
|
|
|
return XST_FAILURE;
|
|
}
|
|
}
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Exit parking mode, the channel will return to circular buffer mode
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE
|
|
*
|
|
* @return
|
|
* None
|
|
*
|
|
* @note
|
|
* If channel is invalid, then do nothing
|
|
*****************************************************************************/
|
|
void XAxiVdma_StopParking(XAxiVdma *InstancePtr, u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (!Channel) {
|
|
return;
|
|
}
|
|
|
|
if (Channel->IsValid) {
|
|
XAxiVdma_ChannelStopParking(Channel);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Start frame count enable on one channel
|
|
*
|
|
* This is needed to start limiting the number of frames to transfer so that
|
|
* software can check the data etc after hardware stops transfer.
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE
|
|
*
|
|
* @return
|
|
* None
|
|
*
|
|
*****************************************************************************/
|
|
void XAxiVdma_StartFrmCntEnable(XAxiVdma *InstancePtr, u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (Channel->IsValid) {
|
|
XAxiVdma_ChannelStartFrmCntEnable(Channel);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Set BD addresses to be different.
|
|
*
|
|
* In some systems, it is convenient to put BDs into a certain region of the
|
|
* memory. This function enables that.
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param BdAddrPhys is the physical starting address for BDs
|
|
* @param BdAddrVirt is the Virtual starting address for BDs. For systems that
|
|
* do not use MMU, then virtual address is the same as physical address
|
|
* @param NumBds is the number of BDs to setup with. This is required to be
|
|
* the same as the number of frame stores for that channel
|
|
* @param Direction is the channel direction
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS for a successful setup
|
|
* - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used
|
|
* - XST_INVALID_PARAM if parameters not valid
|
|
* - XST_DEVICE_NOT_FOUND if the channel is invalid
|
|
*
|
|
* @notes
|
|
* We assume that the memory region starting from BdAddrPhys and BdAddrVirt are
|
|
* large enough to hold all the BDs.
|
|
*****************************************************************************/
|
|
int XAxiVdma_SetBdAddrs(XAxiVdma *InstancePtr, u32 BdAddrPhys, u32 BdAddrVirt,
|
|
int NumBds, u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (Channel->IsValid) {
|
|
if (NumBds != Channel->AllCnt) {
|
|
return XST_INVALID_PARAM;
|
|
}
|
|
|
|
if (BdAddrPhys & (XAXIVDMA_BD_MINIMUM_ALIGNMENT - 1)) {
|
|
return XST_INVALID_PARAM;
|
|
}
|
|
|
|
if (BdAddrVirt & (XAXIVDMA_BD_MINIMUM_ALIGNMENT - 1)) {
|
|
return XST_INVALID_PARAM;
|
|
}
|
|
|
|
return XAxiVdma_ChannelSetBdAddrs(Channel, BdAddrPhys, BdAddrVirt);
|
|
}
|
|
else {
|
|
return XST_DEVICE_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Start a write operation
|
|
*
|
|
* Write corresponds to send data from device to memory
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param DmaConfigPtr is the pointer to the setup structure
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS for a successful submission
|
|
* - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used
|
|
* - XST_INVAID_PARAM if parameters in config structure not valid
|
|
* - XST_DEVICE_NOT_FOUND if the channel is invalid
|
|
*
|
|
*****************************************************************************/
|
|
int XAxiVdma_StartWriteFrame(XAxiVdma *InstancePtr,
|
|
XAxiVdma_DmaSetup *DmaConfigPtr)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_WRITE);
|
|
|
|
if (Channel->IsValid) {
|
|
return XAxiVdma_ChannelStartTransfer(Channel,
|
|
(XAxiVdma_ChannelSetup *)DmaConfigPtr);
|
|
}
|
|
else {
|
|
return XST_DEVICE_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Start a read operation
|
|
*
|
|
* Read corresponds to send data from memory to device
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param DmaConfigPtr is the pointer to the setup structure
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS for a successful submission
|
|
* - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used
|
|
* - XST_INVAID_PARAM if parameters in config structure not valid
|
|
* - XST_DEVICE_NOT_FOUND if the channel is invalid
|
|
*
|
|
*****************************************************************************/
|
|
int XAxiVdma_StartReadFrame(XAxiVdma *InstancePtr,
|
|
XAxiVdma_DmaSetup *DmaConfigPtr)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_READ);
|
|
|
|
if (Channel->IsValid) {
|
|
return XAxiVdma_ChannelStartTransfer(Channel,
|
|
(XAxiVdma_ChannelSetup *)DmaConfigPtr);
|
|
}
|
|
else {
|
|
return XST_DEVICE_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Configure one DMA channel using the configuration structure
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param Direction is the DMA channel to work on
|
|
* @param DmaConfigPtr is the pointer to the setup structure
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if successful
|
|
* - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used
|
|
* - XST_INVAID_PARAM if buffer address not valid, for example, unaligned
|
|
* address with no DRE built in the hardware, or Direction invalid
|
|
* - XST_DEVICE_NOT_FOUND if the channel is invalid
|
|
*
|
|
*****************************************************************************/
|
|
int XAxiVdma_DmaConfig(XAxiVdma *InstancePtr, u16 Direction,
|
|
XAxiVdma_DmaSetup *DmaConfigPtr)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (!Channel) {
|
|
return XST_INVALID_PARAM;
|
|
}
|
|
|
|
|
|
if (Channel->IsValid) {
|
|
|
|
return XAxiVdma_ChannelConfig(Channel,
|
|
(XAxiVdma_ChannelSetup *)DmaConfigPtr);
|
|
}
|
|
else {
|
|
return XST_DEVICE_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Configure buffer addresses for one DMA channel
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param Direction is the DMA channel to work on
|
|
* @param BufferAddrSet is the set of addresses for the transfers
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if successful
|
|
* - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used
|
|
* - XST_INVAID_PARAM if buffer address not valid, for example, unaligned
|
|
* address with no DRE built in the hardware, or Direction invalid
|
|
* - XST_DEVICE_NOT_FOUND if the channel is invalid
|
|
*
|
|
*****************************************************************************/
|
|
int XAxiVdma_DmaSetBufferAddr(XAxiVdma *InstancePtr, u16 Direction,
|
|
u32 *BufferAddrSet)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (!Channel) {
|
|
return XST_INVALID_PARAM;
|
|
}
|
|
|
|
if (Channel->IsValid) {
|
|
return XAxiVdma_ChannelSetBufferAddr(Channel, BufferAddrSet,
|
|
Channel->NumFrames);
|
|
}
|
|
else {
|
|
return XST_DEVICE_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Start one DMA channel
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param Direction is the DMA channel to work on
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if channel started successfully
|
|
* - XST_FAILURE otherwise
|
|
* - XST_DEVICE_NOT_FOUND if the channel is invalid
|
|
* - XST_INVALID_PARAM if Direction invalid
|
|
*
|
|
*****************************************************************************/
|
|
int XAxiVdma_DmaStart(XAxiVdma *InstancePtr, u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (!Channel) {
|
|
return XST_INVALID_PARAM;
|
|
}
|
|
|
|
if (Channel->IsValid) {
|
|
return XAxiVdma_ChannelStart(Channel);
|
|
}
|
|
else {
|
|
return XST_DEVICE_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Stop one DMA channel
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param Direction is the DMA channel to work on
|
|
*
|
|
* @return
|
|
* None
|
|
*
|
|
* @note
|
|
* If channel is invalid, then do nothing on that channel
|
|
*****************************************************************************/
|
|
void XAxiVdma_DmaStop(XAxiVdma *InstancePtr, u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (!Channel) {
|
|
return;
|
|
}
|
|
|
|
if (Channel->IsValid) {
|
|
XAxiVdma_ChannelStop(Channel);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Dump registers of one DMA channel
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param Direction is the DMA channel to work on
|
|
*
|
|
* @return
|
|
* None
|
|
*
|
|
* @note
|
|
* If channel is invalid, then do nothing on that channel
|
|
*****************************************************************************/
|
|
void XAxiVdma_DmaRegisterDump(XAxiVdma *InstancePtr, u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (!Channel) {
|
|
return;
|
|
}
|
|
|
|
if (Channel->IsValid) {
|
|
XAxiVdma_ChannelRegisterDump(Channel);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Set the frame counter and delay counter for both channels
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param CfgPtr is the pointer to the configuration structure
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if setup finishes successfully
|
|
* - XST_INVALID_PARAM if the configuration structure has invalid values
|
|
* - Others if setting channel frame counter fails
|
|
*
|
|
* @note
|
|
* If channel is invalid, then do nothing on that channel
|
|
*****************************************************************************/
|
|
int XAxiVdma_SetFrameCounter(XAxiVdma *InstancePtr,
|
|
XAxiVdma_FrameCounter *CfgPtr)
|
|
{
|
|
int Status;
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
/* Validate parameters */
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == XAXIVDMA_DEVICE_READY);
|
|
Xil_AssertNonvoid(CfgPtr != NULL);
|
|
|
|
if ((CfgPtr->ReadFrameCount == 0) ||
|
|
(CfgPtr->WriteFrameCount == 0)) {
|
|
|
|
return XST_INVALID_PARAM;
|
|
}
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_READ);
|
|
|
|
if (Channel->IsValid) {
|
|
|
|
Status = XAxiVdma_ChannelSetFrmCnt(Channel, CfgPtr->ReadFrameCount,
|
|
CfgPtr->ReadDelayTimerCount);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"Setting read channel frame counter "
|
|
"failed with %d\r\n", Status);
|
|
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_WRITE);
|
|
|
|
if (Channel->IsValid) {
|
|
|
|
Status = XAxiVdma_ChannelSetFrmCnt(Channel,
|
|
CfgPtr->WriteFrameCount,
|
|
CfgPtr->WriteDelayTimerCount);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"Setting write channel frame counter "
|
|
"failed with %d\r\n", Status);
|
|
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Get the frame counter and delay counter for both channels
|
|
*
|
|
* @param InstancePtr is the pointer to the DMA engine to work on
|
|
* @param CfgPtr is the configuration structure to contain return values
|
|
*
|
|
* @return
|
|
* None
|
|
*
|
|
* @note
|
|
* If returned frame counter value is 0, then the channel is not valid
|
|
*****************************************************************************/
|
|
void XAxiVdma_GetFrameCounter(XAxiVdma *InstancePtr,
|
|
XAxiVdma_FrameCounter *CfgPtr)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
u8 FrmCnt;
|
|
u8 DlyCnt;
|
|
|
|
/* Validate parameters */
|
|
Xil_AssertVoid(InstancePtr != NULL);
|
|
Xil_AssertVoid(InstancePtr->IsReady == XAXIVDMA_DEVICE_READY);
|
|
Xil_AssertVoid(CfgPtr != NULL);
|
|
|
|
/* Use a zero frame counter value to indicate failure
|
|
*/
|
|
FrmCnt = 0;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_READ);
|
|
|
|
if (Channel->IsValid) {
|
|
XAxiVdma_ChannelGetFrmCnt(Channel, &FrmCnt, &DlyCnt);
|
|
}
|
|
|
|
CfgPtr->ReadFrameCount = FrmCnt;
|
|
CfgPtr->ReadDelayTimerCount = DlyCnt;
|
|
|
|
/* Use a zero frame counter value to indicate failure
|
|
*/
|
|
FrmCnt = 0;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_WRITE);
|
|
|
|
if (Channel->IsValid) {
|
|
XAxiVdma_ChannelGetFrmCnt(Channel, &FrmCnt, &DlyCnt);
|
|
}
|
|
|
|
CfgPtr->WriteFrameCount = FrmCnt;
|
|
CfgPtr->WriteDelayTimerCount = DlyCnt;
|
|
|
|
return;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Set the number of frame store buffers to use.
|
|
*
|
|
* @param InstancePtr is the XAxiVdma instance to operate on
|
|
* @param FrmStoreNum is the number of frame store buffers to use.
|
|
* @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE
|
|
*
|
|
* @return - XST_SUCCESS if operation is successful
|
|
* - XST_FAILURE if operation fails.
|
|
* - XST_NO_FEATURE if access to FrameStore register is disabled
|
|
* @note None
|
|
*
|
|
*****************************************************************************/
|
|
int XAxiVdma_SetFrmStore(XAxiVdma *InstancePtr, u8 FrmStoreNum, u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
if(FrmStoreNum > InstancePtr->MaxNumFrames) {
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (!Channel) {
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
if(XAxiVdma_ChannelIsRunning(Channel)) {
|
|
xdbg_printf(XDBG_DEBUG_ERROR, "Cannot set frame store..."
|
|
"channel is running\r\n");
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
if (!(Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_FRMSTORE_REG)) {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"Frame Store Register is disabled\n\r");
|
|
return XST_NO_FEATURE;
|
|
}
|
|
|
|
XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_FRMSTORE_OFFSET,
|
|
FrmStoreNum & XAXIVDMA_FRMSTORE_MASK);
|
|
|
|
Channel->NumFrames = FrmStoreNum;
|
|
|
|
XAxiVdma_ChannelInit(Channel);
|
|
|
|
return XST_SUCCESS;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Get the number of frame store buffers to use.
|
|
*
|
|
* @param InstancePtr is the XAxiVdma instance to operate on
|
|
* @param FrmStoreNum is the number of frame store buffers to use.
|
|
* @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE
|
|
*
|
|
* @return None
|
|
*
|
|
* @note None
|
|
*
|
|
*****************************************************************************/
|
|
void XAxiVdma_GetFrmStore(XAxiVdma *InstancePtr, u8 *FrmStoreNum,
|
|
u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (!Channel) {
|
|
return;
|
|
}
|
|
|
|
if (Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_FRMSTORE_REG) {
|
|
*FrmStoreNum = (XAxiVdma_ReadReg(Channel->ChanBase,
|
|
XAXIVDMA_FRMSTORE_OFFSET)) & XAXIVDMA_FRMSTORE_MASK;
|
|
} else {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"Frame Store Register is disabled\n\r");
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Check for DMA Channel Errors.
|
|
*
|
|
* @param InstancePtr is the XAxiVdma instance to operate on
|
|
* @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE
|
|
*
|
|
* @return - Errors seen on the channel
|
|
* - XST_INVALID_PARAM, when channel pointer is invalid.
|
|
* - XST_DEVICE_NOT_FOUND, when the channel is not valid.
|
|
*
|
|
* @note None
|
|
*
|
|
*****************************************************************************/
|
|
int XAxiVdma_GetDmaChannelErrors(XAxiVdma *InstancePtr, u16 Direction)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (!Channel) {
|
|
return XST_INVALID_PARAM;
|
|
}
|
|
|
|
if (Channel->IsValid) {
|
|
return XAxiVdma_ChannelErrors(Channel);
|
|
}
|
|
else {
|
|
return XST_DEVICE_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Clear DMA Channel Errors.
|
|
*
|
|
* @param InstancePtr is the XAxiVdma instance to operate on
|
|
* @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE
|
|
* @param ErrorMask is the mask of error bits to clear
|
|
*
|
|
* @return - XST_SUCCESS, when error bits are cleared.
|
|
* - XST_INVALID_PARAM, when channel pointer is invalid.
|
|
* - XST_DEVICE_NOT_FOUND, when the channel is not valid.
|
|
*
|
|
* @note None
|
|
*
|
|
*****************************************************************************/
|
|
int XAxiVdma_ClearDmaChannelErrors(XAxiVdma *InstancePtr, u16 Direction,
|
|
u32 ErrorMask)
|
|
{
|
|
XAxiVdma_Channel *Channel;
|
|
|
|
Channel = XAxiVdma_GetChannel(InstancePtr, Direction);
|
|
|
|
if (!Channel) {
|
|
return XST_INVALID_PARAM;
|
|
}
|
|
|
|
if (Channel->IsValid) {
|
|
XAxiVdma_ClearChannelErrors(Channel, ErrorMask);
|
|
return XST_SUCCESS;
|
|
}
|
|
else {
|
|
return XST_DEVICE_NOT_FOUND;
|
|
}
|
|
}
|
|
|