/**
 * Check whether a DMA channel is busy
 *
 * @param Channel is the pointer to the channel to work on
 *
 * @return
 * - non zero if the channel is busy
 * - 0 is the channel is idle
 *
 *****************************************************************************/
int XAxiVdma_ChannelIsBusy(XAxiVdma_Channel *Channel)
{
	u32 Bits;

	/* If the channel is idle, then it is not busy
	 */
	Bits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET) &
	          XAXIVDMA_SR_IDLE_MASK;

	if (Bits) {
		return 0;
	}

	/* If the channel is halted, then it is not busy
	 */
	Bits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET) &
	          XAXIVDMA_SR_HALTED_MASK;

	if (Bits) {
		return 0;
	}

	/* Otherwise, it is busy
	 */
	return 1;
}
/**
 * Dump registers from one DMA channel
 *
 * @param Channel is the pointer to the channel to work on
 *
 * @return
 *  None
 *
 *****************************************************************************/
void XAxiVdma_ChannelRegisterDump(XAxiVdma_Channel *Channel)
{
	xil_printf("Dump register for channel %x:\r\n", Channel->ChanBase);
	xil_printf("\tControl Reg: %x\r\n",
	    XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET));
	xil_printf("\tStatus Reg: %x\r\n",
	    XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET));
	xil_printf("\tCDESC Reg: %x\r\n",
	    XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CDESC_OFFSET));
	xil_printf("\tTDESC Reg: %x\r\n",
	    XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_TDESC_OFFSET));

	return;
}
Пример #3
0
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);
}
/**
 * Set the channel to run in circular mode, exiting parking mode
 *
 * @param Channel is the pointer to the channel to work on
 *
 * @return
 *   None
 *
 *****************************************************************************/
void XAxiVdma_ChannelStopParking(XAxiVdma_Channel *Channel)
{
	u32 CrBits;

	CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) |
	            XAXIVDMA_CR_TAIL_EN_MASK;

	XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET,
	    CrBits);

	return;
}
/**
 * Set the channel to run in frame count enable mode
 *
 * @param Channel is the pointer to the channel to work on
 *
 * @return
 *   None
 *
 *****************************************************************************/
void XAxiVdma_ChannelStartFrmCntEnable(XAxiVdma_Channel *Channel)
{
	u32 CrBits;

	CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) |
	            XAXIVDMA_CR_FRMCNT_EN_MASK;

	XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET,
	    CrBits);

	return;
}
/*
 * Clear DMA channel errors
 *
 * @param Channel is the pointer to the channel to work on
 * @param ErrorMask is the mask of error bits to clear.
 *
 * @return
 *  	None
 *
 *****************************************************************************/
void XAxiVdma_ClearChannelErrors(XAxiVdma_Channel *Channel, u32 ErrorMask)
{
	u32 SrBits;

	/* Write on Clear bits */
        SrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET)
                        | ErrorMask;

	XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET,
	    SrBits);

	return;
}
/*
 * Check whether a DMA channel is running
 *
 * @param Channel is the pointer to the channel to work on
 *
 * @return
 * - non zero if the channel is running
 * - 0 is the channel is idle
 *
 *****************************************************************************/
int XAxiVdma_ChannelIsRunning(XAxiVdma_Channel *Channel)
{
	u32 Bits;

	/* If halted bit set, channel is not running
	 */
	Bits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET) &
	          XAXIVDMA_SR_HALTED_MASK;

	if (Bits) {
		return 0;
	}

	/* If Run/Stop bit low, then channel is not running
	 */
	Bits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) &
	          XAXIVDMA_CR_RUNSTOP_MASK;

	if (!Bits) {
		return 0;
	}

	return 1;
}
/**
 * Stop one DMA channel
 *
 * @param Channel is the pointer to the channel to work on
 *
 * @return
 *  None
 *
 *****************************************************************************/
void XAxiVdma_ChannelStop(XAxiVdma_Channel *Channel)
{
	u32 CrBits;

	if (!XAxiVdma_ChannelIsRunning(Channel)) {
		return;
	}

	/* Clear the RS bit in CR register
	 */
	CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) &
		(~XAXIVDMA_CR_RUNSTOP_MASK);

	XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET, CrBits);

	return;
}
/**
 * Get the frame counter and delay counter for both channels
 *
 * @param Channel is the pointer to the channel to work on
 * @param FrmCnt is the pointer for the returning frame counter value
 * @param DlyCnt is the pointer for the returning delay counter value
 *
 * @return
 *  None
 *
 * @note
 *  If FrmCnt return as 0, then the channel is not initialized
 *****************************************************************************/
