summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/tegra/tegra_wm8903.c138
1 files changed, 127 insertions, 11 deletions
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index 4bea080e6f2a..bebccffe38d4 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -34,6 +34,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
#include <mach/tegra_wm8903_pdata.h>
@@ -59,6 +60,8 @@
struct tegra_wm8903 {
struct tegra_asoc_utils_data util_data;
struct tegra_wm8903_platform_data *pdata;
+ struct regulator *spk_reg;
+ struct regulator *dmic_reg;
int gpio_requested;
};
@@ -162,6 +165,13 @@ static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w,
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ if (machine->spk_reg) {
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ regulator_enable(machine->spk_reg);
+ else
+ regulator_disable(machine->spk_reg);
+ }
+
if (!(machine->gpio_requested & GPIO_SPKR_EN))
return 0;
@@ -188,7 +198,57 @@ static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w,
return 0;
}
-static const struct snd_soc_dapm_widget tegra_wm8903_dapm_widgets[] = {
+static int tegra_wm8903_event_int_mic(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ struct snd_soc_dapm_context *dapm = w->dapm;
+ struct snd_soc_card *card = dapm->card;
+ struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_wm8903_platform_data *pdata = machine->pdata;
+
+ if (machine->dmic_reg) {
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ regulator_enable(machine->dmic_reg);
+ else
+ regulator_disable(machine->dmic_reg);
+ }
+
+ if (!(machine->gpio_requested & GPIO_INT_MIC_EN))
+ return 0;
+
+ gpio_set_value_cansleep(pdata->gpio_int_mic_en,
+ SND_SOC_DAPM_EVENT_ON(event));
+
+ return 0;
+}
+
+static int tegra_wm8903_event_ext_mic(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ struct snd_soc_dapm_context *dapm = w->dapm;
+ struct snd_soc_card *card = dapm->card;
+ struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_wm8903_platform_data *pdata = machine->pdata;
+
+ if (!(machine->gpio_requested & GPIO_EXT_MIC_EN))
+ return 0;
+
+ gpio_set_value_cansleep(pdata->gpio_ext_mic_en,
+ SND_SOC_DAPM_EVENT_ON(event));
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget cardhu_dapm_widgets[] = {
+ SND_SOC_DAPM_SPK("Int Spk", tegra_wm8903_event_int_spk),
+ SND_SOC_DAPM_HP("Headphone Jack", tegra_wm8903_event_hp),
+ SND_SOC_DAPM_LINE("Line Out", NULL),
+ SND_SOC_DAPM_MIC("Mic Jack", tegra_wm8903_event_ext_mic),
+ SND_SOC_DAPM_MIC("Int Mic", tegra_wm8903_event_int_mic),
+ SND_SOC_DAPM_LINE("Line In", NULL),
+};
+
+static const struct snd_soc_dapm_widget tegra_wm8903_default_dapm_widgets[] = {
SND_SOC_DAPM_SPK("Int Spk", tegra_wm8903_event_int_spk),
SND_SOC_DAPM_HP("Headphone Jack", tegra_wm8903_event_hp),
SND_SOC_DAPM_MIC("Mic Jack", NULL),
@@ -205,6 +265,24 @@ static const struct snd_soc_dapm_route harmony_audio_map[] = {
{"IN1L", NULL, "Mic Bias"},
};
+static const struct snd_soc_dapm_route cardhu_audio_map[] = {
+ {"Headphone Jack", NULL, "HPOUTR"},
+ {"Headphone Jack", NULL, "HPOUTL"},
+ {"Int Spk", NULL, "ROP"},
+ {"Int Spk", NULL, "RON"},
+ {"Int Spk", NULL, "LOP"},
+ {"Int Spk", NULL, "LON"},
+ {"Line Out", NULL, "LINEOUTL"},
+ {"Line Out", NULL, "LINEOUTR"},
+ {"Mic Bias", NULL, "Mic Jack"},
+ {"IN1L", NULL, "Mic Bias"},
+ {"Mic Bias", NULL, "Int Mic"},
+ {"IN1L", NULL, "Mic Bias"},
+ {"IN1R", NULL, "Mic Bias"},
+ {"IN3L", NULL, "Line In"},
+ {"IN3R", NULL, "Line In"},
+};
+
static const struct snd_soc_dapm_route seaboard_audio_map[] = {
{"Headphone Jack", NULL, "HPOUTR"},
{"Headphone Jack", NULL, "HPOUTL"},
@@ -236,7 +314,16 @@ static const struct snd_soc_dapm_route aebl_audio_map[] = {
{"IN1R", NULL, "Mic Bias"},
};
-static const struct snd_kcontrol_new tegra_wm8903_controls[] = {
+static const struct snd_kcontrol_new cardhu_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Int Spk"),
+ SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+ SOC_DAPM_PIN_SWITCH("LineOut"),
+ SOC_DAPM_PIN_SWITCH("Mic Jack"),
+ SOC_DAPM_PIN_SWITCH("Int Mic"),
+ SOC_DAPM_PIN_SWITCH("LineIn"),
+};
+
+static const struct snd_kcontrol_new tegra_wm8903_default_controls[] = {
SOC_DAPM_PIN_SWITCH("Int Spk"),
};
@@ -320,9 +407,10 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
/* FIXME: Calculate automatically based on DAPM routes? */
if (!machine_is_harmony() && !machine_is_ventana() &&
- !machine_is_ventana())
+ !machine_is_cardhu())
snd_soc_dapm_nc_pin(dapm, "IN1L");
- if (!machine_is_seaboard() && !machine_is_aebl())
+ if (!machine_is_seaboard() && !machine_is_aebl() &&
+ !machine_is_cardhu())
snd_soc_dapm_nc_pin(dapm, "IN1R");
snd_soc_dapm_nc_pin(dapm, "IN2L");
if (!machine_is_kaen())
@@ -371,11 +459,6 @@ static struct snd_soc_card snd_soc_tegra_wm8903 = {
.name = "tegra-wm8903",
.dai_link = tegra_wm8903_dai,
.num_links = ARRAY_SIZE(tegra_wm8903_dai),
-
- .controls = tegra_wm8903_controls,
- .num_controls = ARRAY_SIZE(tegra_wm8903_controls),
- .dapm_widgets = tegra_wm8903_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(tegra_wm8903_dapm_widgets),
};
static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
@@ -403,6 +486,18 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
if (ret)
goto err_free_machine;
+ machine->spk_reg = regulator_get(&pdev->dev, "vdd_spk_amp");
+ if (IS_ERR(machine->spk_reg)) {
+ dev_info(&pdev->dev, "No speaker regulator found\n");
+ machine->spk_reg = 0;
+ }
+
+ machine->dmic_reg = regulator_get(&pdev->dev, "vdd_dmic");
+ if (IS_ERR(machine->dmic_reg)) {
+ dev_info(&pdev->dev, "No digital mic regulator found\n");
+ machine->dmic_reg = 0;
+ }
+
if (machine_is_cardhu()) {
tegra_wm8903_dai[0].codec_name = "wm8903.4-001a",
tegra_wm8903_dai[0].cpu_dai_name = "tegra30-i2s.1";
@@ -414,10 +509,26 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, card);
snd_soc_card_set_drvdata(card, machine);
- if (machine_is_harmony() || machine_is_ventana() ||
- machine_is_cardhu()) {
+ if (machine_is_cardhu() || machine_is_ventana()) {
+ card->controls = cardhu_controls;
+ card->num_controls = ARRAY_SIZE(cardhu_controls);
+
+ card->dapm_widgets = cardhu_dapm_widgets;
+ card->num_dapm_widgets = ARRAY_SIZE(cardhu_dapm_widgets);
+ } else {
+ card->controls = tegra_wm8903_default_controls;
+ card->num_controls = ARRAY_SIZE(tegra_wm8903_default_controls);
+
+ card->dapm_widgets = tegra_wm8903_default_dapm_widgets;
+ card->num_dapm_widgets = ARRAY_SIZE(tegra_wm8903_default_dapm_widgets);
+ }
+
+ if (machine_is_harmony()) {
card->dapm_routes = harmony_audio_map;
card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map);
+ } else if (machine_is_ventana() || machine_is_cardhu()) {
+ card->dapm_routes = cardhu_audio_map;
+ card->num_dapm_routes = ARRAY_SIZE(cardhu_audio_map);
} else if (machine_is_seaboard()) {
card->dapm_routes = seaboard_audio_map;
card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map);
@@ -465,6 +576,11 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
gpio_free(pdata->gpio_spkr_en);
machine->gpio_requested = 0;
+ if (machine->spk_reg)
+ regulator_put(machine->spk_reg);
+ if (machine->dmic_reg)
+ regulator_put(machine->dmic_reg);
+
snd_soc_unregister_card(card);
tegra_asoc_utils_fini(&machine->util_data);