kernel: clean up patch fuzz
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.4 / 950-0072-ASoC-Add-driver-for-Cirrus-Logic-Audio-Card.patch
1 From 759d6a02f75342beff69ec1c07389a151a1cacd2 Mon Sep 17 00:00:00 2001
2 From: Matthias Reichl <hias@horus.com>
3 Date: Sun, 22 Jan 2017 12:49:37 +0100
4 Subject: [PATCH] ASoC: Add driver for Cirrus Logic Audio Card
5
6 Note: due to problems with deferred probing of regulators
7 the following softdep should be added to a modprobe.d file
8
9 softdep arizona-spi pre: arizona-ldo1
10
11 Signed-off-by: Matthias Reichl <hias@horus.com>
12
13 ASoC: rpi-cirrus: use modern dai_link style
14
15 Signed-off-by: Matthias Reichl <hias@horus.com>
16 ---
17 sound/soc/bcm/rpi-cirrus.c | 1035 ++++++++++++++++++++++++++++++++++++
18 1 file changed, 1035 insertions(+)
19 create mode 100644 sound/soc/bcm/rpi-cirrus.c
20
21 --- /dev/null
22 +++ b/sound/soc/bcm/rpi-cirrus.c
23 @@ -0,0 +1,1035 @@
24 +/*
25 + * ASoC machine driver for Cirrus Logic Audio Card
26 + * (with WM5102 and WM8804 codecs)
27 + *
28 + * Copyright 2015-2017 Matthias Reichl <hias@horus.com>
29 + *
30 + * Based on rpi-cirrus-sound-pi driver (c) Wolfson / Cirrus Logic Inc.
31 + *
32 + * This program is free software; you can redistribute it and/or modify
33 + * it under the terms of the GNU General Public License version 2 as
34 + * published by the Free Software Foundation.
35 + */
36 +
37 +#include <linux/module.h>
38 +#include <linux/mutex.h>
39 +#include <linux/slab.h>
40 +#include <linux/list.h>
41 +#include <linux/delay.h>
42 +#include <sound/pcm_params.h>
43 +
44 +#include <linux/mfd/arizona/registers.h>
45 +
46 +#include "../codecs/wm5102.h"
47 +#include "../codecs/wm8804.h"
48 +
49 +#define WM8804_CLKOUT_HZ 12000000
50 +
51 +#define RPI_CIRRUS_DEFAULT_RATE 44100
52 +#define WM5102_MAX_SYSCLK_1 49152000 /* max sysclk for 4K family */
53 +#define WM5102_MAX_SYSCLK_2 45158400 /* max sysclk for 11.025K family */
54 +
55 +static inline unsigned int calc_sysclk(unsigned int rate)
56 +{
57 + return (rate % 4000) ? WM5102_MAX_SYSCLK_2 : WM5102_MAX_SYSCLK_1;
58 +}
59 +
60 +enum {
61 + DAI_WM5102 = 0,
62 + DAI_WM8804,
63 +};
64 +
65 +struct rpi_cirrus_priv {
66 + /* mutex for synchronzing FLL1 access with DAPM */
67 + struct mutex lock;
68 + unsigned int card_rate;
69 + int sync_path_enable;
70 + int fll1_freq; /* negative means RefClock in spdif rx case */
71 +
72 + /* track hw params/free for substreams */
73 + unsigned int params_set;
74 + unsigned int min_rate_idx, max_rate_idx;
75 + unsigned char iec958_status[4];
76 +};
77 +
78 +/* helper functions */
79 +static inline struct snd_soc_pcm_runtime *get_wm5102_runtime(
80 + struct snd_soc_card *card) {
81 + return snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM5102].name);
82 +}
83 +
84 +static inline struct snd_soc_pcm_runtime *get_wm8804_runtime(
85 + struct snd_soc_card *card) {
86 + return snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM8804].name);
87 +}
88 +
89 +
90 +struct rate_info {
91 + unsigned int value;
92 + char *text;
93 +};
94 +
95 +static struct rate_info min_rates[] = {
96 + { 0, "off"},
97 + { 32000, "32kHz"},
98 + { 44100, "44.1kHz"}
99 +};
100 +
101 +#define NUM_MIN_RATES ARRAY_SIZE(min_rates)
102 +
103 +static int rpi_cirrus_min_rate_info(struct snd_kcontrol *kcontrol,
104 + struct snd_ctl_elem_info *uinfo)
105 +{
106 + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
107 + uinfo->count = 1;
108 + uinfo->value.enumerated.items = NUM_MIN_RATES;
109 +
110 + if (uinfo->value.enumerated.item >= NUM_MIN_RATES)
111 + uinfo->value.enumerated.item = NUM_MIN_RATES - 1;
112 + strcpy(uinfo->value.enumerated.name,
113 + min_rates[uinfo->value.enumerated.item].text);
114 + return 0;
115 +}
116 +
117 +static int rpi_cirrus_min_rate_get(struct snd_kcontrol *kcontrol,
118 + struct snd_ctl_elem_value *ucontrol)
119 +{
120 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
121 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
122 +
123 + ucontrol->value.enumerated.item[0] = priv->min_rate_idx;
124 + return 0;
125 +}
126 +
127 +static int rpi_cirrus_min_rate_put(struct snd_kcontrol *kcontrol,
128 + struct snd_ctl_elem_value *ucontrol)
129 +{
130 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
131 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
132 + int changed = 0;
133 +
134 + if (priv->min_rate_idx != ucontrol->value.enumerated.item[0]) {
135 + changed = 1;
136 + priv->min_rate_idx = ucontrol->value.enumerated.item[0];
137 + }
138 +
139 + return changed;
140 +}
141 +
142 +static struct rate_info max_rates[] = {
143 + { 0, "off"},
144 + { 48000, "48kHz"},
145 + { 96000, "96kHz"}
146 +};
147 +
148 +#define NUM_MAX_RATES ARRAY_SIZE(max_rates)
149 +
150 +static int rpi_cirrus_max_rate_info(struct snd_kcontrol *kcontrol,
151 + struct snd_ctl_elem_info *uinfo)
152 +{
153 + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
154 + uinfo->count = 1;
155 + uinfo->value.enumerated.items = NUM_MAX_RATES;
156 + if (uinfo->value.enumerated.item >= NUM_MAX_RATES)
157 + uinfo->value.enumerated.item = NUM_MAX_RATES - 1;
158 + strcpy(uinfo->value.enumerated.name,
159 + max_rates[uinfo->value.enumerated.item].text);
160 + return 0;
161 +}
162 +
163 +static int rpi_cirrus_max_rate_get(struct snd_kcontrol *kcontrol,
164 + struct snd_ctl_elem_value *ucontrol)
165 +{
166 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
167 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
168 +
169 + ucontrol->value.enumerated.item[0] = priv->max_rate_idx;
170 + return 0;
171 +}
172 +
173 +static int rpi_cirrus_max_rate_put(struct snd_kcontrol *kcontrol,
174 + struct snd_ctl_elem_value *ucontrol)
175 +{
176 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
177 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
178 + int changed = 0;
179 +
180 + if (priv->max_rate_idx != ucontrol->value.enumerated.item[0]) {
181 + changed = 1;
182 + priv->max_rate_idx = ucontrol->value.enumerated.item[0];
183 + }
184 +
185 + return changed;
186 +}
187 +
188 +static int rpi_cirrus_spdif_info(struct snd_kcontrol *kcontrol,
189 + struct snd_ctl_elem_info *uinfo)
190 +{
191 + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
192 + uinfo->count = 1;
193 + return 0;
194 +}
195 +
196 +static int rpi_cirrus_spdif_playback_get(struct snd_kcontrol *kcontrol,
197 + struct snd_ctl_elem_value *ucontrol)
198 +{
199 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
200 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
201 + int i;
202 +
203 + for (i = 0; i < 4; i++)
204 + ucontrol->value.iec958.status[i] = priv->iec958_status[i];
205 +
206 + return 0;
207 +}
208 +
209 +static int rpi_cirrus_spdif_playback_put(struct snd_kcontrol *kcontrol,
210 + struct snd_ctl_elem_value *ucontrol)
211 +{
212 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
213 + struct snd_soc_component *wm8804_component =
214 + get_wm8804_runtime(card)->codec_dai->component;
215 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
216 + unsigned char *stat = priv->iec958_status;
217 + unsigned char *ctrl_stat = ucontrol->value.iec958.status;
218 + unsigned int mask;
219 + int i, changed = 0;
220 +
221 + for (i = 0; i < 4; i++) {
222 + mask = (i == 3) ? 0x3f : 0xff;
223 + if ((ctrl_stat[i] & mask) != (stat[i] & mask)) {
224 + changed = 1;
225 + stat[i] = ctrl_stat[i] & mask;
226 + snd_soc_component_update_bits(wm8804_component,
227 + WM8804_SPDTX1 + i, mask, stat[i]);
228 + }
229 + }
230 +
231 + return changed;
232 +}
233 +
234 +static int rpi_cirrus_spdif_mask_get(struct snd_kcontrol *kcontrol,
235 + struct snd_ctl_elem_value *ucontrol)
236 +{
237 + ucontrol->value.iec958.status[0] = 0xff;
238 + ucontrol->value.iec958.status[1] = 0xff;
239 + ucontrol->value.iec958.status[2] = 0xff;
240 + ucontrol->value.iec958.status[3] = 0x3f;
241 +
242 + return 0;
243 +}
244 +
245 +static int rpi_cirrus_spdif_capture_get(struct snd_kcontrol *kcontrol,
246 + struct snd_ctl_elem_value *ucontrol)
247 +{
248 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
249 + struct snd_soc_component *wm8804_component =
250 + get_wm8804_runtime(card)->codec_dai->component;
251 + unsigned int val, mask;
252 + int i, ret;
253 +
254 + for (i = 0; i < 4; i++) {
255 + ret = snd_soc_component_read(wm8804_component,
256 + WM8804_RXCHAN1 + i, &val);
257 + if (ret)
258 + return ret;
259 + mask = (i == 3) ? 0x3f : 0xff;
260 + ucontrol->value.iec958.status[i] = val & mask;
261 + }
262 +
263 + return 0;
264 +}
265 +
266 +#define SPDIF_FLAG_CTRL(desc, reg, bit, invert) \
267 +{ \
268 + .access = SNDRV_CTL_ELEM_ACCESS_READ \
269 + | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
270 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
271 + .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) \
272 + desc " Flag", \
273 + .info = snd_ctl_boolean_mono_info, \
274 + .get = rpi_cirrus_spdif_status_flag_get, \
275 + .private_value = \
276 + (bit) | ((reg) << 8) | ((invert) << 16) \
277 +}
278 +
279 +static int rpi_cirrus_spdif_status_flag_get(struct snd_kcontrol *kcontrol,
280 + struct snd_ctl_elem_value *ucontrol)
281 +{
282 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
283 + struct snd_soc_component *wm8804_component =
284 + get_wm8804_runtime(card)->codec_dai->component;
285 +
286 + unsigned int bit = kcontrol->private_value & 0xff;
287 + unsigned int reg = (kcontrol->private_value >> 8) & 0xff;
288 + unsigned int invert = (kcontrol->private_value >> 16) & 0xff;
289 + int ret;
290 + unsigned int val;
291 + bool flag;
292 +
293 + ret = snd_soc_component_read(wm8804_component, reg, &val);
294 + if (ret)
295 + return ret;
296 +
297 + flag = val & (1 << bit);
298 +
299 + ucontrol->value.integer.value[0] = invert ? !flag : flag;
300 +
301 + return 0;
302 +}
303 +
304 +static const char * const recovered_frequency_texts[] = {
305 + "176.4/192 kHz",
306 + "88.2/96 kHz",
307 + "44.1/48 kHz",
308 + "32 kHz"
309 +};
310 +
311 +#define NUM_RECOVERED_FREQUENCIES \
312 + ARRAY_SIZE(recovered_frequency_texts)
313 +
314 +static int rpi_cirrus_recovered_frequency_info(struct snd_kcontrol *kcontrol,
315 + struct snd_ctl_elem_info *uinfo)
316 +{
317 + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
318 + uinfo->count = 1;
319 + uinfo->value.enumerated.items = NUM_RECOVERED_FREQUENCIES;
320 + if (uinfo->value.enumerated.item >= NUM_RECOVERED_FREQUENCIES)
321 + uinfo->value.enumerated.item = NUM_RECOVERED_FREQUENCIES - 1;
322 + strcpy(uinfo->value.enumerated.name,
323 + recovered_frequency_texts[uinfo->value.enumerated.item]);
324 + return 0;
325 +}
326 +
327 +static int rpi_cirrus_recovered_frequency_get(struct snd_kcontrol *kcontrol,
328 + struct snd_ctl_elem_value *ucontrol)
329 +{
330 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
331 + struct snd_soc_component *wm8804_component =
332 + get_wm8804_runtime(card)->codec_dai->component;
333 + unsigned int val;
334 + int ret;
335 +
336 + ret = snd_soc_component_read(wm8804_component, WM8804_SPDSTAT, &val);
337 + if (ret)
338 + return ret;
339 +
340 + ucontrol->value.enumerated.item[0] = (val >> 4) & 0x03;
341 + return 0;
342 +}
343 +
344 +static const struct snd_kcontrol_new rpi_cirrus_controls[] = {
345 + {
346 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
347 + .name = "Min Sample Rate",
348 + .info = rpi_cirrus_min_rate_info,
349 + .get = rpi_cirrus_min_rate_get,
350 + .put = rpi_cirrus_min_rate_put,
351 + },
352 + {
353 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
354 + .name = "Max Sample Rate",
355 + .info = rpi_cirrus_max_rate_info,
356 + .get = rpi_cirrus_max_rate_get,
357 + .put = rpi_cirrus_max_rate_put,
358 + },
359 + {
360 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
361 + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
362 + .info = rpi_cirrus_spdif_info,
363 + .get = rpi_cirrus_spdif_playback_get,
364 + .put = rpi_cirrus_spdif_playback_put,
365 + },
366 + {
367 + .access = SNDRV_CTL_ELEM_ACCESS_READ
368 + | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
369 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
370 + .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
371 + .info = rpi_cirrus_spdif_info,
372 + .get = rpi_cirrus_spdif_capture_get,
373 + },
374 + {
375 + .access = SNDRV_CTL_ELEM_ACCESS_READ,
376 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
377 + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
378 + .info = rpi_cirrus_spdif_info,
379 + .get = rpi_cirrus_spdif_mask_get,
380 + },
381 + {
382 + .access = SNDRV_CTL_ELEM_ACCESS_READ
383 + | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
384 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
385 + .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE)
386 + "Recovered Frequency",
387 + .info = rpi_cirrus_recovered_frequency_info,
388 + .get = rpi_cirrus_recovered_frequency_get,
389 + },
390 + SPDIF_FLAG_CTRL("Audio", WM8804_SPDSTAT, 0, 1),
391 + SPDIF_FLAG_CTRL("Non-PCM", WM8804_SPDSTAT, 1, 0),
392 + SPDIF_FLAG_CTRL("Copyright", WM8804_SPDSTAT, 2, 1),
393 + SPDIF_FLAG_CTRL("De-Emphasis", WM8804_SPDSTAT, 3, 0),
394 + SPDIF_FLAG_CTRL("Lock", WM8804_SPDSTAT, 6, 1),
395 + SPDIF_FLAG_CTRL("Invalid", WM8804_INTSTAT, 1, 0),
396 + SPDIF_FLAG_CTRL("TransErr", WM8804_INTSTAT, 3, 0),
397 +};
398 +
399 +static const char * const linein_micbias_texts[] = {
400 + "off", "on",
401 +};
402 +
403 +static SOC_ENUM_SINGLE_VIRT_DECL(linein_micbias_enum,
404 + linein_micbias_texts);
405 +
406 +static const struct snd_kcontrol_new linein_micbias_mux =
407 + SOC_DAPM_ENUM("Route", linein_micbias_enum);
408 +
409 +static int rpi_cirrus_spdif_rx_enable_event(struct snd_soc_dapm_widget *w,
410 + struct snd_kcontrol *kcontrol, int event);
411 +
412 +const struct snd_soc_dapm_widget rpi_cirrus_dapm_widgets[] = {
413 + SND_SOC_DAPM_MIC("DMIC", NULL),
414 + SND_SOC_DAPM_MIC("Headset Mic", NULL),
415 + SND_SOC_DAPM_INPUT("Line Input"),
416 + SND_SOC_DAPM_MIC("Line Input with Micbias", NULL),
417 + SND_SOC_DAPM_MUX("Line Input Micbias", SND_SOC_NOPM, 0, 0,
418 + &linein_micbias_mux),
419 + SND_SOC_DAPM_INPUT("dummy SPDIF in"),
420 + SND_SOC_DAPM_PGA_E("dummy SPDIFRX", SND_SOC_NOPM, 0, 0, NULL, 0,
421 + rpi_cirrus_spdif_rx_enable_event,
422 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
423 + SND_SOC_DAPM_INPUT("Dummy Input"),
424 + SND_SOC_DAPM_OUTPUT("Dummy Output"),
425 +};
426 +
427 +const struct snd_soc_dapm_route rpi_cirrus_dapm_routes[] = {
428 + { "IN1L", NULL, "Headset Mic" },
429 + { "IN1R", NULL, "Headset Mic" },
430 + { "Headset Mic", NULL, "MICBIAS1" },
431 +
432 + { "IN2L", NULL, "DMIC" },
433 + { "IN2R", NULL, "DMIC" },
434 + { "DMIC", NULL, "MICBIAS2" },
435 +
436 + { "IN3L", NULL, "Line Input Micbias" },
437 + { "IN3R", NULL, "Line Input Micbias" },
438 +
439 + { "Line Input Micbias", "off", "Line Input" },
440 + { "Line Input Micbias", "on", "Line Input with Micbias" },
441 +
442 + /* Make sure MICVDD is enabled, otherwise we get noise */
443 + { "Line Input", NULL, "MICVDD" },
444 + { "Line Input with Micbias", NULL, "MICBIAS3" },
445 +
446 + /* Dummy routes to check whether SPDIF RX is enabled or not */
447 + {"dummy SPDIFRX", NULL, "dummy SPDIF in"},
448 + {"AIFTX", NULL, "dummy SPDIFRX"},
449 +
450 + /*
451 + * Dummy routes to keep wm5102 from staying off on
452 + * playback/capture if all mixers are off.
453 + */
454 + { "Dummy Output", NULL, "AIF1RX1" },
455 + { "Dummy Output", NULL, "AIF1RX2" },
456 + { "AIF1TX1", NULL, "Dummy Input" },
457 + { "AIF1TX2", NULL, "Dummy Input" },
458 +};
459 +
460 +static int rpi_cirrus_clear_flls(struct snd_soc_card *card,
461 + struct snd_soc_component *wm5102_component) {
462 +
463 + int ret1, ret2;
464 +
465 + ret1 = snd_soc_component_set_pll(wm5102_component,
466 + WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0);
467 + ret2 = snd_soc_component_set_pll(wm5102_component,
468 + WM5102_FLL1_REFCLK, ARIZONA_FLL_SRC_NONE, 0, 0);
469 +
470 + if (ret1) {
471 + dev_warn(card->dev,
472 + "setting FLL1 to zero failed: %d\n", ret1);
473 + return ret1;
474 + }
475 + if (ret2) {
476 + dev_warn(card->dev,
477 + "setting FLL1_REFCLK to zero failed: %d\n", ret2);
478 + return ret2;
479 + }
480 + return 0;
481 +}
482 +
483 +static int rpi_cirrus_set_fll(struct snd_soc_card *card,
484 + struct snd_soc_component *wm5102_component, unsigned int clk_freq)
485 +{
486 + int ret = snd_soc_component_set_pll(wm5102_component,
487 + WM5102_FLL1,
488 + ARIZONA_CLK_SRC_MCLK1,
489 + WM8804_CLKOUT_HZ,
490 + clk_freq);
491 + if (ret)
492 + dev_err(card->dev, "Failed to set FLL1 to %d: %d\n",
493 + clk_freq, ret);
494 +
495 + usleep_range(1000, 2000);
496 + return ret;
497 +}
498 +
499 +static int rpi_cirrus_set_fll_refclk(struct snd_soc_card *card,
500 + struct snd_soc_component *wm5102_component,
501 + unsigned int clk_freq, unsigned int aif2_freq)
502 +{
503 + int ret = snd_soc_component_set_pll(wm5102_component,
504 + WM5102_FLL1_REFCLK,
505 + ARIZONA_CLK_SRC_MCLK1,
506 + WM8804_CLKOUT_HZ,
507 + clk_freq);
508 + if (ret) {
509 + dev_err(card->dev,
510 + "Failed to set FLL1_REFCLK to %d: %d\n",
511 + clk_freq, ret);
512 + return ret;
513 + }
514 +
515 + ret = snd_soc_component_set_pll(wm5102_component,
516 + WM5102_FLL1,
517 + ARIZONA_CLK_SRC_AIF2BCLK,
518 + aif2_freq, clk_freq);
519 + if (ret)
520 + dev_err(card->dev,
521 + "Failed to set FLL1 with Sync Clock %d to %d: %d\n",
522 + aif2_freq, clk_freq, ret);
523 +
524 + usleep_range(1000, 2000);
525 + return ret;
526 +}
527 +
528 +static int rpi_cirrus_spdif_rx_enable_event(struct snd_soc_dapm_widget *w,
529 + struct snd_kcontrol *kcontrol, int event)
530 +{
531 + struct snd_soc_card *card = w->dapm->card;
532 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
533 + struct snd_soc_component *wm5102_component =
534 + get_wm5102_runtime(card)->codec_dai->component;
535 +
536 + unsigned int clk_freq, aif2_freq;
537 + int ret = 0;
538 +
539 + switch (event) {
540 + case SND_SOC_DAPM_POST_PMU:
541 + mutex_lock(&priv->lock);
542 +
543 + /* Enable sync path in case of SPDIF capture use case */
544 +
545 + clk_freq = calc_sysclk(priv->card_rate);
546 + aif2_freq = 64 * priv->card_rate;
547 +
548 + dev_dbg(card->dev,
549 + "spdif_rx: changing FLL1 to use Ref Clock clk: %d spdif: %d\n",
550 + clk_freq, aif2_freq);
551 +
552 + ret = rpi_cirrus_clear_flls(card, wm5102_component);
553 + if (ret) {
554 + dev_err(card->dev, "spdif_rx: failed to clear FLLs\n");
555 + goto out;
556 + }
557 +
558 + ret = rpi_cirrus_set_fll_refclk(card, wm5102_component,
559 + clk_freq, aif2_freq);
560 +
561 + if (ret) {
562 + dev_err(card->dev, "spdif_rx: failed to set FLLs\n");
563 + goto out;
564 + }
565 +
566 + /* set to negative to indicate we're doing spdif rx */
567 + priv->fll1_freq = -clk_freq;
568 + priv->sync_path_enable = 1;
569 + break;
570 +
571 + case SND_SOC_DAPM_POST_PMD:
572 + mutex_lock(&priv->lock);
573 + priv->sync_path_enable = 0;
574 + break;
575 +
576 + default:
577 + return 0;
578 + }
579 +
580 +out:
581 + mutex_unlock(&priv->lock);
582 + return ret;
583 +}
584 +
585 +static int rpi_cirrus_set_bias_level(struct snd_soc_card *card,
586 + struct snd_soc_dapm_context *dapm,
587 + enum snd_soc_bias_level level)
588 +{
589 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
590 + struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card);
591 + struct snd_soc_component *wm5102_component =
592 + wm5102_runtime->codec_dai->component;
593 +
594 + int ret = 0;
595 + unsigned int clk_freq;
596 +
597 + if (dapm->dev != wm5102_runtime->codec_dai->dev)
598 + return 0;
599 +
600 + switch (level) {
601 + case SND_SOC_BIAS_PREPARE:
602 + if (dapm->bias_level == SND_SOC_BIAS_ON)
603 + break;
604 +
605 + mutex_lock(&priv->lock);
606 +
607 + if (!priv->sync_path_enable) {
608 + clk_freq = calc_sysclk(priv->card_rate);
609 +
610 + dev_dbg(card->dev,
611 + "set_bias: changing FLL1 from %d to %d\n",
612 + priv->fll1_freq, clk_freq);
613 +
614 + ret = rpi_cirrus_set_fll(card,
615 + wm5102_component, clk_freq);
616 + if (ret)
617 + dev_err(card->dev,
618 + "set_bias: Failed to set FLL1\n");
619 + else
620 + priv->fll1_freq = clk_freq;
621 + }
622 + mutex_unlock(&priv->lock);
623 + break;
624 + default:
625 + break;
626 + }
627 +
628 + return ret;
629 +}
630 +
631 +static int rpi_cirrus_set_bias_level_post(struct snd_soc_card *card,
632 + struct snd_soc_dapm_context *dapm,
633 + enum snd_soc_bias_level level)
634 +{
635 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
636 + struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card);
637 + struct snd_soc_component *wm5102_component =
638 + wm5102_runtime->codec_dai->component;
639 +
640 + if (dapm->dev != wm5102_runtime->codec_dai->dev)
641 + return 0;
642 +
643 + switch (level) {
644 + case SND_SOC_BIAS_STANDBY:
645 + mutex_lock(&priv->lock);
646 +
647 + dev_dbg(card->dev,
648 + "set_bias_post: changing FLL1 from %d to off\n",
649 + priv->fll1_freq);
650 +
651 + if (rpi_cirrus_clear_flls(card, wm5102_component))
652 + dev_err(card->dev,
653 + "set_bias_post: failed to clear FLLs\n");
654 + else
655 + priv->fll1_freq = 0;
656 +
657 + mutex_unlock(&priv->lock);
658 +
659 + break;
660 + default:
661 + break;
662 + }
663 +
664 + return 0;
665 +}
666 +
667 +static int rpi_cirrus_set_wm8804_pll(struct snd_soc_card *card,
668 + struct snd_soc_dai *wm8804_dai, unsigned int rate)
669 +{
670 + int ret;
671 +
672 + /* use 256fs */
673 + unsigned int clk_freq = rate * 256;
674 +
675 + ret = snd_soc_dai_set_pll(wm8804_dai, 0, 0,
676 + WM8804_CLKOUT_HZ, clk_freq);
677 + if (ret) {
678 + dev_err(card->dev,
679 + "Failed to set WM8804 PLL to %d: %d\n", clk_freq, ret);
680 + return ret;
681 + }
682 +
683 + /* Set MCLK as PLL Output */
684 + ret = snd_soc_dai_set_sysclk(wm8804_dai,
685 + WM8804_TX_CLKSRC_PLL, clk_freq, 0);
686 + if (ret) {
687 + dev_err(card->dev,
688 + "Failed to set MCLK as PLL Output: %d\n", ret);
689 + return ret;
690 + }
691 +
692 + return ret;
693 +}
694 +
695 +static int rpi_cirrus_startup(struct snd_pcm_substream *substream)
696 +{
697 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
698 + struct snd_soc_card *card = rtd->card;
699 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
700 + unsigned int min_rate = min_rates[priv->min_rate_idx].value;
701 + unsigned int max_rate = max_rates[priv->max_rate_idx].value;
702 +
703 + if (min_rate || max_rate) {
704 + if (max_rate == 0)
705 + max_rate = UINT_MAX;
706 +
707 + dev_dbg(card->dev,
708 + "startup: limiting rate to %u-%u\n",
709 + min_rate, max_rate);
710 +
711 + snd_pcm_hw_constraint_minmax(substream->runtime,
712 + SNDRV_PCM_HW_PARAM_RATE, min_rate, max_rate);
713 + }
714 +
715 + return 0;
716 +}
717 +
718 +static struct snd_soc_pcm_stream rpi_cirrus_dai_link2_params = {
719 + .formats = SNDRV_PCM_FMTBIT_S24_LE,
720 + .channels_min = 2,
721 + .channels_max = 2,
722 + .rate_min = RPI_CIRRUS_DEFAULT_RATE,
723 + .rate_max = RPI_CIRRUS_DEFAULT_RATE,
724 +};
725 +
726 +static int rpi_cirrus_hw_params(struct snd_pcm_substream *substream,
727 + struct snd_pcm_hw_params *params)
728 +{
729 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
730 + struct snd_soc_card *card = rtd->card;
731 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
732 + struct snd_soc_dai *bcm_i2s_dai = rtd->cpu_dai;
733 + struct snd_soc_component *wm5102_component = rtd->codec_dai->component;
734 + struct snd_soc_dai *wm8804_dai = get_wm8804_runtime(card)->codec_dai;
735 +
736 + int ret;
737 +
738 + unsigned int width = snd_pcm_format_physical_width(
739 + params_format(params));
740 + unsigned int rate = params_rate(params);
741 + unsigned int clk_freq = calc_sysclk(rate);
742 +
743 + mutex_lock(&priv->lock);
744 +
745 + dev_dbg(card->dev, "hw_params: setting rate to %d\n", rate);
746 +
747 + ret = snd_soc_dai_set_bclk_ratio(bcm_i2s_dai, 2 * width);
748 + if (ret) {
749 + dev_err(card->dev, "set_bclk_ratio failed: %d\n", ret);
750 + goto out;
751 + }
752 +
753 + ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0x03, 0x03, 2, width);
754 + if (ret) {
755 + dev_err(card->dev, "set_tdm_slot failed: %d\n", ret);
756 + goto out;
757 + }
758 +
759 + /* WM8804 supports sample rates from 32k only */
760 + if (rate >= 32000) {
761 + ret = rpi_cirrus_set_wm8804_pll(card, wm8804_dai, rate);
762 + if (ret)
763 + goto out;
764 + }
765 +
766 + ret = snd_soc_component_set_sysclk(wm5102_component,
767 + ARIZONA_CLK_SYSCLK,
768 + ARIZONA_CLK_SRC_FLL1,
769 + clk_freq,
770 + SND_SOC_CLOCK_IN);
771 + if (ret) {
772 + dev_err(card->dev, "Failed to set SYSCLK: %d\n", ret);
773 + goto out;
774 + }
775 +
776 + if ((priv->fll1_freq > 0) && (priv->fll1_freq != clk_freq)) {
777 + dev_dbg(card->dev,
778 + "hw_params: changing FLL1 from %d to %d\n",
779 + priv->fll1_freq, clk_freq);
780 +
781 + if (rpi_cirrus_clear_flls(card, wm5102_component)) {
782 + dev_err(card->dev, "hw_params: failed to clear FLLs\n");
783 + goto out;
784 + }
785 +
786 + if (rpi_cirrus_set_fll(card, wm5102_component, clk_freq)) {
787 + dev_err(card->dev, "hw_params: failed to set FLL\n");
788 + goto out;
789 + }
790 +
791 + priv->fll1_freq = clk_freq;
792 + }
793 +
794 + priv->card_rate = rate;
795 + rpi_cirrus_dai_link2_params.rate_min = rate;
796 + rpi_cirrus_dai_link2_params.rate_max = rate;
797 +
798 + priv->params_set |= 1 << substream->stream;
799 +
800 +out:
801 + mutex_unlock(&priv->lock);
802 +
803 + return ret;
804 +}
805 +
806 +static int rpi_cirrus_hw_free(struct snd_pcm_substream *substream)
807 +{
808 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
809 + struct snd_soc_card *card = rtd->card;
810 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
811 + struct snd_soc_component *wm5102_component = rtd->codec_dai->component;
812 + int ret;
813 + unsigned int old_params_set = priv->params_set;
814 +
815 + priv->params_set &= ~(1 << substream->stream);
816 +
817 + /* disable sysclk if this was the last open stream */
818 + if (priv->params_set == 0 && old_params_set) {
819 + dev_dbg(card->dev,
820 + "hw_free: Setting SYSCLK to Zero\n");
821 +
822 + ret = snd_soc_component_set_sysclk(wm5102_component,
823 + ARIZONA_CLK_SYSCLK,
824 + ARIZONA_CLK_SRC_FLL1,
825 + 0,
826 + SND_SOC_CLOCK_IN);
827 + if (ret)
828 + dev_err(card->dev,
829 + "hw_free: Failed to set SYSCLK to Zero: %d\n",
830 + ret);
831 + }
832 + return 0;
833 +}
834 +
835 +static int rpi_cirrus_init_wm5102(struct snd_soc_pcm_runtime *rtd)
836 +{
837 + struct snd_soc_component *component = rtd->codec_dai->component;
838 + int ret;
839 +
840 + /* no 32kHz input, derive it from sysclk if needed */
841 + snd_soc_component_update_bits(component,
842 + ARIZONA_CLOCK_32K_1, ARIZONA_CLK_32K_SRC_MASK, 2);
843 +
844 + if (rpi_cirrus_clear_flls(rtd->card, component))
845 + dev_warn(rtd->card->dev,
846 + "init_wm5102: failed to clear FLLs\n");
847 +
848 + ret = snd_soc_component_set_sysclk(component,
849 + ARIZONA_CLK_SYSCLK, ARIZONA_CLK_SRC_FLL1,
850 + 0, SND_SOC_CLOCK_IN);
851 + if (ret) {
852 + dev_err(rtd->card->dev,
853 + "Failed to set SYSCLK to Zero: %d\n", ret);
854 + return ret;
855 + }
856 +
857 + return 0;
858 +}
859 +
860 +static int rpi_cirrus_init_wm8804(struct snd_soc_pcm_runtime *rtd)
861 +{
862 + struct snd_soc_dai *codec_dai = rtd->codec_dai;
863 + struct snd_soc_component *component = codec_dai->component;
864 + struct snd_soc_card *card = rtd->card;
865 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
866 + unsigned int val, mask;
867 + int i, ret;
868 +
869 + for (i = 0; i < 4; i++) {
870 + ret = snd_soc_component_read(component,
871 + WM8804_SPDTX1 + i, &val);
872 + if (ret)
873 + return ret;
874 + mask = (i == 3) ? 0x3f : 0xff;
875 + priv->iec958_status[i] = val & mask;
876 + }
877 +
878 + /* Setup for 256fs */
879 + ret = snd_soc_dai_set_clkdiv(codec_dai,
880 + WM8804_MCLK_DIV, WM8804_MCLKDIV_256FS);
881 + if (ret) {
882 + dev_err(card->dev,
883 + "init_wm8804: Failed to set MCLK_DIV to 256fs: %d\n",
884 + ret);
885 + return ret;
886 + }
887 +
888 + /* Output OSC on CLKOUT */
889 + ret = snd_soc_dai_set_sysclk(codec_dai,
890 + WM8804_CLKOUT_SRC_OSCCLK, WM8804_CLKOUT_HZ, 0);
891 + if (ret)
892 + dev_err(card->dev,
893 + "init_wm8804: Failed to set CLKOUT as OSC Frequency: %d\n",
894 + ret);
895 +
896 + /* Init PLL with default samplerate */
897 + ret = rpi_cirrus_set_wm8804_pll(card, codec_dai,
898 + RPI_CIRRUS_DEFAULT_RATE);
899 + if (ret)
900 + dev_err(card->dev,
901 + "init_wm8804: Failed to setup PLL for %dHz: %d\n",
902 + RPI_CIRRUS_DEFAULT_RATE, ret);
903 +
904 + return ret;
905 +}
906 +
907 +static struct snd_soc_ops rpi_cirrus_ops = {
908 + .startup = rpi_cirrus_startup,
909 + .hw_params = rpi_cirrus_hw_params,
910 + .hw_free = rpi_cirrus_hw_free,
911 +};
912 +
913 +SND_SOC_DAILINK_DEFS(wm5102,
914 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
915 + DAILINK_COMP_ARRAY(COMP_CODEC("wm5102-codec", "wm5102-aif1")),
916 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
917 +
918 +SND_SOC_DAILINK_DEFS(wm8804,
919 + DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif2")),
920 + DAILINK_COMP_ARRAY(COMP_CODEC("wm8804.1-003b", "wm8804-spdif")));
921 +
922 +static struct snd_soc_dai_link rpi_cirrus_dai[] = {
923 + [DAI_WM5102] = {
924 + .name = "WM5102",
925 + .stream_name = "WM5102 AiFi",
926 + .dai_fmt = SND_SOC_DAIFMT_I2S
927 + | SND_SOC_DAIFMT_NB_NF
928 + | SND_SOC_DAIFMT_CBM_CFM,
929 + .ops = &rpi_cirrus_ops,
930 + .init = rpi_cirrus_init_wm5102,
931 + SND_SOC_DAILINK_REG(wm5102),
932 + },
933 + [DAI_WM8804] = {
934 + .name = "WM5102 SPDIF",
935 + .stream_name = "SPDIF Tx/Rx",
936 + .dai_fmt = SND_SOC_DAIFMT_I2S
937 + | SND_SOC_DAIFMT_NB_NF
938 + | SND_SOC_DAIFMT_CBM_CFM,
939 + .ignore_suspend = 1,
940 + .params = &rpi_cirrus_dai_link2_params,
941 + .init = rpi_cirrus_init_wm8804,
942 + SND_SOC_DAILINK_REG(wm8804),
943 + },
944 +};
945 +
946 +
947 +static int rpi_cirrus_late_probe(struct snd_soc_card *card)
948 +{
949 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
950 + struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card);
951 + struct snd_soc_pcm_runtime *wm8804_runtime = get_wm8804_runtime(card);
952 + int ret;
953 +
954 + dev_dbg(card->dev, "iec958_bits: %02x %02x %02x %02x\n",
955 + priv->iec958_status[0],
956 + priv->iec958_status[1],
957 + priv->iec958_status[2],
958 + priv->iec958_status[3]);
959 +
960 + ret = snd_soc_dai_set_sysclk(
961 + wm5102_runtime->codec_dai, ARIZONA_CLK_SYSCLK, 0, 0);
962 + if (ret) {
963 + dev_err(card->dev,
964 + "Failed to set WM5102 codec dai clk domain: %d\n", ret);
965 + return ret;
966 + }
967 +
968 + ret = snd_soc_dai_set_sysclk(
969 + wm8804_runtime->cpu_dai, ARIZONA_CLK_SYSCLK, 0, 0);
970 + if (ret)
971 + dev_err(card->dev,
972 + "Failed to set WM8804 codec dai clk domain: %d\n", ret);
973 +
974 + return ret;
975 +}
976 +
977 +/* audio machine driver */
978 +static struct snd_soc_card rpi_cirrus_card = {
979 + .name = "RPi-Cirrus",
980 + .driver_name = "RPiCirrus",
981 + .owner = THIS_MODULE,
982 + .dai_link = rpi_cirrus_dai,
983 + .num_links = ARRAY_SIZE(rpi_cirrus_dai),
984 + .late_probe = rpi_cirrus_late_probe,
985 + .controls = rpi_cirrus_controls,
986 + .num_controls = ARRAY_SIZE(rpi_cirrus_controls),
987 + .dapm_widgets = rpi_cirrus_dapm_widgets,
988 + .num_dapm_widgets = ARRAY_SIZE(rpi_cirrus_dapm_widgets),
989 + .dapm_routes = rpi_cirrus_dapm_routes,
990 + .num_dapm_routes = ARRAY_SIZE(rpi_cirrus_dapm_routes),
991 + .set_bias_level = rpi_cirrus_set_bias_level,
992 + .set_bias_level_post = rpi_cirrus_set_bias_level_post,
993 +};
994 +
995 +static int rpi_cirrus_probe(struct platform_device *pdev)
996 +{
997 + int ret = 0;
998 + struct rpi_cirrus_priv *priv;
999 + struct device_node *i2s_node;
1000 +
1001 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
1002 + if (!priv)
1003 + return -ENOMEM;
1004 +
1005 + priv->min_rate_idx = 1; /* min samplerate 32kHz */
1006 + priv->card_rate = RPI_CIRRUS_DEFAULT_RATE;
1007 +
1008 + mutex_init(&priv->lock);
1009 +
1010 + snd_soc_card_set_drvdata(&rpi_cirrus_card, priv);
1011 +
1012 + if (!pdev->dev.of_node)
1013 + return -ENODEV;
1014 +
1015 + i2s_node = of_parse_phandle(
1016 + pdev->dev.of_node, "i2s-controller", 0);
1017 + if (!i2s_node) {
1018 + dev_err(&pdev->dev, "i2s-controller missing in DT\n");
1019 + return -ENODEV;
1020 + }
1021 +
1022 + rpi_cirrus_dai[DAI_WM5102].cpus->of_node = i2s_node;
1023 + rpi_cirrus_dai[DAI_WM5102].platforms->of_node = i2s_node;
1024 +
1025 + rpi_cirrus_card.dev = &pdev->dev;
1026 +
1027 + ret = devm_snd_soc_register_card(&pdev->dev, &rpi_cirrus_card);
1028 + if (ret) {
1029 + if (ret == -EPROBE_DEFER)
1030 + dev_dbg(&pdev->dev,
1031 + "register card requested probe deferral\n");
1032 + else
1033 + dev_err(&pdev->dev,
1034 + "Failed to register card: %d\n", ret);
1035 + }
1036 +
1037 + return ret;
1038 +}
1039 +
1040 +static const struct of_device_id rpi_cirrus_of_match[] = {
1041 + { .compatible = "wlf,rpi-cirrus", },
1042 + {},
1043 +};
1044 +MODULE_DEVICE_TABLE(of, rpi_cirrus_of_match);
1045 +
1046 +static struct platform_driver rpi_cirrus_driver = {
1047 + .driver = {
1048 + .name = "snd-rpi-cirrus",
1049 + .of_match_table = of_match_ptr(rpi_cirrus_of_match),
1050 + },
1051 + .probe = rpi_cirrus_probe,
1052 +};
1053 +
1054 +module_platform_driver(rpi_cirrus_driver);
1055 +
1056 +MODULE_AUTHOR("Matthias Reichl <hias@horus.com>");
1057 +MODULE_DESCRIPTION("ASoC driver for Cirrus Logic Audio Card");
1058 +MODULE_LICENSE("GPL");