diff options
Diffstat (limited to 'sound/soc/intel/boards/byt-max98090.c')
-rw-r--r-- | sound/soc/intel/boards/byt-max98090.c | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/sound/soc/intel/boards/byt-max98090.c b/sound/soc/intel/boards/byt-max98090.c new file mode 100644 index 000000000000..7ab8cc9fbfd5 --- /dev/null +++ b/sound/soc/intel/boards/byt-max98090.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * Intel Baytrail SST MAX98090 machine driver | ||
3 | * Copyright (c) 2014, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/acpi.h> | ||
19 | #include <linux/device.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <linux/gpio/consumer.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/jack.h> | ||
27 | #include "../../codecs/max98090.h" | ||
28 | |||
29 | struct byt_max98090_private { | ||
30 | struct snd_soc_jack jack; | ||
31 | }; | ||
32 | |||
33 | static const struct snd_soc_dapm_widget byt_max98090_widgets[] = { | ||
34 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
35 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
36 | SND_SOC_DAPM_MIC("Int Mic", NULL), | ||
37 | SND_SOC_DAPM_SPK("Ext Spk", NULL), | ||
38 | }; | ||
39 | |||
40 | static const struct snd_soc_dapm_route byt_max98090_audio_map[] = { | ||
41 | {"IN34", NULL, "Headset Mic"}, | ||
42 | {"Headset Mic", NULL, "MICBIAS"}, | ||
43 | {"DMICL", NULL, "Int Mic"}, | ||
44 | {"Headphone", NULL, "HPL"}, | ||
45 | {"Headphone", NULL, "HPR"}, | ||
46 | {"Ext Spk", NULL, "SPKL"}, | ||
47 | {"Ext Spk", NULL, "SPKR"}, | ||
48 | }; | ||
49 | |||
50 | static const struct snd_kcontrol_new byt_max98090_controls[] = { | ||
51 | SOC_DAPM_PIN_SWITCH("Headphone"), | ||
52 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
53 | SOC_DAPM_PIN_SWITCH("Int Mic"), | ||
54 | SOC_DAPM_PIN_SWITCH("Ext Spk"), | ||
55 | }; | ||
56 | |||
57 | static struct snd_soc_jack_pin hs_jack_pins[] = { | ||
58 | { | ||
59 | .pin = "Headphone", | ||
60 | .mask = SND_JACK_HEADPHONE, | ||
61 | }, | ||
62 | { | ||
63 | .pin = "Headset Mic", | ||
64 | .mask = SND_JACK_MICROPHONE, | ||
65 | }, | ||
66 | }; | ||
67 | |||
68 | static struct snd_soc_jack_gpio hs_jack_gpios[] = { | ||
69 | { | ||
70 | .name = "hp-gpio", | ||
71 | .idx = 0, | ||
72 | .report = SND_JACK_HEADPHONE | SND_JACK_LINEOUT, | ||
73 | .debounce_time = 200, | ||
74 | }, | ||
75 | { | ||
76 | .name = "mic-gpio", | ||
77 | .idx = 1, | ||
78 | .invert = 1, | ||
79 | .report = SND_JACK_MICROPHONE, | ||
80 | .debounce_time = 200, | ||
81 | }, | ||
82 | }; | ||
83 | |||
84 | static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) | ||
85 | { | ||
86 | int ret; | ||
87 | struct snd_soc_card *card = runtime->card; | ||
88 | struct byt_max98090_private *drv = snd_soc_card_get_drvdata(card); | ||
89 | struct snd_soc_jack *jack = &drv->jack; | ||
90 | |||
91 | card->dapm.idle_bias_off = true; | ||
92 | |||
93 | ret = snd_soc_dai_set_sysclk(runtime->codec_dai, | ||
94 | M98090_REG_SYSTEM_CLOCK, | ||
95 | 25000000, SND_SOC_CLOCK_IN); | ||
96 | if (ret < 0) { | ||
97 | dev_err(card->dev, "Can't set codec clock %d\n", ret); | ||
98 | return ret; | ||
99 | } | ||
100 | |||
101 | /* Enable jack detection */ | ||
102 | ret = snd_soc_card_jack_new(runtime->card, "Headset", | ||
103 | SND_JACK_LINEOUT | SND_JACK_HEADSET, jack, | ||
104 | hs_jack_pins, ARRAY_SIZE(hs_jack_pins)); | ||
105 | if (ret) | ||
106 | return ret; | ||
107 | |||
108 | return snd_soc_jack_add_gpiods(card->dev->parent, jack, | ||
109 | ARRAY_SIZE(hs_jack_gpios), | ||
110 | hs_jack_gpios); | ||
111 | } | ||
112 | |||
113 | static struct snd_soc_dai_link byt_max98090_dais[] = { | ||
114 | { | ||
115 | .name = "Baytrail Audio", | ||
116 | .stream_name = "Audio", | ||
117 | .cpu_dai_name = "baytrail-pcm-audio", | ||
118 | .codec_dai_name = "HiFi", | ||
119 | .codec_name = "i2c-193C9890:00", | ||
120 | .platform_name = "baytrail-pcm-audio", | ||
121 | .init = byt_max98090_init, | ||
122 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
123 | SND_SOC_DAIFMT_CBS_CFS, | ||
124 | }, | ||
125 | }; | ||
126 | |||
127 | static struct snd_soc_card byt_max98090_card = { | ||
128 | .name = "byt-max98090", | ||
129 | .dai_link = byt_max98090_dais, | ||
130 | .num_links = ARRAY_SIZE(byt_max98090_dais), | ||
131 | .dapm_widgets = byt_max98090_widgets, | ||
132 | .num_dapm_widgets = ARRAY_SIZE(byt_max98090_widgets), | ||
133 | .dapm_routes = byt_max98090_audio_map, | ||
134 | .num_dapm_routes = ARRAY_SIZE(byt_max98090_audio_map), | ||
135 | .controls = byt_max98090_controls, | ||
136 | .num_controls = ARRAY_SIZE(byt_max98090_controls), | ||
137 | .fully_routed = true, | ||
138 | }; | ||
139 | |||
140 | static int byt_max98090_probe(struct platform_device *pdev) | ||
141 | { | ||
142 | int ret_val = 0; | ||
143 | struct byt_max98090_private *priv; | ||
144 | |||
145 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); | ||
146 | if (!priv) { | ||
147 | dev_err(&pdev->dev, "allocation failed\n"); | ||
148 | return -ENOMEM; | ||
149 | } | ||
150 | |||
151 | byt_max98090_card.dev = &pdev->dev; | ||
152 | snd_soc_card_set_drvdata(&byt_max98090_card, priv); | ||
153 | ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_max98090_card); | ||
154 | if (ret_val) { | ||
155 | dev_err(&pdev->dev, | ||
156 | "snd_soc_register_card failed %d\n", ret_val); | ||
157 | return ret_val; | ||
158 | } | ||
159 | |||
160 | return ret_val; | ||
161 | } | ||
162 | |||
163 | static int byt_max98090_remove(struct platform_device *pdev) | ||
164 | { | ||
165 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
166 | struct byt_max98090_private *priv = snd_soc_card_get_drvdata(card); | ||
167 | |||
168 | snd_soc_jack_free_gpios(&priv->jack, ARRAY_SIZE(hs_jack_gpios), | ||
169 | hs_jack_gpios); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static struct platform_driver byt_max98090_driver = { | ||
175 | .probe = byt_max98090_probe, | ||
176 | .remove = byt_max98090_remove, | ||
177 | .driver = { | ||
178 | .name = "byt-max98090", | ||
179 | .pm = &snd_soc_pm_ops, | ||
180 | }, | ||
181 | }; | ||
182 | module_platform_driver(byt_max98090_driver) | ||
183 | |||
184 | MODULE_DESCRIPTION("ASoC Intel(R) Baytrail Machine driver"); | ||
185 | MODULE_AUTHOR("Omair Md Abdullah, Jarkko Nikula"); | ||
186 | MODULE_LICENSE("GPL v2"); | ||
187 | MODULE_ALIAS("platform:byt-max98090"); | ||