Commit 54e9070b authored by Vaibhav Agarwal's avatar Vaibhav Agarwal Committed by Greg Kroah-Hartman

greybus: audio: Reorder gb_deactivate sequence to avoid protocol error

gb_activate_tx/rx is triggered from _prepare() & gb_deactivate
from shutdown(). This may cause protocol error in case shutdown
executes without _prepare due to some hw_params failure.

Also, reorganise _prepare & _shutdown calls to make it more
readable & cleaner.
Signed-off-by: default avatarVaibhav Agarwal <vaibhav.agarwal@linaro.org>
Reviewed-by: default avatarMark Greer <mgreer@animalcreek.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 2b8c2b51
...@@ -395,12 +395,88 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, ...@@ -395,12 +395,88 @@ static int gbcodec_startup(struct snd_pcm_substream *substream,
return ret; return ret;
} }
static int gbmodule_shutdown_tx(struct gbaudio_module_info *module,
struct gbaudio_data_connection *data,
int codec_state, struct device *dev)
{
int ret, module_state;
__u16 i2s_port, cportid;
module_state = module->ctrlstate[0];
if (module_state == GBAUDIO_CODEC_SHUTDOWN) {
dev_dbg(dev, "%s: module already configured\n",
module->name);
return 0;
}
if (codec_state == GBAUDIO_CODEC_STOP) {
ret = gb_audio_apbridgea_shutdown_tx(data->connection, 0);
if (ret)
return ret;
}
/* deactivate */
cportid = data->connection->intf_cport_id;
if (module_state >= GBAUDIO_CODEC_PREPARE) {
ret = gb_audio_gb_deactivate_tx(module->mgmt_connection,
cportid);
if (ret)
return ret;
}
/* unregister cport */
i2s_port = 0; /* fixed for now */
cportid = data->connection->hd_cport_id;
ret = gb_audio_apbridgea_unregister_cport(data->connection, i2s_port,
cportid,
AUDIO_APBRIDGEA_DIRECTION_TX);
return ret;
}
static int gbmodule_shutdown_rx(struct gbaudio_module_info *module,
struct gbaudio_data_connection *data,
int codec_state, struct device *dev)
{
int ret, module_state;
__u16 i2s_port, cportid;
module_state = module->ctrlstate[1];
if (module_state == GBAUDIO_CODEC_SHUTDOWN) {
dev_dbg(dev, "%s: module already configured\n",
module->name);
return 0;
}
if (codec_state == GBAUDIO_CODEC_STOP) {
ret = gb_audio_apbridgea_shutdown_rx(data->connection, 0);
if (ret)
return ret;
}
/* deactivate */
cportid = data->connection->intf_cport_id;
if (module_state >= GBAUDIO_CODEC_PREPARE) {
ret = gb_audio_gb_deactivate_rx(module->mgmt_connection,
cportid);
if (ret)
return ret;
}
/* unregister cport */
i2s_port = 0; /* fixed for now */
cportid = data->connection->hd_cport_id;
ret = gb_audio_apbridgea_unregister_cport(data->connection, i2s_port,
cportid,
AUDIO_APBRIDGEA_DIRECTION_RX);
return ret;
}
static void gbcodec_shutdown(struct snd_pcm_substream *substream, static void gbcodec_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
int ret; int ret, state;
__u16 i2s_port, cportid;
int state, module_state;
struct gbaudio_module_info *module; struct gbaudio_module_info *module;
struct gbaudio_data_connection *data; struct gbaudio_data_connection *data;
struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev);
...@@ -423,14 +499,6 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, ...@@ -423,14 +499,6 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream,
mutex_unlock(&module->lock); mutex_unlock(&module->lock);
continue; continue;
} }
module_state = module->ctrlstate[substream->stream];
if (module_state == GBAUDIO_CODEC_SHUTDOWN) {
dev_dbg(codec->dev, "%s: module already configured\n",
module->name);
mutex_unlock(&module->lock);
continue;
}
/* find the dai */ /* find the dai */
data = find_data(module, dai->name); data = find_data(module, dai->name);
if (!data) { if (!data) {
...@@ -440,32 +508,18 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, ...@@ -440,32 +508,18 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream,
continue; continue;
} }
/* deactivate */
cportid = data->connection->intf_cport_id;
switch (substream->stream) { switch (substream->stream) {
case SNDRV_PCM_STREAM_CAPTURE:
ret = gb_audio_gb_deactivate_rx(module->mgmt_connection,
cportid);
/* unregister cport */
i2s_port = 0; /* fixed for now */
cportid = data->connection->hd_cport_id;
ret = gb_audio_apbridgea_unregister_cport(
data->connection, i2s_port, cportid,
AUDIO_APBRIDGEA_DIRECTION_RX);
break;
case SNDRV_PCM_STREAM_PLAYBACK: case SNDRV_PCM_STREAM_PLAYBACK:
ret = gb_audio_gb_deactivate_tx(module->mgmt_connection, ret = gbmodule_shutdown_tx(module, data, state,
cportid); dai->dev);
/* unregister cport */ break;
i2s_port = 0; /* fixed for now */ case SNDRV_PCM_STREAM_CAPTURE:
cportid = data->connection->hd_cport_id; ret = gbmodule_shutdown_rx(module, data, state,
ret = gb_audio_apbridgea_unregister_cport( dai->dev);
data->connection, i2s_port, cportid,
AUDIO_APBRIDGEA_DIRECTION_TX);
break; break;
} }
dev_dbg(dai->dev, "Unregister %s:%d DAI, ret:%d\n", dai->name, dev_dbg(dai->dev, "Unregister %s DAI, ret:%d\n", dai->name,
cportid, ret); ret);
state = GBAUDIO_CODEC_SHUTDOWN; state = GBAUDIO_CODEC_SHUTDOWN;
module->ctrlstate[substream->stream] = state; module->ctrlstate[substream->stream] = state;
dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); dev_dbg(dai->dev, "%s: state:%d\n", module->name, state);
...@@ -589,14 +643,82 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, ...@@ -589,14 +643,82 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream,
return ret; return ret;
} }
static int gbmodule_prepare_tx(struct gbaudio_module_info *module,
struct gbaudio_data_connection *data,
int codec_state, struct device *dev)
{
int ret;
uint16_t data_cport;
data_cport = data->connection->intf_cport_id;
ret = gb_audio_gb_set_tx_data_size(module->mgmt_connection, data_cport,
192);
if (ret) {
dev_err(dev, "%d:Error during set_tx_data_size, cport:%d\n",
ret, data_cport);
return ret;
}
if (codec_state < GBAUDIO_CODEC_PREPARE) {
ret = gb_audio_apbridgea_set_tx_data_size(data->connection, 0,
192);
if (ret) {
dev_err(dev,
"%d:Error during apbridgea set_tx_data_size, cport\n",
ret);
return ret;
}
}
ret = gb_audio_gb_activate_tx(module->mgmt_connection,
data_cport);
if (ret)
dev_err(dev, "%s:Error during activate stream,%d\n",
module->name, ret);
return ret;
}
static int gbmodule_prepare_rx(struct gbaudio_module_info *module,
struct gbaudio_data_connection *data,
int codec_state, struct device *dev)
{
int ret;
uint16_t data_cport;
data_cport = data->connection->intf_cport_id;
ret = gb_audio_gb_set_rx_data_size(module->mgmt_connection, data_cport,
192);
if (ret) {
dev_err(dev, "%d:Error during set_rx_data_size, cport:%d\n",
ret, data_cport);
return ret;
}
if (codec_state < GBAUDIO_CODEC_PREPARE) {
ret = gb_audio_apbridgea_set_rx_data_size(data->connection, 0,
192);
if (ret) {
dev_err(dev,
"%d:Error during apbridgea_set_rx_data_size\n",
ret);
return ret;
}
}
ret = gb_audio_gb_activate_rx(module->mgmt_connection,
data_cport);
if (ret)
dev_err(dev, "%s:Error during activate stream,%d\n",
module->name, ret);
return ret;
}
static int gbcodec_prepare(struct snd_pcm_substream *substream, static int gbcodec_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
int ret; int ret;
uint16_t data_cport;
struct gbaudio_data_connection *data;
struct gbaudio_module_info *module; struct gbaudio_module_info *module;
int state; int state;
struct gbaudio_data_connection *data;
struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev);
mutex_lock(&codec->lock); mutex_lock(&codec->lock);
...@@ -623,71 +745,24 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, ...@@ -623,71 +745,24 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream,
mutex_unlock(&module->lock); mutex_unlock(&module->lock);
continue; continue;
} }
/* deactivate rx/tx */
data_cport = data->connection->intf_cport_id;
switch (substream->stream) { switch (substream->stream) {
case SNDRV_PCM_STREAM_CAPTURE:
ret = gb_audio_gb_set_rx_data_size(
module->mgmt_connection,
data_cport, 192);
if (ret) {
dev_err(dai->dev,
"%d:Error during set_rx_data_size, cport:%d\n",
ret, data_cport);
mutex_unlock(&module->lock);
goto func_exit;
}
if (state < GBAUDIO_CODEC_PREPARE) {
ret = gb_audio_apbridgea_set_rx_data_size(
data->connection, 0,
192);
if (ret) {
dev_err(dai->dev,
"%d:Error during apbridgea_set_rx_data_size\n",
ret);
mutex_unlock(&module->lock);
goto func_exit;
}
}
ret = gb_audio_gb_activate_rx(module->mgmt_connection,
data_cport);
if (ret)
dev_err(dai->dev,
"%s:Error during activate stream,%d\n",
module->name, ret);
break;
case SNDRV_PCM_STREAM_PLAYBACK: case SNDRV_PCM_STREAM_PLAYBACK:
ret = gb_audio_gb_set_tx_data_size( ret = gbmodule_prepare_tx(module, data, state,
module->mgmt_connection, dai->dev);
data_cport, 192); break;
if (ret) { case SNDRV_PCM_STREAM_CAPTURE:
dev_err(dai->dev, ret = gbmodule_prepare_rx(module, data, state,
"%d:Error during module set_tx_data_size, cport:%d\n", dai->dev);
ret, data_cport);
mutex_unlock(&module->lock);
goto func_exit;
}
if (state < GBAUDIO_CODEC_PREPARE) {
ret = gb_audio_apbridgea_set_tx_data_size(
data->connection, 0,
192);
if (ret) {
dev_err(dai->dev,
"%d:Error during apbridgea set_tx_data_size, cport\n",
ret);
mutex_unlock(&module->lock);
goto func_exit;
}
}
ret = gb_audio_gb_activate_tx(module->mgmt_connection,
data_cport);
if (ret)
dev_err(dai->dev,
"%s:Error during activate stream,%d\n",
module->name, ret);
break; break;
} }
if (ret == -ENODEV)
continue;
if (ret) {
mutex_unlock(&module->lock);
goto func_exit;
}
state = GBAUDIO_CODEC_PREPARE; state = GBAUDIO_CODEC_PREPARE;
module->ctrlstate[substream->stream] = state; module->ctrlstate[substream->stream] = state;
dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); dev_dbg(dai->dev, "%s: state:%d\n", module->name, state);
...@@ -697,7 +772,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, ...@@ -697,7 +772,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream,
func_exit: func_exit:
mutex_unlock(&codec->lock); mutex_unlock(&codec->lock);
return 0; return ret;
} }
static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment