xref: /linux/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c (revision 08b7174fb8d126e607e385e34b9e1da4f3be274f)
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 
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 = asoc_substream_to_rtd(substream);
73 	codec_dai = asoc_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 
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 
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 
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 
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 
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 
223 static int acp3x_es83xx_configure_gpios(struct acp3x_es83xx_private *priv)
224 {
225 	int ret = 0;
226 
227 	priv->enable_spk_gpio.crs_entry_index = 0;
228 	priv->enable_hp_gpio.crs_entry_index = 1;
229 
230 	priv->enable_spk_gpio.active_low = false;
231 	priv->enable_hp_gpio.active_low = false;
232 
233 	priv->gpio_mapping[0].name = "speakers-enable-gpios";
234 	priv->gpio_mapping[0].data = &priv->enable_spk_gpio;
235 	priv->gpio_mapping[0].size = 1;
236 	priv->gpio_mapping[0].quirks = ACPI_GPIO_QUIRK_ONLY_GPIOIO;
237 
238 	priv->gpio_mapping[1].name = "headphone-enable-gpios";
239 	priv->gpio_mapping[1].data = &priv->enable_hp_gpio;
240 	priv->gpio_mapping[1].size = 1;
241 	priv->gpio_mapping[1].quirks = ACPI_GPIO_QUIRK_ONLY_GPIOIO;
242 
243 	dev_info(priv->codec_dev, "speaker gpio %d active %s, headphone gpio %d active %s\n",
244 		 priv->enable_spk_gpio.crs_entry_index,
245 		 priv->enable_spk_gpio.active_low ? "low" : "high",
246 		 priv->enable_hp_gpio.crs_entry_index,
247 		 priv->enable_hp_gpio.active_low ? "low" : "high");
248 	return ret;
249 }
250 
251 static int acp3x_es83xx_configure_mics(struct acp3x_es83xx_private *priv)
252 {
253 	int num_routes = 0;
254 	int i;
255 
256 	if (!(priv->quirk & ES83XX_ENABLE_DMIC)) {
257 		priv->mic_map[num_routes].sink = "MIC1";
258 		priv->mic_map[num_routes].source = "Internal Mic";
259 		num_routes++;
260 	}
261 
262 	priv->mic_map[num_routes].sink = "MIC2";
263 	priv->mic_map[num_routes].source = "Headset Mic";
264 	num_routes++;
265 
266 	for (i = 0; i < num_routes; i++)
267 		dev_info(priv->codec_dev, "%s is %s\n",
268 			 priv->mic_map[i].source, priv->mic_map[i].sink);
269 
270 	return num_routes;
271 }
272 
273 static int acp3x_es83xx_init(struct snd_soc_pcm_runtime *runtime)
274 {
275 	struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component;
276 	struct snd_soc_card *card = runtime->card;
277 	struct acp3x_es83xx_private *priv = get_mach_priv(card);
278 	int ret = 0;
279 	int num_routes;
280 
281 	ret = snd_soc_card_jack_new_pins(card, "Headset",
282 					 SND_JACK_HEADSET | SND_JACK_BTN_0,
283 					 &es83xx_jack, es83xx_jack_pins,
284 					 ARRAY_SIZE(es83xx_jack_pins));
285 	if (ret) {
286 		dev_err(card->dev, "jack creation failed %d\n", ret);
287 		return ret;
288 	}
289 
290 	snd_jack_set_key(es83xx_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
291 
292 	snd_soc_component_set_jack(codec, &es83xx_jack, NULL);
293 
294 	priv->codec = codec;
295 	acp3x_es83xx_configure_gpios(priv);
296 
297 	ret = devm_acpi_dev_add_driver_gpios(priv->codec_dev, priv->gpio_mapping);
298 	if (ret)
299 		dev_warn(priv->codec_dev, "failed to add speaker gpio\n");
300 
301 	priv->gpio_speakers = gpiod_get_optional(priv->codec_dev, "speakers-enable",
302 				priv->enable_spk_gpio.active_low ? GPIOD_OUT_LOW : GPIOD_OUT_HIGH);
303 	if (IS_ERR(priv->gpio_speakers)) {
304 		dev_err(priv->codec_dev, "could not get speakers-enable GPIO\n");
305 		return PTR_ERR(priv->gpio_speakers);
306 	}
307 
308 	priv->gpio_headphone = gpiod_get_optional(priv->codec_dev, "headphone-enable",
309 				priv->enable_hp_gpio.active_low ? GPIOD_OUT_LOW : GPIOD_OUT_HIGH);
310 	if (IS_ERR(priv->gpio_headphone)) {
311 		dev_err(priv->codec_dev, "could not get headphone-enable GPIO\n");
312 		return PTR_ERR(priv->gpio_headphone);
313 	}
314 
315 	num_routes = acp3x_es83xx_configure_mics(priv);
316 	if (num_routes > 0) {
317 		ret = snd_soc_dapm_add_routes(&card->dapm, priv->mic_map, num_routes);
318 		if (ret != 0)
319 			device_remove_software_node(priv->codec_dev);
320 	}
321 
322 	return ret;
323 }
324 
325 static const struct snd_soc_ops acp3x_es83xx_ops = {
326 	.startup = acp3x_es83xx_codec_startup,
327 };
328 
329 
330 SND_SOC_DAILINK_DEF(codec,
331 		    DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8336:00", "ES8316 HiFi")));
332 
333 static const struct dmi_system_id acp3x_es83xx_dmi_table[] = {
334 	{
335 		.matches = {
336 			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
337 			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "KLVL-WXXW"),
338 			DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"),
339 		},
340 		.driver_data = (void *)(ES83XX_ENABLE_DMIC),
341 	},
342 	{
343 		.matches = {
344 			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
345 			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "KLVL-WXX9"),
346 			DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"),
347 		},
348 		.driver_data = (void *)(ES83XX_ENABLE_DMIC),
349 	},
350 	{
351 		.matches = {
352 			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
353 			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "BOM-WXX9"),
354 			DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"),
355 		},
356 		.driver_data = (void *)(ES83XX_ENABLE_DMIC|ES83XX_48_MHZ_MCLK),
357 	},
358 	{
359 		.matches = {
360 			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
361 			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"),
362 			DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1020"),
363 		},
364 		.driver_data = (void *)(ES83XX_ENABLE_DMIC),
365 	},
366 	{
367 		.matches = {
368 			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
369 			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"),
370 			DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1040"),
371 		},
372 		.driver_data = (void *)(ES83XX_ENABLE_DMIC),
373 	},
374 	{}
375 };
376 
377 static int acp3x_es83xx_configure_link(struct snd_soc_card *card, struct snd_soc_dai_link *link)
378 {
379 	link->codecs = codec;
380 	link->num_codecs = ARRAY_SIZE(codec);
381 	link->init = acp3x_es83xx_init;
382 	link->ops = &acp3x_es83xx_ops;
383 	link->dai_fmt = SND_SOC_DAIFMT_I2S
384 		| SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
385 
386 	return 0;
387 }
388 
389 static int acp3x_es83xx_probe(struct snd_soc_card *card)
390 {
391 	int ret = 0;
392 	struct device *dev = card->dev;
393 	const struct dmi_system_id *dmi_id;
394 
395 	dmi_id = dmi_first_match(acp3x_es83xx_dmi_table);
396 	if (dmi_id && dmi_id->driver_data) {
397 		struct acp3x_es83xx_private *priv;
398 		struct acp_card_drvdata *acp_drvdata;
399 		struct acpi_device *adev;
400 		struct device *codec_dev;
401 
402 		acp_drvdata = (struct acp_card_drvdata *)card->drvdata;
403 
404 		dev_info(dev, "matched DMI table with this system, trying to register sound card\n");
405 
406 		adev = acpi_dev_get_first_match_dev(acp_drvdata->acpi_mach->id, NULL, -1);
407 		if (!adev) {
408 			dev_err(dev, "Error cannot find '%s' dev\n", acp_drvdata->acpi_mach->id);
409 			return -ENXIO;
410 		}
411 
412 		codec_dev = acpi_get_first_physical_node(adev);
413 		acpi_dev_put(adev);
414 		if (!codec_dev) {
415 			dev_warn(dev, "Error cannot find codec device, will defer probe\n");
416 			return -EPROBE_DEFER;
417 		}
418 
419 		priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
420 		if (!priv) {
421 			put_device(codec_dev);
422 			return -ENOMEM;
423 		}
424 
425 		priv->codec_dev = codec_dev;
426 		priv->quirk = (unsigned long)dmi_id->driver_data;
427 		acp_drvdata->mach_priv = priv;
428 		dev_info(dev, "successfully probed the sound card\n");
429 	} else {
430 		ret = -ENODEV;
431 		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");
432 	}
433 	return ret;
434 }
435 
436 
437 void acp3x_es83xx_init_ops(struct acp_mach_ops *ops)
438 {
439 	ops->probe = acp3x_es83xx_probe;
440 	ops->configure_widgets = acp3x_es83xx_configure_widgets;
441 	ops->configure_link = acp3x_es83xx_configure_link;
442 	ops->suspend_pre = acp3x_es83xx_suspend_pre;
443 	ops->resume_post = acp3x_es83xx_resume_post;
444 }
445