drivers: imx: sdma: Enhance channel status handling

Channel 0 is special. It goes from READY (at init) to ACTIVE (at run)
and then back to READY (at stop).

The rest of the channels go to PREPARE (at set_config) or they can be
SUSPENDED or PAUSED the same state machine as for EDMA.

Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
This commit is contained in:
Daniel Baluta 2020-03-25 21:16:23 +02:00 committed by Daniel Baluta
parent 93dbbe2ca6
commit 7341f43cad
1 changed files with 30 additions and 6 deletions

View File

@ -478,11 +478,22 @@ static int sdma_start(struct dma_chan_data *channel)
{
struct sdma_chan *pdata = dma_chan_get_data(channel);
if (channel->status == COMP_STATE_INIT)
return -EINVAL;
trace_sdma_error("sdma_start(%d)", channel->index);
if (channel->index) {
/* rest of the channels are prepared first */
if (channel->status != COMP_STATE_PREPARE &&
channel->status != COMP_STATE_SUSPEND)
return -EINVAL;
} else {
/* channel 0 doesn't get set_config set on */
if (channel->status != COMP_STATE_READY)
return -EINVAL;
}
channel->status = COMP_STATE_ACTIVE;
/* If channel is event driven, allow it to run by setting HOSTOVR.
* If it's manually controlled, kickstart it by writing to SDMA_HSTART.
*/
@ -508,8 +519,12 @@ static int sdma_stop(struct dma_chan_data *channel)
{
struct sdma_chan *pdata = dma_chan_get_data(channel);
if (channel->status == COMP_STATE_INIT)
return -EINVAL;
/* do not try to stop multiple times */
if (channel->status != COMP_STATE_ACTIVE &&
channel->status != COMP_STATE_PAUSED)
return 0;
channel->status = COMP_STATE_READY;
tracev_sdma("sdma_stop(%d)", channel->index);
if (pdata->hw_event != -1) {
@ -533,9 +548,11 @@ static int sdma_pause(struct dma_chan_data *channel)
{
struct sdma_chan *pdata = dma_chan_get_data(channel);
if (channel->status == COMP_STATE_INIT)
if (channel->status != COMP_STATE_ACTIVE)
return -EINVAL;
channel->status = COMP_STATE_PAUSED;
/* Manually controlled channels need not be paused. */
if (pdata->hw_event != -1)
dma_reg_update_bits(channel->dma, SDMA_HOSTOVR,
@ -546,6 +563,11 @@ static int sdma_pause(struct dma_chan_data *channel)
static int sdma_release(struct dma_chan_data *channel)
{
if (channel->status != COMP_STATE_PAUSED)
return -EINVAL;
channel->status = COMP_STATE_ACTIVE;
/* No pointer realignment is necessary for release, context points
* correctly to beginning of the following BD.
*/
@ -824,6 +846,8 @@ static int sdma_set_config(struct dma_chan_data *channel,
/* Finally set channel priority */
dma_reg_write(channel->dma, SDMA_CHNPRI(channel->index), SDMA_DEFPRI);
channel->status = COMP_STATE_PREPARE;
return 0;
}