void XAxiVdma_ChannelGetFrmCnt(XAxiVdma_Channel *Channel, u8 *FrmCnt,
        u8 *DlyCnt)
{
	u32 CrBits;

	if (!Channel->IsValid) {
		xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n");

		*FrmCnt = 0;
		return;
	}

	CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET);

	if (Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_FRM_CNTR) {
		*FrmCnt = (CrBits & XAXIVDMA_FRMCNT_MASK) >>
				XAXIVDMA_FRMCNT_SHIFT;
	} else {
/**
 * Set the channel to run in parking mode
 *
 * @param Channel is the pointer to the channel to work on
 *
 * @return
 *   - XST_SUCCESS if everything is fine
 *   - XST_FAILURE if hardware is not running
 *
 *****************************************************************************/
int XAxiVdma_ChannelStartParking(XAxiVdma_Channel *Channel)
{
	u32 CrBits;

	if (!XAxiVdma_ChannelIsRunning(Channel)) {
		xdbg_printf(XDBG_DEBUG_ERROR,
		    "Channel is not running, cannot start park mode\r\n");

		return XST_FAILURE;
	}

	CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) &
	            ~XAXIVDMA_CR_TAIL_EN_MASK;

	XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET,
	    CrBits);

	return XST_SUCCESS;
}
/**
 * Set the frame counter and delay counter for one channel
 *
 * @param Channel is the pointer to the channel to work on
 * @param FrmCnt is the frame counter value to be set
 * @param DlyCnt is the delay counter value to be set
 *
 * @return
 *   - XST_SUCCESS if setup finishes successfully
 *   - XST_FAILURE if channel is not initialized
 *   - XST_INVALID_PARAM if the configuration structure has invalid values
 *   - XST_NO_FEATURE if Frame Counter or Delay Counter is disabled
 *
 *****************************************************************************/
int XAxiVdma_ChannelSetFrmCnt(XAxiVdma_Channel *Channel, u8 FrmCnt, u8 DlyCnt)
{
	u32 CrBits;

	if (!Channel->IsValid) {
		xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n");

		return XST_FAILURE;
	}

	if (!FrmCnt) {
		xdbg_printf(XDBG_DEBUG_ERROR,
		    "Frame counter value must be non-zero\r\n");

		return XST_INVALID_PARAM;
	}

	CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) &
		~(XAXIVDMA_DELAY_MASK | XAXIVDMA_FRMCNT_MASK);

	if (Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_FRM_CNTR) {
		CrBits |= (FrmCnt << XAXIVDMA_FRMCNT_SHIFT);
	} else {
		xdbg_printf(XDBG_DEBUG_ERROR,
		    "Channel Frame counter is disabled\r\n");
		return XST_NO_FEATURE;
	}
	if (Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_DLY_CNTR) {
		CrBits |= (DlyCnt << XAXIVDMA_DELAY_SHIFT);
	} else {
		xdbg_printf(XDBG_DEBUG_ERROR,
		    "Channel Delay counter is disabled\r\n");
		return XST_NO_FEATURE;
	}

	XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET,
	    CrBits);

	return XST_SUCCESS;
}
Пример #12
0
/**
 * 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;
		}
	}
/**
 * Start one DMA channel
 *
 * @param Channel is the pointer to the channel to work on
 *
 * @return
 * - XST_SUCCESS if successful
 * - XST_FAILURE if channel is not initialized
 * - XST_DMA_ERROR if:
 *   . The DMA channel fails to stop
 *   . The DMA channel fails to start
 * - XST_DEVICE_BUSY is the channel is doing transfers
 *
 *****************************************************************************/
