#define XILINX_DMA_REG_FRMPTR_STS 0x0024
#define XILINX_DMA_REG_PARK_PTR 0x0028
#define XILINX_DMA_PARK_PTR_WR_REF_SHIFT 8
+#define XILINX_DMA_PARK_PTR_WR_REF_MASK GENMASK(12, 8)
#define XILINX_DMA_PARK_PTR_RD_REF_SHIFT 0
+#define XILINX_DMA_PARK_PTR_RD_REF_MASK GENMASK(4, 0)
#define XILINX_DMA_REG_VDMA_VERSION 0x002c
/* Register Direct Mode Registers */
* @genlock: Support genlock mode
* @err: Channel has errors
* @idle: Check for channel idle
- * @has_fstoreen: Check for frame store configuration
* @tasklet: Cleanup work after irq
* @config: Device configuration info
* @flush_on_fsync: Flush on Frame sync
bool genlock;
bool err;
bool idle;
- bool has_fstoreen;
struct tasklet_struct tasklet;
struct xilinx_vdma_config config;
bool flush_on_fsync;
{
struct xilinx_vdma_config *config = &chan->config;
struct xilinx_dma_tx_descriptor *desc, *tail_desc;
- u32 reg;
+ u32 reg, j;
struct xilinx_vdma_tx_segment *tail_segment;
/* This function was invoked with lock held */
if (list_empty(&chan->pending_list))
return;
- /*
- * Note: When VDMA is built with default h/w configuration
- * User should submit frames upto H/W configured.
- * If users submits less than h/w configured
- * VDMA engine tries to write to a invalid location
- * Results undefined behaviour/memory corruption.
- *
- * If user would like to submit frames less than h/w capable
- * On S2MM side please enable debug info 13 at the h/w level
- * On MM2S side please enable debug info 6 at the h/w level
- * It will allows the frame buffers numbers to be modified at runtime.
- */
- if (!chan->has_fstoreen &&
- chan->desc_pendingcount < chan->num_frms) {
- dev_warn(chan->dev, "Frame Store Configuration is not enabled at the\n");
- dev_warn(chan->dev, "H/w level enable Debug info 13 or 6 at the h/w level\n");
- dev_warn(chan->dev, "OR Submit the frames upto h/w Capable\n\r");
-
- return;
- }
-
desc = list_first_entry(&chan->pending_list,
struct xilinx_dma_tx_descriptor, node);
tail_desc = list_last_entry(&chan->pending_list,
else
reg &= ~XILINX_DMA_DMACR_FRAMECNT_EN;
- /* Configure channel to allow number frame buffers */
- dma_ctrl_write(chan, XILINX_DMA_REG_FRMSTORE,
- chan->desc_pendingcount);
-
/*
* With SG, start with circular mode, so that BDs can be fetched.
* In direct register mode, if not parking, enable circular mode
dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
- if (config->park && (config->park_frm >= 0) &&
- (config->park_frm < chan->num_frms)) {
- if (chan->direction == DMA_MEM_TO_DEV)
- dma_write(chan, XILINX_DMA_REG_PARK_PTR,
- config->park_frm <<
- XILINX_DMA_PARK_PTR_RD_REF_SHIFT);
- else
- dma_write(chan, XILINX_DMA_REG_PARK_PTR,
- config->park_frm <<
- XILINX_DMA_PARK_PTR_WR_REF_SHIFT);
+ j = chan->desc_submitcount;
+ reg = dma_read(chan, XILINX_DMA_REG_PARK_PTR);
+ if (chan->direction == DMA_MEM_TO_DEV) {
+ reg &= ~XILINX_DMA_PARK_PTR_RD_REF_MASK;
+ reg |= j << XILINX_DMA_PARK_PTR_RD_REF_SHIFT;
+ } else {
+ reg &= ~XILINX_DMA_PARK_PTR_WR_REF_MASK;
+ reg |= j << XILINX_DMA_PARK_PTR_WR_REF_SHIFT;
}
+ dma_write(chan, XILINX_DMA_REG_PARK_PTR, reg);
/* Start the hardware */
xilinx_dma_start(chan);
chan->desc_pendingcount = 0;
} else {
struct xilinx_vdma_tx_segment *segment, *last = NULL;
- int i = 0, j = 0;
+ int i = 0;
if (chan->desc_submitcount < chan->num_frms)
i = chan->desc_submitcount;
- for (j = 0; j < chan->num_frms; ) {
- list_for_each_entry(segment, &desc->segments, node) {
- if (chan->ext_addr)
- vdma_desc_write_64(chan,
- XILINX_VDMA_REG_START_ADDRESS_64(i++),
- segment->hw.buf_addr,
- segment->hw.buf_addr_msb);
- else
- vdma_desc_write(chan,
- XILINX_VDMA_REG_START_ADDRESS(i++),
- segment->hw.buf_addr);
-
- last = segment;
- }
- list_del(&desc->node);
- list_add_tail(&desc->node, &chan->active_list);
- j++;
- if (list_empty(&chan->pending_list) ||
- (i == chan->num_frms))
- break;
- desc = list_first_entry(&chan->pending_list,
- struct xilinx_dma_tx_descriptor,
- node);
+ list_for_each_entry(segment, &desc->segments, node) {
+ if (chan->ext_addr)
+ vdma_desc_write_64(chan,
+ XILINX_VDMA_REG_START_ADDRESS_64(i++),
+ segment->hw.buf_addr,
+ segment->hw.buf_addr_msb);
+ else
+ vdma_desc_write(chan,
+ XILINX_VDMA_REG_START_ADDRESS(i++),
+ segment->hw.buf_addr);
+
+ last = segment;
}
if (!last)
last->hw.stride);
vdma_desc_write(chan, XILINX_DMA_REG_VSIZE, last->hw.vsize);
- chan->desc_submitcount += j;
- chan->desc_pendingcount -= j;
+ chan->desc_submitcount++;
+ chan->desc_pendingcount--;
+ list_del(&desc->node);
+ list_add_tail(&desc->node, &chan->active_list);
if (chan->desc_submitcount == chan->num_frms)
chan->desc_submitcount = 0;
}
has_dre = of_property_read_bool(node, "xlnx,include-dre");
chan->genlock = of_property_read_bool(node, "xlnx,genlock-mode");
- chan->has_fstoreen = of_property_read_bool(node, "xlnx,fstore-enable");
err = of_property_read_u32(node, "xlnx,datawidth", &value);
if (err) {
chan->ctrl_offset = XILINX_DMA_MM2S_CTRL_OFFSET;
if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
+ chan->config.park = 1;
chan->desc_offset = XILINX_VDMA_MM2S_DESC_OFFSET;
if (xdev->flush_on_fsync == XILINX_DMA_FLUSH_BOTH ||
chan->ctrl_offset = XILINX_DMA_S2MM_CTRL_OFFSET;
if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
+ chan->config.park = 1;
chan->desc_offset = XILINX_VDMA_S2MM_DESC_OFFSET;
if (xdev->flush_on_fsync == XILINX_DMA_FLUSH_BOTH ||