mirror of
https://github.com/apache/nuttx.git
synced 2026-05-27 11:26:12 +08:00
cxd56: add support for pause and resume
Implements pause and resume functionality
This commit is contained in:
committed by
patacongo
parent
7a83177419
commit
36e756a915
+63
-24
@@ -929,6 +929,8 @@ static void cxd56_dma_int_handler(void)
|
|||||||
|
|
||||||
if (dev->mq != NULL)
|
if (dev->mq != NULL)
|
||||||
{
|
{
|
||||||
|
/* Request more data */
|
||||||
|
|
||||||
msg.msg_id = AUDIO_MSG_DATA_REQUEST;
|
msg.msg_id = AUDIO_MSG_DATA_REQUEST;
|
||||||
msg.u.data = 0;
|
msg.u.data = 0;
|
||||||
(void)nxmq_send(dev->mq, (FAR const char *) &msg,
|
(void)nxmq_send(dev->mq, (FAR const char *) &msg,
|
||||||
@@ -937,12 +939,15 @@ static void cxd56_dma_int_handler(void)
|
|||||||
|
|
||||||
if (ecode == CXD56_AUDIO_ECODE_DMA_TRANS)
|
if (ecode == CXD56_AUDIO_ECODE_DMA_TRANS)
|
||||||
{
|
{
|
||||||
/* End of data */
|
/* Notify end of data */
|
||||||
|
|
||||||
msg.msg_id = AUDIO_MSG_STOP;
|
if (dev->state != CXD56_DEV_STATE_PAUSED)
|
||||||
msg.u.data = 0;
|
{
|
||||||
(void)nxmq_send(dev->mq, (FAR const char *)&msg,
|
msg.msg_id = AUDIO_MSG_STOP;
|
||||||
sizeof(msg), CONFIG_CXD56_MSG_PRIO);
|
msg.u.data = 0;
|
||||||
|
(void)nxmq_send(dev->mq, (FAR const char *)&msg,
|
||||||
|
sizeof(msg), CONFIG_CXD56_MSG_PRIO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1283,21 +1288,17 @@ static uint32_t cxd56_power_on(FAR struct cxd56_dev_s *dev)
|
|||||||
write_reg(REG_AC_DSR_RATE, 1);
|
write_reg(REG_AC_DSR_RATE, 1);
|
||||||
write_reg(REG_AC_DIGSFT, 1);
|
write_reg(REG_AC_DIGSFT, 1);
|
||||||
|
|
||||||
#if defined(CONFIG_CXD56_I2S0) || defined(CONFIG_CXD56_I2S1)
|
|
||||||
/* Clear interrupt status of bck_err */
|
/* Clear interrupt status of bck_err */
|
||||||
|
|
||||||
write_reg(REG_INT_M_I2S1_BCL_ERR1, 0);
|
write_reg(REG_INT_M_I2S1_BCL_ERR1, 0);
|
||||||
write_reg(REG_INT_M_I2S1_BCL_ERR2, 0);
|
write_reg(REG_INT_M_I2S1_BCL_ERR2, 0);
|
||||||
|
|
||||||
cxd56_power_on_i2s1(dev);
|
cxd56_power_on_i2s1(dev);
|
||||||
#endif /* defined(CONFIG_CXD56_I2S0) || defined(CONFIG_CXD56_I2S1) */
|
|
||||||
|
|
||||||
#ifdef CONFIG_CXD56_I2S0
|
|
||||||
/* Enable I2S data input and output of SRC1 */
|
/* Enable I2S data input and output of SRC1 */
|
||||||
|
|
||||||
write_reg(REG_AC_SDIN1_EN, 1);
|
write_reg(REG_AC_SDIN1_EN, 1);
|
||||||
write_reg(REG_AC_SDOUT1_EN, 1);
|
write_reg(REG_AC_SDOUT1_EN, 1);
|
||||||
#endif /* CONFIG_CXD56_I2S0 */
|
|
||||||
|
|
||||||
/* Enable BCK, LRCK output if master (1). */
|
/* Enable BCK, LRCK output if master (1). */
|
||||||
|
|
||||||
@@ -1347,7 +1348,6 @@ static uint32_t cxd56_power_on(FAR struct cxd56_dev_s *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_codec_start_count++;
|
g_codec_start_count++;
|
||||||
dev->state = CXD56_DEV_STATE_STOPPED;
|
|
||||||
|
|
||||||
return CXD56_AUDIO_ECODE_OK;
|
return CXD56_AUDIO_ECODE_OK;
|
||||||
}
|
}
|
||||||
@@ -1639,6 +1639,8 @@ static int cxd56_configure(FAR struct audio_lowerhalf_s *lower,
|
|||||||
auderr("Power on analog output failed- (%d)\n", ret);
|
auderr("Power on analog output failed- (%d)\n", ret);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->state = CXD56_DEV_STATE_STOPPED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1680,8 +1682,6 @@ static int cxd56_start(FAR struct audio_lowerhalf_s *lower)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->state = CXD56_DEV_STATE_STARTING;
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1717,8 +1717,6 @@ static int cxd56_stop_dma(FAR struct cxd56_dev_s *priv)
|
|||||||
write_reg(REG_AC_PDN_SMSTR, 1);
|
write_reg(REG_AC_PDN_SMSTR, 1);
|
||||||
as_aca_control(CXD56_ACA_CTL_POWER_OFF_OUTPUT, (uint32_t)NULL);
|
as_aca_control(CXD56_ACA_CTL_POWER_OFF_OUTPUT, (uint32_t)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->state = CXD56_DEV_STATE_STOPPED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1743,8 +1741,6 @@ static int cxd56_stop(FAR struct audio_lowerhalf_s *lower)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->state = CXD56_DEV_STATE_STOPPING;
|
|
||||||
|
|
||||||
msg.msg_id = AUDIO_MSG_STOP;
|
msg.msg_id = AUDIO_MSG_STOP;
|
||||||
msg.u.data = 0;
|
msg.u.data = 0;
|
||||||
(void)nxmq_send(priv->mq, (FAR const char *)&msg,
|
(void)nxmq_send(priv->mq, (FAR const char *)&msg,
|
||||||
@@ -1774,8 +1770,22 @@ static int cxd56_pause(FAR struct audio_lowerhalf_s *lower,
|
|||||||
static int cxd56_pause(FAR struct audio_lowerhalf_s *lower)
|
static int cxd56_pause(FAR struct audio_lowerhalf_s *lower)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
int ret = OK;
|
||||||
|
FAR struct cxd56_dev_s *dev = (FAR struct cxd56_dev_s *)lower;
|
||||||
|
|
||||||
audinfo("cxd56_pause\n");
|
audinfo("cxd56_pause\n");
|
||||||
return OK;
|
|
||||||
|
if (dev->state == CXD56_DEV_STATE_STARTED)
|
||||||
|
{
|
||||||
|
dev->state = CXD56_DEV_STATE_PAUSED;
|
||||||
|
|
||||||
|
ret = cxd56_stop_dma(dev);
|
||||||
|
if (ret != CXD56_AUDIO_ECODE_OK)
|
||||||
|
{
|
||||||
|
auderr("Could not stop DMA transfer. (%d)\n", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -1792,8 +1802,24 @@ static int cxd56_resume(FAR struct audio_lowerhalf_s *lower,
|
|||||||
static int cxd56_resume(FAR struct audio_lowerhalf_s *lower)
|
static int cxd56_resume(FAR struct audio_lowerhalf_s *lower)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
int ret = OK;
|
||||||
|
FAR struct cxd56_dev_s *dev = (FAR struct cxd56_dev_s *)lower;
|
||||||
|
|
||||||
audinfo("cxd56_resume\n");
|
audinfo("cxd56_resume\n");
|
||||||
return OK;
|
|
||||||
|
if (dev->state == CXD56_DEV_STATE_PAUSED)
|
||||||
|
{
|
||||||
|
dev->state = CXD56_DEV_STATE_STARTED;
|
||||||
|
cxd56_power_on_analog_output(dev);
|
||||||
|
board_external_amp_mute_control(false);
|
||||||
|
|
||||||
|
ret = cxd56_start_dma(dev);
|
||||||
|
if (ret != CXD56_AUDIO_ECODE_OK)
|
||||||
|
{
|
||||||
|
audinfo("Could not resume DMA transfer. (%d)\n", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME */
|
#endif /* CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME */
|
||||||
|
|
||||||
@@ -1858,14 +1884,19 @@ static int cxd56_start_dma(FAR struct cxd56_dev_s *dev)
|
|||||||
int timeout;
|
int timeout;
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
static int bufcount = 0;
|
|
||||||
CXD56_AUDIO_ECODE ret = CXD56_AUDIO_ECODE_OK;
|
CXD56_AUDIO_ECODE ret = CXD56_AUDIO_ECODE_OK;
|
||||||
|
|
||||||
cxd56_take_sem(&dev->pendsem);
|
cxd56_take_sem(&dev->pendsem);
|
||||||
if (dq_count(&dev->pendingq) == 0)
|
if (dq_count(&dev->pendingq) == 0)
|
||||||
{
|
{
|
||||||
audinfo("Pending queue empty! Played %d buffers.\n", bufcount);
|
/* Pending queue empty, nothing to do */
|
||||||
dev->state = CXD56_DEV_STATE_STOPPING;
|
|
||||||
|
struct audio_msg_s msg;
|
||||||
|
|
||||||
|
msg.msg_id = AUDIO_MSG_STOP;
|
||||||
|
msg.u.data = 0;
|
||||||
|
(void)nxmq_send(dev->mq, (FAR const char *)&msg,
|
||||||
|
sizeof(msg), CONFIG_CXD56_MSG_PRIO);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2003,7 +2034,6 @@ static int cxd56_start_dma(FAR struct cxd56_dev_s *dev)
|
|||||||
dq_pop(&dev->pendingq);
|
dq_pop(&dev->pendingq);
|
||||||
dq_push(&dev->runningq, &apb->dq_entry);
|
dq_push(&dev->runningq, &apb->dq_entry);
|
||||||
dev->state = CXD56_DEV_STATE_STARTED;
|
dev->state = CXD56_DEV_STATE_STARTED;
|
||||||
bufcount++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2148,13 +2178,22 @@ static void *cxd56_workerthread(pthread_addr_t pvarg)
|
|||||||
switch (msg.msg_id)
|
switch (msg.msg_id)
|
||||||
{
|
{
|
||||||
case AUDIO_MSG_STOP:
|
case AUDIO_MSG_STOP:
|
||||||
cxd56_stop_dma(priv);
|
ret = cxd56_stop_dma(priv);
|
||||||
|
if (ret != CXD56_AUDIO_ECODE_OK)
|
||||||
|
{
|
||||||
|
auderr("Could not stop DMA transfer. (%d)\n", ret);
|
||||||
|
priv->running = false;
|
||||||
|
}
|
||||||
|
priv->state = CXD56_DEV_STATE_STOPPED;
|
||||||
priv->running = false;
|
priv->running = false;
|
||||||
audinfo("Workerthread stopped.\n");
|
audinfo("Workerthread stopped.\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUDIO_MSG_DATA_REQUEST:
|
case AUDIO_MSG_DATA_REQUEST:
|
||||||
cxd56_start_dma(priv);
|
if (priv->state == CXD56_DEV_STATE_STARTED)
|
||||||
|
{
|
||||||
|
cxd56_start_dma(priv);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUDIO_MSG_ENQUEUE:
|
case AUDIO_MSG_ENQUEUE:
|
||||||
|
|||||||
@@ -205,10 +205,9 @@ typedef enum cxd56_dmahandle_e cxd56_dmahandle_t;
|
|||||||
enum cxd56_devstate_e
|
enum cxd56_devstate_e
|
||||||
{
|
{
|
||||||
CXD56_DEV_STATE_OFF,
|
CXD56_DEV_STATE_OFF,
|
||||||
CXD56_DEV_STATE_STOPPED,
|
CXD56_DEV_STATE_PAUSED,
|
||||||
CXD56_DEV_STATE_STARTING,
|
|
||||||
CXD56_DEV_STATE_STARTED,
|
CXD56_DEV_STATE_STARTED,
|
||||||
CXD56_DEV_STATE_STOPPING,
|
CXD56_DEV_STATE_STOPPED
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cxd56_dev_s
|
struct cxd56_dev_s
|
||||||
|
|||||||
Reference in New Issue
Block a user