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,
struct gbaudio_data_connection *data;
struct gbaudio_stream_params *params;
module_state = module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK];
/* find the dai */
data = find_data(module, id);
if (!data) {
dev_err(module->dev, "%d:DATA connection missing\n", id);
return -ENODEV;
}
module_state = data->state[SNDRV_PCM_STREAM_PLAYBACK];
params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_PLAYBACK);
if (!params) {
......@@ -79,7 +78,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec,
"reg_cport failed:%d\n", ret);
return ret;
}
module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] =
data->state[SNDRV_PCM_STREAM_PLAYBACK] =
GBAUDIO_CODEC_STARTUP;
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,
ret);
return ret;
}
module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] =
data->state[SNDRV_PCM_STREAM_PLAYBACK] =
GBAUDIO_CODEC_HWPARAMS;
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,
"activate_tx failed:%d\n", ret);
return ret;
}
module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] =
data->state[SNDRV_PCM_STREAM_PLAYBACK] =
GBAUDIO_CODEC_PREPARE;
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)
int module_state;
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 */
data = find_data(module, id);
if (!data) {
dev_err(module->dev, "%d:DATA connection missing\n", id);
return -ENODEV;
}
module_state = data->state[SNDRV_PCM_STREAM_PLAYBACK];
if (module_state > GBAUDIO_CODEC_HWPARAMS) {
data_cport = data->connection->intf_cport_id;
......@@ -160,7 +153,7 @@ static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id)
return ret;
}
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;
}
......@@ -177,7 +170,7 @@ static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id)
return ret;
}
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;
}
......@@ -194,14 +187,13 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec,
struct gbaudio_data_connection *data;
struct gbaudio_stream_params *params;
module_state = module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE];
/* find the dai */
data = find_data(module, id);
if (!data) {
dev_err(module->dev, "%d:DATA connection missing\n", id);
return -ENODEV;
}
module_state = data->state[SNDRV_PCM_STREAM_CAPTURE];
params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_CAPTURE);
if (!params) {
......@@ -221,7 +213,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec,
"reg_cport failed:%d\n", ret);
return ret;
}
module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] =
data->state[SNDRV_PCM_STREAM_CAPTURE] =
GBAUDIO_CODEC_STARTUP;
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,
ret);
return ret;
}
module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] =
data->state[SNDRV_PCM_STREAM_CAPTURE] =
GBAUDIO_CODEC_HWPARAMS;
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,
"activate_rx failed:%d\n", ret);
return ret;
}
module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] =
data->state[SNDRV_PCM_STREAM_CAPTURE] =
GBAUDIO_CODEC_PREPARE;
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)
int module_state;
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 */
data = find_data(module, id);
if (!data) {
dev_err(module->dev, "%d:DATA connection missing\n", id);
return -ENODEV;
}
module_state = data->state[SNDRV_PCM_STREAM_CAPTURE];
if (module_state > GBAUDIO_CODEC_HWPARAMS) {
data_cport = data->connection->intf_cport_id;
......@@ -303,7 +288,7 @@ static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id)
return ret;
}
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;
}
......@@ -320,7 +305,7 @@ static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id)
return ret;
}
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;
}
......@@ -855,68 +840,67 @@ int gbaudio_register_module(struct gbaudio_module_info *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;
uint16_t i2s_port, cportid;
int ret;
if (list_is_singular(&gbcodec->module_list)) {
ret = gb_audio_apbridgea_stop_tx(data->connection, 0);
if (ret)
return;
ret = gb_audio_apbridgea_shutdown_tx(data->connection,
0);
if (ret)
return;
}
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);
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;
/* locks already acquired */
if (!pb_state && !cap_state)
return;
if (list_is_singular(&gbcodec->module_list)) {
ret = gb_audio_apbridgea_stop_rx(data->connection, 0);
if (ret)
return;
ret = gb_audio_apbridgea_shutdown_rx(data->connection,
0);
if (ret)
return;
}
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);
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);
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;
}
list_for_each_entry(data, &module->data_list, list) {
pb_state = data->state[0];
cap_state = data->state[1];
if (list_is_singular(&gbcodec->module_list)) {
ret = gb_audio_apbridgea_stop_tx(data->connection, 0);
if (ret)
return;
ret = gb_audio_apbridgea_shutdown_tx(data->connection,
0);
if (ret)
return;
}
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);
module->ctrlstate[0] = GBAUDIO_CODEC_SHUTDOWN;
}
if (pb_state > GBAUDIO_CODEC_SHUTDOWN)
gbaudio_codec_clean_data_tx(data);
if (cap_state > GBAUDIO_CODEC_SHUTDOWN)
gbaudio_codec_clean_data_rx(data);
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)) {
ret = gb_audio_apbridgea_stop_rx(data->connection, 0);
if (ret)
return;
ret = gb_audio_apbridgea_shutdown_rx(data->connection,
0);
if (ret)
return;
}
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);
module->ctrlstate[1] = GBAUDIO_CODEC_SHUTDOWN;
}
}
......
......@@ -140,6 +140,8 @@ struct gbaudio_data_connection {
__le16 data_cport;
struct gb_connection *connection;
struct list_head list;
/* maintain runtime state for playback/capture stream */
int state[2];
};
/* stream direction */
......@@ -178,9 +180,6 @@ struct gbaudio_module_info {
struct snd_soc_jack headset_jack;
struct snd_soc_jack button_jack;
/* used by codec_ops */
int ctrlstate[2]; /* PB/CAP */
/* connection info */
struct gb_connection *mgmt_connection;
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