Commit 591c4522 authored by Vaibhav Agarwal's avatar Vaibhav Agarwal Committed by Greg Kroah-Hartman

greybus: audio: Maintain module stream state for each data connection

For SPK module, each data connection corresponds to codec DAI. Now
stream state is maintained for each DAI. So, need to maintain stream
state for each DAI/data connection for individual module as well.
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 19866603
...@@ -52,14 +52,13 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, ...@@ -52,14 +52,13 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec,
struct gbaudio_data_connection *data; struct gbaudio_data_connection *data;
struct gbaudio_stream_params *params; struct gbaudio_stream_params *params;
module_state = module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK];
/* find the dai */ /* find the dai */
data = find_data(module, id); data = find_data(module, id);
if (!data) { if (!data) {
dev_err(module->dev, "%d:DATA connection missing\n", id); dev_err(module->dev, "%d:DATA connection missing\n", id);
return -ENODEV; return -ENODEV;
} }
module_state = data->state[SNDRV_PCM_STREAM_PLAYBACK];
params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_PLAYBACK); params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_PLAYBACK);
if (!params) { if (!params) {
...@@ -79,7 +78,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, ...@@ -79,7 +78,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec,
"reg_cport failed:%d\n", ret); "reg_cport failed:%d\n", ret);
return ret; return ret;
} }
module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = data->state[SNDRV_PCM_STREAM_PLAYBACK] =
GBAUDIO_CODEC_STARTUP; GBAUDIO_CODEC_STARTUP;
dev_dbg(module->dev, "Dynamic Register %d DAI\n", cportid); dev_dbg(module->dev, "Dynamic Register %d DAI\n", cportid);
} }
...@@ -98,7 +97,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, ...@@ -98,7 +97,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec,
ret); ret);
return ret; return ret;
} }
module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = data->state[SNDRV_PCM_STREAM_PLAYBACK] =
GBAUDIO_CODEC_HWPARAMS; GBAUDIO_CODEC_HWPARAMS;
dev_dbg(module->dev, "Dynamic hw_params %d DAI\n", data_cport); dev_dbg(module->dev, "Dynamic hw_params %d DAI\n", data_cport);
} }
...@@ -121,7 +120,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, ...@@ -121,7 +120,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec,
"activate_tx failed:%d\n", ret); "activate_tx failed:%d\n", ret);
return ret; return ret;
} }
module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = data->state[SNDRV_PCM_STREAM_PLAYBACK] =
GBAUDIO_CODEC_PREPARE; GBAUDIO_CODEC_PREPARE;
dev_dbg(module->dev, "Dynamic prepare %d DAI\n", data_cport); dev_dbg(module->dev, "Dynamic prepare %d DAI\n", data_cport);
} }
...@@ -136,19 +135,13 @@ static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id) ...@@ -136,19 +135,13 @@ static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id)
int module_state; int module_state;
struct gbaudio_data_connection *data; struct gbaudio_data_connection *data;
module_state = module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK];
if (module_state == GBAUDIO_CODEC_SHUTDOWN) {
dev_dbg(module->dev, "module already configured\n");
return 0;
}
/* find the dai */ /* find the dai */
data = find_data(module, id); data = find_data(module, id);
if (!data) { if (!data) {
dev_err(module->dev, "%d:DATA connection missing\n", id); dev_err(module->dev, "%d:DATA connection missing\n", id);
return -ENODEV; return -ENODEV;
} }
module_state = data->state[SNDRV_PCM_STREAM_PLAYBACK];
if (module_state > GBAUDIO_CODEC_HWPARAMS) { if (module_state > GBAUDIO_CODEC_HWPARAMS) {
data_cport = data->connection->intf_cport_id; data_cport = data->connection->intf_cport_id;
...@@ -160,7 +153,7 @@ static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id) ...@@ -160,7 +153,7 @@ static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id)
return ret; return ret;
} }
dev_dbg(module->dev, "Dynamic deactivate %d DAI\n", data_cport); dev_dbg(module->dev, "Dynamic deactivate %d DAI\n", data_cport);
module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = data->state[SNDRV_PCM_STREAM_PLAYBACK] =
GBAUDIO_CODEC_HWPARAMS; GBAUDIO_CODEC_HWPARAMS;
} }
...@@ -177,7 +170,7 @@ static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id) ...@@ -177,7 +170,7 @@ static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id)
return ret; return ret;
} }
dev_dbg(module->dev, "Dynamic Unregister %d DAI\n", cportid); dev_dbg(module->dev, "Dynamic Unregister %d DAI\n", cportid);
module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = data->state[SNDRV_PCM_STREAM_PLAYBACK] =
GBAUDIO_CODEC_SHUTDOWN; GBAUDIO_CODEC_SHUTDOWN;
} }
...@@ -194,14 +187,13 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, ...@@ -194,14 +187,13 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec,
struct gbaudio_data_connection *data; struct gbaudio_data_connection *data;
struct gbaudio_stream_params *params; struct gbaudio_stream_params *params;
module_state = module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE];
/* find the dai */ /* find the dai */
data = find_data(module, id); data = find_data(module, id);
if (!data) { if (!data) {
dev_err(module->dev, "%d:DATA connection missing\n", id); dev_err(module->dev, "%d:DATA connection missing\n", id);
return -ENODEV; return -ENODEV;
} }
module_state = data->state[SNDRV_PCM_STREAM_CAPTURE];
params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_CAPTURE); params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_CAPTURE);
if (!params) { if (!params) {
...@@ -221,7 +213,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, ...@@ -221,7 +213,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec,
"reg_cport failed:%d\n", ret); "reg_cport failed:%d\n", ret);
return ret; return ret;
} }
module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = data->state[SNDRV_PCM_STREAM_CAPTURE] =
GBAUDIO_CODEC_STARTUP; GBAUDIO_CODEC_STARTUP;
dev_dbg(module->dev, "Dynamic Register %d DAI\n", cportid); dev_dbg(module->dev, "Dynamic Register %d DAI\n", cportid);
} }
...@@ -240,7 +232,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, ...@@ -240,7 +232,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec,
ret); ret);
return ret; return ret;
} }
module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = data->state[SNDRV_PCM_STREAM_CAPTURE] =
GBAUDIO_CODEC_HWPARAMS; GBAUDIO_CODEC_HWPARAMS;
dev_dbg(module->dev, "Dynamic hw_params %d DAI\n", data_cport); dev_dbg(module->dev, "Dynamic hw_params %d DAI\n", data_cport);
} }
...@@ -263,7 +255,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, ...@@ -263,7 +255,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec,
"activate_rx failed:%d\n", ret); "activate_rx failed:%d\n", ret);
return ret; return ret;
} }
module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = data->state[SNDRV_PCM_STREAM_CAPTURE] =
GBAUDIO_CODEC_PREPARE; GBAUDIO_CODEC_PREPARE;
dev_dbg(module->dev, "Dynamic prepare %d DAI\n", data_cport); dev_dbg(module->dev, "Dynamic prepare %d DAI\n", data_cport);
} }
...@@ -278,20 +270,13 @@ static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id) ...@@ -278,20 +270,13 @@ static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id)
int module_state; int module_state;
struct gbaudio_data_connection *data; struct gbaudio_data_connection *data;
module_state = module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE];
if (module_state == GBAUDIO_CODEC_SHUTDOWN) {
dev_dbg(module->dev, "%s: module already configured\n",
module->name);
return 0;
}
/* find the dai */ /* find the dai */
data = find_data(module, id); data = find_data(module, id);
if (!data) { if (!data) {
dev_err(module->dev, "%d:DATA connection missing\n", id); dev_err(module->dev, "%d:DATA connection missing\n", id);
return -ENODEV; return -ENODEV;
} }
module_state = data->state[SNDRV_PCM_STREAM_CAPTURE];
if (module_state > GBAUDIO_CODEC_HWPARAMS) { if (module_state > GBAUDIO_CODEC_HWPARAMS) {
data_cport = data->connection->intf_cport_id; data_cport = data->connection->intf_cport_id;
...@@ -303,7 +288,7 @@ static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id) ...@@ -303,7 +288,7 @@ static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id)
return ret; return ret;
} }
dev_dbg(module->dev, "Dynamic deactivate %d DAI\n", data_cport); dev_dbg(module->dev, "Dynamic deactivate %d DAI\n", data_cport);
module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = data->state[SNDRV_PCM_STREAM_CAPTURE] =
GBAUDIO_CODEC_HWPARAMS; GBAUDIO_CODEC_HWPARAMS;
} }
...@@ -320,7 +305,7 @@ static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id) ...@@ -320,7 +305,7 @@ static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id)
return ret; return ret;
} }
dev_dbg(module->dev, "Dynamic Unregister %d DAI\n", cportid); dev_dbg(module->dev, "Dynamic Unregister %d DAI\n", cportid);
module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = data->state[SNDRV_PCM_STREAM_CAPTURE] =
GBAUDIO_CODEC_SHUTDOWN; GBAUDIO_CODEC_SHUTDOWN;
} }
...@@ -855,27 +840,10 @@ int gbaudio_register_module(struct gbaudio_module_info *module) ...@@ -855,27 +840,10 @@ int gbaudio_register_module(struct gbaudio_module_info *module)
} }
EXPORT_SYMBOL(gbaudio_register_module); EXPORT_SYMBOL(gbaudio_register_module);
static void gbaudio_codec_cleanup(struct gbaudio_module_info *module) static void gbaudio_codec_clean_data_tx(struct gbaudio_data_connection *data)
{ {
struct gbaudio_data_connection *data;
int pb_state = gbcodec->stream[0].state;
int cap_state = gbcodec->stream[1].state;
int ret;
uint16_t i2s_port, cportid; uint16_t i2s_port, cportid;
int ret;
/* locks already acquired */
if (!pb_state && !cap_state)
return;
dev_dbg(gbcodec->dev, "%s: removed, cleanup APBridge\n", module->name);
if (pb_state == GBAUDIO_CODEC_START) {
/* cleanup PB path, only APBridge specific */
data = find_data(module, 1);
if (!data) {
dev_err(gbcodec->dev, "%s: Missing data pointer\n",
__func__);
return;
}
if (list_is_singular(&gbcodec->module_list)) { if (list_is_singular(&gbcodec->module_list)) {
ret = gb_audio_apbridgea_stop_tx(data->connection, 0); ret = gb_audio_apbridgea_stop_tx(data->connection, 0);
...@@ -891,17 +859,14 @@ static void gbaudio_codec_cleanup(struct gbaudio_module_info *module) ...@@ -891,17 +859,14 @@ static void gbaudio_codec_cleanup(struct gbaudio_module_info *module)
ret = gb_audio_apbridgea_unregister_cport(data->connection, ret = gb_audio_apbridgea_unregister_cport(data->connection,
i2s_port, cportid, i2s_port, cportid,
AUDIO_APBRIDGEA_DIRECTION_TX); AUDIO_APBRIDGEA_DIRECTION_TX);
module->ctrlstate[0] = GBAUDIO_CODEC_SHUTDOWN; data->state[0] = GBAUDIO_CODEC_SHUTDOWN;
} }
static void gbaudio_codec_clean_data_rx(struct gbaudio_data_connection *data)
{
uint16_t i2s_port, cportid;
int ret;
if (cap_state == GBAUDIO_CODEC_START) {
/* cleanup CAP path, only APBridge specific */
data = find_data(module, 1);
if (!data) {
dev_err(gbcodec->dev, "%s: Missing data pointer\n",
__func__);
return;
}
if (list_is_singular(&gbcodec->module_list)) { if (list_is_singular(&gbcodec->module_list)) {
ret = gb_audio_apbridgea_stop_rx(data->connection, 0); ret = gb_audio_apbridgea_stop_rx(data->connection, 0);
if (ret) if (ret)
...@@ -916,7 +881,26 @@ static void gbaudio_codec_cleanup(struct gbaudio_module_info *module) ...@@ -916,7 +881,26 @@ static void gbaudio_codec_cleanup(struct gbaudio_module_info *module)
ret = gb_audio_apbridgea_unregister_cport(data->connection, ret = gb_audio_apbridgea_unregister_cport(data->connection,
i2s_port, cportid, i2s_port, cportid,
AUDIO_APBRIDGEA_DIRECTION_RX); AUDIO_APBRIDGEA_DIRECTION_RX);
module->ctrlstate[1] = GBAUDIO_CODEC_SHUTDOWN; data->state[1] = GBAUDIO_CODEC_SHUTDOWN;
}
static void gbaudio_codec_cleanup(struct gbaudio_module_info *module)
{
struct gbaudio_data_connection *data;
int pb_state, cap_state;
dev_dbg(gbcodec->dev, "%s: removed, cleanup APBridge\n", module->name);
list_for_each_entry(data, &module->data_list, list) {
pb_state = data->state[0];
cap_state = data->state[1];
if (pb_state > GBAUDIO_CODEC_SHUTDOWN)
gbaudio_codec_clean_data_tx(data);
if (cap_state > GBAUDIO_CODEC_SHUTDOWN)
gbaudio_codec_clean_data_rx(data);
} }
} }
......
...@@ -140,6 +140,8 @@ struct gbaudio_data_connection { ...@@ -140,6 +140,8 @@ struct gbaudio_data_connection {
__le16 data_cport; __le16 data_cport;
struct gb_connection *connection; struct gb_connection *connection;
struct list_head list; struct list_head list;
/* maintain runtime state for playback/capture stream */
int state[2];
}; };
/* stream direction */ /* stream direction */
...@@ -178,9 +180,6 @@ struct gbaudio_module_info { ...@@ -178,9 +180,6 @@ struct gbaudio_module_info {
struct snd_soc_jack headset_jack; struct snd_soc_jack headset_jack;
struct snd_soc_jack button_jack; struct snd_soc_jack button_jack;
/* used by codec_ops */
int ctrlstate[2]; /* PB/CAP */
/* connection info */ /* connection info */
struct gb_connection *mgmt_connection; struct gb_connection *mgmt_connection;
size_t num_data_connections; size_t num_data_connections;
......
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