mirror of https://github.com/thesofproject/sof.git
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:
parent
93dbbe2ca6
commit
7341f43cad
|
@ -478,11 +478,22 @@ static int sdma_start(struct dma_chan_data *channel)
|
||||||
{
|
{
|
||||||
struct sdma_chan *pdata = dma_chan_get_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);
|
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 channel is event driven, allow it to run by setting HOSTOVR.
|
||||||
* If it's manually controlled, kickstart it by writing to SDMA_HSTART.
|
* 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);
|
struct sdma_chan *pdata = dma_chan_get_data(channel);
|
||||||
|
|
||||||
if (channel->status == COMP_STATE_INIT)
|
/* do not try to stop multiple times */
|
||||||
return -EINVAL;
|
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);
|
tracev_sdma("sdma_stop(%d)", channel->index);
|
||||||
if (pdata->hw_event != -1) {
|
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);
|
struct sdma_chan *pdata = dma_chan_get_data(channel);
|
||||||
|
|
||||||
if (channel->status == COMP_STATE_INIT)
|
if (channel->status != COMP_STATE_ACTIVE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
channel->status = COMP_STATE_PAUSED;
|
||||||
|
|
||||||
/* Manually controlled channels need not be paused. */
|
/* Manually controlled channels need not be paused. */
|
||||||
if (pdata->hw_event != -1)
|
if (pdata->hw_event != -1)
|
||||||
dma_reg_update_bits(channel->dma, SDMA_HOSTOVR,
|
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)
|
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
|
/* No pointer realignment is necessary for release, context points
|
||||||
* correctly to beginning of the following BD.
|
* 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 */
|
/* Finally set channel priority */
|
||||||
dma_reg_write(channel->dma, SDMA_CHNPRI(channel->index), SDMA_DEFPRI);
|
dma_reg_write(channel->dma, SDMA_CHNPRI(channel->index), SDMA_DEFPRI);
|
||||||
|
|
||||||
|
channel->status = COMP_STATE_PREPARE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue