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