int XAxiVdma_ChannelStart(XAxiVdma_Channel *Channel)
{
	u32 CrBits;

	if (!Channel->IsValid) {
		xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n");

		return XST_FAILURE;
	}

	if (Channel->HasSG && XAxiVdma_ChannelIsBusy(Channel)) {

		xdbg_printf(XDBG_DEBUG_ERROR,
		    "Start DMA channel while channel is busy\r\n");

		return XST_DEVICE_BUSY;
	}

	/* If channel is not running, setup the CDESC register and
	 * set the channel to run
	 */
	if (!XAxiVdma_ChannelIsRunning(Channel)) {

		if (Channel->HasSG) {
			/* Set up the current bd register
			 *
			 * Can only setup current bd register when channel is halted
			 */
			XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CDESC_OFFSET,
			    Channel->HeadBdPhysAddr);
		}

		/* Start DMA hardware
		 */
		CrBits = XAxiVdma_ReadReg(Channel->ChanBase,
		     XAXIVDMA_CR_OFFSET);

		CrBits = XAxiVdma_ReadReg(Channel->ChanBase,
		     XAXIVDMA_CR_OFFSET) | XAXIVDMA_CR_RUNSTOP_MASK;

		XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET,
		    CrBits);

	}

	if (XAxiVdma_ChannelIsRunning(Channel)) {

		/* Start DMA transfers
		 *
		 */

		if (Channel->HasSG) {
			/* SG mode:
			 * Update the tail pointer so that hardware will start
			 * fetching BDs
			 */
			XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_TDESC_OFFSET,
			   Channel->TailBdPhysAddr);
		}
		else {
			/* Direct register mode:
			 * Update vsize to start the channel
			 */
			XAxiVdma_WriteReg(Channel->StartAddrBase,
			    XAXIVDMA_VSIZE_OFFSET, Channel->Vsize);

		}

		return XST_SUCCESS;
	}
	else {
		xdbg_printf(XDBG_DEBUG_ERROR,
		    "Failed to start channel %x\r\n",
			    (unsigned int)Channel->ChanBase);

		return XST_DMA_ERROR;
	}
}
/**
 * Configure one DMA channel using the configuration structure
 *
 * Setup the control register and BDs, however, BD addresses are not set.
 *
 * @param Channel is the pointer to the channel to work on
 * @param ChannelCfgPtr is the pointer to the setup structure
 *
 * @return
 * - XST_SUCCESS if successful
 * - XST_FAILURE if channel has not being initialized
 * - XST_DEVICE_BUSY if the DMA channel is not idle
 * - XST_INVALID_PARAM if fields in ChannelCfgPtr is not valid
 *
 *****************************************************************************/
