Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * seaboard.c - Seaboard machine ASoC driver | 2 * seaboard.c - Seaboard machine ASoC driver |
| 3 * | 3 * |
| 4 * Author: Stephen Warren <swarren@nvidia.com> | 4 * Author: Stephen Warren <swarren@nvidia.com> |
| 5 * Copyright (C) 2010-2011 - NVIDIA, Inc. | 5 * Copyright (C) 2010-2011 - NVIDIA, Inc. |
| 6 * | 6 * |
| 7 * Based on code copyright/by: | 7 * Based on code copyright/by: |
| 8 * | 8 * |
| 9 * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd. | 9 * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd. |
| 10 * | 10 * |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 * along with this program; if not, write to the Free Software | 25 * along with this program; if not, write to the Free Software |
| 26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | 26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA |
| 27 * 02110-1301 USA | 27 * 02110-1301 USA |
| 28 * | 28 * |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include <asm/mach-types.h> | 31 #include <asm/mach-types.h> |
| 32 | 32 |
| 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/regulator/consumer.h> | |
| 35 #include <linux/slab.h> | 36 #include <linux/slab.h> |
| 36 #include <linux/gpio.h> | 37 #include <linux/gpio.h> |
| 37 | 38 |
| 38 #include <mach/seaboard_audio.h> | 39 #include <mach/seaboard_audio.h> |
| 39 | 40 |
| 40 #include <sound/core.h> | 41 #include <sound/core.h> |
| 41 #include <sound/jack.h> | 42 #include <sound/jack.h> |
| 42 #include <sound/pcm.h> | 43 #include <sound/pcm.h> |
| 43 #include <sound/pcm_params.h> | 44 #include <sound/pcm_params.h> |
| 44 #include <sound/soc.h> | 45 #include <sound/soc.h> |
| 45 | 46 |
| 46 #include "../codecs/wm8903.h" | 47 #include "../codecs/wm8903.h" |
| 47 | 48 |
| 48 #include "tegra_das.h" | 49 #include "tegra_das.h" |
| 49 #include "tegra_i2s.h" | 50 #include "tegra_i2s.h" |
| 50 #include "tegra_pcm.h" | 51 #include "tegra_pcm.h" |
| 51 #include "tegra_asoc_utils.h" | 52 #include "tegra_asoc_utils.h" |
| 52 | 53 |
| 53 #define DRV_NAME "tegra-snd-seaboard" | 54 #define DRV_NAME "tegra-snd-seaboard" |
| 54 | 55 |
| 55 #define GPIO_SPKR_EN BIT(0) | 56 #define GPIO_SPKR_EN BIT(0) |
| 56 #define GPIO_HP_MUTE BIT(1) | 57 #define GPIO_HP_MUTE BIT(1) |
| 57 | 58 |
| 58 struct tegra_seaboard { | 59 struct tegra_seaboard { |
| 59 struct tegra_asoc_utils_data util_data; | 60 struct tegra_asoc_utils_data util_data; |
| 60 struct seaboard_audio_platform_data *pdata; | 61 struct seaboard_audio_platform_data *pdata; |
| 61 int gpio_requested; | 62 int gpio_requested; |
| 63 struct regulator *vdd_dmic; | |
| 64 bool first_dmic_event; | |
|
jiesun
2011/04/25 18:21:04
I understand this is for preventing regulator_disa
Stephen Warren
2011/04/25 22:27:41
The issue isn't continual interleaving; it's a sta
| |
| 62 }; | 65 }; |
| 63 | 66 |
| 64 static int seaboard_asoc_hw_params(struct snd_pcm_substream *substream, | 67 static int seaboard_asoc_hw_params(struct snd_pcm_substream *substream, |
| 65 struct snd_pcm_hw_params *params) | 68 struct snd_pcm_hw_params *params) |
| 66 { | 69 { |
| 67 struct snd_soc_pcm_runtime *rtd = substream->private_data; | 70 struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 68 struct snd_soc_dai *codec_dai = rtd->codec_dai; | 71 struct snd_soc_dai *codec_dai = rtd->codec_dai; |
| 69 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 72 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
| 70 struct snd_soc_codec *codec = rtd->codec; | 73 struct snd_soc_codec *codec = rtd->codec; |
| 71 struct snd_soc_card *card = codec->card; | 74 struct snd_soc_card *card = codec->card; |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 222 struct seaboard_audio_platform_data *pdata = seaboard->pdata; | 225 struct seaboard_audio_platform_data *pdata = seaboard->pdata; |
| 223 | 226 |
| 224 if (!(seaboard->gpio_requested & GPIO_HP_MUTE)) | 227 if (!(seaboard->gpio_requested & GPIO_HP_MUTE)) |
| 225 return 0; | 228 return 0; |
| 226 | 229 |
| 227 gpio_set_value_cansleep(pdata->gpio_hp_mute, | 230 gpio_set_value_cansleep(pdata->gpio_hp_mute, |
| 228 !SND_SOC_DAPM_EVENT_ON(event)); | 231 !SND_SOC_DAPM_EVENT_ON(event)); |
| 229 | 232 |
| 230 return 0; | 233 return 0; |
| 231 } | 234 } |
| 235 | |
| 236 static int seaboard_event_dmic(struct snd_soc_dapm_widget *w, | |
| 237 struct snd_kcontrol *k, int event) | |
| 238 { | |
| 239 struct snd_soc_codec *codec = w->codec; | |
| 240 struct snd_soc_card *card = codec->card; | |
| 241 struct tegra_seaboard *seaboard = snd_soc_card_get_drvdata(card); | |
| 242 | |
| 243 if (IS_ERR(seaboard->vdd_dmic)) | |
| 244 return 0; | |
| 245 | |
| 246 if (SND_SOC_DAPM_EVENT_ON(event)) { | |
| 247 return regulator_enable(seaboard->vdd_dmic); | |
| 248 } else { | |
| 249 if (!seaboard->first_dmic_event) | |
| 250 return regulator_disable(seaboard->vdd_dmic); | |
| 251 } | |
| 252 | |
| 253 seaboard->first_dmic_event = false; | |
| 254 } | |
| 255 | |
| 232 static const struct snd_soc_dapm_widget seaboard_dapm_widgets[] = { | 256 static const struct snd_soc_dapm_widget seaboard_dapm_widgets[] = { |
| 233 SND_SOC_DAPM_SPK("Int Spk", seaboard_event_int_spk), | 257 SND_SOC_DAPM_SPK("Int Spk", seaboard_event_int_spk), |
| 234 SND_SOC_DAPM_HP("Headphone Jack", seaboard_event_hp), | 258 SND_SOC_DAPM_HP("Headphone Jack", seaboard_event_hp), |
| 235 SND_SOC_DAPM_MIC("Mic Jack", NULL), | 259 SND_SOC_DAPM_MIC("Mic Jack", NULL), |
| 236 » SND_SOC_DAPM_MIC("Digital Mic", NULL), | 260 » SND_SOC_DAPM_MIC("Digital Mic", seaboard_event_dmic), |
| 237 }; | 261 }; |
| 238 | 262 |
| 239 static const struct snd_soc_dapm_route seaboard_audio_map[] = { | 263 static const struct snd_soc_dapm_route seaboard_audio_map[] = { |
| 240 {"Headphone Jack", NULL, "HPOUTR"}, | 264 {"Headphone Jack", NULL, "HPOUTR"}, |
| 241 {"Headphone Jack", NULL, "HPOUTL"}, | 265 {"Headphone Jack", NULL, "HPOUTL"}, |
| 242 {"Int Spk", NULL, "ROP"}, | 266 {"Int Spk", NULL, "ROP"}, |
| 243 {"Int Spk", NULL, "RON"}, | 267 {"Int Spk", NULL, "RON"}, |
| 244 {"Int Spk", NULL, "LOP"}, | 268 {"Int Spk", NULL, "LOP"}, |
| 245 {"Int Spk", NULL, "LON"}, | 269 {"Int Spk", NULL, "LON"}, |
| 246 {"Mic Bias", NULL, "Mic Jack"}, | 270 {"Mic Bias", NULL, "Mic Jack"}, |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 418 dev_err(&pdev->dev, "Can't allocate tegra_seaboard\n"); | 442 dev_err(&pdev->dev, "Can't allocate tegra_seaboard\n"); |
| 419 return -ENOMEM; | 443 return -ENOMEM; |
| 420 } | 444 } |
| 421 | 445 |
| 422 seaboard->pdata = pdata; | 446 seaboard->pdata = pdata; |
| 423 | 447 |
| 424 ret = tegra_asoc_utils_init(&seaboard->util_data, &pdev->dev); | 448 ret = tegra_asoc_utils_init(&seaboard->util_data, &pdev->dev); |
| 425 if (ret) | 449 if (ret) |
| 426 goto err_free_seaboard; | 450 goto err_free_seaboard; |
| 427 | 451 |
| 452 seaboard->vdd_dmic = regulator_get(&pdev->dev, "vdd_dmic"); | |
| 453 if (IS_ERR(seaboard->vdd_dmic)) { | |
| 454 dev_info(&pdev->dev, "regulator_get() returned error %ld\n", | |
| 455 PTR_ERR(seaboard->vdd_dmic)); | |
| 456 ret = PTR_ERR(seaboard->vdd_dmic); | |
| 457 goto err_fini_utils; | |
| 458 } | |
| 459 seaboard->first_dmic_event = true; | |
| 460 | |
| 428 card->dev = &pdev->dev; | 461 card->dev = &pdev->dev; |
| 429 platform_set_drvdata(pdev, card); | 462 platform_set_drvdata(pdev, card); |
| 430 snd_soc_card_set_drvdata(card, seaboard); | 463 snd_soc_card_set_drvdata(card, seaboard); |
| 431 | 464 |
| 432 ret = snd_soc_register_card(card); | 465 ret = snd_soc_register_card(card); |
| 433 if (ret) { | 466 if (ret) { |
| 434 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", | 467 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", |
| 435 ret); | 468 ret); |
| 436 goto err_clear_drvdata; | 469 goto err_clear_drvdata; |
| 437 } | 470 } |
| 438 | 471 |
| 439 return 0; | 472 return 0; |
| 440 | 473 |
| 441 err_clear_drvdata: | 474 err_clear_drvdata: |
| 442 snd_soc_card_set_drvdata(card, NULL); | 475 snd_soc_card_set_drvdata(card, NULL); |
| 443 platform_set_drvdata(pdev, NULL); | 476 platform_set_drvdata(pdev, NULL); |
| 444 card->dev = NULL; | 477 card->dev = NULL; |
|
jiesun
2011/04/25 18:21:04
missing a regulator_put here.
| |
| 478 err_fini_utils: | |
| 445 tegra_asoc_utils_fini(&seaboard->util_data); | 479 tegra_asoc_utils_fini(&seaboard->util_data); |
| 446 err_free_seaboard: | 480 err_free_seaboard: |
| 447 kfree(seaboard); | 481 kfree(seaboard); |
| 448 return ret; | 482 return ret; |
| 449 } | 483 } |
| 450 | 484 |
| 451 static int __devexit tegra_snd_seaboard_remove(struct platform_device *pdev) | 485 static int __devexit tegra_snd_seaboard_remove(struct platform_device *pdev) |
| 452 { | 486 { |
| 453 struct snd_soc_card *card = platform_get_drvdata(pdev); | 487 struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 454 struct tegra_seaboard *seaboard = snd_soc_card_get_drvdata(card); | 488 struct tegra_seaboard *seaboard = snd_soc_card_get_drvdata(card); |
| 455 struct seaboard_audio_platform_data *pdata = seaboard->pdata; | 489 struct seaboard_audio_platform_data *pdata = seaboard->pdata; |
| 456 | 490 |
| 457 snd_soc_unregister_card(card); | 491 snd_soc_unregister_card(card); |
| 458 | 492 |
| 459 snd_soc_card_set_drvdata(card, NULL); | 493 snd_soc_card_set_drvdata(card, NULL); |
| 460 platform_set_drvdata(pdev, NULL); | 494 platform_set_drvdata(pdev, NULL); |
| 461 card->dev = NULL; | 495 card->dev = NULL; |
| 462 | 496 |
| 497 regulator_put(seaboard->vdd_dmic); | |
| 498 | |
| 463 tegra_asoc_utils_fini(&seaboard->util_data); | 499 tegra_asoc_utils_fini(&seaboard->util_data); |
| 464 | 500 |
| 465 if (seaboard->gpio_requested & GPIO_HP_MUTE) | 501 if (seaboard->gpio_requested & GPIO_HP_MUTE) |
| 466 gpio_free(pdata->gpio_hp_mute); | 502 gpio_free(pdata->gpio_hp_mute); |
| 467 if (seaboard->gpio_requested & GPIO_SPKR_EN) | 503 if (seaboard->gpio_requested & GPIO_SPKR_EN) |
| 468 gpio_free(pdata->gpio_spkr_en); | 504 gpio_free(pdata->gpio_spkr_en); |
| 469 | 505 |
| 470 kfree(seaboard); | 506 kfree(seaboard); |
| 471 | 507 |
| 472 return 0; | 508 return 0; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 491 static void __exit snd_tegra_seaboard_exit(void) | 527 static void __exit snd_tegra_seaboard_exit(void) |
| 492 { | 528 { |
| 493 platform_driver_unregister(&tegra_snd_seaboard_driver); | 529 platform_driver_unregister(&tegra_snd_seaboard_driver); |
| 494 } | 530 } |
| 495 module_exit(snd_tegra_seaboard_exit); | 531 module_exit(snd_tegra_seaboard_exit); |
| 496 | 532 |
| 497 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | 533 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); |
| 498 MODULE_DESCRIPTION("Seaboard machine ASoC driver"); | 534 MODULE_DESCRIPTION("Seaboard machine ASoC driver"); |
| 499 MODULE_LICENSE("GPL"); | 535 MODULE_LICENSE("GPL"); |
| 500 MODULE_ALIAS("platform:" DRV_NAME); | 536 MODULE_ALIAS("platform:" DRV_NAME); |
| OLD | NEW |