aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2011-04-12 13:40:39 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-04-18 16:34:16 -0400
commit773b1d3d31bbf7257c48f6257b4ab06bcf4f5dfa (patch)
treed13b18f3155a408af36855fa23f2741efd78d36a
parent3eb25f998d3aede5f0011ba236e7586351e450bf (diff)
ASoC: Tegra: Support more boards
* Ventana is identical to Harmony. * Seaboard, Kaen, and Aebl are all pretty similar, mainly with slightly different sets of GPIOs, and slightly different WM8903 pin connectivity. Signed-off-by: Stephen Warren <swarren@nvidia.com> Acked-by: Liam Girdwood <lrg@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--sound/soc/tegra/Kconfig7
-rw-r--r--sound/soc/tegra/tegra_wm8903.c180
2 files changed, 145 insertions, 42 deletions
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 21125b302630..14f711977ae3 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -16,12 +16,13 @@ config SND_SOC_TEGRA_I2S
16 16
17config SND_SOC_TEGRA_WM8903 17config SND_SOC_TEGRA_WM8903
18 tristate "SoC Audio support for Tegra boards using a WM8903 codec" 18 tristate "SoC Audio support for Tegra boards using a WM8903 codec"
19 depends on SND_SOC_TEGRA && MACH_HARMONY && I2C 19 depends on SND_SOC_TEGRA && I2C
20 depends on MACH_HARMONY || MACH_VENTANA || MACH_SEABOARD || MACH_KAEN || MACH_AEBL
20 default m 21 default m
21 select SND_SOC_TEGRA_I2S 22 select SND_SOC_TEGRA_I2S
22 select SND_SOC_WM8903 23 select SND_SOC_WM8903
23 help 24 help
24 Say Y or M here if you want to add support for SoC audio on Tegra 25 Say Y or M here if you want to add support for SoC audio on Tegra
25 boards using the WM8093 codec. Currently, the only supported board 26 boards using the WM8093 codec. Currently, the supported boards are
26 is Harmony. 27 Harmony, Ventana, Seaboard, Kaen, and Aebl.
27 28
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index 2b3844322c40..37f6010a9109 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -53,8 +53,9 @@
53#define DRV_NAME "tegra-snd-wm8903" 53#define DRV_NAME "tegra-snd-wm8903"
54 54
55#define GPIO_SPKR_EN BIT(0) 55#define GPIO_SPKR_EN BIT(0)
56#define GPIO_INT_MIC_EN BIT(1) 56#define GPIO_HP_MUTE BIT(1)
57#define GPIO_EXT_MIC_EN BIT(2) 57#define GPIO_INT_MIC_EN BIT(2)
58#define GPIO_EXT_MIC_EN BIT(3)
58 59
59struct tegra_wm8903 { 60struct tegra_wm8903 {
60 struct tegra_asoc_utils_data util_data; 61 struct tegra_asoc_utils_data util_data;
@@ -163,15 +164,35 @@ static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w,
163 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 164 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
164 struct tegra_wm8903_platform_data *pdata = machine->pdata; 165 struct tegra_wm8903_platform_data *pdata = machine->pdata;
165 166
167 if (!(machine->gpio_requested & GPIO_SPKR_EN))
168 return 0;
169
166 gpio_set_value_cansleep(pdata->gpio_spkr_en, 170 gpio_set_value_cansleep(pdata->gpio_spkr_en,
167 SND_SOC_DAPM_EVENT_ON(event)); 171 SND_SOC_DAPM_EVENT_ON(event));
168 172
169 return 0; 173 return 0;
170} 174}
171 175
176static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w,
177 struct snd_kcontrol *k, int event)
178{
179 struct snd_soc_codec *codec = w->codec;
180 struct snd_soc_card *card = codec->card;
181 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
182 struct tegra_wm8903_platform_data *pdata = machine->pdata;
183
184 if (!(machine->gpio_requested & GPIO_HP_MUTE))
185 return 0;
186
187 gpio_set_value_cansleep(pdata->gpio_hp_mute,
188 !SND_SOC_DAPM_EVENT_ON(event));
189
190 return 0;
191}
192
172static const struct snd_soc_dapm_widget tegra_wm8903_dapm_widgets[] = { 193static const struct snd_soc_dapm_widget tegra_wm8903_dapm_widgets[] = {
173 SND_SOC_DAPM_SPK("Int Spk", tegra_wm8903_event_int_spk), 194 SND_SOC_DAPM_SPK("Int Spk", tegra_wm8903_event_int_spk),
174 SND_SOC_DAPM_HP("Headphone Jack", NULL), 195 SND_SOC_DAPM_HP("Headphone Jack", tegra_wm8903_event_hp),
175 SND_SOC_DAPM_MIC("Mic Jack", NULL), 196 SND_SOC_DAPM_MIC("Mic Jack", NULL),
176}; 197};
177 198
@@ -186,6 +207,37 @@ static const struct snd_soc_dapm_route harmony_audio_map[] = {
186 {"IN1L", NULL, "Mic Bias"}, 207 {"IN1L", NULL, "Mic Bias"},
187}; 208};
188 209
210static const struct snd_soc_dapm_route seaboard_audio_map[] = {
211 {"Headphone Jack", NULL, "HPOUTR"},
212 {"Headphone Jack", NULL, "HPOUTL"},
213 {"Int Spk", NULL, "ROP"},
214 {"Int Spk", NULL, "RON"},
215 {"Int Spk", NULL, "LOP"},
216 {"Int Spk", NULL, "LON"},
217 {"Mic Bias", NULL, "Mic Jack"},
218 {"IN1R", NULL, "Mic Bias"},
219};
220
221static const struct snd_soc_dapm_route kaen_audio_map[] = {
222 {"Headphone Jack", NULL, "HPOUTR"},
223 {"Headphone Jack", NULL, "HPOUTL"},
224 {"Int Spk", NULL, "ROP"},
225 {"Int Spk", NULL, "RON"},
226 {"Int Spk", NULL, "LOP"},
227 {"Int Spk", NULL, "LON"},
228 {"Mic Bias", NULL, "Mic Jack"},
229 {"IN2R", NULL, "Mic Bias"},
230};
231
232static const struct snd_soc_dapm_route aebl_audio_map[] = {
233 {"Headphone Jack", NULL, "HPOUTR"},
234 {"Headphone Jack", NULL, "HPOUTL"},
235 {"Int Spk", NULL, "LINEOUTR"},
236 {"Int Spk", NULL, "LINEOUTL"},
237 {"Mic Bias", NULL, "Mic Jack"},
238 {"IN1R", NULL, "Mic Bias"},
239};
240
189static const struct snd_kcontrol_new tegra_wm8903_controls[] = { 241static const struct snd_kcontrol_new tegra_wm8903_controls[] = {
190 SOC_DAPM_PIN_SWITCH("Int Spk"), 242 SOC_DAPM_PIN_SWITCH("Int Spk"),
191}; 243};
@@ -199,34 +251,51 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
199 struct tegra_wm8903_platform_data *pdata = machine->pdata; 251 struct tegra_wm8903_platform_data *pdata = machine->pdata;
200 int ret; 252 int ret;
201 253
202 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); 254 if (gpio_is_valid(pdata->gpio_spkr_en)) {
203 if (ret) { 255 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
204 dev_err(card->dev, "cannot get spkr_en gpio\n"); 256 if (ret) {
205 return ret; 257 dev_err(card->dev, "cannot get spkr_en gpio\n");
258 return ret;
259 }
260 machine->gpio_requested |= GPIO_SPKR_EN;
261
262 gpio_direction_output(pdata->gpio_spkr_en, 0);
206 } 263 }
207 machine->gpio_requested |= GPIO_SPKR_EN;
208 264
209 gpio_direction_output(pdata->gpio_spkr_en, 0); 265 if (gpio_is_valid(pdata->gpio_hp_mute)) {
266 ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
267 if (ret) {
268 dev_err(card->dev, "cannot get hp_mute gpio\n");
269 return ret;
270 }
271 machine->gpio_requested |= GPIO_HP_MUTE;
210 272
211 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en"); 273 gpio_direction_output(pdata->gpio_hp_mute, 0);
212 if (ret) {
213 dev_err(card->dev, "cannot get int_mic_en gpio\n");
214 return ret;
215 } 274 }
216 machine->gpio_requested |= GPIO_INT_MIC_EN;
217 275
218 /* Disable int mic; enable signal is active-high */ 276 if (gpio_is_valid(pdata->gpio_int_mic_en)) {
219 gpio_direction_output(pdata->gpio_int_mic_en, 0); 277 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
278 if (ret) {
279 dev_err(card->dev, "cannot get int_mic_en gpio\n");
280 return ret;
281 }
282 machine->gpio_requested |= GPIO_INT_MIC_EN;
220 283
221 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en"); 284 /* Disable int mic; enable signal is active-high */
222 if (ret) { 285 gpio_direction_output(pdata->gpio_int_mic_en, 0);
223 dev_err(card->dev, "cannot get ext_mic_en gpio\n");
224 return ret;
225 } 286 }
226 machine->gpio_requested |= GPIO_EXT_MIC_EN;
227 287
228 /* Enable ext mic; enable signal is active-low */ 288 if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
229 gpio_direction_output(pdata->gpio_ext_mic_en, 0); 289 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
290 if (ret) {
291 dev_err(card->dev, "cannot get ext_mic_en gpio\n");
292 return ret;
293 }
294 machine->gpio_requested |= GPIO_EXT_MIC_EN;
295
296 /* Enable ext mic; enable signal is active-low */
297 gpio_direction_output(pdata->gpio_ext_mic_en, 0);
298 }
230 299
231 ret = snd_soc_add_controls(codec, tegra_wm8903_controls, 300 ret = snd_soc_add_controls(codec, tegra_wm8903_controls,
232 ARRAY_SIZE(tegra_wm8903_controls)); 301 ARRAY_SIZE(tegra_wm8903_controls));
@@ -236,18 +305,31 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
236 snd_soc_dapm_new_controls(dapm, tegra_wm8903_dapm_widgets, 305 snd_soc_dapm_new_controls(dapm, tegra_wm8903_dapm_widgets,
237 ARRAY_SIZE(tegra_wm8903_dapm_widgets)); 306 ARRAY_SIZE(tegra_wm8903_dapm_widgets));
238 307
239 snd_soc_dapm_add_routes(dapm, harmony_audio_map, 308 if (machine_is_harmony() || machine_is_ventana()) {
240 ARRAY_SIZE(harmony_audio_map)); 309 snd_soc_dapm_add_routes(dapm, harmony_audio_map,
310 ARRAY_SIZE(harmony_audio_map));
311 } else if (machine_is_seaboard()) {
312 snd_soc_dapm_add_routes(dapm, seaboard_audio_map,
313 ARRAY_SIZE(seaboard_audio_map));
314 } else if (machine_is_kaen()) {
315 snd_soc_dapm_add_routes(dapm, kaen_audio_map,
316 ARRAY_SIZE(kaen_audio_map));
317 } else {
318 snd_soc_dapm_add_routes(dapm, aebl_audio_map,
319 ARRAY_SIZE(aebl_audio_map));
320 }
241 321
242 tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det; 322 if (gpio_is_valid(pdata->gpio_hp_det)) {
243 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, 323 tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det;
244 &tegra_wm8903_hp_jack); 324 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
245 snd_soc_jack_add_pins(&tegra_wm8903_hp_jack, 325 &tegra_wm8903_hp_jack);
246 ARRAY_SIZE(tegra_wm8903_hp_jack_pins), 326 snd_soc_jack_add_pins(&tegra_wm8903_hp_jack,
247 tegra_wm8903_hp_jack_pins); 327 ARRAY_SIZE(tegra_wm8903_hp_jack_pins),
248 snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack, 328 tegra_wm8903_hp_jack_pins);
249 1, 329 snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack,
250 &tegra_wm8903_hp_jack_gpio); 330 1,
331 &tegra_wm8903_hp_jack_gpio);
332 }
251 333
252 snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, 334 snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE,
253 &tegra_wm8903_mic_jack); 335 &tegra_wm8903_mic_jack);
@@ -259,10 +341,26 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
259 341
260 snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); 342 snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
261 343
344 /* FIXME: Calculate automatically based on DAPM routes? */
345 if (!machine_is_harmony() && !machine_is_ventana())
346 snd_soc_dapm_nc_pin(dapm, "IN1L");
347 if (!machine_is_seaboard() && !machine_is_aebl())
348 snd_soc_dapm_nc_pin(dapm, "IN1R");
349 snd_soc_dapm_nc_pin(dapm, "IN2L");
350 if (!machine_is_kaen())
351 snd_soc_dapm_nc_pin(dapm, "IN2R");
262 snd_soc_dapm_nc_pin(dapm, "IN3L"); 352 snd_soc_dapm_nc_pin(dapm, "IN3L");
263 snd_soc_dapm_nc_pin(dapm, "IN3R"); 353 snd_soc_dapm_nc_pin(dapm, "IN3R");
264 snd_soc_dapm_nc_pin(dapm, "LINEOUTL"); 354
265 snd_soc_dapm_nc_pin(dapm, "LINEOUTR"); 355 if (machine_is_aebl()) {
356 snd_soc_dapm_nc_pin(dapm, "LON");
357 snd_soc_dapm_nc_pin(dapm, "RON");
358 snd_soc_dapm_nc_pin(dapm, "ROP");
359 snd_soc_dapm_nc_pin(dapm, "LOP");
360 } else {
361 snd_soc_dapm_nc_pin(dapm, "LINEOUTR");
362 snd_soc_dapm_nc_pin(dapm, "LINEOUTL");
363 }
266 364
267 snd_soc_dapm_sync(dapm); 365 snd_soc_dapm_sync(dapm);
268 366
@@ -293,14 +391,16 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
293 struct tegra_wm8903_platform_data *pdata; 391 struct tegra_wm8903_platform_data *pdata;
294 int ret; 392 int ret;
295 393
296 if (!machine_is_harmony()) { 394 if (!machine_is_harmony() && !machine_is_ventana() &&
297 dev_err(&pdev->dev, "Not running on Tegra Harmony!\n"); 395 !machine_is_seaboard() && !machine_is_kaen() &&
396 !machine_is_aebl()) {
397 dev_err(&pdev->dev, "Not running on a supported board!\n");
298 return -ENODEV; 398 return -ENODEV;
299 } 399 }
300 400
301 pdata = pdev->dev.platform_data; 401 pdata = pdev->dev.platform_data;
302 if (!pdata) { 402 if (!pdata) {
303 dev_err(&pdev->dev, "no platform data supplied\n"); 403 dev_err(&pdev->dev, "No platform data supplied\n");
304 return -EINVAL; 404 return -EINVAL;
305 } 405 }
306 406
@@ -357,6 +457,8 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
357 gpio_free(pdata->gpio_ext_mic_en); 457 gpio_free(pdata->gpio_ext_mic_en);
358 if (machine->gpio_requested & GPIO_INT_MIC_EN) 458 if (machine->gpio_requested & GPIO_INT_MIC_EN)
359 gpio_free(pdata->gpio_int_mic_en); 459 gpio_free(pdata->gpio_int_mic_en);
460 if (machine->gpio_requested & GPIO_HP_MUTE)
461 gpio_free(pdata->gpio_hp_mute);
360 if (machine->gpio_requested & GPIO_SPKR_EN) 462 if (machine->gpio_requested & GPIO_SPKR_EN)
361 gpio_free(pdata->gpio_spkr_en); 463 gpio_free(pdata->gpio_spkr_en);
362 464