diff options
author | Vaibhav Agarwal <vaibhav.agarwal@linaro.org> | 2016-03-29 16:32:36 +0530 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@google.com> | 2016-03-31 10:19:57 -0700 |
commit | 64a7e2cceb75ccabaec713944a95511605751b29 (patch) | |
tree | 1c745b4cb31d73c8acb1c3ac2eda3b087195142f /drivers/staging/greybus/audio_codec.c | |
parent | 6da549ec851117293a07e64f97170f7dc9d55578 (diff) |
greybus: audio: Added jack support to audio module
Register jack with ASoC sound card in case audio module
populates it via codec FW. Currently, only a single jack
with 4 buttons can be registered for each module.
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.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 803bab20cf0c..66a954806cf5 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -9,6 +9,7 @@ #include <linux/module.h> #include <sound/soc.h> #include <sound/pcm_params.h> +#include <uapi/linux/input.h> #include "audio_codec.h" #include "audio_apbridgea.h" @@ -735,10 +736,80 @@ static struct snd_soc_dai_ops gbcodec_dai_ops = { .digital_mute = gbcodec_digital_mute, }; +static int gbaudio_init_jack(struct gbaudio_module_info *module, + struct snd_soc_codec *codec) +{ + int ret; + + if (!module->num_jacks) + return 0; + + /* register jack(s) in case any */ + if (module->num_jacks > 1) { + dev_err(module->dev, "Currently supports max=1 jack\n"); + return -EINVAL; + } + + snprintf(module->jack_name, NAME_SIZE, "GB %d Headset Jack", + module->dev_id); + ret = snd_soc_jack_new(codec, module->jack_name, GBCODEC_JACK_MASK, + &module->headset_jack); + if (ret) { + dev_err(module->dev, "Failed to create new jack\n"); + return ret; + } + + snprintf(module->button_name, NAME_SIZE, "GB %d Button Jack", + module->dev_id); + ret = snd_soc_jack_new(codec, module->button_name, + GBCODEC_JACK_BUTTON_MASK, &module->button_jack); + if (ret) { + dev_err(module->dev, "Failed to create button jack\n"); + return ret; + } + + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_0, + KEY_MEDIA); + if (ret) { + dev_err(module->dev, "Failed to set BTN_0\n"); + return ret; + } + + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_1, + KEY_VOICECOMMAND); + if (ret) { + dev_err(module->dev, "Failed to set BTN_1\n"); + return ret; + } + + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_2, + KEY_VOLUMEUP); + if (ret) { + dev_err(module->dev, "Failed to set BTN_2\n"); + return ret; + } + + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_3, + KEY_VOLUMEDOWN); + if (ret) { + dev_err(module->dev, "Failed to set BTN_0\n"); + return ret; + } + + /* FIXME + * verify if this is really required + set_bit(INPUT_PROP_NO_DUMMY_RELEASE, + module->button_jack.jack->input_dev->propbit); + */ + + return 0; +} + int gbaudio_register_module(struct gbaudio_module_info *module) { int ret; struct snd_soc_codec *codec; + struct snd_soc_jack *jack = NULL; if (!gbcodec) { dev_err(module->dev, "GB Codec not yet probed\n"); @@ -756,6 +827,12 @@ int gbaudio_register_module(struct gbaudio_module_info *module) return -EINVAL; } + ret = gbaudio_init_jack(module, codec); + if (ret) { + mutex_unlock(&gbcodec->lock); + return ret; + } + if (module->dapm_widgets) snd_soc_dapm_new_controls(&codec->dapm, module->dapm_widgets, module->num_dapm_widgets); @@ -774,6 +851,15 @@ int gbaudio_register_module(struct gbaudio_module_info *module) &codec->dapm); } +#ifdef CONFIG_SND_JACK + /* register jack devices for this module from codec->jack_list */ + list_for_each_entry(jack, &codec->jack_list, list) { + if ((jack == &module->headset_jack) + || (jack == &module->button_jack)) + snd_device_register(codec->card->snd_card, jack->jack); + } +#endif + list_add(&module->list, &gbcodec->module_list); dev_dbg(codec->dev, "Registered %s module\n", module->name); @@ -851,6 +937,7 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) { struct snd_soc_codec *codec = gbcodec->codec; struct snd_card *card = codec->card->snd_card; + struct snd_soc_jack *jack, *next_j; dev_dbg(codec->dev, "Unregister %s module\n", module->name); @@ -862,6 +949,17 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) dev_dbg(codec->dev, "Process Unregister %s module\n", module->name); mutex_lock(&module->lock); +#ifdef CONFIG_SND_JACK + /* free jack devices for this module from codec->jack_list */ + list_for_each_entry_safe(jack, next_j, &codec->jack_list, list) { + if ((jack == &module->headset_jack) + || (jack == &module->button_jack)) { + snd_device_free(codec->card->snd_card, jack->jack); + list_del(&jack->list); + } + } +#endif + gbaudio_codec_cleanup(module); module->is_connected = 0; |