int XAxiVdma_ChannelConfig(XAxiVdma_Channel *Channel,
        XAxiVdma_ChannelSetup *ChannelCfgPtr)
{
	u32 CrBits;
	int i;
	int NumBds;
	int Status;
	u32 hsize_align;
	u32 stride_align;

	if (!Channel->IsValid) {
		//xil_printf("Channel not initialized\r\n");
		xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n");

		return XST_FAILURE;
	}

	if (Channel->HasSG && XAxiVdma_ChannelIsBusy(Channel)) {
		xdbg_printf(XDBG_DEBUG_ERROR,
		    "Channel is busy, cannot config!\r\n");
		//xil_printf("Channel is busy, cannot config!\r\n");
		return XST_DEVICE_BUSY;
	}

	Channel->Vsize = ChannelCfgPtr->VertSizeInput;

	/* Check whether Hsize is properly aligned */
	if (Channel->direction == XAXIVDMA_WRITE) {
		if (ChannelCfgPtr->HoriSizeInput < Channel->WordLength) {
			hsize_align = (u32)Channel->WordLength;
		} else {
			hsize_align =
				(u32)(ChannelCfgPtr->HoriSizeInput % Channel->WordLength);
			if (hsize_align > 0)
				hsize_align = (Channel->WordLength - hsize_align);
		}
	} else {
		if (ChannelCfgPtr->HoriSizeInput < Channel->WordLength) {
			hsize_align = (u32)Channel->WordLength;
		} else {
			hsize_align =
				(u32)(ChannelCfgPtr->HoriSizeInput % Channel->StreamWidth);
			if (hsize_align > 0)
				hsize_align = (Channel->StreamWidth - hsize_align);
		}
	}

	/* Check whether Stride is properly aligned */
	if (ChannelCfgPtr->Stride < Channel->WordLength) {
		stride_align = (u32)Channel->WordLength;
	} else {
		stride_align = (u32)(ChannelCfgPtr->Stride % Channel->WordLength);
		if (stride_align > 0)
			stride_align = (Channel->WordLength - stride_align);
	}

	/* If hardware has no DRE, then Hsize and Stride must
	 * be word-aligned
	 */
	if (!Channel->HasDRE) {
		if (hsize_align != 0) {
			/* Adjust hsize to multiples of stream/mm data width*/
			ChannelCfgPtr->HoriSizeInput += hsize_align;
		}
		if (stride_align != 0) {
			/* Adjust stride to multiples of stream/mm data width*/
			ChannelCfgPtr->Stride += stride_align;
		}
	}

	Channel->Hsize = ChannelCfgPtr->HoriSizeInput;

	CrBits = XAxiVdma_ReadReg(Channel->ChanBase,
	     XAXIVDMA_CR_OFFSET);

	CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) &
	    ~(XAXIVDMA_CR_TAIL_EN_MASK | XAXIVDMA_CR_SYNC_EN_MASK |
	      XAXIVDMA_CR_FRMCNT_EN_MASK | XAXIVDMA_CR_RD_PTR_MASK);

	if (ChannelCfgPtr->EnableCircularBuf) {
		CrBits |= XAXIVDMA_CR_TAIL_EN_MASK;
	}
	else {
		/* Park mode */
		u32 FrmBits;
		u32 RegValue;

		if ((!XAxiVdma_ChannelIsRunning(Channel)) &&
		    Channel->HasSG) {
			xdbg_printf(XDBG_DEBUG_ERROR,
			    "Channel is not running, cannot set park mode\r\n");

			return XST_INVALID_PARAM;
		}

		if (ChannelCfgPtr->FixedFrameStoreAddr > XAXIVDMA_FRM_MAX) {
			//xil_printf("Invalid frame to park on\n\r");
			xdbg_printf(XDBG_DEBUG_ERROR,
			    "Invalid frame to park on %d\r\n",
			    ChannelCfgPtr->FixedFrameStoreAddr);

			return XST_INVALID_PARAM;
		}

		if (Channel->IsRead) {
			FrmBits = ChannelCfgPtr->FixedFrameStoreAddr &
			              XAXIVDMA_PARKPTR_READREF_MASK;

			RegValue = XAxiVdma_ReadReg(Channel->InstanceBase,
			              XAXIVDMA_PARKPTR_OFFSET);

			RegValue &= ~XAXIVDMA_PARKPTR_READREF_MASK;

			RegValue |= FrmBits;

			XAxiVdma_WriteReg(Channel->InstanceBase,
			    XAXIVDMA_PARKPTR_OFFSET, RegValue);
		}
		else {
			FrmBits = ChannelCfgPtr->FixedFrameStoreAddr <<
			            XAXIVDMA_WRTREF_SHIFT;

			FrmBits &= XAXIVDMA_PARKPTR_WRTREF_MASK;

			RegValue = XAxiVdma_ReadReg(Channel->InstanceBase,
			              XAXIVDMA_PARKPTR_OFFSET);

			RegValue &= ~XAXIVDMA_PARKPTR_WRTREF_MASK;

			RegValue |= FrmBits;

			XAxiVdma_WriteReg(Channel->InstanceBase,
			    XAXIVDMA_PARKPTR_OFFSET, RegValue);
		}
	}

	if (ChannelCfgPtr->EnableSync) {
		if (Channel->GenLock != XAXIVDMA_GENLOCK_MASTER)
			CrBits |= XAXIVDMA_CR_SYNC_EN_MASK;
	}

	if (ChannelCfgPtr->GenLockRepeat) {
		if ((Channel->GenLock == XAXIVDMA_GENLOCK_MASTER) ||
			(Channel->GenLock == XAXIVDMA_DYN_GENLOCK_MASTER))
			CrBits |= XAXIVDMA_CR_GENLCK_RPT_MASK;
	}

	if (ChannelCfgPtr->EnableFrameCounter) {
		CrBits |= XAXIVDMA_CR_FRMCNT_EN_MASK;
	}

	CrBits |= (ChannelCfgPtr->PointNum << XAXIVDMA_CR_RD_PTR_SHIFT) &
	    XAXIVDMA_CR_RD_PTR_MASK;

	/* Write the control register value out
	 */
	XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET,
	    CrBits);

	if (Channel->HasSG) {
		/* Setup the information in BDs
		 *
		 * All information is available except the buffer addrs
		 * Buffer addrs are set through XAxiVdma_ChannelSetBufferAddr()
		 */
		NumBds = Channel->AllCnt;

		for (i = 0; i < NumBds; i++) {
			XAxiVdma_Bd *BdPtr = (XAxiVdma_Bd *)(Channel->HeadBdAddr +
			         i * sizeof(XAxiVdma_Bd));

			Status = XAxiVdma_BdSetVsize(BdPtr,
			             ChannelCfgPtr->VertSizeInput);
			if (Status != XST_SUCCESS) {
				xdbg_printf(XDBG_DEBUG_ERROR,
				    "Set vertical size failed %d\r\n", Status);

				return Status;
			}

			Status = XAxiVdma_BdSetHsize(BdPtr,
			    ChannelCfgPtr->HoriSizeInput);
			if (Status != XST_SUCCESS) {
				xdbg_printf(XDBG_DEBUG_ERROR,
				    "Set horizontal size failed %d\r\n", Status);

				return Status;
			}

			Status = XAxiVdma_BdSetStride(BdPtr,
			    ChannelCfgPtr->Stride);
			if (Status != XST_SUCCESS) {
				xdbg_printf(XDBG_DEBUG_ERROR,
				    "Set stride size failed %d\r\n", Status);

				return Status;
			}

			Status = XAxiVdma_BdSetFrmDly(BdPtr,
			ChannelCfgPtr->FrameDelay);
			if (Status != XST_SUCCESS) {
				xdbg_printf(XDBG_DEBUG_ERROR,
				    "Set frame delay failed %d\r\n", Status);

				return Status;
			}
		}
	}
	else {   /* direct register mode */
		if ((ChannelCfgPtr->VertSizeInput > XAXIVDMA_MAX_VSIZE) ||
		    (ChannelCfgPtr->VertSizeInput <= 0) ||
		    (ChannelCfgPtr->HoriSizeInput > XAXIVDMA_MAX_HSIZE) ||
		    (ChannelCfgPtr->HoriSizeInput <= 0) ||
		    (ChannelCfgPtr->Stride > XAXIVDMA_MAX_STRIDE) ||
		    (ChannelCfgPtr->Stride <= 0) ||
		    (ChannelCfgPtr->FrameDelay < 0) ||
		    (ChannelCfgPtr->FrameDelay > XAXIVDMA_FRMDLY_MAX)) {

			return XST_INVALID_PARAM;
		}

		XAxiVdma_WriteReg(Channel->StartAddrBase,
		    XAXIVDMA_HSIZE_OFFSET, ChannelCfgPtr->HoriSizeInput);

		XAxiVdma_WriteReg(Channel->StartAddrBase,
		    XAXIVDMA_STRD_FRMDLY_OFFSET,
		    (ChannelCfgPtr->FrameDelay << XAXIVDMA_FRMDLY_SHIFT) |
		    ChannelCfgPtr->Stride);
	}

	return XST_SUCCESS;
}
/**
 * This function checks whether reset operation is done
 *
 * @param Channel is the pointer to the DMA channel to work on
 *
 * @return
 * - 0 if reset is done
 * - 1 if reset is still going
 *
 *****************************************************************************/
int XAxiVdma_ChannelResetNotDone(XAxiVdma_Channel *Channel)
{
	return (XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) &
	        XAXIVDMA_CR_RESET_MASK);
}
/**
 * Get the current status of a channel
 *
 * @param Channel is the pointer to the channel to work on
 *
 * @return
 * The status of the channel
 *
 *****************************************************************************/
u32 XAxiVdma_ChannelGetStatus(XAxiVdma_Channel *Channel)
{
	return XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET);
}
/*
 * Check DMA channel errors
 *
 * @param Channel is the pointer to the channel to work on
 *
 * @return
 *  	Error bits of the channel, 0 means no errors
 *
 *****************************************************************************/
u32 XAxiVdma_ChannelErrors(XAxiVdma_Channel *Channel)
{
	return (XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET)
			& XAXIVDMA_SR_ERR_ALL_MASK);
}