1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  bytcr_wm5102.c - ASoc Machine driver for Intel Baytrail platforms with a
4  *                   Wolfson Microelectronics WM5102 codec
5  *
6  *  Copyright (C) 2020 Hans de Goede <hdegoede@redhat.com>
7  *  Loosely based on bytcr_rt5640.c which is:
8  *  Copyright (C) 2014-2020 Intel Corp
9  *  Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
10  */
11 
12 #include <linux/acpi.h>
13 #include <linux/clk.h>
14 #include <linux/device.h>
15 #include <linux/init.h>
16 #include <linux/module.h>
17 #include <linux/moduleparam.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
20 #include <linux/spi/spi.h>
21 #include <sound/pcm.h>
22 #include <sound/pcm_params.h>
23 #include <sound/soc.h>
24 #include <sound/soc-acpi.h>
25 #include "../../codecs/wm5102.h"
26 #include "../atom/sst-atom-controls.h"
27 
28 #define MCLK_FREQ		25000000
29 
30 #define WM5102_MAX_SYSCLK_4K	49152000 /* max sysclk for 4K family */
31 #define WM5102_MAX_SYSCLK_11025	45158400 /* max sysclk for 11.025K family */
32 
33 struct byt_wm5102_private {
34 	struct clk *mclk;
35 	struct gpio_desc *spkvdd_en_gpio;
36 };
37 
38 static int byt_wm5102_spkvdd_power_event(struct snd_soc_dapm_widget *w,
39 	struct snd_kcontrol *kcontrol, int event)
40 {
41 	struct snd_soc_card *card = w->dapm->card;
42 	struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
43 
44 	gpiod_set_value_cansleep(priv->spkvdd_en_gpio,
45 				 !!SND_SOC_DAPM_EVENT_ON(event));
46 
47 	return 0;
48 }
49 
50 static int byt_wm5102_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai, int rate)
51 {
52 	struct snd_soc_component *codec_component = codec_dai->component;
53 	int sr_mult = ((rate % 4000) == 0) ?
54 		(WM5102_MAX_SYSCLK_4K / rate) :
55 		(WM5102_MAX_SYSCLK_11025 / rate);
56 	int ret;
57 
58 	/* Reset FLL1 */
59 	snd_soc_dai_set_pll(codec_dai, WM5102_FLL1_REFCLK, ARIZONA_FLL_SRC_NONE, 0, 0);
60 	snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0);
61 
62 	/* Configure the FLL1 PLL before selecting it */
63 	ret = snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_CLK_SRC_MCLK1,
64 				  MCLK_FREQ, rate * sr_mult);
65 	if (ret) {
66 		dev_err(codec_component->dev, "Error setting PLL: %d\n", ret);
67 		return ret;
68 	}
69 
70 	ret = snd_soc_component_set_sysclk(codec_component, ARIZONA_CLK_SYSCLK,
71 					   ARIZONA_CLK_SRC_FLL1, rate * sr_mult,
72 					   SND_SOC_CLOCK_IN);
73 	if (ret) {
74 		dev_err(codec_component->dev, "Error setting SYSCLK: %d\n", ret);
75 		return ret;
76 	}
77 
78 	ret = snd_soc_dai_set_sysclk(codec_dai, ARIZONA_CLK_SYSCLK,
79 				     rate * 512, SND_SOC_CLOCK_IN);
80 	if (ret) {
81 		dev_err(codec_component->dev, "Error setting clock: %d\n", ret);
82 		return ret;
83 	}
84 
85 	return 0;
86 }
87 
88 static int platform_clock_control(struct snd_soc_dapm_widget *w,
89 				  struct snd_kcontrol *k, int event)
90 {
91 	struct snd_soc_dapm_context *dapm = w->dapm;
92 	struct snd_soc_card *card = dapm->card;
93 	struct snd_soc_dai *codec_dai;
94 	struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
95 	int ret;
96 
97 	codec_dai = snd_soc_card_get_codec_dai(card, "wm5102-aif1");
98 	if (!codec_dai) {
99 		dev_err(card->dev, "Error codec DAI not found\n");
100 		return -EIO;
101 	}
102 
103 	if (SND_SOC_DAPM_EVENT_ON(event)) {
104 		ret = clk_prepare_enable(priv->mclk);
105 		if (ret) {
106 			dev_err(card->dev, "Error enabling MCLK: %d\n", ret);
107 			return ret;
108 		}
109 		ret = byt_wm5102_prepare_and_enable_pll1(codec_dai, 48000);
110 		if (ret) {
111 			dev_err(card->dev, "Error setting codec sysclk: %d\n", ret);
112 			return ret;
113 		}
114 	} else {
115 		/*
116 		 * The WM5102 has a separate 32KHz clock for jack-detect
117 		 * so we can disable the PLL, followed by disabling the
118 		 * platform clock which is the source-clock for the PLL.
119 		 */
120 		snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0);
121 		clk_disable_unprepare(priv->mclk);
122 	}
123 
124 	return 0;
125 }
126 
127 static const struct snd_soc_dapm_widget byt_wm5102_widgets[] = {
128 	SND_SOC_DAPM_HP("Headphone", NULL),
129 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
130 	SND_SOC_DAPM_MIC("Internal Mic", NULL),
131 	SND_SOC_DAPM_SPK("Speaker", NULL),
132 	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
133 			    platform_clock_control, SND_SOC_DAPM_PRE_PMU |
134 			    SND_SOC_DAPM_POST_PMD),
135 	SND_SOC_DAPM_SUPPLY("Speaker VDD", SND_SOC_NOPM, 0, 0,
136 			    byt_wm5102_spkvdd_power_event,
137 			    SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
138 };
139 
140 static const struct snd_soc_dapm_route byt_wm5102_audio_map[] = {
141 	{"Headphone", NULL, "Platform Clock"},
142 	{"Headset Mic", NULL, "Platform Clock"},
143 	{"Internal Mic", NULL, "Platform Clock"},
144 	{"Speaker", NULL, "Platform Clock"},
145 
146 	{"Speaker", NULL, "SPKOUTLP"},
147 	{"Speaker", NULL, "SPKOUTLN"},
148 	{"Speaker", NULL, "SPKOUTRP"},
149 	{"Speaker", NULL, "SPKOUTRN"},
150 	{"Speaker", NULL, "Speaker VDD"},
151 
152 	{"Headphone", NULL, "HPOUT1L"},
153 	{"Headphone", NULL, "HPOUT1R"},
154 
155 	{"Internal Mic", NULL, "MICBIAS3"},
156 	{"IN3L", NULL, "Internal Mic"},
157 
158 	/*
159 	 * The Headset Mix uses MICBIAS1 or 2 depending on if a CTIA/OMTP Headset
160 	 * is connected, as the MICBIAS is applied after the CTIA/OMTP cross-switch.
161 	 */
162 	{"Headset Mic", NULL, "MICBIAS1"},
163 	{"Headset Mic", NULL, "MICBIAS2"},
164 	{"IN1L", NULL, "Headset Mic"},
165 
166 	{"AIF1 Playback", NULL, "ssp0 Tx"},
167 	{"ssp0 Tx", NULL, "modem_out"},
168 
169 	{"modem_in", NULL, "ssp0 Rx"},
170 	{"ssp0 Rx", NULL, "AIF1 Capture"},
171 };
172 
173 static const struct snd_kcontrol_new byt_wm5102_controls[] = {
174 	SOC_DAPM_PIN_SWITCH("Headphone"),
175 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
176 	SOC_DAPM_PIN_SWITCH("Internal Mic"),
177 	SOC_DAPM_PIN_SWITCH("Speaker"),
178 };
179 
180 static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime)
181 {
182 	struct snd_soc_card *card = runtime->card;
183 	struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
184 	int ret;
185 
186 	card->dapm.idle_bias_off = true;
187 
188 	ret = snd_soc_add_card_controls(card, byt_wm5102_controls,
189 					ARRAY_SIZE(byt_wm5102_controls));
190 	if (ret) {
191 		dev_err(card->dev, "Error adding card controls: %d\n", ret);
192 		return ret;
193 	}
194 
195 	/*
196 	 * The firmware might enable the clock at boot (this information
197 	 * may or may not be reflected in the enable clock register).
198 	 * To change the rate we must disable the clock first to cover these
199 	 * cases. Due to common clock framework restrictions that do not allow
200 	 * to disable a clock that has not been enabled, we need to enable
201 	 * the clock first.
202 	 */
203 	ret = clk_prepare_enable(priv->mclk);
204 	if (!ret)
205 		clk_disable_unprepare(priv->mclk);
206 
207 	ret = clk_set_rate(priv->mclk, MCLK_FREQ);
208 	if (ret) {
209 		dev_err(card->dev, "Error setting MCLK rate: %d\n", ret);
210 		return ret;
211 	}
212 
213 	return 0;
214 }
215 
216 static const struct snd_soc_pcm_stream byt_wm5102_dai_params = {
217 	.formats = SNDRV_PCM_FMTBIT_S16_LE,
218 	.rate_min = 48000,
219 	.rate_max = 48000,
220 	.channels_min = 2,
221 	.channels_max = 2,
222 };
223 
224 static int byt_wm5102_codec_fixup(struct snd_soc_pcm_runtime *rtd,
225 				  struct snd_pcm_hw_params *params)
226 {
227 	struct snd_interval *rate = hw_param_interval(params,
228 						      SNDRV_PCM_HW_PARAM_RATE);
229 	struct snd_interval *channels = hw_param_interval(params,
230 							  SNDRV_PCM_HW_PARAM_CHANNELS);
231 	int ret;
232 
233 	/* The DSP will covert the FE rate to 48k, stereo */
234 	rate->min = 48000;
235 	rate->max = 48000;
236 	channels->min = 2;
237 	channels->max = 2;
238 
239 	/* set SSP0 to 16-bit */
240 	params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
241 
242 	/*
243 	 * Default mode for SSP configuration is TDM 4 slot, override config
244 	 * with explicit setting to I2S 2ch 16-bit. The word length is set with
245 	 * dai_set_tdm_slot() since there is no other API exposed
246 	 */
247 	ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
248 				  SND_SOC_DAIFMT_I2S     |
249 				  SND_SOC_DAIFMT_NB_NF   |
250 				  SND_SOC_DAIFMT_CBS_CFS);
251 	if (ret) {
252 		dev_err(rtd->dev, "Error setting format to I2S: %d\n", ret);
253 		return ret;
254 	}
255 
256 	ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, 16);
257 	if (ret) {
258 		dev_err(rtd->dev, "Error setting I2S config: %d\n", ret);
259 		return ret;
260 	}
261 
262 	return 0;
263 }
264 
265 static int byt_wm5102_aif1_startup(struct snd_pcm_substream *substream)
266 {
267 	return snd_pcm_hw_constraint_single(substream->runtime,
268 					    SNDRV_PCM_HW_PARAM_RATE, 48000);
269 }
270 
271 static const struct snd_soc_ops byt_wm5102_aif1_ops = {
272 	.startup = byt_wm5102_aif1_startup,
273 };
274 
275 SND_SOC_DAILINK_DEF(dummy,
276 	DAILINK_COMP_ARRAY(COMP_DUMMY()));
277 
278 SND_SOC_DAILINK_DEF(media,
279 	DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
280 
281 SND_SOC_DAILINK_DEF(deepbuffer,
282 	DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
283 
284 SND_SOC_DAILINK_DEF(ssp0_port,
285 	DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port")));
286 
287 SND_SOC_DAILINK_DEF(ssp0_codec,
288 	DAILINK_COMP_ARRAY(COMP_CODEC(
289 	/*
290 	 * Note there is no need to overwrite the codec-name as is done in
291 	 * other bytcr machine drivers, because the codec is a MFD child-dev.
292 	 */
293 	"wm5102-codec",
294 	"wm5102-aif1")));
295 
296 SND_SOC_DAILINK_DEF(platform,
297 	DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
298 
299 static struct snd_soc_dai_link byt_wm5102_dais[] = {
300 	[MERR_DPCM_AUDIO] = {
301 		.name = "Baytrail Audio Port",
302 		.stream_name = "Baytrail Audio",
303 		.nonatomic = true,
304 		.dynamic = 1,
305 		.dpcm_playback = 1,
306 		.dpcm_capture = 1,
307 		.ops = &byt_wm5102_aif1_ops,
308 		SND_SOC_DAILINK_REG(media, dummy, platform),
309 
310 	},
311 	[MERR_DPCM_DEEP_BUFFER] = {
312 		.name = "Deep-Buffer Audio Port",
313 		.stream_name = "Deep-Buffer Audio",
314 		.nonatomic = true,
315 		.dynamic = 1,
316 		.dpcm_playback = 1,
317 		.ops = &byt_wm5102_aif1_ops,
318 		SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
319 	},
320 		/* back ends */
321 	{
322 		/*
323 		 * This must be named SSP2-Codec even though this machine driver
324 		 * always uses SSP0. Most machine drivers support both and dynamically
325 		 * update the dailink to point to SSP0 or SSP2, while keeping the name
326 		 * as "SSP2-Codec". The SOF tplg files hardcode the "SSP2-Codec" even
327 		 * in the byt-foo-ssp0.tplg versions because the other machine-drivers
328 		 * use "SSP2-Codec" even when SSP0 is used.
329 		 */
330 		.name = "SSP2-Codec",
331 		.id = 0,
332 		.no_pcm = 1,
333 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
334 						| SND_SOC_DAIFMT_CBS_CFS,
335 		.be_hw_params_fixup = byt_wm5102_codec_fixup,
336 		.nonatomic = true,
337 		.dpcm_playback = 1,
338 		.dpcm_capture = 1,
339 		.init = byt_wm5102_init,
340 		SND_SOC_DAILINK_REG(ssp0_port, ssp0_codec, platform),
341 	},
342 };
343 
344 /* use space before codec name to simplify card ID, and simplify driver name */
345 #define SOF_CARD_NAME "bytcht wm5102" /* card name will be 'sof-bytcht wm5102' */
346 #define SOF_DRIVER_NAME "SOF"
347 
348 #define CARD_NAME "bytcr-wm5102"
349 #define DRIVER_NAME NULL /* card name will be used for driver name */
350 
351 /* SoC card */
352 static struct snd_soc_card byt_wm5102_card = {
353 	.owner = THIS_MODULE,
354 	.dai_link = byt_wm5102_dais,
355 	.num_links = ARRAY_SIZE(byt_wm5102_dais),
356 	.dapm_widgets = byt_wm5102_widgets,
357 	.num_dapm_widgets = ARRAY_SIZE(byt_wm5102_widgets),
358 	.dapm_routes = byt_wm5102_audio_map,
359 	.num_dapm_routes = ARRAY_SIZE(byt_wm5102_audio_map),
360 	.fully_routed = true,
361 };
362 
363 static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
364 {
365 	char codec_name[SND_ACPI_I2C_ID_LEN];
366 	struct device *dev = &pdev->dev;
367 	struct byt_wm5102_private *priv;
368 	struct snd_soc_acpi_mach *mach;
369 	const char *platform_name;
370 	struct acpi_device *adev;
371 	struct device *codec_dev;
372 	bool sof_parent;
373 	int ret;
374 
375 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_ATOMIC);
376 	if (!priv)
377 		return -ENOMEM;
378 
379 	/* Get MCLK */
380 	priv->mclk = devm_clk_get(dev, "pmc_plt_clk_3");
381 	if (IS_ERR(priv->mclk))
382 		return dev_err_probe(dev, PTR_ERR(priv->mclk), "getting pmc_plt_clk_3\n");
383 
384 	/*
385 	 * Get speaker VDD enable GPIO:
386 	 * 1. Get codec-device-name
387 	 * 2. Get codec-device
388 	 * 3. Get GPIO from codec-device
389 	 */
390 	mach = dev->platform_data;
391 	adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
392 	if (!adev) {
393 		dev_err(dev, "Error cannot find acpi-dev for codec\n");
394 		return -ENOENT;
395 	}
396 	snprintf(codec_name, sizeof(codec_name), "spi-%s", acpi_dev_name(adev));
397 	put_device(&adev->dev);
398 
399 	codec_dev = bus_find_device_by_name(&spi_bus_type, NULL, codec_name);
400 	if (!codec_dev)
401 		return -EPROBE_DEFER;
402 
403 	/* Note no devm_ here since we call gpiod_get on codec_dev rather then dev */
404 	priv->spkvdd_en_gpio = gpiod_get(codec_dev, "wlf,spkvdd-ena", GPIOD_OUT_LOW);
405 	put_device(codec_dev);
406 
407 	if (IS_ERR(priv->spkvdd_en_gpio))
408 		return dev_err_probe(dev, PTR_ERR(priv->spkvdd_en_gpio), "getting spkvdd-GPIO\n");
409 
410 	/* override platform name, if required */
411 	byt_wm5102_card.dev = dev;
412 	platform_name = mach->mach_params.platform;
413 	ret = snd_soc_fixup_dai_links_platform_name(&byt_wm5102_card, platform_name);
414 	if (ret)
415 		goto out_put_gpio;
416 
417 	/* set card and driver name and pm-ops */
418 	sof_parent = snd_soc_acpi_sof_parent(dev);
419 	if (sof_parent) {
420 		byt_wm5102_card.name = SOF_CARD_NAME;
421 		byt_wm5102_card.driver_name = SOF_DRIVER_NAME;
422 		dev->driver->pm = &snd_soc_pm_ops;
423 	} else {
424 		byt_wm5102_card.name = CARD_NAME;
425 		byt_wm5102_card.driver_name = DRIVER_NAME;
426 	}
427 
428 	snd_soc_card_set_drvdata(&byt_wm5102_card, priv);
429 	ret = devm_snd_soc_register_card(dev, &byt_wm5102_card);
430 	if (ret) {
431 		dev_err_probe(dev, ret, "registering card\n");
432 		goto out_put_gpio;
433 	}
434 
435 	platform_set_drvdata(pdev, &byt_wm5102_card);
436 	return 0;
437 
438 out_put_gpio:
439 	gpiod_put(priv->spkvdd_en_gpio);
440 	return ret;
441 }
442 
443 static int snd_byt_wm5102_mc_remove(struct platform_device *pdev)
444 {
445 	struct snd_soc_card *card = platform_get_drvdata(pdev);
446 	struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
447 
448 	gpiod_put(priv->spkvdd_en_gpio);
449 	return 0;
450 }
451 
452 static struct platform_driver snd_byt_wm5102_mc_driver = {
453 	.driver = {
454 		.name = "bytcr_wm5102",
455 	},
456 	.probe = snd_byt_wm5102_mc_probe,
457 	.remove = snd_byt_wm5102_mc_remove,
458 };
459 
460 module_platform_driver(snd_byt_wm5102_mc_driver);
461 
462 MODULE_DESCRIPTION("ASoC Baytrail with WM5102 codec machine driver");
463 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
464 MODULE_LICENSE("GPL v2");
465 MODULE_ALIAS("platform:bytcr_wm5102");
466