aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/tegra/tegra_wm8903.c
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 /sound/soc/tegra/tegra_wm8903.c
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>
Diffstat (limited to 'sound/soc/tegra/tegra_wm8903.c')
-rw-r--r--sound/soc/tegra/tegra_wm8903.c180
1 files changed, 141 insertions, 39 deletions
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