1 // SPDX-License-Identifier: GPL-2.0+
2 //
3 // Machine driver for AMD ACP Audio engine using ES8336 codec.
4 //
5 // Copyright 2023 Marian Postevca <posteuca@mutex.one>
6 #include <sound/core.h>
7 #include <sound/soc.h>
8 #include <sound/pcm.h>
9 #include <sound/pcm_params.h>
10 #include <sound/soc-dapm.h>
11 #include <sound/jack.h>
12 #include <sound/soc-acpi.h>
13 #include <linux/clk.h>
14 #include <linux/gpio.h>
15 #include <linux/gpio/consumer.h>
16 #include <linux/module.h>
17 #include <linux/i2c.h>
18 #include <linux/input.h>
19 #include <linux/io.h>
20 #include <linux/acpi.h>
21 #include <linux/dmi.h>
22 #include "../acp-mach.h"
23 #include "acp3x-es83xx.h"
24
25 #define get_mach_priv(card) ((struct acp3x_es83xx_private *)((acp_get_drvdata(card))->mach_priv))
26
27 #define DUAL_CHANNEL 2
28
29 #define ES83XX_ENABLE_DMIC BIT(4)
30 #define ES83XX_48_MHZ_MCLK BIT(5)
31
32 struct acp3x_es83xx_private {
33 bool speaker_on;
34 bool headphone_on;
35 unsigned long quirk;
36 struct snd_soc_component *codec;
37 struct device *codec_dev;
38 struct gpio_desc *gpio_speakers, *gpio_headphone;
39 struct acpi_gpio_params enable_spk_gpio, enable_hp_gpio;
40 struct acpi_gpio_mapping gpio_mapping[3];
41 struct snd_soc_dapm_route mic_map[2];
42 };
43
44 static const unsigned int channels[] = {
45 DUAL_CHANNEL,
46 };
47
48 static const struct snd_pcm_hw_constraint_list constraints_channels = {
49 .count = ARRAY_SIZE(channels),
50 .list = channels,
51 .mask = 0,
52 };
53
54 #define ES83xx_12288_KHZ_MCLK_FREQ (48000 * 256)
55 #define ES83xx_48_MHZ_MCLK_FREQ (48000 * 1000)
56
57 static int acp3x_es83xx_headphone_power_event(struct snd_soc_dapm_widget *w,
58 struct snd_kcontrol *kcontrol, int event);
59 static int acp3x_es83xx_speaker_power_event(struct snd_soc_dapm_widget *w,
60 struct snd_kcontrol *kcontrol, int event);
61
acp3x_es83xx_codec_startup(struct snd_pcm_substream * substream)62 static int acp3x_es83xx_codec_startup(struct snd_pcm_substream *substream)
63 {
64 struct snd_pcm_runtime *runtime;
65 struct snd_soc_pcm_runtime *rtd;
66 struct snd_soc_dai *codec_dai;
67 struct acp3x_es83xx_private *priv;
68 unsigned int freq;
69 int ret;
70
71 runtime = substream->runtime;
72 rtd = snd_soc_substream_to_rtd(substream);
73 codec_dai = snd_soc_rtd_to_codec(rtd, 0);
74 priv = get_mach_priv(rtd->card);
75
76 if (priv->quirk & ES83XX_48_MHZ_MCLK) {
77 dev_dbg(priv->codec_dev, "using a 48Mhz MCLK\n");
78 freq = ES83xx_48_MHZ_MCLK_FREQ;
79 } else {
80 dev_dbg(priv->codec_dev, "using a 12.288Mhz MCLK\n");
81 freq = ES83xx_12288_KHZ_MCLK_FREQ;
82 }
83
84 ret = snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_OUT);
85 if (ret < 0) {
86 dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret);
87 return ret;
88 }
89
90 runtime->hw.channels_max = DUAL_CHANNEL;
91 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
92 &constraints_channels);
93
94 return 0;
95 }
96
97 static struct snd_soc_jack es83xx_jack;
98
99 static struct snd_soc_jack_pin es83xx_jack_pins[] = {
100 {
101 .pin = "Headphone",
102 .mask = SND_JACK_HEADPHONE,
103 },
104 {
105 .pin = "Headset Mic",
106 .mask = SND_JACK_MICROPHONE,
107 },
108 };
109
110 static const struct snd_soc_dapm_widget acp3x_es83xx_widgets[] = {
111 SND_SOC_DAPM_SPK("Speaker", NULL),
112 SND_SOC_DAPM_HP("Headphone", NULL),
113 SND_SOC_DAPM_MIC("Headset Mic", NULL),
114 SND_SOC_DAPM_MIC("Internal Mic", NULL),
115
116 SND_SOC_DAPM_SUPPLY("Headphone Power", SND_SOC_NOPM, 0, 0,
117 acp3x_es83xx_headphone_power_event,
118 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
119 SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0,
120 acp3x_es83xx_speaker_power_event,
121 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
122 };
123
124 static const struct snd_soc_dapm_route acp3x_es83xx_audio_map[] = {
125 {"Headphone", NULL, "HPOL"},
126 {"Headphone", NULL, "HPOR"},
127 {"Headphone", NULL, "Headphone Power"},
128
129 /*
130 * There is no separate speaker output instead the speakers are muxed to
131 * the HP outputs. The mux is controlled Speaker and/or headphone switch.
132 */
133 {"Speaker", NULL, "HPOL"},
134 {"Speaker", NULL, "HPOR"},
135 {"Speaker", NULL, "Speaker Power"},
136 };
137
138
139 static const struct snd_kcontrol_new acp3x_es83xx_controls[] = {
140 SOC_DAPM_PIN_SWITCH("Speaker"),
141 SOC_DAPM_PIN_SWITCH("Headphone"),
142 SOC_DAPM_PIN_SWITCH("Headset Mic"),
143 SOC_DAPM_PIN_SWITCH("Internal Mic"),
144 };
145
acp3x_es83xx_configure_widgets(struct snd_soc_card * card)146 static int acp3x_es83xx_configure_widgets(struct snd_soc_card *card)
147 {
148 card->dapm_widgets = acp3x_es83xx_widgets;
149 card->num_dapm_widgets = ARRAY_SIZE(acp3x_es83xx_widgets);
150 card->controls = acp3x_es83xx_controls;
151 card->num_controls = ARRAY_SIZE(acp3x_es83xx_controls);
152 card->dapm_routes = acp3x_es83xx_audio_map;
153 card->num_dapm_routes = ARRAY_SIZE(acp3x_es83xx_audio_map);
154
155 return 0;
156 }
157
acp3x_es83xx_headphone_power_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)158 static int acp3x_es83xx_headphone_power_event(struct snd_soc_dapm_widget *w,
159 struct snd_kcontrol *kcontrol, int event)
160 {
161 struct acp3x_es83xx_private *priv = get_mach_priv(w->dapm->card);
162
163 dev_dbg(priv->codec_dev, "headphone power event = %d\n", event);
164 if (SND_SOC_DAPM_EVENT_ON(event))
165 priv->headphone_on = true;
166 else
167 priv->headphone_on = false;
168
169 gpiod_set_value_cansleep(priv->gpio_speakers, priv->speaker_on);
170 gpiod_set_value_cansleep(priv->gpio_headphone, priv->headphone_on);
171
172 return 0;
173 }
174
acp3x_es83xx_speaker_power_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)175 static int acp3x_es83xx_speaker_power_event(struct snd_soc_dapm_widget *w,
176 struct snd_kcontrol *kcontrol, int event)
177 {
178 struct acp3x_es83xx_private *priv = get_mach_priv(w->dapm->card);
179
180 dev_dbg(priv->codec_dev, "speaker power event: %d\n", event);
181 if (SND_SOC_DAPM_EVENT_ON(event))
182 priv->speaker_on = true;
183 else
184 priv->speaker_on = false;
185
186 gpiod_set_value_cansleep(priv->gpio_speakers, priv->speaker_on);
187 gpiod_set_value_cansleep(priv->gpio_headphone, priv->headphone_on);
188
189 return 0;
190 }
191
acp3x_es83xx_suspend_pre(struct snd_soc_card * card)192 static int acp3x_es83xx_suspend_pre(struct snd_soc_card *card)
193 {
194 struct acp3x_es83xx_private *priv = get_mach_priv(card);
195
196 /* We need to disable the jack in the machine driver suspend
197 * callback so that the CODEC suspend callback actually gets
198 * called. Without doing it, the CODEC suspend/resume
199 * callbacks do not get called if headphones are plugged in.
200 * This is because plugging in headphones keeps some supplies
201 * active, this in turn means that the lowest bias level
202 * that the CODEC can go to is SND_SOC_BIAS_STANDBY.
203 * If components do not set idle_bias_on to true then
204 * their suspend/resume callbacks do not get called.
205 */
206 dev_dbg(priv->codec_dev, "card suspend\n");
207 snd_soc_component_set_jack(priv->codec, NULL, NULL);
208 return 0;
209 }
210
acp3x_es83xx_resume_post(struct snd_soc_card * card)211 static int acp3x_es83xx_resume_post(struct snd_soc_card *card)
212 {
213 struct acp3x_es83xx_private *priv = get_mach_priv(card);
214
215 /* We disabled jack detection in suspend callback,
216 * enable it back.
217 */
218 dev_dbg(priv->codec_dev, "card resume\n");
219 snd_soc_component_set_jack(priv->codec, &es83xx_jack, NULL);
220 return 0;
221 }
222
acp3x_es83xx_configure_gpios(struct acp3x_es83xx_private * priv)223 static int acp3x_es83xx_configure_gpios(struct acp3x_es83xx_private *priv)
224 {
225
226 priv->enable_spk_gpio.crs_entry_index = 0;
227 priv->enable_hp_gpio.crs_entry_index = 1;
228
229 priv->enable_spk_gpio.active_low = false;
230 priv->enable_hp_gpio.active_low = false;
231
232 priv->gpio_mapping[0].name = "speakers-enable-gpios";
233 priv->gpio_mapping[0].data = &priv->enable_spk_gpio;
234 priv->gpio_mapping[0].size = 1;
235 priv->gpio_mapping[0].quirks = ACPI_GPIO_QUIRK_ONLY_GPIOIO;
236
237 priv->gpio_mapping[1].name = "headphone-enable-gpios";
238 priv->gpio_mapping[1].data = &priv->enable_hp_gpio;
239 priv->gpio_mapping[1].size = 1;
240 priv->gpio_mapping[1].quirks = ACPI_GPIO_QUIRK_ONLY_GPIOIO;
241
242 dev_info(priv->codec_dev, "speaker gpio %d active %s, headphone gpio %d active %s\n",
243 priv->enable_spk_gpio.crs_entry_index,
244 priv->enable_spk_gpio.active_low ? "low" : "high",
245 priv->enable_hp_gpio.crs_entry_index,
246 priv->enable_hp_gpio.active_low ? "low" : "high");
247 return 0;
248 }
249
acp3x_es83xx_configure_mics(struct acp3x_es83xx_private * priv)250 static int acp3x_es83xx_configure_mics(struct acp3x_es83xx_private *priv)
251 {
252 int num_routes = 0;
253 int i;
254
255 if (!(priv->quirk & ES83XX_ENABLE_DMIC)) {
256 priv->mic_map[num_routes].sink = "MIC1";
257 priv->mic_map[num_routes].source = "Internal Mic";
258 num_routes++;
259 }
260
261 priv->mic_map[num_routes].sink = "MIC2";
262 priv->mic_map[num_routes].source = "Headset Mic";
263 num_routes++;
264
265 for (i = 0; i < num_routes; i++)
266 dev_info(priv->codec_dev, "%s is %s\n",
267 priv->mic_map[i].source, priv->mic_map[i].sink);
268
269 return num_routes;
270 }
271
acp3x_es83xx_init(struct snd_soc_pcm_runtime * runtime)272 static int acp3x_es83xx_init(struct snd_soc_pcm_runtime *runtime)
273 {
274 struct snd_soc_component *codec = snd_soc_rtd_to_codec(runtime, 0)->component;
275 struct snd_soc_card *card = runtime->card;
276 struct acp3x_es83xx_private *priv = get_mach_priv(card);
277 int ret = 0;
278 int num_routes;
279
280 ret = snd_soc_card_jack_new_pins(card, "Headset",
281 SND_JACK_HEADSET | SND_JACK_BTN_0,
282 &es83xx_jack, es83xx_jack_pins,
283 ARRAY_SIZE(es83xx_jack_pins));
284 if (ret) {
285 dev_err(card->dev, "jack creation failed %d\n", ret);
286 return ret;
287 }
288
289 snd_jack_set_key(es83xx_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
290
291 snd_soc_component_set_jack(codec, &es83xx_jack, NULL);
292
293 priv->codec = codec;
294 acp3x_es83xx_configure_gpios(priv);
295
296 ret = devm_acpi_dev_add_driver_gpios(priv->codec_dev, priv->gpio_mapping);
297 if (ret)
298 dev_warn(priv->codec_dev, "failed to add speaker gpio\n");
299
300 priv->gpio_speakers = gpiod_get_optional(priv->codec_dev, "speakers-enable",
301 priv->enable_spk_gpio.active_low ? GPIOD_OUT_LOW : GPIOD_OUT_HIGH);
302 if (IS_ERR(priv->gpio_speakers)) {
303 dev_err(priv->codec_dev, "could not get speakers-enable GPIO\n");
304 return PTR_ERR(priv->gpio_speakers);
305 }
306
307 priv->gpio_headphone = gpiod_get_optional(priv->codec_dev, "headphone-enable",
308 priv->enable_hp_gpio.active_low ? GPIOD_OUT_LOW : GPIOD_OUT_HIGH);
309 if (IS_ERR(priv->gpio_headphone)) {
310 dev_err(priv->codec_dev, "could not get headphone-enable GPIO\n");
311 return PTR_ERR(priv->gpio_headphone);
312 }
313
314 num_routes = acp3x_es83xx_configure_mics(priv);
315 if (num_routes > 0) {
316 ret = snd_soc_dapm_add_routes(&card->dapm, priv->mic_map, num_routes);
317 if (ret != 0)
318 device_remove_software_node(priv->codec_dev);
319 }
320
321 return ret;
322 }
323
324 static const struct snd_soc_ops acp3x_es83xx_ops = {
325 .startup = acp3x_es83xx_codec_startup,
326 };
327
328
329 SND_SOC_DAILINK_DEF(codec,
330 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8336:00", "ES8316 HiFi")));
331
332 static const struct dmi_system_id acp3x_es83xx_dmi_table[] = {
333 {
334 .matches = {
335 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
336 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "KLVL-WXXW"),
337 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"),
338 },
339 .driver_data = (void *)(ES83XX_ENABLE_DMIC),
340 },
341 {
342 .matches = {
343 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
344 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "KLVL-WXX9"),
345 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"),
346 },
347 .driver_data = (void *)(ES83XX_ENABLE_DMIC),
348 },
349 {
350 .matches = {
351 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
352 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "BOM-WXX9"),
353 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"),
354 },
355 .driver_data = (void *)(ES83XX_ENABLE_DMIC|ES83XX_48_MHZ_MCLK),
356 },
357 {
358 .matches = {
359 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
360 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"),
361 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"),
362 },
363 .driver_data = (void *)(ES83XX_ENABLE_DMIC),
364 },
365 {
366 .matches = {
367 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
368 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"),
369 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1020"),
370 },
371 .driver_data = (void *)(ES83XX_ENABLE_DMIC),
372 },
373 {
374 .matches = {
375 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
376 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"),
377 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1040"),
378 },
379 .driver_data = (void *)(ES83XX_ENABLE_DMIC),
380 },
381 {}
382 };
383
acp3x_es83xx_configure_link(struct snd_soc_card * card,struct snd_soc_dai_link * link)384 static int acp3x_es83xx_configure_link(struct snd_soc_card *card, struct snd_soc_dai_link *link)
385 {
386 link->codecs = codec;
387 link->num_codecs = ARRAY_SIZE(codec);
388 link->init = acp3x_es83xx_init;
389 link->ops = &acp3x_es83xx_ops;
390 link->dai_fmt = SND_SOC_DAIFMT_I2S
391 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
392
393 return 0;
394 }
395
acp3x_es83xx_probe(struct snd_soc_card * card)396 static int acp3x_es83xx_probe(struct snd_soc_card *card)
397 {
398 int ret = 0;
399 struct device *dev = card->dev;
400 const struct dmi_system_id *dmi_id;
401
402 dmi_id = dmi_first_match(acp3x_es83xx_dmi_table);
403 if (dmi_id && dmi_id->driver_data) {
404 struct acp3x_es83xx_private *priv;
405 struct acp_card_drvdata *acp_drvdata;
406 struct acpi_device *adev;
407 struct device *codec_dev;
408
409 acp_drvdata = (struct acp_card_drvdata *)card->drvdata;
410
411 dev_info(dev, "matched DMI table with this system, trying to register sound card\n");
412
413 adev = acpi_dev_get_first_match_dev(acp_drvdata->acpi_mach->id, NULL, -1);
414 if (!adev) {
415 dev_err(dev, "Error cannot find '%s' dev\n", acp_drvdata->acpi_mach->id);
416 return -ENXIO;
417 }
418
419 codec_dev = acpi_get_first_physical_node(adev);
420 acpi_dev_put(adev);
421 if (!codec_dev) {
422 dev_warn(dev, "Error cannot find codec device, will defer probe\n");
423 return -EPROBE_DEFER;
424 }
425
426 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
427 if (!priv) {
428 put_device(codec_dev);
429 return -ENOMEM;
430 }
431
432 priv->codec_dev = codec_dev;
433 priv->quirk = (unsigned long)dmi_id->driver_data;
434 acp_drvdata->mach_priv = priv;
435 dev_info(dev, "successfully probed the sound card\n");
436 } else {
437 ret = -ENODEV;
438 dev_warn(dev, "this system has a ES83xx codec defined in ACPI, but the driver doesn't have this system registered in DMI table\n");
439 }
440 return ret;
441 }
442
443
acp3x_es83xx_init_ops(struct acp_mach_ops * ops)444 void acp3x_es83xx_init_ops(struct acp_mach_ops *ops)
445 {
446 ops->probe = acp3x_es83xx_probe;
447 ops->configure_widgets = acp3x_es83xx_configure_widgets;
448 ops->configure_link = acp3x_es83xx_configure_link;
449 ops->suspend_pre = acp3x_es83xx_suspend_pre;
450 ops->resume_post = acp3x_es83xx_resume_post;
451 }
452