Commit 1cbd4466 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Vinod Koul
Browse files

dmaengine: xilinx: dpdma: Fix descriptor issuing on video group



When multiple channels are part of a video group, the transfer is
triggered only when all channels in the group are ready. The logic to do
so is incorrect, as it causes the descriptors for all channels but the
last one in a group to not being pushed to the hardware. Fix it.

Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://lore.kernel.org/r/20210307040629.29308-2-laurent.pinchart@ideasonboard.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent a38fd874
Loading
Loading
Loading
Loading
+17 −11
Original line number Diff line number Diff line
@@ -839,6 +839,7 @@ static void xilinx_dpdma_chan_queue_transfer(struct xilinx_dpdma_chan *chan)
	struct xilinx_dpdma_tx_desc *desc;
	struct virt_dma_desc *vdesc;
	u32 reg, channels;
	bool first_frame;

	lockdep_assert_held(&chan->lock);

@@ -852,14 +853,6 @@ static void xilinx_dpdma_chan_queue_transfer(struct xilinx_dpdma_chan *chan)
		chan->running = true;
	}

	if (chan->video_group)
		channels = xilinx_dpdma_chan_video_group_ready(chan);
	else
		channels = BIT(chan->id);

	if (!channels)
		return;

	vdesc = vchan_next_desc(&chan->vchan);
	if (!vdesc)
		return;
@@ -884,13 +877,26 @@ static void xilinx_dpdma_chan_queue_transfer(struct xilinx_dpdma_chan *chan)
			    FIELD_PREP(XILINX_DPDMA_CH_DESC_START_ADDRE_MASK,
				       upper_32_bits(sw_desc->dma_addr)));

	if (chan->first_frame)
	first_frame = chan->first_frame;
	chan->first_frame = false;

	if (chan->video_group) {
		channels = xilinx_dpdma_chan_video_group_ready(chan);
		/*
		 * Trigger the transfer only when all channels in the group are
		 * ready.
		 */
		if (!channels)
			return;
	} else {
		channels = BIT(chan->id);
	}

	if (first_frame)
		reg = XILINX_DPDMA_GBL_TRIG_MASK(channels);
	else
		reg = XILINX_DPDMA_GBL_RETRIG_MASK(channels);

	chan->first_frame = false;

	dpdma_write(xdev->reg, XILINX_DPDMA_GBL, reg);
}