aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/tegra/harmony.c
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2011-01-28 16:26:37 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-01-31 08:15:59 -0500
commit6e267645046ecc161791b5a0d2eef6e494681416 (patch)
tree0a7fd9a8b14efde0a57799a7479f7d9b0aa8208a /sound/soc/tegra/harmony.c
parent72de2b1a9a5b869c1eaea098dd2a75e6bbbf0488 (diff)
ASoC: Tegra: Harmony: Support the internal speaker
Add DAPM widget definitions for the internal speaker paths. Currently, this path is always enabled while playback is active. Add code to control the speaker amplifier GPIO. The GPIO is requested during _init, since that's the first time it is guaranteed that the WM8903 module is loaded, probed, and hence has exported its GPIO chip. Signed-off-by: Stephen Warren <swarren@nvidia.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/tegra/harmony.c')
-rw-r--r--sound/soc/tegra/harmony.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/sound/soc/tegra/harmony.c b/sound/soc/tegra/harmony.c
index 2d6a15c6bdfe..0f5a48150930 100644
--- a/sound/soc/tegra/harmony.c
+++ b/sound/soc/tegra/harmony.c
@@ -33,6 +33,9 @@
33#include <linux/module.h> 33#include <linux/module.h>
34#include <linux/platform_device.h> 34#include <linux/platform_device.h>
35#include <linux/slab.h> 35#include <linux/slab.h>
36#include <linux/gpio.h>
37
38#include <mach/harmony_audio.h>
36 39
37#include <sound/core.h> 40#include <sound/core.h>
38#include <sound/pcm.h> 41#include <sound/pcm.h>
@@ -48,6 +51,8 @@
48#define PREFIX DRV_NAME ": " 51#define PREFIX DRV_NAME ": "
49 52
50struct tegra_harmony { 53struct tegra_harmony {
54 struct harmony_audio_platform_data *pdata;
55 int gpio_spkr_en_requested;
51}; 56};
52 57
53static int harmony_asoc_hw_params(struct snd_pcm_substream *substream, 58static int harmony_asoc_hw_params(struct snd_pcm_substream *substream,
@@ -113,7 +118,22 @@ static struct snd_soc_ops harmony_asoc_ops = {
113 .hw_params = harmony_asoc_hw_params, 118 .hw_params = harmony_asoc_hw_params,
114}; 119};
115 120
121static int harmony_event_int_spk(struct snd_soc_dapm_widget *w,
122 struct snd_kcontrol *k, int event)
123{
124 struct snd_soc_codec *codec = w->codec;
125 struct snd_soc_card *card = codec->card;
126 struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card);
127 struct harmony_audio_platform_data *pdata = harmony->pdata;
128
129 gpio_set_value_cansleep(pdata->gpio_spkr_en,
130 !!SND_SOC_DAPM_EVENT_ON(event));
131
132 return 0;
133}
134
116static const struct snd_soc_dapm_widget harmony_dapm_widgets[] = { 135static const struct snd_soc_dapm_widget harmony_dapm_widgets[] = {
136 SND_SOC_DAPM_SPK("Int Spk", harmony_event_int_spk),
117 SND_SOC_DAPM_HP("Headphone Jack", NULL), 137 SND_SOC_DAPM_HP("Headphone Jack", NULL),
118 SND_SOC_DAPM_MIC("Mic Jack", NULL), 138 SND_SOC_DAPM_MIC("Mic Jack", NULL),
119}; 139};
@@ -121,6 +141,10 @@ static const struct snd_soc_dapm_widget harmony_dapm_widgets[] = {
121static const struct snd_soc_dapm_route harmony_audio_map[] = { 141static const struct snd_soc_dapm_route harmony_audio_map[] = {
122 {"Headphone Jack", NULL, "HPOUTR"}, 142 {"Headphone Jack", NULL, "HPOUTR"},
123 {"Headphone Jack", NULL, "HPOUTL"}, 143 {"Headphone Jack", NULL, "HPOUTL"},
144 {"Int Spk", NULL, "ROP"},
145 {"Int Spk", NULL, "RON"},
146 {"Int Spk", NULL, "LOP"},
147 {"Int Spk", NULL, "LON"},
124 {"Mic Bias", NULL, "Mic Jack"}, 148 {"Mic Bias", NULL, "Mic Jack"},
125 {"IN1L", NULL, "Mic Bias"}, 149 {"IN1L", NULL, "Mic Bias"},
126}; 150};
@@ -129,6 +153,19 @@ static int harmony_asoc_init(struct snd_soc_pcm_runtime *rtd)
129{ 153{
130 struct snd_soc_codec *codec = rtd->codec; 154 struct snd_soc_codec *codec = rtd->codec;
131 struct snd_soc_dapm_context *dapm = &codec->dapm; 155 struct snd_soc_dapm_context *dapm = &codec->dapm;
156 struct snd_soc_card *card = codec->card;
157 struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card);
158 struct harmony_audio_platform_data *pdata = harmony->pdata;
159 int ret;
160
161 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
162 if (ret) {
163 dev_err(card->dev, "cannot get spkr_en gpio\n");
164 return ret;
165 }
166 harmony->gpio_spkr_en_requested = 1;
167
168 gpio_direction_output(pdata->gpio_spkr_en, 0);
132 169
133 snd_soc_dapm_new_controls(dapm, harmony_dapm_widgets, 170 snd_soc_dapm_new_controls(dapm, harmony_dapm_widgets,
134 ARRAY_SIZE(harmony_dapm_widgets)); 171 ARRAY_SIZE(harmony_dapm_widgets));
@@ -137,6 +174,7 @@ static int harmony_asoc_init(struct snd_soc_pcm_runtime *rtd)
137 ARRAY_SIZE(harmony_audio_map)); 174 ARRAY_SIZE(harmony_audio_map));
138 175
139 snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); 176 snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
177 snd_soc_dapm_enable_pin(dapm, "Int Spk");
140 snd_soc_dapm_enable_pin(dapm, "Mic Jack"); 178 snd_soc_dapm_enable_pin(dapm, "Mic Jack");
141 snd_soc_dapm_sync(dapm); 179 snd_soc_dapm_sync(dapm);
142 180
@@ -164,6 +202,7 @@ static __devinit int tegra_snd_harmony_probe(struct platform_device *pdev)
164{ 202{
165 struct snd_soc_card *card = &snd_soc_harmony; 203 struct snd_soc_card *card = &snd_soc_harmony;
166 struct tegra_harmony *harmony; 204 struct tegra_harmony *harmony;
205 struct harmony_audio_platform_data *pdata;
167 int ret; 206 int ret;
168 207
169 if (!machine_is_harmony()) { 208 if (!machine_is_harmony()) {
@@ -171,12 +210,20 @@ static __devinit int tegra_snd_harmony_probe(struct platform_device *pdev)
171 return -ENODEV; 210 return -ENODEV;
172 } 211 }
173 212
213 pdata = pdev->dev.platform_data;
214 if (!pdata) {
215 dev_err(&pdev->dev, "no platform data supplied\n");
216 return -EINVAL;
217 }
218
174 harmony = kzalloc(sizeof(struct tegra_harmony), GFP_KERNEL); 219 harmony = kzalloc(sizeof(struct tegra_harmony), GFP_KERNEL);
175 if (!harmony) { 220 if (!harmony) {
176 dev_err(&pdev->dev, "Can't allocate tegra_harmony\n"); 221 dev_err(&pdev->dev, "Can't allocate tegra_harmony\n");
177 return -ENOMEM; 222 return -ENOMEM;
178 } 223 }
179 224
225 harmony->pdata = pdata;
226
180 ret = tegra_asoc_utils_init(); 227 ret = tegra_asoc_utils_init();
181 if (ret) 228 if (ret)
182 goto err_free_harmony; 229 goto err_free_harmony;
@@ -208,6 +255,7 @@ static int __devexit tegra_snd_harmony_remove(struct platform_device *pdev)
208{ 255{
209 struct snd_soc_card *card = platform_get_drvdata(pdev); 256 struct snd_soc_card *card = platform_get_drvdata(pdev);
210 struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card); 257 struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card);
258 struct harmony_audio_platform_data *pdata = harmony->pdata;
211 259
212 snd_soc_unregister_card(card); 260 snd_soc_unregister_card(card);
213 261
@@ -217,6 +265,9 @@ static int __devexit tegra_snd_harmony_remove(struct platform_device *pdev)
217 265
218 tegra_asoc_utils_fini(); 266 tegra_asoc_utils_fini();
219 267
268 if (harmony->gpio_spkr_en_requested)
269 gpio_free(pdata->gpio_spkr_en);
270
220 kfree(harmony); 271 kfree(harmony);
221 272
222 return 0; 273 return 0;