xref: /linux/sound/soc/intel/boards/sof_maxim_common.c (revision 24168c5e6dfbdd5b414f048f47f75d64533296ca)
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Copyright(c) 2020 Intel Corporation
4 #include <linux/module.h>
5 #include <linux/string.h>
6 #include <sound/pcm.h>
7 #include <sound/pcm_params.h>
8 #include <sound/soc.h>
9 #include <sound/soc-acpi.h>
10 #include <sound/soc-dai.h>
11 #include <sound/soc-dapm.h>
12 #include <uapi/sound/asound.h>
13 #include "../common/soc-intel-quirks.h"
14 #include "sof_maxim_common.h"
15 
16 /*
17  * Common structures and functions
18  */
19 static const struct snd_kcontrol_new maxim_2spk_kcontrols[] = {
20 	SOC_DAPM_PIN_SWITCH("Left Spk"),
21 	SOC_DAPM_PIN_SWITCH("Right Spk"),
22 
23 };
24 
25 static const struct snd_soc_dapm_widget maxim_2spk_widgets[] = {
26 	SND_SOC_DAPM_SPK("Left Spk", NULL),
27 	SND_SOC_DAPM_SPK("Right Spk", NULL),
28 };
29 
30 /* helper function to get the number of specific codec */
31 static unsigned int get_num_codecs(const char *hid)
32 {
33 	struct acpi_device *adev;
34 	unsigned int dev_num = 0;
35 
36 	for_each_acpi_dev_match(adev, hid, NULL, -1)
37 		dev_num++;
38 
39 	return dev_num;
40 }
41 
42 /*
43  * Maxim MAX98373
44  */
45 #define MAX_98373_PIN_NAME 16
46 
47 static const struct snd_soc_dapm_route max_98373_dapm_routes[] = {
48 	/* speaker */
49 	{ "Left Spk", NULL, "Left BE_OUT" },
50 	{ "Right Spk", NULL, "Right BE_OUT" },
51 };
52 
53 static struct snd_soc_codec_conf max_98373_codec_conf[] = {
54 	{
55 		.dlc = COMP_CODEC_CONF(MAX_98373_DEV0_NAME),
56 		.name_prefix = "Right",
57 	},
58 	{
59 		.dlc = COMP_CODEC_CONF(MAX_98373_DEV1_NAME),
60 		.name_prefix = "Left",
61 	},
62 };
63 
64 static struct snd_soc_dai_link_component max_98373_components[] = {
65 	{  /* For Right */
66 		.name = MAX_98373_DEV0_NAME,
67 		.dai_name = MAX_98373_CODEC_DAI,
68 	},
69 	{  /* For Left */
70 		.name = MAX_98373_DEV1_NAME,
71 		.dai_name = MAX_98373_CODEC_DAI,
72 	},
73 };
74 
75 static int max_98373_hw_params(struct snd_pcm_substream *substream,
76 			       struct snd_pcm_hw_params *params)
77 {
78 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
79 	struct snd_soc_dai *codec_dai;
80 	int ret = 0;
81 	int j;
82 
83 	for_each_rtd_codec_dais(rtd, j, codec_dai) {
84 		if (!strcmp(codec_dai->component->name, MAX_98373_DEV0_NAME)) {
85 			/* DEV0 tdm slot configuration */
86 			ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x03, 3, 8, 32);
87 		} else if (!strcmp(codec_dai->component->name, MAX_98373_DEV1_NAME)) {
88 			/* DEV1 tdm slot configuration */
89 			ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0C, 3, 8, 32);
90 		}
91 		if (ret < 0) {
92 			dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n",
93 				ret);
94 			return ret;
95 		}
96 	}
97 	return 0;
98 }
99 
100 static int max_98373_trigger(struct snd_pcm_substream *substream, int cmd)
101 {
102 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
103 	struct snd_soc_dai *codec_dai;
104 	struct snd_soc_dai *cpu_dai;
105 	int j;
106 	int ret = 0;
107 
108 	/* set spk pin by playback only */
109 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
110 		return 0;
111 
112 	cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
113 	for_each_rtd_codec_dais(rtd, j, codec_dai) {
114 		struct snd_soc_dapm_context *dapm =
115 				snd_soc_component_get_dapm(cpu_dai->component);
116 		char pin_name[MAX_98373_PIN_NAME];
117 
118 		snprintf(pin_name, ARRAY_SIZE(pin_name), "%s Spk",
119 			 codec_dai->component->name_prefix);
120 
121 		switch (cmd) {
122 		case SNDRV_PCM_TRIGGER_START:
123 		case SNDRV_PCM_TRIGGER_RESUME:
124 		case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
125 			ret = snd_soc_dapm_enable_pin(dapm, pin_name);
126 			if (!ret)
127 				snd_soc_dapm_sync(dapm);
128 			break;
129 		case SNDRV_PCM_TRIGGER_STOP:
130 		case SNDRV_PCM_TRIGGER_SUSPEND:
131 		case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
132 			ret = snd_soc_dapm_disable_pin(dapm, pin_name);
133 			if (!ret)
134 				snd_soc_dapm_sync(dapm);
135 			break;
136 		default:
137 			break;
138 		}
139 	}
140 
141 	return ret;
142 }
143 
144 static const struct snd_soc_ops max_98373_ops = {
145 	.hw_params = max_98373_hw_params,
146 	.trigger = max_98373_trigger,
147 };
148 
149 static int max_98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd)
150 {
151 	struct snd_soc_card *card = rtd->card;
152 	unsigned int num_codecs = get_num_codecs(MAX_98373_ACPI_HID);
153 	int ret;
154 
155 	switch (num_codecs) {
156 	case 2:
157 		ret = snd_soc_dapm_new_controls(&card->dapm, maxim_2spk_widgets,
158 						ARRAY_SIZE(maxim_2spk_widgets));
159 		if (ret) {
160 			dev_err(rtd->dev, "fail to add max98373 widgets, ret %d\n",
161 				ret);
162 			return ret;
163 		}
164 
165 		ret = snd_soc_add_card_controls(card, maxim_2spk_kcontrols,
166 						ARRAY_SIZE(maxim_2spk_kcontrols));
167 		if (ret) {
168 			dev_err(rtd->dev, "fail to add max98373 kcontrols, ret %d\n",
169 				ret);
170 			return ret;
171 		}
172 
173 		ret = snd_soc_dapm_add_routes(&card->dapm, max_98373_dapm_routes,
174 					      ARRAY_SIZE(max_98373_dapm_routes));
175 		if (ret) {
176 			dev_err(rtd->dev, "fail to add max98373 routes, ret %d\n",
177 				ret);
178 			return ret;
179 		}
180 		break;
181 	default:
182 		dev_err(rtd->dev, "max98373: invalid num_codecs %d\n", num_codecs);
183 		return -EINVAL;
184 	}
185 
186 	return ret;
187 }
188 
189 void max_98373_dai_link(struct device *dev, struct snd_soc_dai_link *link)
190 {
191 	link->codecs = max_98373_components;
192 	link->num_codecs = ARRAY_SIZE(max_98373_components);
193 	link->init = max_98373_spk_codec_init;
194 	link->ops = &max_98373_ops;
195 }
196 EXPORT_SYMBOL_NS(max_98373_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
197 
198 void max_98373_set_codec_conf(struct snd_soc_card *card)
199 {
200 	card->codec_conf = max_98373_codec_conf;
201 	card->num_configs = ARRAY_SIZE(max_98373_codec_conf);
202 }
203 EXPORT_SYMBOL_NS(max_98373_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON);
204 
205 /*
206  * Maxim MAX98390
207  */
208 static const struct snd_soc_dapm_route max_98390_dapm_routes[] = {
209 	/* speaker */
210 	{ "Left Spk", NULL, "Left BE_OUT" },
211 	{ "Right Spk", NULL, "Right BE_OUT" },
212 };
213 
214 static const struct snd_kcontrol_new max_98390_tt_kcontrols[] = {
215 	SOC_DAPM_PIN_SWITCH("TL Spk"),
216 	SOC_DAPM_PIN_SWITCH("TR Spk"),
217 };
218 
219 static const struct snd_soc_dapm_widget max_98390_tt_dapm_widgets[] = {
220 	SND_SOC_DAPM_SPK("TL Spk", NULL),
221 	SND_SOC_DAPM_SPK("TR Spk", NULL),
222 };
223 
224 static const struct snd_soc_dapm_route max_98390_tt_dapm_routes[] = {
225 	/* Tweeter speaker */
226 	{ "TL Spk", NULL, "Tweeter Left BE_OUT" },
227 	{ "TR Spk", NULL, "Tweeter Right BE_OUT" },
228 };
229 
230 static struct snd_soc_codec_conf max_98390_cml_codec_conf[] = {
231 	{
232 		.dlc = COMP_CODEC_CONF(MAX_98390_DEV0_NAME),
233 		.name_prefix = "Left",
234 	},
235 	{
236 		.dlc = COMP_CODEC_CONF(MAX_98390_DEV1_NAME),
237 		.name_prefix = "Right",
238 	},
239 };
240 
241 static struct snd_soc_codec_conf max_98390_codec_conf[] = {
242 	{
243 		.dlc = COMP_CODEC_CONF(MAX_98390_DEV0_NAME),
244 		.name_prefix = "Right",
245 	},
246 	{
247 		.dlc = COMP_CODEC_CONF(MAX_98390_DEV1_NAME),
248 		.name_prefix = "Left",
249 	},
250 	{
251 		.dlc = COMP_CODEC_CONF(MAX_98390_DEV2_NAME),
252 		.name_prefix = "Tweeter Right",
253 	},
254 	{
255 		.dlc = COMP_CODEC_CONF(MAX_98390_DEV3_NAME),
256 		.name_prefix = "Tweeter Left",
257 	},
258 };
259 
260 static struct snd_soc_dai_link_component max_98390_components[] = {
261 	{
262 		.name = MAX_98390_DEV0_NAME,
263 		.dai_name = MAX_98390_CODEC_DAI,
264 	},
265 	{
266 		.name = MAX_98390_DEV1_NAME,
267 		.dai_name = MAX_98390_CODEC_DAI,
268 	},
269 	{
270 		.name = MAX_98390_DEV2_NAME,
271 		.dai_name = MAX_98390_CODEC_DAI,
272 	},
273 	{
274 		.name = MAX_98390_DEV3_NAME,
275 		.dai_name = MAX_98390_CODEC_DAI,
276 	},
277 };
278 
279 static const struct {
280 	unsigned int tx;
281 	unsigned int rx;
282 } max_98390_tdm_mask[] = {
283 	{.tx = 0x01, .rx = 0x3},
284 	{.tx = 0x02, .rx = 0x3},
285 	{.tx = 0x04, .rx = 0x3},
286 	{.tx = 0x08, .rx = 0x3},
287 };
288 
289 static int max_98390_hw_params(struct snd_pcm_substream *substream,
290 			       struct snd_pcm_hw_params *params)
291 {
292 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
293 	struct snd_soc_dai_link *dai_link = rtd->dai_link;
294 	struct snd_soc_dai *codec_dai;
295 	int i, ret;
296 
297 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
298 		if (i >= ARRAY_SIZE(max_98390_tdm_mask)) {
299 			dev_err(codec_dai->dev, "invalid codec index %d\n", i);
300 			return -ENODEV;
301 		}
302 
303 		switch (dai_link->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
304 		case SND_SOC_DAIFMT_DSP_A:
305 		case SND_SOC_DAIFMT_DSP_B:
306 			/* 4-slot TDM */
307 			ret = snd_soc_dai_set_tdm_slot(codec_dai,
308 						       max_98390_tdm_mask[i].tx,
309 						       max_98390_tdm_mask[i].rx,
310 						       4,
311 						       params_width(params));
312 			if (ret < 0) {
313 				dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n",
314 					ret);
315 				return ret;
316 			}
317 			break;
318 		default:
319 			dev_dbg(codec_dai->dev, "codec is in I2S mode\n");
320 			break;
321 		}
322 	}
323 	return 0;
324 }
325 
326 static int max_98390_init(struct snd_soc_pcm_runtime *rtd)
327 {
328 	struct snd_soc_card *card = rtd->card;
329 	unsigned int num_codecs = get_num_codecs(MAX_98390_ACPI_HID);
330 	int ret;
331 
332 	switch (num_codecs) {
333 	case 4:
334 		/* add widgets/controls/dapm for tweeter speakers */
335 		ret = snd_soc_dapm_new_controls(&card->dapm, max_98390_tt_dapm_widgets,
336 						ARRAY_SIZE(max_98390_tt_dapm_widgets));
337 		if (ret) {
338 			dev_err(rtd->dev, "unable to add tweeter dapm widgets, ret %d\n",
339 				ret);
340 			/* Don't need to add routes if widget addition failed */
341 			return ret;
342 		}
343 
344 		ret = snd_soc_add_card_controls(card, max_98390_tt_kcontrols,
345 						ARRAY_SIZE(max_98390_tt_kcontrols));
346 		if (ret) {
347 			dev_err(rtd->dev, "unable to add tweeter controls, ret %d\n",
348 				ret);
349 			return ret;
350 		}
351 
352 		ret = snd_soc_dapm_add_routes(&card->dapm, max_98390_tt_dapm_routes,
353 					      ARRAY_SIZE(max_98390_tt_dapm_routes));
354 		if (ret) {
355 			dev_err(rtd->dev, "unable to add tweeter dapm routes, ret %d\n",
356 				ret);
357 			return ret;
358 		}
359 
360 		fallthrough;
361 	case 2:
362 		/* add regular speakers dapm route */
363 		ret = snd_soc_dapm_new_controls(&card->dapm, maxim_2spk_widgets,
364 						ARRAY_SIZE(maxim_2spk_widgets));
365 		if (ret) {
366 			dev_err(rtd->dev, "fail to add max98390 woofer widgets, ret %d\n",
367 				ret);
368 			return ret;
369 		}
370 
371 		ret = snd_soc_add_card_controls(card, maxim_2spk_kcontrols,
372 						ARRAY_SIZE(maxim_2spk_kcontrols));
373 		if (ret) {
374 			dev_err(rtd->dev, "fail to add max98390 woofer kcontrols, ret %d\n",
375 				ret);
376 			return ret;
377 		}
378 
379 		ret = snd_soc_dapm_add_routes(&card->dapm, max_98390_dapm_routes,
380 					      ARRAY_SIZE(max_98390_dapm_routes));
381 		if (ret) {
382 			dev_err(rtd->dev, "unable to add dapm routes, ret %d\n",
383 				ret);
384 			return ret;
385 		}
386 		break;
387 	default:
388 		dev_err(rtd->dev, "invalid codec number %d\n", num_codecs);
389 		return -EINVAL;
390 	}
391 
392 	return ret;
393 }
394 
395 static const struct snd_soc_ops max_98390_ops = {
396 	.hw_params = max_98390_hw_params,
397 };
398 
399 void max_98390_dai_link(struct device *dev, struct snd_soc_dai_link *link)
400 {
401 	unsigned int num_codecs = get_num_codecs(MAX_98390_ACPI_HID);
402 
403 	link->codecs = max_98390_components;
404 
405 	switch (num_codecs) {
406 	case 2:
407 	case 4:
408 		link->num_codecs = num_codecs;
409 		break;
410 	default:
411 		dev_err(dev, "invalid codec number %d for %s\n", num_codecs,
412 			MAX_98390_ACPI_HID);
413 		break;
414 	}
415 
416 	link->init = max_98390_init;
417 	link->ops = &max_98390_ops;
418 }
419 EXPORT_SYMBOL_NS(max_98390_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
420 
421 void max_98390_set_codec_conf(struct device *dev, struct snd_soc_card *card)
422 {
423 	unsigned int num_codecs = get_num_codecs(MAX_98390_ACPI_HID);
424 
425 	card->codec_conf = max_98390_codec_conf;
426 
427 	switch (num_codecs) {
428 	case 2:
429 		if (soc_intel_is_cml())
430 			card->codec_conf = max_98390_cml_codec_conf;
431 
432 		fallthrough;
433 	case 4:
434 		card->num_configs = num_codecs;
435 		break;
436 	default:
437 		dev_err(dev, "invalid codec number %d for %s\n", num_codecs,
438 			MAX_98390_ACPI_HID);
439 		break;
440 	}
441 }
442 EXPORT_SYMBOL_NS(max_98390_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON);
443 
444 /*
445  * Maxim MAX98357A/MAX98360A
446  */
447 static const struct snd_kcontrol_new max_98357a_kcontrols[] = {
448 	SOC_DAPM_PIN_SWITCH("Spk"),
449 };
450 
451 static const struct snd_soc_dapm_widget max_98357a_dapm_widgets[] = {
452 	SND_SOC_DAPM_SPK("Spk", NULL),
453 };
454 
455 static const struct snd_soc_dapm_route max_98357a_dapm_routes[] = {
456 	/* speaker */
457 	{"Spk", NULL, "Speaker"},
458 };
459 
460 static struct snd_soc_dai_link_component max_98357a_components[] = {
461 	{
462 		.name = MAX_98357A_DEV0_NAME,
463 		.dai_name = MAX_98357A_CODEC_DAI,
464 	}
465 };
466 
467 static struct snd_soc_dai_link_component max_98360a_components[] = {
468 	{
469 		.name = MAX_98360A_DEV0_NAME,
470 		.dai_name = MAX_98357A_CODEC_DAI,
471 	}
472 };
473 
474 static int max_98357a_init(struct snd_soc_pcm_runtime *rtd)
475 {
476 	struct snd_soc_card *card = rtd->card;
477 	int ret;
478 
479 	ret = snd_soc_dapm_new_controls(&card->dapm, max_98357a_dapm_widgets,
480 					ARRAY_SIZE(max_98357a_dapm_widgets));
481 	if (ret) {
482 		dev_err(rtd->dev, "unable to add dapm controls, ret %d\n", ret);
483 		/* Don't need to add routes if widget addition failed */
484 		return ret;
485 	}
486 
487 	ret = snd_soc_add_card_controls(card, max_98357a_kcontrols,
488 					ARRAY_SIZE(max_98357a_kcontrols));
489 	if (ret) {
490 		dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);
491 		return ret;
492 	}
493 
494 	ret = snd_soc_dapm_add_routes(&card->dapm, max_98357a_dapm_routes,
495 				      ARRAY_SIZE(max_98357a_dapm_routes));
496 
497 	if (ret)
498 		dev_err(rtd->dev, "unable to add dapm routes, ret %d\n", ret);
499 
500 	return ret;
501 }
502 
503 void max_98357a_dai_link(struct snd_soc_dai_link *link)
504 {
505 	link->codecs = max_98357a_components;
506 	link->num_codecs = ARRAY_SIZE(max_98357a_components);
507 	link->init = max_98357a_init;
508 }
509 EXPORT_SYMBOL_NS(max_98357a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
510 
511 void max_98360a_dai_link(struct snd_soc_dai_link *link)
512 {
513 	link->codecs = max_98360a_components;
514 	link->num_codecs = ARRAY_SIZE(max_98360a_components);
515 	link->init = max_98357a_init;
516 }
517 EXPORT_SYMBOL_NS(max_98360a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
518 
519 MODULE_DESCRIPTION("ASoC Intel SOF Maxim helpers");
520 MODULE_LICENSE("GPL");
521