e740_wm9705.c (4310B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * e740-wm9705.c -- SoC audio for e740 4 * 5 * Copyright 2007 (c) Ian Molton <spyro@f2s.com> 6 */ 7 8#include <linux/module.h> 9#include <linux/moduleparam.h> 10#include <linux/gpio/consumer.h> 11 12#include <sound/core.h> 13#include <sound/pcm.h> 14#include <sound/soc.h> 15 16#include <linux/platform_data/asoc-pxa.h> 17 18#include <asm/mach-types.h> 19 20static struct gpio_desc *gpiod_output_amp, *gpiod_input_amp; 21static struct gpio_desc *gpiod_audio_power; 22 23#define E740_AUDIO_OUT 1 24#define E740_AUDIO_IN 2 25 26static int e740_audio_power; 27 28static void e740_sync_audio_power(int status) 29{ 30 gpiod_set_value(gpiod_audio_power, !status); 31 gpiod_set_value(gpiod_output_amp, (status & E740_AUDIO_OUT) ? 1 : 0); 32 gpiod_set_value(gpiod_input_amp, (status & E740_AUDIO_IN) ? 1 : 0); 33} 34 35static int e740_mic_amp_event(struct snd_soc_dapm_widget *w, 36 struct snd_kcontrol *kcontrol, int event) 37{ 38 if (event & SND_SOC_DAPM_PRE_PMU) 39 e740_audio_power |= E740_AUDIO_IN; 40 else if (event & SND_SOC_DAPM_POST_PMD) 41 e740_audio_power &= ~E740_AUDIO_IN; 42 43 e740_sync_audio_power(e740_audio_power); 44 45 return 0; 46} 47 48static int e740_output_amp_event(struct snd_soc_dapm_widget *w, 49 struct snd_kcontrol *kcontrol, int event) 50{ 51 if (event & SND_SOC_DAPM_PRE_PMU) 52 e740_audio_power |= E740_AUDIO_OUT; 53 else if (event & SND_SOC_DAPM_POST_PMD) 54 e740_audio_power &= ~E740_AUDIO_OUT; 55 56 e740_sync_audio_power(e740_audio_power); 57 58 return 0; 59} 60 61static const struct snd_soc_dapm_widget e740_dapm_widgets[] = { 62 SND_SOC_DAPM_HP("Headphone Jack", NULL), 63 SND_SOC_DAPM_SPK("Speaker", NULL), 64 SND_SOC_DAPM_MIC("Mic (Internal)", NULL), 65 SND_SOC_DAPM_PGA_E("Output Amp", SND_SOC_NOPM, 0, 0, NULL, 0, 66 e740_output_amp_event, SND_SOC_DAPM_PRE_PMU | 67 SND_SOC_DAPM_POST_PMD), 68 SND_SOC_DAPM_PGA_E("Mic Amp", SND_SOC_NOPM, 0, 0, NULL, 0, 69 e740_mic_amp_event, SND_SOC_DAPM_PRE_PMU | 70 SND_SOC_DAPM_POST_PMD), 71}; 72 73static const struct snd_soc_dapm_route audio_map[] = { 74 {"Output Amp", NULL, "LOUT"}, 75 {"Output Amp", NULL, "ROUT"}, 76 {"Output Amp", NULL, "MONOOUT"}, 77 78 {"Speaker", NULL, "Output Amp"}, 79 {"Headphone Jack", NULL, "Output Amp"}, 80 81 {"MIC1", NULL, "Mic Amp"}, 82 {"Mic Amp", NULL, "Mic (Internal)"}, 83}; 84 85SND_SOC_DAILINK_DEFS(ac97, 86 DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97")), 87 DAILINK_COMP_ARRAY(COMP_CODEC("wm9705-codec", "wm9705-hifi")), 88 DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); 89 90SND_SOC_DAILINK_DEFS(ac97_aux, 91 DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97-aux")), 92 DAILINK_COMP_ARRAY(COMP_CODEC("wm9705-codec", "wm9705-aux")), 93 DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio"))); 94 95static struct snd_soc_dai_link e740_dai[] = { 96 { 97 .name = "AC97", 98 .stream_name = "AC97 HiFi", 99 SND_SOC_DAILINK_REG(ac97), 100 }, 101 { 102 .name = "AC97 Aux", 103 .stream_name = "AC97 Aux", 104 SND_SOC_DAILINK_REG(ac97_aux), 105 }, 106}; 107 108static struct snd_soc_card e740 = { 109 .name = "Toshiba e740", 110 .owner = THIS_MODULE, 111 .dai_link = e740_dai, 112 .num_links = ARRAY_SIZE(e740_dai), 113 114 .dapm_widgets = e740_dapm_widgets, 115 .num_dapm_widgets = ARRAY_SIZE(e740_dapm_widgets), 116 .dapm_routes = audio_map, 117 .num_dapm_routes = ARRAY_SIZE(audio_map), 118 .fully_routed = true, 119}; 120 121static int e740_probe(struct platform_device *pdev) 122{ 123 struct snd_soc_card *card = &e740; 124 int ret; 125 126 gpiod_input_amp = devm_gpiod_get(&pdev->dev, "Mic amp", GPIOD_OUT_LOW); 127 ret = PTR_ERR_OR_ZERO(gpiod_input_amp); 128 if (ret) 129 return ret; 130 gpiod_output_amp = devm_gpiod_get(&pdev->dev, "Output amp", GPIOD_OUT_LOW); 131 ret = PTR_ERR_OR_ZERO(gpiod_output_amp); 132 if (ret) 133 return ret; 134 gpiod_audio_power = devm_gpiod_get(&pdev->dev, "Audio power", GPIOD_OUT_HIGH); 135 ret = PTR_ERR_OR_ZERO(gpiod_audio_power); 136 if (ret) 137 return ret; 138 139 card->dev = &pdev->dev; 140 141 ret = devm_snd_soc_register_card(&pdev->dev, card); 142 if (ret) 143 dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", 144 ret); 145 return ret; 146} 147 148static int e740_remove(struct platform_device *pdev) 149{ 150 return 0; 151} 152 153static struct platform_driver e740_driver = { 154 .driver = { 155 .name = "e740-audio", 156 .pm = &snd_soc_pm_ops, 157 }, 158 .probe = e740_probe, 159 .remove = e740_remove, 160}; 161 162module_platform_driver(e740_driver); 163 164/* Module information */ 165MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); 166MODULE_DESCRIPTION("ALSA SoC driver for e740"); 167MODULE_LICENSE("GPL v2"); 168MODULE_ALIAS("platform:e740-audio");