1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // neo1973_wm8753.c - SoC audio for Openmoko Neo1973 and Freerunner devices
4*4882a593Smuzhiyun //
5*4882a593Smuzhiyun // Copyright 2007 Openmoko Inc
6*4882a593Smuzhiyun // Author: Graeme Gregory <graeme@openmoko.org>
7*4882a593Smuzhiyun // Copyright 2007 Wolfson Microelectronics PLC.
8*4882a593Smuzhiyun // Author: Graeme Gregory
9*4882a593Smuzhiyun // graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
10*4882a593Smuzhiyun // Copyright 2009 Wolfson Microelectronics
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/platform_device.h>
14*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include <sound/soc.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include "regs-iis.h"
19*4882a593Smuzhiyun #include "../codecs/wm8753.h"
20*4882a593Smuzhiyun #include "s3c24xx-i2s.h"
21*4882a593Smuzhiyun
neo1973_hifi_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)22*4882a593Smuzhiyun static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
23*4882a593Smuzhiyun struct snd_pcm_hw_params *params)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
26*4882a593Smuzhiyun struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
27*4882a593Smuzhiyun struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
28*4882a593Smuzhiyun unsigned int pll_out = 0, bclk = 0;
29*4882a593Smuzhiyun int ret = 0;
30*4882a593Smuzhiyun unsigned long iis_clkrate;
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun iis_clkrate = s3c24xx_i2s_get_clockrate();
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun switch (params_rate(params)) {
35*4882a593Smuzhiyun case 8000:
36*4882a593Smuzhiyun case 16000:
37*4882a593Smuzhiyun pll_out = 12288000;
38*4882a593Smuzhiyun break;
39*4882a593Smuzhiyun case 48000:
40*4882a593Smuzhiyun bclk = WM8753_BCLK_DIV_4;
41*4882a593Smuzhiyun pll_out = 12288000;
42*4882a593Smuzhiyun break;
43*4882a593Smuzhiyun case 96000:
44*4882a593Smuzhiyun bclk = WM8753_BCLK_DIV_2;
45*4882a593Smuzhiyun pll_out = 12288000;
46*4882a593Smuzhiyun break;
47*4882a593Smuzhiyun case 11025:
48*4882a593Smuzhiyun bclk = WM8753_BCLK_DIV_16;
49*4882a593Smuzhiyun pll_out = 11289600;
50*4882a593Smuzhiyun break;
51*4882a593Smuzhiyun case 22050:
52*4882a593Smuzhiyun bclk = WM8753_BCLK_DIV_8;
53*4882a593Smuzhiyun pll_out = 11289600;
54*4882a593Smuzhiyun break;
55*4882a593Smuzhiyun case 44100:
56*4882a593Smuzhiyun bclk = WM8753_BCLK_DIV_4;
57*4882a593Smuzhiyun pll_out = 11289600;
58*4882a593Smuzhiyun break;
59*4882a593Smuzhiyun case 88200:
60*4882a593Smuzhiyun bclk = WM8753_BCLK_DIV_2;
61*4882a593Smuzhiyun pll_out = 11289600;
62*4882a593Smuzhiyun break;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun /* set the codec system clock for DAC and ADC */
66*4882a593Smuzhiyun ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
67*4882a593Smuzhiyun SND_SOC_CLOCK_IN);
68*4882a593Smuzhiyun if (ret < 0)
69*4882a593Smuzhiyun return ret;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun /* set MCLK division for sample rate */
72*4882a593Smuzhiyun ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
73*4882a593Smuzhiyun S3C2410_IISMOD_32FS);
74*4882a593Smuzhiyun if (ret < 0)
75*4882a593Smuzhiyun return ret;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun /* set codec BCLK division for sample rate */
78*4882a593Smuzhiyun ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk);
79*4882a593Smuzhiyun if (ret < 0)
80*4882a593Smuzhiyun return ret;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /* set prescaler division for sample rate */
83*4882a593Smuzhiyun ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
84*4882a593Smuzhiyun S3C24XX_PRESCALE(4, 4));
85*4882a593Smuzhiyun if (ret < 0)
86*4882a593Smuzhiyun return ret;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun /* codec PLL input is PCLK/4 */
89*4882a593Smuzhiyun ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0,
90*4882a593Smuzhiyun iis_clkrate / 4, pll_out);
91*4882a593Smuzhiyun if (ret < 0)
92*4882a593Smuzhiyun return ret;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun return 0;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
neo1973_hifi_hw_free(struct snd_pcm_substream * substream)97*4882a593Smuzhiyun static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
100*4882a593Smuzhiyun struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun /* disable the PLL */
103*4882a593Smuzhiyun return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun /*
107*4882a593Smuzhiyun * Neo1973 WM8753 HiFi DAI opserations.
108*4882a593Smuzhiyun */
109*4882a593Smuzhiyun static struct snd_soc_ops neo1973_hifi_ops = {
110*4882a593Smuzhiyun .hw_params = neo1973_hifi_hw_params,
111*4882a593Smuzhiyun .hw_free = neo1973_hifi_hw_free,
112*4882a593Smuzhiyun };
113*4882a593Smuzhiyun
neo1973_voice_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)114*4882a593Smuzhiyun static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
115*4882a593Smuzhiyun struct snd_pcm_hw_params *params)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
118*4882a593Smuzhiyun struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
119*4882a593Smuzhiyun unsigned int pcmdiv = 0;
120*4882a593Smuzhiyun int ret = 0;
121*4882a593Smuzhiyun unsigned long iis_clkrate;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun iis_clkrate = s3c24xx_i2s_get_clockrate();
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun if (params_rate(params) != 8000)
126*4882a593Smuzhiyun return -EINVAL;
127*4882a593Smuzhiyun if (params_channels(params) != 1)
128*4882a593Smuzhiyun return -EINVAL;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun /* set the codec system clock for DAC and ADC */
133*4882a593Smuzhiyun ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, 12288000,
134*4882a593Smuzhiyun SND_SOC_CLOCK_IN);
135*4882a593Smuzhiyun if (ret < 0)
136*4882a593Smuzhiyun return ret;
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun /* set codec PCM division for sample rate */
139*4882a593Smuzhiyun ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
140*4882a593Smuzhiyun if (ret < 0)
141*4882a593Smuzhiyun return ret;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun /* configure and enable PLL for 12.288MHz output */
144*4882a593Smuzhiyun ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
145*4882a593Smuzhiyun iis_clkrate / 4, 12288000);
146*4882a593Smuzhiyun if (ret < 0)
147*4882a593Smuzhiyun return ret;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun return 0;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
neo1973_voice_hw_free(struct snd_pcm_substream * substream)152*4882a593Smuzhiyun static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
155*4882a593Smuzhiyun struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun /* disable the PLL */
158*4882a593Smuzhiyun return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun static struct snd_soc_ops neo1973_voice_ops = {
162*4882a593Smuzhiyun .hw_params = neo1973_voice_hw_params,
163*4882a593Smuzhiyun .hw_free = neo1973_voice_hw_free,
164*4882a593Smuzhiyun };
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun static struct gpio_desc *gpiod_hp_in, *gpiod_amp_shut;
167*4882a593Smuzhiyun static int gta02_speaker_enabled;
168*4882a593Smuzhiyun
lm4853_set_spk(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)169*4882a593Smuzhiyun static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
170*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun gta02_speaker_enabled = ucontrol->value.integer.value[0];
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun gpiod_set_value(gpiod_hp_in, !gta02_speaker_enabled);
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun return 0;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
lm4853_get_spk(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)179*4882a593Smuzhiyun static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
180*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun ucontrol->value.integer.value[0] = gta02_speaker_enabled;
183*4882a593Smuzhiyun return 0;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
lm4853_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * k,int event)186*4882a593Smuzhiyun static int lm4853_event(struct snd_soc_dapm_widget *w,
187*4882a593Smuzhiyun struct snd_kcontrol *k, int event)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun gpiod_set_value(gpiod_amp_shut, SND_SOC_DAPM_EVENT_OFF(event));
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun return 0;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = {
195*4882a593Smuzhiyun SND_SOC_DAPM_LINE("GSM Line Out", NULL),
196*4882a593Smuzhiyun SND_SOC_DAPM_LINE("GSM Line In", NULL),
197*4882a593Smuzhiyun SND_SOC_DAPM_MIC("Headset Mic", NULL),
198*4882a593Smuzhiyun SND_SOC_DAPM_MIC("Handset Mic", NULL),
199*4882a593Smuzhiyun SND_SOC_DAPM_SPK("Handset Spk", NULL),
200*4882a593Smuzhiyun SND_SOC_DAPM_SPK("Stereo Out", lm4853_event),
201*4882a593Smuzhiyun };
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = {
204*4882a593Smuzhiyun /* Connections to the GSM Module */
205*4882a593Smuzhiyun {"GSM Line Out", NULL, "MONO1"},
206*4882a593Smuzhiyun {"GSM Line Out", NULL, "MONO2"},
207*4882a593Smuzhiyun {"RXP", NULL, "GSM Line In"},
208*4882a593Smuzhiyun {"RXN", NULL, "GSM Line In"},
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /* Connections to Headset */
211*4882a593Smuzhiyun {"MIC1", NULL, "Mic Bias"},
212*4882a593Smuzhiyun {"Mic Bias", NULL, "Headset Mic"},
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun /* Call Mic */
215*4882a593Smuzhiyun {"MIC2", NULL, "Mic Bias"},
216*4882a593Smuzhiyun {"MIC2N", NULL, "Mic Bias"},
217*4882a593Smuzhiyun {"Mic Bias", NULL, "Handset Mic"},
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun /* Connect the ALC pins */
220*4882a593Smuzhiyun {"ACIN", NULL, "ACOP"},
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun /* Connections to the amp */
223*4882a593Smuzhiyun {"Stereo Out", NULL, "LOUT1"},
224*4882a593Smuzhiyun {"Stereo Out", NULL, "ROUT1"},
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun /* Call Speaker */
227*4882a593Smuzhiyun {"Handset Spk", NULL, "LOUT2"},
228*4882a593Smuzhiyun {"Handset Spk", NULL, "ROUT2"},
229*4882a593Smuzhiyun };
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun static const struct snd_kcontrol_new neo1973_wm8753_controls[] = {
232*4882a593Smuzhiyun SOC_DAPM_PIN_SWITCH("GSM Line Out"),
233*4882a593Smuzhiyun SOC_DAPM_PIN_SWITCH("GSM Line In"),
234*4882a593Smuzhiyun SOC_DAPM_PIN_SWITCH("Headset Mic"),
235*4882a593Smuzhiyun SOC_DAPM_PIN_SWITCH("Handset Mic"),
236*4882a593Smuzhiyun SOC_DAPM_PIN_SWITCH("Handset Spk"),
237*4882a593Smuzhiyun SOC_DAPM_PIN_SWITCH("Stereo Out"),
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun SOC_SINGLE_BOOL_EXT("Amp Spk Switch", 0,
240*4882a593Smuzhiyun lm4853_get_spk,
241*4882a593Smuzhiyun lm4853_set_spk),
242*4882a593Smuzhiyun };
243*4882a593Smuzhiyun
neo1973_wm8753_init(struct snd_soc_pcm_runtime * rtd)244*4882a593Smuzhiyun static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun struct snd_soc_card *card = rtd->card;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun /* set endpoints to default off mode */
249*4882a593Smuzhiyun snd_soc_dapm_disable_pin(&card->dapm, "GSM Line Out");
250*4882a593Smuzhiyun snd_soc_dapm_disable_pin(&card->dapm, "GSM Line In");
251*4882a593Smuzhiyun snd_soc_dapm_disable_pin(&card->dapm, "Headset Mic");
252*4882a593Smuzhiyun snd_soc_dapm_disable_pin(&card->dapm, "Handset Mic");
253*4882a593Smuzhiyun snd_soc_dapm_disable_pin(&card->dapm, "Stereo Out");
254*4882a593Smuzhiyun snd_soc_dapm_disable_pin(&card->dapm, "Handset Spk");
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun /* allow audio paths from the GSM modem to run during suspend */
257*4882a593Smuzhiyun snd_soc_dapm_ignore_suspend(&card->dapm, "GSM Line Out");
258*4882a593Smuzhiyun snd_soc_dapm_ignore_suspend(&card->dapm, "GSM Line In");
259*4882a593Smuzhiyun snd_soc_dapm_ignore_suspend(&card->dapm, "Headset Mic");
260*4882a593Smuzhiyun snd_soc_dapm_ignore_suspend(&card->dapm, "Handset Mic");
261*4882a593Smuzhiyun snd_soc_dapm_ignore_suspend(&card->dapm, "Stereo Out");
262*4882a593Smuzhiyun snd_soc_dapm_ignore_suspend(&card->dapm, "Handset Spk");
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun return 0;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun SND_SOC_DAILINK_DEFS(wm8753,
268*4882a593Smuzhiyun DAILINK_COMP_ARRAY(COMP_CPU("s3c24xx-iis")),
269*4882a593Smuzhiyun DAILINK_COMP_ARRAY(COMP_CODEC("wm8753.0-001a", "wm8753-hifi")),
270*4882a593Smuzhiyun DAILINK_COMP_ARRAY(COMP_PLATFORM("s3c24xx-iis")));
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun SND_SOC_DAILINK_DEFS(bluetooth,
273*4882a593Smuzhiyun DAILINK_COMP_ARRAY(COMP_CPU("bt-sco-pcm")),
274*4882a593Smuzhiyun DAILINK_COMP_ARRAY(COMP_CODEC("wm8753.0-001a", "wm8753-voice")));
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun static struct snd_soc_dai_link neo1973_dai[] = {
277*4882a593Smuzhiyun { /* Hifi Playback - for similatious use with voice below */
278*4882a593Smuzhiyun .name = "WM8753",
279*4882a593Smuzhiyun .stream_name = "WM8753 HiFi",
280*4882a593Smuzhiyun .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
281*4882a593Smuzhiyun SND_SOC_DAIFMT_CBM_CFM,
282*4882a593Smuzhiyun .init = neo1973_wm8753_init,
283*4882a593Smuzhiyun .ops = &neo1973_hifi_ops,
284*4882a593Smuzhiyun SND_SOC_DAILINK_REG(wm8753),
285*4882a593Smuzhiyun },
286*4882a593Smuzhiyun { /* Voice via BT */
287*4882a593Smuzhiyun .name = "Bluetooth",
288*4882a593Smuzhiyun .stream_name = "Voice",
289*4882a593Smuzhiyun .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
290*4882a593Smuzhiyun SND_SOC_DAIFMT_CBS_CFS,
291*4882a593Smuzhiyun .ops = &neo1973_voice_ops,
292*4882a593Smuzhiyun SND_SOC_DAILINK_REG(bluetooth),
293*4882a593Smuzhiyun },
294*4882a593Smuzhiyun };
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun static struct snd_soc_aux_dev neo1973_aux_devs[] = {
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun .dlc = COMP_AUX("dfbmcs320.0"),
299*4882a593Smuzhiyun },
300*4882a593Smuzhiyun };
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun static struct snd_soc_codec_conf neo1973_codec_conf[] = {
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun .dlc = COMP_CODEC_CONF("lm4857.0-007c"),
305*4882a593Smuzhiyun .name_prefix = "Amp",
306*4882a593Smuzhiyun },
307*4882a593Smuzhiyun };
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun static struct snd_soc_card neo1973 = {
310*4882a593Smuzhiyun .name = "neo1973gta02",
311*4882a593Smuzhiyun .owner = THIS_MODULE,
312*4882a593Smuzhiyun .dai_link = neo1973_dai,
313*4882a593Smuzhiyun .num_links = ARRAY_SIZE(neo1973_dai),
314*4882a593Smuzhiyun .aux_dev = neo1973_aux_devs,
315*4882a593Smuzhiyun .num_aux_devs = ARRAY_SIZE(neo1973_aux_devs),
316*4882a593Smuzhiyun .codec_conf = neo1973_codec_conf,
317*4882a593Smuzhiyun .num_configs = ARRAY_SIZE(neo1973_codec_conf),
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun .controls = neo1973_wm8753_controls,
320*4882a593Smuzhiyun .num_controls = ARRAY_SIZE(neo1973_wm8753_controls),
321*4882a593Smuzhiyun .dapm_widgets = neo1973_wm8753_dapm_widgets,
322*4882a593Smuzhiyun .num_dapm_widgets = ARRAY_SIZE(neo1973_wm8753_dapm_widgets),
323*4882a593Smuzhiyun .dapm_routes = neo1973_wm8753_routes,
324*4882a593Smuzhiyun .num_dapm_routes = ARRAY_SIZE(neo1973_wm8753_routes),
325*4882a593Smuzhiyun .fully_routed = true,
326*4882a593Smuzhiyun };
327*4882a593Smuzhiyun
neo1973_probe(struct platform_device * pdev)328*4882a593Smuzhiyun static int neo1973_probe(struct platform_device *pdev)
329*4882a593Smuzhiyun {
330*4882a593Smuzhiyun struct device *dev = &pdev->dev;
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun gpiod_hp_in = devm_gpiod_get(dev, "hp", GPIOD_OUT_HIGH);
333*4882a593Smuzhiyun if (IS_ERR(gpiod_hp_in)) {
334*4882a593Smuzhiyun dev_err(dev, "missing gpio %s\n", "hp");
335*4882a593Smuzhiyun return PTR_ERR(gpiod_hp_in);
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun gpiod_amp_shut = devm_gpiod_get(dev, "amp-shut", GPIOD_OUT_HIGH);
338*4882a593Smuzhiyun if (IS_ERR(gpiod_amp_shut)) {
339*4882a593Smuzhiyun dev_err(dev, "missing gpio %s\n", "amp-shut");
340*4882a593Smuzhiyun return PTR_ERR(gpiod_amp_shut);
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun neo1973.dev = dev;
344*4882a593Smuzhiyun return devm_snd_soc_register_card(dev, &neo1973);
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun struct platform_driver neo1973_audio = {
348*4882a593Smuzhiyun .driver = {
349*4882a593Smuzhiyun .name = "neo1973-audio",
350*4882a593Smuzhiyun .pm = &snd_soc_pm_ops,
351*4882a593Smuzhiyun },
352*4882a593Smuzhiyun .probe = neo1973_probe,
353*4882a593Smuzhiyun };
354*4882a593Smuzhiyun module_platform_driver(neo1973_audio);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun /* Module information */
357*4882a593Smuzhiyun MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org");
358*4882a593Smuzhiyun MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 and Frerunner");
359*4882a593Smuzhiyun MODULE_LICENSE("GPL");
360*4882a593Smuzhiyun MODULE_ALIAS("platform:neo1973-audio");
361