summaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/audio_codec.c
diff options
context:
space:
mode:
authorVaibhav Agarwal2016-06-09 06:00:39 +0200
committerGreg Kroah-Hartman2016-06-10 06:21:09 +0200
commit27c243cf5fcf4b3bb525f1f3f15ed8db91199507 (patch)
treeb8a204021996ee419362e9b7f75e675638347c50 /drivers/staging/greybus/audio_codec.c
parentgreybus: update UniPro Set Interface Power Mode operation to match spec (diff)
downloadkernel-qcow2-linux-27c243cf5fcf4b3bb525f1f3f15ed8db91199507.tar.gz
kernel-qcow2-linux-27c243cf5fcf4b3bb525f1f3f15ed8db91199507.tar.xz
kernel-qcow2-linux-27c243cf5fcf4b3bb525f1f3f15ed8db91199507.zip
greybus: Use mute_stream callback to initiate GB data xfer
Currently trigger callback is used to start/stop greybus tx/rx path. This works well for almost all scenario except few specially handled usecases by Android Audio subsystem. In case of Music playback followed by Incoming ringtone, above layer tries to trigger_pause from one FE dailink and start a fresh playback via different FE dailink. Since, same BE dailink is used for both cases, an invalid state transition is requested i.e. from PAUSE->START. This fails & thus causes ringtone playback failure. With built-in codec, trigger callback is not required to initiate data xfer unlike gb-codec driver. This state transition should be handled in Android layer, but since it can lead to multiple side effects for various usecase we are trying to avoid trigger callback in gbcodec driver 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>
Diffstat (limited to 'drivers/staging/greybus/audio_codec.c')
-rw-r--r--drivers/staging/greybus/audio_codec.c77
1 files changed, 19 insertions, 58 deletions
diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c
index 975d2e86b113..334469345f87 100644
--- a/drivers/staging/greybus/audio_codec.c
+++ b/drivers/staging/greybus/audio_codec.c
@@ -731,54 +731,24 @@ func_exit:
return ret;
}
-static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
+static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
{
int ret;
- int tx, rx, start, stop;
struct gbaudio_data_connection *data;
struct gbaudio_module_info *module;
struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev);
+
+ dev_dbg(dai->dev, "Mute:%d, Direction:%s\n", mute,
+ stream ? "CAPTURE":"PLAYBACK");
+
mutex_lock(&codec->lock);
if (list_empty(&codec->module_list)) {
dev_err(codec->dev, "No codec module available\n");
mutex_unlock(&codec->lock);
- if (cmd == SNDRV_PCM_TRIGGER_STOP)
- return 0;
return -ENODEV;
}
- tx = rx = start = stop = 0;
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- start = 1;
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- stop = 1;
- break;
- default:
- dev_err(dai->dev, "Invalid tigger cmd:%d\n", cmd);
- ret = -EINVAL;
- goto func_exit;
- }
-
- switch (substream->stream) {
- case SNDRV_PCM_STREAM_CAPTURE:
- rx = 1;
- break;
- case SNDRV_PCM_STREAM_PLAYBACK:
- tx = 1;
- break;
- default:
- dev_err(dai->dev, "Invalid stream type:%d\n",
- substream->stream);
- ret = -EINVAL;
- goto func_exit;
- }
-
list_for_each_entry(module, &codec->module_list, list) {
/* find the dai */
data = find_data(module, dai->name);
@@ -791,50 +761,43 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd,
ret = -ENODEV;
goto func_exit;
}
- if (start && tx) {
+
+ if (!mute && !stream) {/* start playback */
ret = gb_audio_apbridgea_prepare_tx(data->connection,
0);
if (!ret)
ret = gb_audio_apbridgea_start_tx(data->connection,
0, 0);
- codec->stream[substream->stream].state = GBAUDIO_CODEC_START;
- } else if (start && rx) {
+ codec->stream[stream].state = GBAUDIO_CODEC_START;
+ } else if (!mute && stream) {/* start capture */
ret = gb_audio_apbridgea_prepare_rx(data->connection,
0);
if (!ret)
ret = gb_audio_apbridgea_start_rx(data->connection,
0);
- codec->stream[substream->stream].state = GBAUDIO_CODEC_START;
- } else if (stop && tx) {
+ codec->stream[stream].state = GBAUDIO_CODEC_START;
+ } else if (mute && !stream) {/* stop playback */
ret = gb_audio_apbridgea_stop_tx(data->connection, 0);
if (!ret)
ret = gb_audio_apbridgea_shutdown_tx(data->connection,
0);
- codec->stream[substream->stream].state = GBAUDIO_CODEC_STOP;
- } else if (stop && rx) {
+ codec->stream[stream].state = GBAUDIO_CODEC_STOP;
+ } else if (mute && stream) {/* stop capture */
ret = gb_audio_apbridgea_stop_rx(data->connection, 0);
if (!ret)
ret = gb_audio_apbridgea_shutdown_rx(data->connection,
0);
- codec->stream[substream->stream].state = GBAUDIO_CODEC_STOP;
+ codec->stream[stream].state = GBAUDIO_CODEC_STOP;
} else
ret = -EINVAL;
if (ret)
- dev_err_ratelimited(dai->dev, "%s:Error during %s stream:%d\n",
- module->name, start ? "Start" : "Stop", ret);
+ dev_err_ratelimited(dai->dev,
+ "%s:Error during %s %s stream:%d\n",
+ module->name, mute ? "Mute" : "Unmute",
+ stream ? "Capture" : "Playback", ret);
func_exit:
mutex_unlock(&codec->lock);
- return ret;
-}
-
-static int gbcodec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-{
- return 0;
-}
-
-static int gbcodec_digital_mute(struct snd_soc_dai *dai, int mute)
-{
return 0;
}
@@ -842,10 +805,8 @@ static struct snd_soc_dai_ops gbcodec_dai_ops = {
.startup = gbcodec_startup,
.shutdown = gbcodec_shutdown,
.hw_params = gbcodec_hw_params,
- .trigger = gbcodec_trigger,
.prepare = gbcodec_prepare,
- .set_fmt = gbcodec_set_dai_fmt,
- .digital_mute = gbcodec_digital_mute,
+ .mute_stream = gbcodec_mute_stream,
};
static int gbaudio_init_jack(struct gbaudio_module_info *module,