greybus: audio: Maintain module stream state for each data connection
authorVaibhav Agarwal <vaibhav.agarwal@linaro.org>
Thu, 4 Aug 2016 09:44:39 +0000 (15:14 +0530)
committerGreg Kroah-Hartman <gregkh@google.com>
Thu, 4 Aug 2016 17:07:30 +0000 (19:07 +0200)
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: Vaibhav Agarwal <vaibhav.agarwal@linaro.org>
Reviewed-by: Mark Greer <mgreer@animalcreek.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/audio_codec.c
drivers/staging/greybus/audio_codec.h

index e1ad685..cf86f51 100644 (file)
@@ -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;
        }
 }
 
index 40c39b3..0de2ad9 100644 (file)
@@ -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;