d561396df5d849be91777d343a83fdcbe27c76d8
[openwrt/staging/stintel.git] /
1 From 6e520cdc4c898f0d02bbe40e2c466f9694933d9c Mon Sep 17 00:00:00 2001
2 From: Florian Meier <florian.meier@koalo.de>
3 Date: Mon, 25 Jan 2016 15:48:59 +0000
4 Subject: [PATCH] Add support for all the downstream rpi sound card
5 drivers
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 ASoC: Add support for Rpi-DAC
11
12 ASoC: Add prompt for ICS43432 codec
13
14 Without a prompt string, a config setting can't be included in a
15 defconfig. Give CONFIG_SND_SOC_ICS43432 a prompt so that Pi soundcards
16 can use the driver.
17
18 Signed-off-by: Phil Elwell <phil@raspberrypi.org>
19
20 Add IQaudIO Sound Card support for Raspberry Pi
21
22 Set a limit of 0dB on Digital Volume Control
23
24 The main volume control in the PCM512x DAC has a range up to
25 +24dB. This is dangerously loud and can potentially cause massive
26 clipping in the output stages. Therefore this sets a sensible
27 limit of 0dB for this control.
28
29 Allow up to 24dB digital gain to be applied when using IQAudIO DAC+
30
31 24db_digital_gain DT param can be used to specify that PCM512x
32 codec "Digital" volume control should not be limited to 0dB gain,
33 and if specified will allow the full 24dB gain.
34
35 Modify IQAudIO DAC+ ASoC driver to set card/dai config from dt
36
37 Add the ability to set the card name, dai name and dai stream name, from
38 dt config.
39
40 Signed-off-by: DigitalDreamtime <clive.messer@digitaldreamtime.co.uk>
41
42 IQaudIO: auto-mute for AMP+ and DigiAMP+
43
44 IQAudIO amplifier mute via GPIO22. Add dt params for "one-shot" unmute
45 and auto mute.
46
47 Revision 2, auto mute implementing HiassofT suggestion to mute/unmute
48 using set_bias_level, rather than startup/shutdown....
49 "By default DAPM waits 5 seconds (pmdown_time) before shutting down
50 playback streams so a close/stop immediately followed by open/start
51 doesn't trigger an amp mute+unmute."
52
53 Tested on both AMP+ (via DAC+) and DigiAMP+, with both options...
54
55 dtoverlay=iqaudio-dacplus,unmute_amp
56 "one-shot" unmute when kernel module loads.
57
58 dtoverlay=iqaudio-dacplus,auto_mute_amp
59 Unmute amp when ALSA device opened by a client. Mute, with 5 second delay
60 when ALSA device closed. (Re-opening the device within the 5 second close
61 window, will cancel mute.)
62
63 Revision 4, using gpiod.
64
65 Revision 5, clean-up formatting before adding mute code.
66 - Convert tab plus 4 space formatting to 2x tab
67 - Remove '// NOT USED' commented code
68
69 Revision 6, don't attempt to "one-shot" unmute amp, unless card is
70 successfully registered.
71
72 Signed-off-by: DigitalDreamtime <clive.messer@digitaldreamtime.co.uk>
73
74 ASoC: iqaudio-dac: fix S24_LE format
75
76 Remove set_bclk_ratio call so 24-bit data is transmitted in
77 24 bclk cycles.
78
79 Signed-off-by: Matthias Reichl <hias@horus.com>
80
81 ASoC: iqaudio-dac: use modern dai_link style
82
83 Signed-off-by: Matthias Reichl <hias@horus.com>
84
85 Added support for HiFiBerry DAC+
86
87 The driver is based on the HiFiBerry DAC driver. However HiFiBerry DAC+ uses
88 a different codec chip (PCM5122), therefore a new driver is necessary.
89
90 Add support for the HiFiBerry DAC+ Pro.
91
92 The HiFiBerry DAC+ and DAC+ Pro products both use the existing bcm sound driver with the DAC+ Pro having a special clock device driver representing the two high precision oscillators.
93
94 An addition bug fix is included for the PCM512x codec where by the physical size of the sample frame is used in the calculation of the LRCK divisor as it was found to be wrong when using 24-bit depth sample contained in a little endian 4-byte sample frame.
95
96 Limit PCM512x "Digital" gain to 0dB by default with HiFiBerry DAC+
97
98 24db_digital_gain DT param can be used to specify that PCM512x
99 codec "Digital" volume control should not be limited to 0dB gain,
100 and if specified will allow the full 24dB gain.
101
102 Add dt param to force HiFiBerry DAC+ Pro into slave mode
103
104 "dtoverlay=hifiberry-dacplus,slave"
105
106 Add 'slave' param to use HiFiBerry DAC+ Pro in slave mode,
107 with Pi as master for bit and frame clock.
108
109 Signed-off-by: DigitalDreamtime <clive.messer@digitaldreamtime.co.uk>
110
111 Fixed a bug when using 352.8kHz sample rate
112
113 Signed-off-by: Daniel Matuschek <daniel@hifiberry.com>
114
115 ASoC: pcm512x: revert downstream changes
116
117 This partially reverts commit 185ea05465aac8bf02a0d2b2f4289d42c72870b7
118 which was added by https://github.com/raspberrypi/linux/pull/1152
119
120 The downstream pcm512x changes caused a regression, it broke normal
121 use of the 24bit format with the codec, eg when using simple-audio-card.
122
123 The actual bug with 24bit playback is the incorrect usage
124 of physical_width in various drivers in the downstream tree
125 which causes 24bit data to be transmitted with 32 clock
126 cycles. So it's not the pcm512x that needs fixing, it's the
127 soundcard drivers.
128
129 Signed-off-by: Matthias Reichl <hias@horus.com>
130
131 ASoC: hifiberry_dacplus: fix S24_LE format
132
133 Remove set_bclk_ratio call so 24-bit data is transmitted in
134 24 bclk cycles.
135
136 Signed-off-by: Matthias Reichl <hias@horus.com>
137
138 ASoC: hifiberry_dacplus: transmit S24_LE with 64 BCLK cycles
139
140 Signed-off-by: Matthias Reichl <hias@horus.com>
141
142 hifiberry_dacplus: switch to snd_soc_dai_set_bclk_ratio
143
144 Signed-off-by: Matthias Reichl <hias@horus.com>
145
146 ASoC: hifiberry_dacplus: use modern dai_link style
147
148 Signed-off-by: Hui Wang <hui.wang@canonical.com>
149
150 Add driver for rpi-proto
151
152 Forward port of 3.10.x driver from https://github.com/koalo
153 We are using a custom board and would like to use rpi 3.18.x
154 kernel. Patch works fine for our embedded system.
155
156 URL to the audio chip:
157 http://www.mikroe.com/add-on-boards/audio-voice/audio-codec-proto/
158
159 Playback tested with devicetree enabled.
160
161 Signed-off-by: Waldemar Brodkorb <wbrodkorb@conet.de>
162
163 ASoC: rpi-proto: use modern dai_link style
164
165 Signed-off-by: Hui Wang <hui.wang@canonical.com>
166
167 Add Support for JustBoom Audio boards
168
169 justboom-dac: Adjust for ALSA API change
170
171 As of 4.4, snd_soc_limit_volume now takes a struct snd_soc_card *
172 rather than a struct snd_soc_codec *.
173
174 Signed-off-by: Phil Elwell <phil@raspberrypi.org>
175
176 ASoC: justboom-dac: fix S24_LE format
177
178 Remove set_bclk_ratio call so 24-bit data is transmitted in
179 24 bclk cycles.
180
181 Also remove hw_params as it's no longer needed.
182
183 Signed-off-by: Matthias Reichl <hias@horus.com>
184
185 ASoC: justboom-dac: use modern dai_link style
186
187 Signed-off-by: Matthias Reichl <hias@horus.com>
188
189 New AudioInjector.net Pi soundcard with low jitter audio in and out.
190
191 Contains the sound/soc/bcm ALSA machine driver and necessary alterations to the Kconfig and Makefile.
192 Adds the dts overlay and updates the Makefile and README.
193 Updates the relevant defconfig files to enable building for the Raspberry Pi.
194 Thanks to Phil Elwell (pelwell) for the review, simple-card concepts and discussion. Thanks to Clive Messer for overlay naming suggestions.
195
196 Added support for headphones, microphone and bclk_ratio settings.
197
198 This patch adds headphone and microphone capability to the Audio Injector sound card. The patch also sets the bit clock ratio for use in the bcm2835-i2s driver. The bcm2835-i2s can't handle an 8 kHz sample rate when the bit clock is at 12 MHz because its register is only 10 bits wide which can't represent the ch2 offset of 1508. For that reason, the rate constraint is added.
199
200 ASoC: audioinjector-pi-soundcard: use modern dai_link style
201
202 Signed-off-by: Hui Wang <hui.wang@canonical.com>
203
204 New driver for RRA DigiDAC1 soundcard using WM8741 + WM8804
205
206 ASoC: digidac1-soundcard: use modern dai_link style
207
208 Signed-off-by: Hui Wang <hui.wang@canonical.com>
209
210 Add support for Dion Audio LOCO DAC-AMP HAT
211
212 Using dedicated machine driver and pcm5102a codec driver.
213
214 Signed-off-by: DigitalDreamtime <clive.messer@digitaldreamtime.co.uk>
215
216 ASoC: dionaudio_loco: use modern dai_link style
217
218 Signed-off-by: Hui Wang <hui.wang@canonical.com>
219
220 Allo Piano DAC boards: Initial 2 channel (stereo) support (#1645)
221
222 Add initial 2 channel (stereo) support for Allo Piano DAC (2.0/2.1) boards,
223 using allo-piano-dac-pcm512x-audio overlay and allo-piano-dac ALSA ASoC
224 machine driver.
225
226 NB. The initial support is 2 channel (stereo) ONLY!
227 (The Piano DAC 2.1 will only support 2 channel (stereo) left/right output,
228 pending an update to the upstream pcm512x codec driver, which will have
229 to be submitted via upstream. With the initial downstream support,
230 provided by this patch, the Piano DAC 2.1 subwoofer outputs will
231 not function.)
232
233 Signed-off-by: Baswaraj K <jaikumar@cem-solutions.net>
234 Signed-off-by: Clive Messer <clive.messer@digitaldreamtime.co.uk>
235 Tested-by: Clive Messer <clive.messer@digitaldreamtime.co.uk>
236
237 ASoC: allo-piano-dac: fix S24_LE format
238
239 Remove set_bclk_ratio call so 24-bit data is transmitted in
240 24 bclk cycles.
241
242 Also remove hw_params and ops as they are no longer needed.
243
244 Signed-off-by: Matthias Reichl <hias@horus.com>
245
246 ASoC: allo-piano-dac: use modern dai_link style
247
248 Signed-off-by: Hui Wang <hui.wang@canonical.com>
249
250 Add support for Allo Piano DAC 2.1 plus add-on board for Raspberry Pi.
251
252 The Piano DAC 2.1 has support for 4 channels with subwoofer.
253
254 Signed-off-by: Baswaraj K <jaikumar@cem-solutions.net>
255 Reviewed-by: Vijay Kumar B. <vijaykumar@zilogic.com>
256 Reviewed-by: Raashid Muhammed <raashidmuhammed@zilogic.com>
257
258 Add clock changes and mute gpios (#1938)
259
260 Also improve code style and adhere to ALSA coding conventions.
261
262 Signed-off-by: Baswaraj K <jaikumar@cem-solutions.net>
263 Reviewed-by: Vijay Kumar B. <vijaykumar@zilogic.com>
264 Reviewed-by: Raashid Muhammed <raashidmuhammed@zilogic.com>
265
266 PianoPlus: Dual Mono & Dual Stereo features added (#2069)
267
268 allo-piano-dac-plus: Master volume added + fixes
269
270 Master volume added, which controls both DACs volumes.
271
272 See: https://github.com/raspberrypi/linux/pull/2149
273
274 Also fix initial max volume, default mode value, and unmute.
275
276 Signed-off-by: allocom <sparky-dev@allo.com>
277
278 ASoC: allo-piano-dac-plus: fix S24_LE format
279
280 Remove set_bclk_ratio call so 24-bit data is transmitted in
281 24 bclk cycles.
282
283 Signed-off-by: Matthias Reichl <hias@horus.com>
284
285 sound: bcm: Fix memset dereference warning
286
287 This warning appears with GCC 6.4.0 from toolchains.bootlin.com:
288
289 ../sound/soc/bcm/allo-piano-dac-plus.c: In function ‘snd_allo_piano_dac_init’:
290 ../sound/soc/bcm/allo-piano-dac-plus.c:711:30: warning: argument to ‘sizeof’ in ‘memset’ call is the same expression as the destination; did you mean to dereference it? [-Wsizeof-pointer-memaccess]
291 memset(glb_ptr, 0x00, sizeof(glb_ptr));
292 ^
293
294 Suggested-by: Phil Elwell <phil@raspberrypi.org>
295 Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
296
297 ASoC: allo-piano-dac-plus: use modern dai_link style
298
299 Signed-off-by: Hui Wang <hui.wang@canonical.com>
300
301 Add support for Allo Boss DAC add-on board for Raspberry Pi. (#1924)
302
303 Signed-off-by: Baswaraj K <jaikumar@cem-solutions.net>
304 Reviewed-by: Deepak <deepak@zilogic.com>
305 Reviewed-by: BabuSubashChandar <babusubashchandar@zilogic.com>
306
307 Add support for new clock rate and mute gpios.
308
309 Signed-off-by: Baswaraj K <jaikumar@cem-solutions.net>
310 Reviewed-by: Deepak <deepak@zilogic.com>
311 Reviewed-by: BabuSubashChandar <babusubashchandar@zilogic.com>
312
313 ASoC: allo-boss-dac: fix S24_LE format
314
315 Remove set_bclk_ratio call so 24-bit data is transmitted in
316 24 bclk cycles.
317
318 Signed-off-by: Matthias Reichl <hias@horus.com>
319
320 ASoC: allo-boss-dac: transmit S24_LE with 64 BCLK cycles
321
322 Signed-off-by: Matthias Reichl <hias@horus.com>
323
324 allo-boss-dac: switch to snd_soc_dai_set_bclk_ratio
325
326 Signed-off-by: Matthias Reichl <hias@horus.com>
327
328 ASoC: allo-boss-dac: use modern dai_link style
329
330 Signed-off-by: Hui Wang <hui.wang@canonical.com>
331
332 Support for Blokas Labs pisound board
333
334 Pisound dynamic overlay (#1760)
335
336 Restructuring pisound-overlay.dts, so it can be loaded and unloaded dynamically using dtoverlay.
337
338 Print a logline when the kernel module is removed.
339
340 pisound improvements:
341
342 * Added a writable sysfs object to enable scripts / user space software
343 to blink MIDI activity LEDs for variable duration.
344 * Improved hw_param constraints setting.
345 * Added compatibility with S16_LE sample format.
346 * Exposed some simple placeholder volume controls, so the card appears
347 in volumealsa widget.
348
349 Add missing SND_PISOUND selects dependency to SND_RAWMIDI
350
351 Without it the Pisound module fails to compile.
352 See https://github.com/raspberrypi/linux/issues/2366
353
354 Updates for Pisound module code:
355
356 * Merged 'Fix a warning in DEBUG builds' (1c8b82b).
357 * Updating some strings and copyright information.
358 * Fix for handling high load of MIDI input and output.
359 * Use dual rate oversampling ratio for 96kHz instead of single
360 rate one.
361
362 Signed-off-by: Giedrius Trainavicius <giedrius@blokas.io>
363
364 Fixing memset call in pisound.c
365
366 Signed-off-by: Giedrius Trainavicius <giedrius@blokas.io>
367
368 Fix for Pisound's MIDI Input getting blocked for a while in rare cases.
369
370 There was a possible race condition which could lead to Input's FIFO queue
371 to be underflown, causing high amount of processing in the worker thread for
372 some period of time.
373
374 Signed-off-by: Giedrius Trainavicius <giedrius@blokas.io>
375
376 Fix for Pisound kernel module in Real Time kernel configuration.
377
378 When handler of data_available interrupt is fired, queue_work ends up
379 getting called and it can block on a spin lock which is not allowed in
380 interrupt context. The fix was to run the handler from a thread context
381 instead.
382
383 Pisound: Remove spinlock usage around spi_sync
384
385 ASoC: pisound: use modern dai_link style
386
387 Signed-off-by: Hui Wang <hui.wang@canonical.com>
388
389 ASoC: pisound: fix the parameter for spi_device_match
390
391 Signed-off-by: Hui Wang <hui.wang@canonical.com>
392
393 ASoC: Add driver for Cirrus Logic Audio Card
394
395 Note: due to problems with deferred probing of regulators
396 the following softdep should be added to a modprobe.d file
397
398 softdep arizona-spi pre: arizona-ldo1
399
400 Signed-off-by: Matthias Reichl <hias@horus.com>
401
402 ASoC: rpi-cirrus: use modern dai_link style
403
404 Signed-off-by: Matthias Reichl <hias@horus.com>
405
406 sound: Support for Dion Audio LOCO-V2 DAC-AMP HAT
407
408 Signed-off-by: Miquel Blauw <info@dionaudio.nl>
409
410 ASoC: dionaudio_loco-v2: fix S24_LE format
411
412 Remove set_bclk_ratio call so 24-bit data is transmitted in
413 24 bclk cycles.
414
415 Also remove hw_params and ops as they are no longer needed.
416
417 Signed-off-by: Matthias Reichl <hias@horus.com>
418
419 ASoC: dionaudio_loco-v2: use modern dai_link style
420
421 Signed-off-by: Hui Wang <hui.wang@canonical.com>
422
423 Add support for Fe-Pi audio sound card. (#1867)
424
425 Fe-Pi Audio Sound Card is based on NXP SGTL5000 codec.
426 Mechanical specification of the board is the same the Raspberry Pi Zero.
427 3.5mm jacks for Headphone/Mic, Line In, and Line Out.
428
429 Signed-off-by: Henry Kupis <fe-pi@cox.net>
430
431 ASoC: fe-pi-audio: use modern dai_link style
432
433 Signed-off-by: Hui Wang <hui.wang@canonical.com>
434
435 Add support for the AudioInjector.net Octo sound card
436
437 AudioInjector Octo: sample rates, regulators, reset
438
439 This patch adds new sample rates to the Audioinjector Octo sound card. The
440 new supported rates are (in kHz) :
441 96, 48, 32, 24, 16, 8, 88.2, 44.1, 29.4, 22.05, 14.7
442
443 Reference the bcm270x DT regulators in the overlay.
444
445 This patch adds a reset GPIO for the AudioInjector.net octo sound card.
446
447 Audioinjector octo : Make the playback and capture symmetric
448
449 This patch ensures that the sample rate and channel count of the audioinjector
450 octo sound card are symmetric.
451
452 audioinjector-octo: Add continuous clock feature
453
454 By user request, add a switch to prevent the clocks being stopped when
455 the stream is paused, stopped or shutdown. Provide access to the switch
456 by adding a 'non-stop-clocks' parameter to the audioinjector-addons
457 overlay.
458
459 See: https://github.com/raspberrypi/linux/issues/2409
460
461 Signed-off-by: Phil Elwell <phil@raspberrypi.org>
462
463 sound: Fixes for audioinjector-octo under 4.19
464
465 1. Move the DT alias declaration to the I2C shim in the cases
466 where the shim is enabled. This works around a problem caused by a
467 4.19 commit [1] that generates DT/OF uevents for I2C drivers.
468
469 2. Fix the diagnostics in an error path of the soundcard driver to
470 correctly identify the reason for the failure to load.
471
472 3. Move the declaration of the clock node in the overlay outside
473 the I2C node to avoid warnings.
474
475 4. Sort the overlay nodes so that dependencies are only to earlier
476 fragments, in an attempt to get runtime dtoverlay application to
477 work (it still doesn't...)
478
479 See: https://github.com/Audio-Injector/Octo/issues/14
480 Signed-off-by: Phil Elwell <phil@raspberrypi.org>
481
482 [1] af503716ac14 ("i2c: core: report OF style module alias for devices registered via OF")
483
484 ASoC: audioinjector-octo-soundcard: use modern dai_link style
485
486 Signed-off-by: Hui Wang <hui.wang@canonical.com>
487
488 Driver support for Google voiceHAT soundcard.
489
490 ASoC: googlevoicehat-codec: Use correct device when grabbing GPIO
491
492 The fixup for the VoiceHAT in 4.18 incorrectly tried to find the
493 sdmode GPIO pin under the card device, not the codec device.
494 This failed, and therefore caused the device probe to fail.
495
496 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
497
498 ASoC: googlevoicehat-codec: Reformat for kernel coding standards
499
500 Fix all whitespace, indentation, and bracing errors.
501
502 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
503
504 ASoC: googlevoicehat-codec: Make driver function structure const
505
506 Make voicehat_component_driver a const structure.
507
508 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
509
510 ASoC: googlevoicehat-codec: Only convert from ms to jiffies once
511
512 Minor optimisation and allows to become checkpatch clean.
513 A msec value is read out of DT or from a define, and convert once to
514 jiffies, rather than every time that it is used.
515
516 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
517
518 Driver and overlay for Allo Katana DAC
519
520 Allo Katana DAC: Updated default values
521
522 Signed-off-by: Jaikumar <jaikumar@cem-solutions.com>
523
524 Added mute stream func
525
526 Signed-off-by: Jaikumar <jaikumar@cem-solutions.net>
527
528 codecs: Correct Katana minimum volume
529
530 Update Katana minimum volume to get the exact 0.5 dB value in each step.
531
532 Signed-off-by: Sudeep Kumar <sudeepkumar@cem-solutions.net>
533
534 ASoC: Add generic RPI driver for simple soundcards.
535
536 The RPI simple sound card driver provides a generic ALSA SOC card driver
537 supporting a variety of Pi HAT soundcards. The intention is to avoid
538 the duplication of code for cards that can't be fully supported by
539 the soc simple/graph cards but are otherwise almost identical.
540
541 This initial commit adds support for the ADAU1977 ADC, Google VoiceHat,
542 HifiBerry AMP, HifiBerry DAC and RPI DAC.
543
544 Signed-off-by: Tim Gover <tim.gover@raspberrypi.org>
545
546 ASoC: Use correct card name in rpi-simple driver
547
548 Use the specific card name from drvdata instead of the snd_rpi_simple
549
550 rpi-simple-soundcard: Use nicer driver name "RPi-simple"
551
552 Rename the driver from "RPI simple soundcard" to "RPi-simple" so that
553 the driver name won't be mangled allowing to be used unaltered as the
554 card conf filename.
555
556 ASoC: rpi-simple-soundcard: use modern dai_link style
557
558 Signed-off-by: Hui Wang <hui.wang@canonical.com>
559
560 ASoC: Add Kconfig and Makefile for sound/soc/bcm
561
562 Signed-off-by: popcornmix <popcornmix@gmail.com>
563
564 ASoC: Create a generic Pi Hat WM8804 driver
565
566 Reduce the amount of duplicated code by creating a generic driver for
567 Pi Hat digi cards using the WM8804 codec.
568
569 This replaces the
570 Allo DigiOne, Hifiberry Digi/Pro, JustBoom Digi and IQAudIO Digi
571 dedicate soundcard drivers with a generic driver.
572
573 There are no significant changes to the runtime behavior of the drivers
574 and end users should not have to change any configuration settings
575 after upgrading.
576
577 Minor changes
578 * Check the return value of snd_soc_component_update_bits
579 * Added some pr_debug tracing
580 * Various checkpatch tidyups
581 * Updated allodigi-one to use use 128FS at > 96 Khz. This appears to
582 be an omission in the original driver code so followed the Hifiberry
583 DAC driver approach.
584
585 ASoC: rpi-wm8804-soundcard: use modern dai_link style
586
587 Signed-off-by: Matthias Reichl <hias@horus.com>
588
589 rpi-wm8804-soundcard: drop PWRDN register writes
590
591 Since kernel 4.0 the PWRDN register bits are under DAPM
592 control from the wm8804 driver.
593
594 Drop code that modifies that register to avoid interfering
595 with DAPM.
596
597 Signed-off-by: Matthias Reichl <hias@horus.com>
598
599 rpi-wm8804-soundcard: configure wm8804 clocks only on rate change
600
601 This should avoid clicks when stopping and immediately afterwards
602 starting a stream with the same samplerate as before.
603
604 Signed-off-by: Matthias Reichl <hias@horus.com>
605
606 rpi-wm8804-soundcard: Fixed MCLKDIV for Allo Digione
607
608 The Allo Digione board wants a fixed MCLKDIV of 256.
609
610 See: https://github.com/raspberrypi/linux/issues/3296
611
612 Signed-off-by: Phil Elwell <phil@raspberrypi.org>
613
614 ASoC: Add support for AudioSense-Pi add-on soundcard
615
616 AudioSense-Pi is a RPi HAT based on a TI's TLV320AIC32x4 stereo codec
617
618 This hardware provides multiple audio I/O capabilities to the RPi.
619 The codec connects to the RPi's SoC through the I2S Bus.
620
621 The following devices can be connected through a 3.5mm jack
622 1. Line-In: Plain old audio in from mobile phones, PCs, etc.,
623 2. Mic-In: Connect a microphone
624 3. Line-Out: Connect the output to a speaker
625 4. Headphones: Connect a Headphone w or w/o microphones
626
627 Multiple Inputs:
628 It supports the following combinations
629 1. Two stereo Line-Inputs and a microphone
630 2. One stereo Line-Input and two microphones
631 3. Two stereo Line-Inputs, a microphone and
632 one mono line-input (with h/w hack)
633 4. One stereo Line-Input, two microphones and
634 one mono line-input (with h/w hack)
635
636 Multiple Outputs:
637 Audio output can be routed to the headphones or
638 speakers (with additional hardware)
639
640 Signed-off-by: b-ak <anur.bhargav@gmail.com>
641
642 ASoC: audiosense-pi: use modern dai_link style
643
644 Signed-off-by: Hui Wang <hui.wang@canonical.com>
645
646 Added driver for the HiFiBerry DAC+ ADC (#2694)
647
648 Signed-off-by: Daniel Matuschek <daniel@hifiberry.com>
649
650 hifiberry_dacplusadc: switch to snd_soc_dai_set_bclk_ratio
651
652 Signed-off-by: Matthias Reichl <hias@horus.com>
653
654 ASoC: hifiberry_dacplusadc: fix DAI link setup
655
656 The driver only defines a single DAI link and the code that tries
657 to setup the second (non-existent) DAI link looks wrong - using dmic
658 as a CPU/platform driver doesn't make any sense.
659
660 The DT overlay doesn't define a dmic property, so the code was never
661 executed (otherwise it would have resulted in a memory corruption).
662
663 So drop the offending code to prevent issues if a dmic property
664 should be added to the DT overlay.
665
666 Signed-off-by: Matthias Reichl <hias@horus.com>
667
668 ASoC: hifiberry_dacplusadc: use modern dai_link style
669
670 Signed-off-by: Matthias Reichl <hias@horus.com>
671
672 Audiophonics I-Sabre 9038Q2M DAC driver
673
674 Signed-off-by: Audiophonics <contact@audiophonics.fr>
675
676 ASoC: i-sabre-q2m: use modern dai_link style
677
678 Signed-off-by: Hui Wang <hui.wang@canonical.com>
679
680 Added IQaudIO Pi-Codec board support (#2969)
681
682 Add support for the IQaudIO Pi-Codec board.
683
684 Signed-off-by: Gordon <gordon@iqaudio.com>
685
686 Fixed 48k timing issue
687
688 ASoC: iqaudio-codec: use modern dai_link style
689
690 Signed-off-by: Hui Wang <hui.wang@canonical.com>
691
692 adds the Hifiberry DAC+ADC PRO version
693
694 This adds the driver for the DAC+ADC PRO version of the Hifiberry soundcard with software controlled PCM1863 ADC
695 Signed-off-by: Joerg Schambacher joerg@i2audio.com
696
697 Add Hifiberry DAC+DSP soundcard driver (#3224)
698
699 Adds the driver for the Hifiberry DAC+DSP. It supports capture and
700 playback depending on the DSP firmware.
701
702 Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
703
704 Allow simultaneous use of JustBoom DAC and Digi
705
706 Signed-off-by: Johannes Krude <johannes@krude.de>
707
708 Pisound: MIDI communication fixes for scaled down CPU.
709
710 * Increased maximum SPI communication speed to avoid running too slow
711 when the CPU is scaled down and losing MIDI data.
712
713 * Keep track of buffer usage in millibytes for higher precision.
714
715 Signed-off-by: Giedrius Trainavičius <giedrius@blokas.io>
716
717 sound: Add the HiFiBerry DAC+HD version
718
719 This adds the driver for the DAC+HD version supporting HiFiBerry's
720 PCM179x based DACs. It also adds PLL control for clock generation.
721
722 Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
723
724 Fix master mode settings of HiFiBerry DAC+ADC PRO card (#3424)
725
726 This patch fixes the board DAI setting when in master-mode.
727 Wrong setting could have caused random pop noise.
728
729 Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
730
731 adds LED OFF feature to HiFiBerry DAC+ADC PRO sound card
732
733 This adds a DT overlay parameter 'leds_off' which allows
734 to switch off the onboard activity LEDs at all times
735 which has been requested by some users.
736
737 Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
738
739 adds LED OFF feature to HiFiBerry DAC+ADC sound card
740
741 This adds a DT overlay parameter 'leds_off' which allows
742 to switch off the onboard activity LEDs at all times
743 which has been requested by some users.
744
745 Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
746
747 adds LED OFF feature to HiFiBerry DAC+/DAC+PRO sound cards
748
749 This adds a DT overlay parameter 'leds_off' which allows
750 to switch off the onboard activity LEDs at all times
751 which has been requested by some users.
752
753 Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
754
755 pisound: Added reading Pisound board hardware revision and exposing it (#3425)
756
757 pisound: Added reading Pisound board hardware revision and exposing it in kernel log and sysfs file:
758
759 /sys/kernel/pisound/hw_version
760
761 Signed-off-by: Giedrius <giedrius@blokas.io>
762
763 Added driver for HiFiBerry Amp amplifier add-on board
764
765 The driver contains a low-level hardware driver for the TAS5713 and the
766 drivers for the Raspberry Pi I2S subsystem.
767
768 TAS5713: return error if initialisation fails
769
770 Existing TAS5713 driver logs errors during initialisation, but does not return
771 an error code. Therefore even if initialisation fails, the driver will still be
772 loaded, but won't work. This patch fixes this. I2C communication error will now
773 reported correctly by a non-zero return code.
774
775 HiFiBerry Amp: fix device-tree problems
776
777 Some code to load the driver based on device-tree-overlays was missing. This is added by this patch.
778
779 According to 5713 pdf doc CLOCK_CTRL is a readonly status register, and it behaves so. Remove useless setting
780
781 sound: pcm512x-codec: Adding 352.8kHz samplerate support
782
783 sound/soc: only first codec is master in multicodec setup
784
785 When using multiple codecs, at most one codec should generate the master
786 clock. All codecs except the first are therefore configured for slave
787 mode.
788
789 Signed-off-by: Johannes Krude <johannes@krude.de>
790
791 ASoC: Fix snd_soc_get_pcm_runtime usage
792
793 Commit [1] changed the snd_soc_get_pcm_runtime to take a dai_link
794 pointer instead of a string. Patch up the downstream drivers to use
795 the modified API.
796
797 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
798
799 [1] 4468189ff307 ("ASoC: soc-core: find rtd via dai_link pointer at snd_soc_get_pcm_runtime()")
800
801 Add support for the AudioInjector.net Isolated sound card
802
803 This patch adds support for the Audio Injector Isolated sound card.
804
805 Signed-off-by: Matt Flax <flatmax@flatmax.org>
806
807 Add support for merus-amp soundcard and ma120x0p codec
808
809 Add 96KHz rate support to MA120X0P codec and make enable and mute gpio
810 pins optional.
811
812 Signed-off-by: AMuszkat <ariel.muszkat@gmail.com>
813
814 Fixes a problem with clock settings of HiFiBerry DAC+ADC PRO (#3545)
815
816 This patch fixes a problem of the re-calculation of
817 i2s-clock and -parameter settings when only the ADC is activated.
818
819 Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
820
821 configs: Enable the AD193x codecs
822
823 See: https://github.com/raspberrypi/linux/issues/2850
824
825 Signed-off-by: Phil Elwell <phil@raspberrypi.org>
826
827 Switch to snd_soc_dai_set_bclk_ratio
828 Replaces obsolete function snd_soc_dai_set_tdm_slot
829
830 Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
831
832 Enhances the DAC+ driver to control the optional headphone amplifier
833
834 Probes on the I2C bus for TPA6130A2, if successful, it sets DT-parameter
835 'status' from 'disabled' to 'okay' using change_sets to enable
836 the headphone control.
837
838 Signed-off-by: Joerg Schambacher joerg@i2audio.com
839 ---
840 .../devicetree/bindings/vendor-prefixes.txt | 463 ++++++
841 .../devicetree/bindings/vendor-prefixes.yaml | 2 +
842 drivers/clk/Kconfig | 6 +
843 drivers/clk/Makefile | 3 +
844 drivers/clk/clk-allo-dac.c | 161 ++
845 drivers/clk/clk-hifiberry-dachd.c | 333 ++++
846 drivers/clk/clk-hifiberry-dacpro.c | 160 ++
847 sound/soc/bcm/Kconfig | 274 ++++
848 sound/soc/bcm/Makefile | 63 +-
849 sound/soc/bcm/allo-boss-dac.c | 456 ++++++
850 sound/soc/bcm/allo-katana-codec.c | 388 +++++
851 sound/soc/bcm/allo-piano-dac-plus.c | 987 ++++++++++++
852 sound/soc/bcm/allo-piano-dac.c | 122 ++
853 .../bcm/audioinjector-isolated-soundcard.c | 183 +++
854 sound/soc/bcm/audioinjector-octo-soundcard.c | 346 +++++
855 sound/soc/bcm/audioinjector-pi-soundcard.c | 187 +++
856 sound/soc/bcm/audiosense-pi.c | 248 +++
857 sound/soc/bcm/digidac1-soundcard.c | 421 +++++
858 sound/soc/bcm/dionaudio_loco-v2.c | 117 ++
859 sound/soc/bcm/dionaudio_loco.c | 117 ++
860 sound/soc/bcm/fe-pi-audio.c | 154 ++
861 sound/soc/bcm/googlevoicehat-codec.c | 214 +++
862 sound/soc/bcm/hifiberry_dacplus.c | 424 +++++
863 sound/soc/bcm/hifiberry_dacplusadc.c | 398 +++++
864 sound/soc/bcm/hifiberry_dacplusadcpro.c | 543 +++++++
865 sound/soc/bcm/hifiberry_dacplusdsp.c | 90 ++
866 sound/soc/bcm/hifiberry_dacplushd.c | 238 +++
867 sound/soc/bcm/i-sabre-q2m.c | 158 ++
868 sound/soc/bcm/iqaudio-codec.c | 274 ++++
869 sound/soc/bcm/iqaudio-dac.c | 223 +++
870 sound/soc/bcm/justboom-both.c | 266 ++++
871 sound/soc/bcm/justboom-dac.c | 147 ++
872 sound/soc/bcm/pisound.c | 1238 +++++++++++++++
873 sound/soc/bcm/rpi-cirrus.c | 1025 ++++++++++++
874 sound/soc/bcm/rpi-proto.c | 147 ++
875 sound/soc/bcm/rpi-simple-soundcard.c | 339 ++++
876 sound/soc/bcm/rpi-wm8804-soundcard.c | 410 +++++
877 sound/soc/codecs/Kconfig | 28 +-
878 sound/soc/codecs/Makefile | 8 +
879 sound/soc/codecs/cs42xx8-i2c.c | 9 +-
880 sound/soc/codecs/cs42xx8.c | 2 +
881 sound/soc/codecs/i-sabre-codec.c | 392 +++++
882 sound/soc/codecs/i-sabre-codec.h | 42 +
883 sound/soc/codecs/ma120x0p.c | 1384 +++++++++++++++++
884 sound/soc/codecs/pcm1794a.c | 69 +
885 sound/soc/codecs/pcm512x.c | 2 +-
886 sound/soc/codecs/tas5713.c | 363 +++++
887 sound/soc/codecs/tas5713.h | 210 +++
888 sound/soc/soc-core.c | 10 +-
889 49 files changed, 13837 insertions(+), 7 deletions(-)
890 create mode 100644 Documentation/devicetree/bindings/vendor-prefixes.txt
891 create mode 100644 drivers/clk/clk-allo-dac.c
892 create mode 100644 drivers/clk/clk-hifiberry-dachd.c
893 create mode 100644 drivers/clk/clk-hifiberry-dacpro.c
894 create mode 100644 sound/soc/bcm/allo-boss-dac.c
895 create mode 100644 sound/soc/bcm/allo-katana-codec.c
896 create mode 100644 sound/soc/bcm/allo-piano-dac-plus.c
897 create mode 100644 sound/soc/bcm/allo-piano-dac.c
898 create mode 100644 sound/soc/bcm/audioinjector-isolated-soundcard.c
899 create mode 100644 sound/soc/bcm/audioinjector-octo-soundcard.c
900 create mode 100644 sound/soc/bcm/audioinjector-pi-soundcard.c
901 create mode 100644 sound/soc/bcm/audiosense-pi.c
902 create mode 100644 sound/soc/bcm/digidac1-soundcard.c
903 create mode 100644 sound/soc/bcm/dionaudio_loco-v2.c
904 create mode 100644 sound/soc/bcm/dionaudio_loco.c
905 create mode 100644 sound/soc/bcm/fe-pi-audio.c
906 create mode 100644 sound/soc/bcm/googlevoicehat-codec.c
907 create mode 100644 sound/soc/bcm/hifiberry_dacplus.c
908 create mode 100644 sound/soc/bcm/hifiberry_dacplusadc.c
909 create mode 100644 sound/soc/bcm/hifiberry_dacplusadcpro.c
910 create mode 100644 sound/soc/bcm/hifiberry_dacplusdsp.c
911 create mode 100644 sound/soc/bcm/hifiberry_dacplushd.c
912 create mode 100644 sound/soc/bcm/i-sabre-q2m.c
913 create mode 100644 sound/soc/bcm/iqaudio-codec.c
914 create mode 100644 sound/soc/bcm/iqaudio-dac.c
915 create mode 100644 sound/soc/bcm/justboom-both.c
916 create mode 100644 sound/soc/bcm/justboom-dac.c
917 create mode 100644 sound/soc/bcm/pisound.c
918 create mode 100644 sound/soc/bcm/rpi-cirrus.c
919 create mode 100644 sound/soc/bcm/rpi-proto.c
920 create mode 100644 sound/soc/bcm/rpi-simple-soundcard.c
921 create mode 100644 sound/soc/bcm/rpi-wm8804-soundcard.c
922 create mode 100644 sound/soc/codecs/i-sabre-codec.c
923 create mode 100644 sound/soc/codecs/i-sabre-codec.h
924 create mode 100644 sound/soc/codecs/ma120x0p.c
925 create mode 100644 sound/soc/codecs/pcm1794a.c
926 create mode 100644 sound/soc/codecs/tas5713.c
927 create mode 100644 sound/soc/codecs/tas5713.h
928
929 --- /dev/null
930 +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
931 @@ -0,0 +1,463 @@
932 +Device tree binding vendor prefix registry. Keep list in alphabetical order.
933 +
934 +This isn't an exhaustive list, but you should add new prefixes to it before
935 +using them to avoid name-space collisions.
936 +
937 +abilis Abilis Systems
938 +abracon Abracon Corporation
939 +actions Actions Semiconductor Co., Ltd.
940 +active-semi Active-Semi International Inc
941 +ad Avionic Design GmbH
942 +adafruit Adafruit Industries, LLC
943 +adapteva Adapteva, Inc.
944 +adaptrum Adaptrum, Inc.
945 +adh AD Holdings Plc.
946 +adi Analog Devices, Inc.
947 +advantech Advantech Corporation
948 +aeroflexgaisler Aeroflex Gaisler AB
949 +al Annapurna Labs
950 +allo Allo.com
951 +allwinner Allwinner Technology Co., Ltd.
952 +alphascale AlphaScale Integrated Circuits Systems, Inc.
953 +altr Altera Corp.
954 +amarula Amarula Solutions
955 +amazon Amazon.com, Inc.
956 +amcc Applied Micro Circuits Corporation (APM, formally AMCC)
957 +amd Advanced Micro Devices (AMD), Inc.
958 +amediatech Shenzhen Amediatech Technology Co., Ltd
959 +amlogic Amlogic, Inc.
960 +ampire Ampire Co., Ltd.
961 +ams AMS AG
962 +amstaos AMS-Taos Inc.
963 +analogix Analogix Semiconductor, Inc.
964 +andestech Andes Technology Corporation
965 +apm Applied Micro Circuits Corporation (APM)
966 +aptina Aptina Imaging
967 +arasan Arasan Chip Systems
968 +archermind ArcherMind Technology (Nanjing) Co., Ltd.
969 +arctic Arctic Sand
970 +aries Aries Embedded GmbH
971 +arm ARM Ltd.
972 +armadeus ARMadeus Systems SARL
973 +arrow Arrow Electronics
974 +artesyn Artesyn Embedded Technologies Inc.
975 +asahi-kasei Asahi Kasei Corp.
976 +aspeed ASPEED Technology Inc.
977 +asus AsusTek Computer Inc.
978 +atlas Atlas Scientific LLC
979 +atmel Atmel Corporation
980 +auo AU Optronics Corporation
981 +auvidea Auvidea GmbH
982 +avago Avago Technologies
983 +avia avia semiconductor
984 +avic Shanghai AVIC Optoelectronics Co., Ltd.
985 +avnet Avnet, Inc.
986 +axentia Axentia Technologies AB
987 +axis Axis Communications AB
988 +bananapi BIPAI KEJI LIMITED
989 +bhf Beckhoff Automation GmbH & Co. KG
990 +bitmain Bitmain Technologies
991 +blokaslabs Vilniaus Blokas UAB
992 +boe BOE Technology Group Co., Ltd.
993 +bosch Bosch Sensortec GmbH
994 +boundary Boundary Devices Inc.
995 +brcm Broadcom Corporation
996 +buffalo Buffalo, Inc.
997 +bticino Bticino International
998 +calxeda Calxeda
999 +capella Capella Microsystems, Inc
1000 +cascoda Cascoda, Ltd.
1001 +catalyst Catalyst Semiconductor, Inc.
1002 +cavium Cavium, Inc.
1003 +cdns Cadence Design Systems Inc.
1004 +cdtech CDTech(H.K.) Electronics Limited
1005 +ceva Ceva, Inc.
1006 +chipidea Chipidea, Inc
1007 +chipone ChipOne
1008 +chipspark ChipSPARK
1009 +chrp Common Hardware Reference Platform
1010 +chunghwa Chunghwa Picture Tubes Ltd.
1011 +ciaa Computadora Industrial Abierta Argentina
1012 +cirrus Cirrus Logic, Inc.
1013 +cloudengines Cloud Engines, Inc.
1014 +cnm Chips&Media, Inc.
1015 +cnxt Conexant Systems, Inc.
1016 +compulab CompuLab Ltd.
1017 +cortina Cortina Systems, Inc.
1018 +cosmic Cosmic Circuits
1019 +crane Crane Connectivity Solutions
1020 +creative Creative Technology Ltd
1021 +crystalfontz Crystalfontz America, Inc.
1022 +csky Hangzhou C-SKY Microsystems Co., Ltd
1023 +cubietech Cubietech, Ltd.
1024 +cypress Cypress Semiconductor Corporation
1025 +cznic CZ.NIC, z.s.p.o.
1026 +dallas Maxim Integrated Products (formerly Dallas Semiconductor)
1027 +dataimage DataImage, Inc.
1028 +davicom DAVICOM Semiconductor, Inc.
1029 +delta Delta Electronics, Inc.
1030 +denx Denx Software Engineering
1031 +devantech Devantech, Ltd.
1032 +dh DH electronics GmbH
1033 +digi Digi International Inc.
1034 +digilent Diglent, Inc.
1035 +dioo Dioo Microcircuit Co., Ltd
1036 +dlc DLC Display Co., Ltd.
1037 +dlg Dialog Semiconductor
1038 +dlink D-Link Corporation
1039 +dmo Data Modul AG
1040 +domintech Domintech Co., Ltd.
1041 +dongwoon Dongwoon Anatech
1042 +dptechnics DPTechnics
1043 +dragino Dragino Technology Co., Limited
1044 +ea Embedded Artists AB
1045 +ebs-systart EBS-SYSTART GmbH
1046 +ebv EBV Elektronik
1047 +eckelmann Eckelmann AG
1048 +edt Emerging Display Technologies
1049 +eeti eGalax_eMPIA Technology Inc
1050 +elan Elan Microelectronic Corp.
1051 +elgin Elgin S/A.
1052 +embest Shenzhen Embest Technology Co., Ltd.
1053 +emlid Emlid, Ltd.
1054 +emmicro EM Microelectronic
1055 +emtrion emtrion GmbH
1056 +endless Endless Mobile, Inc.
1057 +energymicro Silicon Laboratories (formerly Energy Micro AS)
1058 +engicam Engicam S.r.l.
1059 +epcos EPCOS AG
1060 +epfl Ecole Polytechnique Fédérale de Lausanne
1061 +epson Seiko Epson Corp.
1062 +est ESTeem Wireless Modems
1063 +ettus NI Ettus Research
1064 +eukrea Eukréa Electromatique
1065 +everest Everest Semiconductor Co. Ltd.
1066 +everspin Everspin Technologies, Inc.
1067 +exar Exar Corporation
1068 +excito Excito
1069 +ezchip EZchip Semiconductor
1070 +facebook Facebook
1071 +fairphone Fairphone B.V.
1072 +faraday Faraday Technology Corporation
1073 +fastrax Fastrax Oy
1074 +fcs Fairchild Semiconductor
1075 +feiyang Shenzhen Fly Young Technology Co.,LTD.
1076 +firefly Firefly
1077 +focaltech FocalTech Systems Co.,Ltd
1078 +friendlyarm Guangzhou FriendlyARM Computer Tech Co., Ltd
1079 +fsl Freescale Semiconductor
1080 +fujitsu Fujitsu Ltd.
1081 +gateworks Gateworks Corporation
1082 +gcw Game Consoles Worldwide
1083 +ge General Electric Company
1084 +geekbuying GeekBuying
1085 +gef GE Fanuc Intelligent Platforms Embedded Systems, Inc.
1086 +GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc.
1087 +geniatech Geniatech, Inc.
1088 +giantec Giantec Semiconductor, Inc.
1089 +giantplus Giantplus Technology Co., Ltd.
1090 +globalscale Globalscale Technologies, Inc.
1091 +globaltop GlobalTop Technology, Inc.
1092 +gmt Global Mixed-mode Technology, Inc.
1093 +goodix Shenzhen Huiding Technology Co., Ltd.
1094 +google Google, Inc.
1095 +grinn Grinn
1096 +grmn Garmin Limited
1097 +gumstix Gumstix, Inc.
1098 +gw Gateworks Corporation
1099 +hannstar HannStar Display Corporation
1100 +haoyu Haoyu Microelectronic Co. Ltd.
1101 +hardkernel Hardkernel Co., Ltd
1102 +hideep HiDeep Inc.
1103 +himax Himax Technologies, Inc.
1104 +hisilicon Hisilicon Limited.
1105 +hit Hitachi Ltd.
1106 +hitex Hitex Development Tools
1107 +holt Holt Integrated Circuits, Inc.
1108 +honeywell Honeywell
1109 +hp Hewlett Packard
1110 +holtek Holtek Semiconductor, Inc.
1111 +hwacom HwaCom Systems Inc.
1112 +i2se I2SE GmbH
1113 +ibm International Business Machines (IBM)
1114 +icplus IC Plus Corp.
1115 +idt Integrated Device Technologies, Inc.
1116 +ifi Ingenieurburo Fur Ic-Technologie (I/F/I)
1117 +ilitek ILI Technology Corporation (ILITEK)
1118 +img Imagination Technologies Ltd.
1119 +infineon Infineon Technologies
1120 +inforce Inforce Computing
1121 +ingenic Ingenic Semiconductor
1122 +innolux Innolux Corporation
1123 +inside-secure INSIDE Secure
1124 +intel Intel Corporation
1125 +intercontrol Inter Control Group
1126 +invensense InvenSense Inc.
1127 +inversepath Inverse Path
1128 +iom Iomega Corporation
1129 +isee ISEE 2007 S.L.
1130 +isil Intersil
1131 +issi Integrated Silicon Solutions Inc.
1132 +itead ITEAD Intelligent Systems Co.Ltd
1133 +iwave iWave Systems Technologies Pvt. Ltd.
1134 +jdi Japan Display Inc.
1135 +jedec JEDEC Solid State Technology Association
1136 +jianda Jiandangjing Technology Co., Ltd.
1137 +karo Ka-Ro electronics GmbH
1138 +keithkoep Keith & Koep GmbH
1139 +keymile Keymile GmbH
1140 +khadas Khadas
1141 +kiebackpeter Kieback & Peter GmbH
1142 +kinetic Kinetic Technologies
1143 +kingdisplay King & Display Technology Co., Ltd.
1144 +kingnovel Kingnovel Technology Co., Ltd.
1145 +koe Kaohsiung Opto-Electronics Inc.
1146 +kosagi Sutajio Ko-Usagi PTE Ltd.
1147 +kyo Kyocera Corporation
1148 +lacie LaCie
1149 +laird Laird PLC
1150 +lantiq Lantiq Semiconductor
1151 +lattice Lattice Semiconductor
1152 +lego LEGO Systems A/S
1153 +lemaker Shenzhen LeMaker Technology Co., Ltd.
1154 +lenovo Lenovo Group Ltd.
1155 +lg LG Corporation
1156 +libretech Shenzhen Libre Technology Co., Ltd
1157 +licheepi Lichee Pi
1158 +linaro Linaro Limited
1159 +linksys Belkin International, Inc. (Linksys)
1160 +linux Linux-specific binding
1161 +linx Linx Technologies
1162 +lltc Linear Technology Corporation
1163 +logicpd Logic PD, Inc.
1164 +lsi LSI Corp. (LSI Logic)
1165 +lwn Liebherr-Werk Nenzing GmbH
1166 +macnica Macnica Americas
1167 +marvell Marvell Technology Group Ltd.
1168 +maxim Maxim Integrated Products
1169 +mbvl Mobiveil Inc.
1170 +mcube mCube
1171 +meas Measurement Specialties
1172 +mediatek MediaTek Inc.
1173 +megachips MegaChips
1174 +mele Shenzhen MeLE Digital Technology Ltd.
1175 +melexis Melexis N.V.
1176 +melfas MELFAS Inc.
1177 +mellanox Mellanox Technologies
1178 +memsic MEMSIC Inc.
1179 +merrii Merrii Technology Co., Ltd.
1180 +micrel Micrel Inc.
1181 +microchip Microchip Technology Inc.
1182 +microcrystal Micro Crystal AG
1183 +micron Micron Technology Inc.
1184 +mikroe MikroElektronika d.o.o.
1185 +minix MINIX Technology Ltd.
1186 +miramems MiraMEMS Sensing Technology Co., Ltd.
1187 +mitsubishi Mitsubishi Electric Corporation
1188 +mosaixtech Mosaix Technologies, Inc.
1189 +motorola Motorola, Inc.
1190 +moxa Moxa Inc.
1191 +mpl MPL AG
1192 +mqmaker mqmaker Inc.
1193 +mscc Microsemi Corporation
1194 +msi Micro-Star International Co. Ltd.
1195 +mti Imagination Technologies Ltd. (formerly MIPS Technologies Inc.)
1196 +multi-inno Multi-Inno Technology Co.,Ltd
1197 +mundoreader Mundo Reader S.L.
1198 +murata Murata Manufacturing Co., Ltd.
1199 +mxicy Macronix International Co., Ltd.
1200 +myir MYIR Tech Limited
1201 +national National Semiconductor
1202 +nec NEC LCD Technologies, Ltd.
1203 +neonode Neonode Inc.
1204 +netgear NETGEAR
1205 +netlogic Broadcom Corporation (formerly NetLogic Microsystems)
1206 +netron-dy Netron DY
1207 +netxeon Shenzhen Netxeon Technology CO., LTD
1208 +nexbox Nexbox
1209 +nextthing Next Thing Co.
1210 +newhaven Newhaven Display International
1211 +ni National Instruments
1212 +nintendo Nintendo
1213 +nlt NLT Technologies, Ltd.
1214 +nokia Nokia
1215 +nordic Nordic Semiconductor
1216 +novtech NovTech, Inc.
1217 +nutsboard NutsBoard
1218 +nuvoton Nuvoton Technology Corporation
1219 +nvd New Vision Display
1220 +nvidia NVIDIA
1221 +nxp NXP Semiconductors
1222 +okaya Okaya Electric America, Inc.
1223 +oki Oki Electric Industry Co., Ltd.
1224 +olimex OLIMEX Ltd.
1225 +olpc One Laptop Per Child
1226 +onion Onion Corporation
1227 +onnn ON Semiconductor Corp.
1228 +ontat On Tat Industrial Company
1229 +opalkelly Opal Kelly Incorporated
1230 +opencores OpenCores.org
1231 +openrisc OpenRISC.io
1232 +option Option NV
1233 +oranth Shenzhen Oranth Technology Co., Ltd.
1234 +ORCL Oracle Corporation
1235 +orisetech Orise Technology
1236 +ortustech Ortus Technology Co., Ltd.
1237 +ovti OmniVision Technologies
1238 +oxsemi Oxford Semiconductor, Ltd.
1239 +panasonic Panasonic Corporation
1240 +parade Parade Technologies Inc.
1241 +pda Precision Design Associates, Inc.
1242 +pericom Pericom Technology Inc.
1243 +pervasive Pervasive Displays, Inc.
1244 +phicomm PHICOMM Co., Ltd.
1245 +phytec PHYTEC Messtechnik GmbH
1246 +picochip Picochip Ltd
1247 +pine64 Pine64
1248 +pixcir PIXCIR MICROELECTRONICS Co., Ltd
1249 +plantower Plantower Co., Ltd
1250 +plathome Plat'Home Co., Ltd.
1251 +plda PLDA
1252 +plx Broadcom Corporation (formerly PLX Technology)
1253 +pni PNI Sensor Corporation
1254 +portwell Portwell Inc.
1255 +poslab Poslab Technology Co., Ltd.
1256 +powervr PowerVR (deprecated, use img)
1257 +probox2 PROBOX2 (by W2COMP Co., Ltd.)
1258 +pulsedlight PulsedLight, Inc
1259 +qca Qualcomm Atheros, Inc.
1260 +qcom Qualcomm Technologies, Inc
1261 +qemu QEMU, a generic and open source machine emulator and virtualizer
1262 +qi Qi Hardware
1263 +qiaodian QiaoDian XianShi Corporation
1264 +qnap QNAP Systems, Inc.
1265 +radxa Radxa
1266 +raidsonic RaidSonic Technology GmbH
1267 +ralink Mediatek/Ralink Technology Corp.
1268 +ramtron Ramtron International
1269 +raspberrypi Raspberry Pi Foundation
1270 +raydium Raydium Semiconductor Corp.
1271 +rda Unisoc Communications, Inc.
1272 +realtek Realtek Semiconductor Corp.
1273 +renesas Renesas Electronics Corporation
1274 +richtek Richtek Technology Corporation
1275 +ricoh Ricoh Co. Ltd.
1276 +rikomagic Rikomagic Tech Corp. Ltd
1277 +riscv RISC-V Foundation
1278 +rockchip Fuzhou Rockchip Electronics Co., Ltd
1279 +rohm ROHM Semiconductor Co., Ltd
1280 +roofull Shenzhen Roofull Technology Co, Ltd
1281 +samsung Samsung Semiconductor
1282 +samtec Samtec/Softing company
1283 +sancloud Sancloud Ltd
1284 +sandisk Sandisk Corporation
1285 +sbs Smart Battery System
1286 +schindler Schindler
1287 +seagate Seagate Technology PLC
1288 +semtech Semtech Corporation
1289 +sensirion Sensirion AG
1290 +sff Small Form Factor Committee
1291 +sgd Solomon Goldentek Display Corporation
1292 +sgx SGX Sensortech
1293 +sharp Sharp Corporation
1294 +shimafuji Shimafuji Electric, Inc.
1295 +si-en Si-En Technology Ltd.
1296 +sifive SiFive, Inc.
1297 +sigma Sigma Designs, Inc.
1298 +sii Seiko Instruments, Inc.
1299 +sil Silicon Image
1300 +silabs Silicon Laboratories
1301 +silead Silead Inc.
1302 +silergy Silergy Corp.
1303 +siliconmitus Silicon Mitus, Inc.
1304 +simtek
1305 +sirf SiRF Technology, Inc.
1306 +sis Silicon Integrated Systems Corp.
1307 +sitronix Sitronix Technology Corporation
1308 +skyworks Skyworks Solutions, Inc.
1309 +smsc Standard Microsystems Corporation
1310 +snps Synopsys, Inc.
1311 +socionext Socionext Inc.
1312 +solidrun SolidRun
1313 +solomon Solomon Systech Limited
1314 +sony Sony Corporation
1315 +spansion Spansion Inc.
1316 +sprd Spreadtrum Communications Inc.
1317 +sst Silicon Storage Technology, Inc.
1318 +st STMicroelectronics
1319 +starry Starry Electronic Technology (ShenZhen) Co., LTD
1320 +startek Startek
1321 +ste ST-Ericsson
1322 +stericsson ST-Ericsson
1323 +summit Summit microelectronics
1324 +sunchip Shenzhen Sunchip Technology Co., Ltd
1325 +SUNW Sun Microsystems, Inc
1326 +swir Sierra Wireless
1327 +syna Synaptics Inc.
1328 +synology Synology, Inc.
1329 +tbs TBS Technologies
1330 +tbs-biometrics Touchless Biometric Systems AG
1331 +tcg Trusted Computing Group
1332 +tcl Toby Churchill Ltd.
1333 +technexion TechNexion
1334 +technologic Technologic Systems
1335 +tempo Tempo Semiconductor
1336 +techstar Shenzhen Techstar Electronics Co., Ltd.
1337 +terasic Terasic Inc.
1338 +thine THine Electronics, Inc.
1339 +ti Texas Instruments
1340 +tianma Tianma Micro-electronics Co., Ltd.
1341 +tlm Trusted Logic Mobility
1342 +tmt Tecon Microprocessor Technologies, LLC.
1343 +topeet Topeet
1344 +toradex Toradex AG
1345 +toshiba Toshiba Corporation
1346 +toumaz Toumaz
1347 +tpk TPK U.S.A. LLC
1348 +tplink TP-LINK Technologies Co., Ltd.
1349 +tpo TPO
1350 +tronfy Tronfy
1351 +tronsmart Tronsmart
1352 +truly Truly Semiconductors Limited
1353 +tsd Theobroma Systems Design und Consulting GmbH
1354 +tyan Tyan Computer Corporation
1355 +u-blox u-blox
1356 +ucrobotics uCRobotics
1357 +ubnt Ubiquiti Networks
1358 +udoo Udoo
1359 +uniwest United Western Technologies Corp (UniWest)
1360 +upisemi uPI Semiconductor Corp.
1361 +urt United Radiant Technology Corporation
1362 +usi Universal Scientific Industrial Co., Ltd.
1363 +v3 V3 Semiconductor
1364 +vamrs Vamrs Ltd.
1365 +variscite Variscite Ltd.
1366 +via VIA Technologies, Inc.
1367 +virtio Virtual I/O Device Specification, developed by the OASIS consortium
1368 +vishay Vishay Intertechnology, Inc
1369 +vitesse Vitesse Semiconductor Corporation
1370 +vivante Vivante Corporation
1371 +vocore VoCore Studio
1372 +voipac Voipac Technologies s.r.o.
1373 +vot Vision Optical Technology Co., Ltd.
1374 +wd Western Digital Corp.
1375 +wetek WeTek Electronics, limited.
1376 +wexler Wexler
1377 +whwave Shenzhen whwave Electronics, Inc.
1378 +wi2wi Wi2Wi, Inc.
1379 +winbond Winbond Electronics corp.
1380 +winstar Winstar Display Corp.
1381 +wlf Wolfson Microelectronics
1382 +wm Wondermedia Technologies, Inc.
1383 +x-powers X-Powers
1384 +xes Extreme Engineering Solutions (X-ES)
1385 +xillybus Xillybus Ltd.
1386 +xlnx Xilinx
1387 +xunlong Shenzhen Xunlong Software CO.,Limited
1388 +ysoft Y Soft Corporation a.s.
1389 +zarlink Zarlink Semiconductor
1390 +zeitec ZEITEC Semiconductor Co., LTD.
1391 +zidoo Shenzhen Zidoo Technology Co., Ltd.
1392 +zii Zodiac Inflight Innovations
1393 +zte ZTE Corp.
1394 +zyxel ZyXEL Communications Corp.
1395 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
1396 +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
1397 @@ -159,6 +159,8 @@ patternProperties:
1398 description: Beckhoff Automation GmbH & Co. KG
1399 "^bitmain,.*":
1400 description: Bitmain Technologies
1401 + "^blokaslabs,.*":
1402 + description: Vilniaus Blokas UAB
1403 "^boe,.*":
1404 description: BOE Technology Group Co., Ltd.
1405 "^bosch,.*":
1406 --- a/drivers/clk/Kconfig
1407 +++ b/drivers/clk/Kconfig
1408 @@ -86,6 +86,12 @@ config COMMON_CLK_HI655X
1409 multi-function device has one fixed-rate oscillator, clocked
1410 at 32KHz.
1411
1412 +config COMMON_CLK_HIFIBERRY_DACPLUSHD
1413 + tristate
1414 +
1415 +config COMMON_CLK_HIFIBERRY_DACPRO
1416 + tristate
1417 +
1418 config COMMON_CLK_SCMI
1419 tristate "Clock driver controlled via SCMI interface"
1420 depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
1421 --- a/drivers/clk/Makefile
1422 +++ b/drivers/clk/Makefile
1423 @@ -18,6 +18,7 @@ endif
1424
1425 # hardware specific clock types
1426 # please keep this section sorted lexicographically by file path name
1427 +obj-$(CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC) += clk-allo-dac.o
1428 obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o
1429 obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
1430 obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o
1431 @@ -37,6 +38,8 @@ obj-$(CONFIG_MACH_ASPEED_G6) += clk-ast
1432 obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
1433 obj-$(CONFIG_CLK_HSDK) += clk-hsdk-pll.o
1434 obj-$(CONFIG_COMMON_CLK_LOCHNAGAR) += clk-lochnagar.o
1435 +obj-$(CONFIG_COMMON_CLK_HIFIBERRY_DACPRO) += clk-hifiberry-dacpro.o
1436 +obj-$(CONFIG_COMMON_CLK_HIFIBERRY_DACPLUSHD) += clk-hifiberry-dachd.o
1437 obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
1438 obj-$(CONFIG_COMMON_CLK_MAX9485) += clk-max9485.o
1439 obj-$(CONFIG_ARCH_MILBEAUT_M10V) += clk-milbeaut.o
1440 --- /dev/null
1441 +++ b/drivers/clk/clk-allo-dac.c
1442 @@ -0,0 +1,161 @@
1443 +/*
1444 + * Clock Driver for Allo DAC
1445 + *
1446 + * Author: Baswaraj K <jaikumar@cem-solutions.net>
1447 + * Copyright 2016
1448 + * based on code by Stuart MacLean
1449 + *
1450 + * This program is free software; you can redistribute it and/or
1451 + * modify it under the terms of the GNU General Public License
1452 + * version 2 as published by the Free Software Foundation.
1453 + *
1454 + * This program is distributed in the hope that it will be useful, but
1455 + * WITHOUT ANY WARRANTY; without even the implied warranty of
1456 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1457 + * General Public License for more details.
1458 + */
1459 +
1460 +#include <linux/clk-provider.h>
1461 +#include <linux/clkdev.h>
1462 +#include <linux/kernel.h>
1463 +#include <linux/module.h>
1464 +#include <linux/of.h>
1465 +#include <linux/slab.h>
1466 +#include <linux/platform_device.h>
1467 +
1468 +/* Clock rate of CLK44EN attached to GPIO6 pin */
1469 +#define CLK_44EN_RATE 45158400UL
1470 +/* Clock rate of CLK48EN attached to GPIO3 pin */
1471 +#define CLK_48EN_RATE 49152000UL
1472 +
1473 +/**
1474 + * struct allo_dac_clk - Common struct to the Allo DAC
1475 + * @hw: clk_hw for the common clk framework
1476 + * @mode: 0 => CLK44EN, 1 => CLK48EN
1477 + */
1478 +struct clk_allo_hw {
1479 + struct clk_hw hw;
1480 + uint8_t mode;
1481 +};
1482 +
1483 +#define to_allo_clk(_hw) container_of(_hw, struct clk_allo_hw, hw)
1484 +
1485 +static const struct of_device_id clk_allo_dac_dt_ids[] = {
1486 + { .compatible = "allo,dac-clk",},
1487 + { }
1488 +};
1489 +MODULE_DEVICE_TABLE(of, clk_allo_dac_dt_ids);
1490 +
1491 +static unsigned long clk_allo_dac_recalc_rate(struct clk_hw *hw,
1492 + unsigned long parent_rate)
1493 +{
1494 + return (to_allo_clk(hw)->mode == 0) ? CLK_44EN_RATE :
1495 + CLK_48EN_RATE;
1496 +}
1497 +
1498 +static long clk_allo_dac_round_rate(struct clk_hw *hw,
1499 + unsigned long rate, unsigned long *parent_rate)
1500 +{
1501 + long actual_rate;
1502 +
1503 + if (rate <= CLK_44EN_RATE) {
1504 + actual_rate = (long)CLK_44EN_RATE;
1505 + } else if (rate >= CLK_48EN_RATE) {
1506 + actual_rate = (long)CLK_48EN_RATE;
1507 + } else {
1508 + long diff44Rate = (long)(rate - CLK_44EN_RATE);
1509 + long diff48Rate = (long)(CLK_48EN_RATE - rate);
1510 +
1511 + if (diff44Rate < diff48Rate)
1512 + actual_rate = (long)CLK_44EN_RATE;
1513 + else
1514 + actual_rate = (long)CLK_48EN_RATE;
1515 + }
1516 + return actual_rate;
1517 +}
1518 +
1519 +
1520 +static int clk_allo_dac_set_rate(struct clk_hw *hw,
1521 + unsigned long rate, unsigned long parent_rate)
1522 +{
1523 + unsigned long actual_rate;
1524 + struct clk_allo_hw *clk = to_allo_clk(hw);
1525 +
1526 + actual_rate = (unsigned long)clk_allo_dac_round_rate(hw, rate,
1527 + &parent_rate);
1528 + clk->mode = (actual_rate == CLK_44EN_RATE) ? 0 : 1;
1529 + return 0;
1530 +}
1531 +
1532 +
1533 +const struct clk_ops clk_allo_dac_rate_ops = {
1534 + .recalc_rate = clk_allo_dac_recalc_rate,
1535 + .round_rate = clk_allo_dac_round_rate,
1536 + .set_rate = clk_allo_dac_set_rate,
1537 +};
1538 +
1539 +static int clk_allo_dac_probe(struct platform_device *pdev)
1540 +{
1541 + int ret;
1542 + struct clk_allo_hw *proclk;
1543 + struct clk *clk;
1544 + struct device *dev;
1545 + struct clk_init_data init;
1546 +
1547 + dev = &pdev->dev;
1548 +
1549 + proclk = kzalloc(sizeof(struct clk_allo_hw), GFP_KERNEL);
1550 + if (!proclk)
1551 + return -ENOMEM;
1552 +
1553 + init.name = "clk-allo-dac";
1554 + init.ops = &clk_allo_dac_rate_ops;
1555 + init.flags = 0;
1556 + init.parent_names = NULL;
1557 + init.num_parents = 0;
1558 +
1559 + proclk->mode = 0;
1560 + proclk->hw.init = &init;
1561 +
1562 + clk = devm_clk_register(dev, &proclk->hw);
1563 + if (!IS_ERR(clk)) {
1564 + ret = of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
1565 + clk);
1566 + } else {
1567 + dev_err(dev, "Fail to register clock driver\n");
1568 + kfree(proclk);
1569 + ret = PTR_ERR(clk);
1570 + }
1571 + return ret;
1572 +}
1573 +
1574 +static int clk_allo_dac_remove(struct platform_device *pdev)
1575 +{
1576 + of_clk_del_provider(pdev->dev.of_node);
1577 + return 0;
1578 +}
1579 +
1580 +static struct platform_driver clk_allo_dac_driver = {
1581 + .probe = clk_allo_dac_probe,
1582 + .remove = clk_allo_dac_remove,
1583 + .driver = {
1584 + .name = "clk-allo-dac",
1585 + .of_match_table = clk_allo_dac_dt_ids,
1586 + },
1587 +};
1588 +
1589 +static int __init clk_allo_dac_init(void)
1590 +{
1591 + return platform_driver_register(&clk_allo_dac_driver);
1592 +}
1593 +core_initcall(clk_allo_dac_init);
1594 +
1595 +static void __exit clk_allo_dac_exit(void)
1596 +{
1597 + platform_driver_unregister(&clk_allo_dac_driver);
1598 +}
1599 +module_exit(clk_allo_dac_exit);
1600 +
1601 +MODULE_DESCRIPTION("Allo DAC clock driver");
1602 +MODULE_LICENSE("GPL v2");
1603 +MODULE_ALIAS("platform:clk-allo-dac");
1604 --- /dev/null
1605 +++ b/drivers/clk/clk-hifiberry-dachd.c
1606 @@ -0,0 +1,333 @@
1607 +// SPDX-License-Identifier: GPL-2.0
1608 +/*
1609 + * Clock Driver for HiFiBerry DAC+ HD
1610 + *
1611 + * Author: Joerg Schambacher, i2Audio GmbH for HiFiBerry
1612 + * Copyright 2020
1613 + *
1614 + * This program is free software; you can redistribute it and/or
1615 + * modify it under the terms of the GNU General Public License
1616 + * version 2 as published by the Free Software Foundation.
1617 + *
1618 + * This program is distributed in the hope that it will be useful, but
1619 + * WITHOUT ANY WARRANTY; without even the implied warranty of
1620 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1621 + * General Public License for more details.
1622 + */
1623 +
1624 +#include <linux/clk-provider.h>
1625 +#include <linux/clk.h>
1626 +#include <linux/kernel.h>
1627 +#include <linux/module.h>
1628 +#include <linux/of.h>
1629 +#include <linux/slab.h>
1630 +#include <linux/platform_device.h>
1631 +#include <linux/i2c.h>
1632 +#include <linux/regmap.h>
1633 +
1634 +#define NO_PLL_RESET 0
1635 +#define PLL_RESET 1
1636 +#define HIFIBERRY_PLL_MAX_REGISTER 256
1637 +#define DEFAULT_RATE 44100
1638 +
1639 +static struct reg_default hifiberry_pll_reg_defaults[] = {
1640 + {0x02, 0x53}, {0x03, 0x00}, {0x07, 0x20}, {0x0F, 0x00},
1641 + {0x10, 0x0D}, {0x11, 0x1D}, {0x12, 0x0D}, {0x13, 0x8C},
1642 + {0x14, 0x8C}, {0x15, 0x8C}, {0x16, 0x8C}, {0x17, 0x8C},
1643 + {0x18, 0x2A}, {0x1C, 0x00}, {0x1D, 0x0F}, {0x1F, 0x00},
1644 + {0x2A, 0x00}, {0x2C, 0x00}, {0x2F, 0x00}, {0x30, 0x00},
1645 + {0x31, 0x00}, {0x32, 0x00}, {0x34, 0x00}, {0x37, 0x00},
1646 + {0x38, 0x00}, {0x39, 0x00}, {0x3A, 0x00}, {0x3B, 0x01},
1647 + {0x3E, 0x00}, {0x3F, 0x00}, {0x40, 0x00}, {0x41, 0x00},
1648 + {0x5A, 0x00}, {0x5B, 0x00}, {0x95, 0x00}, {0x96, 0x00},
1649 + {0x97, 0x00}, {0x98, 0x00}, {0x99, 0x00}, {0x9A, 0x00},
1650 + {0x9B, 0x00}, {0xA2, 0x00}, {0xA3, 0x00}, {0xA4, 0x00},
1651 + {0xB7, 0x92},
1652 + {0x1A, 0x3D}, {0x1B, 0x09}, {0x1E, 0xF3}, {0x20, 0x13},
1653 + {0x21, 0x75}, {0x2B, 0x04}, {0x2D, 0x11}, {0x2E, 0xE0},
1654 + {0x3D, 0x7A},
1655 + {0x35, 0x9D}, {0x36, 0x00}, {0x3C, 0x42},
1656 + { 177, 0xAC},
1657 +};
1658 +static struct reg_default common_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
1659 +static int num_common_pll_regs;
1660 +static struct reg_default dedicated_192k_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
1661 +static int num_dedicated_192k_pll_regs;
1662 +static struct reg_default dedicated_96k_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
1663 +static int num_dedicated_96k_pll_regs;
1664 +static struct reg_default dedicated_48k_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
1665 +static int num_dedicated_48k_pll_regs;
1666 +static struct reg_default dedicated_176k4_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
1667 +static int num_dedicated_176k4_pll_regs;
1668 +static struct reg_default dedicated_88k2_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
1669 +static int num_dedicated_88k2_pll_regs;
1670 +static struct reg_default dedicated_44k1_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
1671 +static int num_dedicated_44k1_pll_regs;
1672 +
1673 +/**
1674 + * struct clk_hifiberry_drvdata - Common struct to the HiFiBerry DAC HD Clk
1675 + * @hw: clk_hw for the common clk framework
1676 + */
1677 +struct clk_hifiberry_drvdata {
1678 + struct regmap *regmap;
1679 + struct clk *clk;
1680 + struct clk_hw hw;
1681 + unsigned long rate;
1682 +};
1683 +
1684 +#define to_hifiberry_clk(_hw) \
1685 + container_of(_hw, struct clk_hifiberry_drvdata, hw)
1686 +
1687 +static int clk_hifiberry_dachd_write_pll_regs(struct regmap *regmap,
1688 + struct reg_default *regs,
1689 + int num, int do_pll_reset)
1690 +{
1691 + int i;
1692 + int ret = 0;
1693 + char pll_soft_reset[] = { 177, 0xAC, };
1694 +
1695 + for (i = 0; i < num; i++) {
1696 + ret |= regmap_write(regmap, regs[i].reg, regs[i].def);
1697 + if (ret)
1698 + return ret;
1699 + }
1700 + if (do_pll_reset) {
1701 + ret |= regmap_write(regmap, pll_soft_reset[0],
1702 + pll_soft_reset[1]);
1703 + mdelay(10);
1704 + }
1705 + return ret;
1706 +}
1707 +
1708 +static unsigned long clk_hifiberry_dachd_recalc_rate(struct clk_hw *hw,
1709 + unsigned long parent_rate)
1710 +{
1711 + return to_hifiberry_clk(hw)->rate;
1712 +}
1713 +
1714 +static long clk_hifiberry_dachd_round_rate(struct clk_hw *hw,
1715 + unsigned long rate, unsigned long *parent_rate)
1716 +{
1717 + return rate;
1718 +}
1719 +
1720 +static int clk_hifiberry_dachd_set_rate(struct clk_hw *hw,
1721 + unsigned long rate, unsigned long parent_rate)
1722 +{
1723 + int ret;
1724 + struct clk_hifiberry_drvdata *drvdata = to_hifiberry_clk(hw);
1725 +
1726 + switch (rate) {
1727 + case 44100:
1728 + ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
1729 + dedicated_44k1_pll_regs, num_dedicated_44k1_pll_regs,
1730 + PLL_RESET);
1731 + break;
1732 + case 88200:
1733 + ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
1734 + dedicated_88k2_pll_regs, num_dedicated_88k2_pll_regs,
1735 + PLL_RESET);
1736 + break;
1737 + case 176400:
1738 + ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
1739 + dedicated_176k4_pll_regs, num_dedicated_176k4_pll_regs,
1740 + PLL_RESET);
1741 + break;
1742 + case 48000:
1743 + ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
1744 + dedicated_48k_pll_regs, num_dedicated_48k_pll_regs,
1745 + PLL_RESET);
1746 + break;
1747 + case 96000:
1748 + ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
1749 + dedicated_96k_pll_regs, num_dedicated_96k_pll_regs,
1750 + PLL_RESET);
1751 + break;
1752 + case 192000:
1753 + ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
1754 + dedicated_192k_pll_regs, num_dedicated_192k_pll_regs,
1755 + PLL_RESET);
1756 + break;
1757 + default:
1758 + ret = -EINVAL;
1759 + break;
1760 + }
1761 + to_hifiberry_clk(hw)->rate = rate;
1762 +
1763 + return ret;
1764 +}
1765 +
1766 +const struct clk_ops clk_hifiberry_dachd_rate_ops = {
1767 + .recalc_rate = clk_hifiberry_dachd_recalc_rate,
1768 + .round_rate = clk_hifiberry_dachd_round_rate,
1769 + .set_rate = clk_hifiberry_dachd_set_rate,
1770 +};
1771 +
1772 +static int clk_hifiberry_get_prop_values(struct device *dev,
1773 + char *prop_name,
1774 + struct reg_default *regs)
1775 +{
1776 + int ret;
1777 + int i;
1778 + u8 tmp[2 * HIFIBERRY_PLL_MAX_REGISTER];
1779 +
1780 + ret = of_property_read_variable_u8_array(dev->of_node, prop_name,
1781 + tmp, 0, 2 * HIFIBERRY_PLL_MAX_REGISTER);
1782 + if (ret < 0)
1783 + return ret;
1784 + if (ret & 1) {
1785 + dev_err(dev,
1786 + "%s <%s> -> #%i odd number of bytes for reg/val pairs!",
1787 + __func__,
1788 + prop_name,
1789 + ret);
1790 + return -EINVAL;
1791 + }
1792 + ret /= 2;
1793 + for (i = 0; i < ret; i++) {
1794 + regs[i].reg = (u32)tmp[2 * i];
1795 + regs[i].def = (u32)tmp[2 * i + 1];
1796 + }
1797 + return ret;
1798 +}
1799 +
1800 +
1801 +static int clk_hifiberry_dachd_dt_parse(struct device *dev)
1802 +{
1803 + num_common_pll_regs = clk_hifiberry_get_prop_values(dev,
1804 + "common_pll_regs", common_pll_regs);
1805 + num_dedicated_44k1_pll_regs = clk_hifiberry_get_prop_values(dev,
1806 + "44k1_pll_regs", dedicated_44k1_pll_regs);
1807 + num_dedicated_88k2_pll_regs = clk_hifiberry_get_prop_values(dev,
1808 + "88k2_pll_regs", dedicated_88k2_pll_regs);
1809 + num_dedicated_176k4_pll_regs = clk_hifiberry_get_prop_values(dev,
1810 + "176k4_pll_regs", dedicated_176k4_pll_regs);
1811 + num_dedicated_48k_pll_regs = clk_hifiberry_get_prop_values(dev,
1812 + "48k_pll_regs", dedicated_48k_pll_regs);
1813 + num_dedicated_96k_pll_regs = clk_hifiberry_get_prop_values(dev,
1814 + "96k_pll_regs", dedicated_96k_pll_regs);
1815 + num_dedicated_192k_pll_regs = clk_hifiberry_get_prop_values(dev,
1816 + "192k_pll_regs", dedicated_192k_pll_regs);
1817 + return 0;
1818 +}
1819 +
1820 +
1821 +static int clk_hifiberry_dachd_remove(struct device *dev)
1822 +{
1823 + of_clk_del_provider(dev->of_node);
1824 + return 0;
1825 +}
1826 +
1827 +const struct regmap_config hifiberry_pll_regmap = {
1828 + .reg_bits = 8,
1829 + .val_bits = 8,
1830 + .max_register = HIFIBERRY_PLL_MAX_REGISTER,
1831 + .reg_defaults = hifiberry_pll_reg_defaults,
1832 + .num_reg_defaults = ARRAY_SIZE(hifiberry_pll_reg_defaults),
1833 + .cache_type = REGCACHE_RBTREE,
1834 +};
1835 +EXPORT_SYMBOL_GPL(hifiberry_pll_regmap);
1836 +
1837 +
1838 +static int clk_hifiberry_dachd_i2c_probe(struct i2c_client *i2c,
1839 + const struct i2c_device_id *id)
1840 +{
1841 + struct clk_hifiberry_drvdata *hdclk;
1842 + int ret = 0;
1843 + struct clk_init_data init;
1844 + struct device *dev = &i2c->dev;
1845 + struct device_node *dev_node = dev->of_node;
1846 + struct regmap_config config = hifiberry_pll_regmap;
1847 +
1848 + hdclk = devm_kzalloc(&i2c->dev,
1849 + sizeof(struct clk_hifiberry_drvdata), GFP_KERNEL);
1850 + if (!hdclk)
1851 + return -ENOMEM;
1852 +
1853 + i2c_set_clientdata(i2c, hdclk);
1854 +
1855 + hdclk->regmap = devm_regmap_init_i2c(i2c, &config);
1856 +
1857 + if (IS_ERR(hdclk->regmap))
1858 + return PTR_ERR(hdclk->regmap);
1859 +
1860 + /* start PLL to allow detection of DAC */
1861 + ret = clk_hifiberry_dachd_write_pll_regs(hdclk->regmap,
1862 + hifiberry_pll_reg_defaults,
1863 + ARRAY_SIZE(hifiberry_pll_reg_defaults),
1864 + PLL_RESET);
1865 + if (ret)
1866 + return ret;
1867 +
1868 + clk_hifiberry_dachd_dt_parse(dev);
1869 +
1870 + /* restart PLL with configs from DTB */
1871 + ret = clk_hifiberry_dachd_write_pll_regs(hdclk->regmap, common_pll_regs,
1872 + num_common_pll_regs, PLL_RESET);
1873 + if (ret)
1874 + return ret;
1875 +
1876 + init.name = "clk-hifiberry-dachd";
1877 + init.ops = &clk_hifiberry_dachd_rate_ops;
1878 + init.flags = 0;
1879 + init.parent_names = NULL;
1880 + init.num_parents = 0;
1881 +
1882 + hdclk->hw.init = &init;
1883 +
1884 + hdclk->clk = devm_clk_register(dev, &hdclk->hw);
1885 + if (IS_ERR(hdclk->clk)) {
1886 + dev_err(dev, "unable to register %s\n", init.name);
1887 + return PTR_ERR(hdclk->clk);
1888 + }
1889 +
1890 + ret = of_clk_add_provider(dev_node, of_clk_src_simple_get, hdclk->clk);
1891 + if (ret != 0) {
1892 + dev_err(dev, "Cannot of_clk_add_provider");
1893 + return ret;
1894 + }
1895 +
1896 + ret = clk_set_rate(hdclk->hw.clk, DEFAULT_RATE);
1897 + if (ret != 0) {
1898 + dev_err(dev, "Cannot set rate : %d\n", ret);
1899 + return -EINVAL;
1900 + }
1901 +
1902 + return ret;
1903 +}
1904 +
1905 +static int clk_hifiberry_dachd_i2c_remove(struct i2c_client *i2c)
1906 +{
1907 + clk_hifiberry_dachd_remove(&i2c->dev);
1908 + return 0;
1909 +}
1910 +
1911 +static const struct i2c_device_id clk_hifiberry_dachd_i2c_id[] = {
1912 + { "dachd-clk", },
1913 + { }
1914 +};
1915 +MODULE_DEVICE_TABLE(i2c, clk_hifiberry_dachd_i2c_id);
1916 +
1917 +static const struct of_device_id clk_hifiberry_dachd_of_match[] = {
1918 + { .compatible = "hifiberry,dachd-clk", },
1919 + { }
1920 +};
1921 +MODULE_DEVICE_TABLE(of, clk_hifiberry_dachd_of_match);
1922 +
1923 +static struct i2c_driver clk_hifiberry_dachd_i2c_driver = {
1924 + .probe = clk_hifiberry_dachd_i2c_probe,
1925 + .remove = clk_hifiberry_dachd_i2c_remove,
1926 + .id_table = clk_hifiberry_dachd_i2c_id,
1927 + .driver = {
1928 + .name = "dachd-clk",
1929 + .of_match_table = of_match_ptr(clk_hifiberry_dachd_of_match),
1930 + },
1931 +};
1932 +
1933 +module_i2c_driver(clk_hifiberry_dachd_i2c_driver);
1934 +
1935 +
1936 +MODULE_DESCRIPTION("HiFiBerry DAC+ HD clock driver");
1937 +MODULE_AUTHOR("Joerg Schambacher <joerg@i2audio.com>");
1938 +MODULE_LICENSE("GPL v2");
1939 +MODULE_ALIAS("platform:clk-hifiberry-dachd");
1940 --- /dev/null
1941 +++ b/drivers/clk/clk-hifiberry-dacpro.c
1942 @@ -0,0 +1,160 @@
1943 +/*
1944 + * Clock Driver for HiFiBerry DAC Pro
1945 + *
1946 + * Author: Stuart MacLean
1947 + * Copyright 2015
1948 + *
1949 + * This program is free software; you can redistribute it and/or
1950 + * modify it under the terms of the GNU General Public License
1951 + * version 2 as published by the Free Software Foundation.
1952 + *
1953 + * This program is distributed in the hope that it will be useful, but
1954 + * WITHOUT ANY WARRANTY; without even the implied warranty of
1955 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1956 + * General Public License for more details.
1957 + */
1958 +
1959 +#include <linux/clk-provider.h>
1960 +#include <linux/clkdev.h>
1961 +#include <linux/kernel.h>
1962 +#include <linux/module.h>
1963 +#include <linux/of.h>
1964 +#include <linux/slab.h>
1965 +#include <linux/platform_device.h>
1966 +
1967 +/* Clock rate of CLK44EN attached to GPIO6 pin */
1968 +#define CLK_44EN_RATE 22579200UL
1969 +/* Clock rate of CLK48EN attached to GPIO3 pin */
1970 +#define CLK_48EN_RATE 24576000UL
1971 +
1972 +/**
1973 + * struct hifiberry_dacpro_clk - Common struct to the HiFiBerry DAC Pro
1974 + * @hw: clk_hw for the common clk framework
1975 + * @mode: 0 => CLK44EN, 1 => CLK48EN
1976 + */
1977 +struct clk_hifiberry_hw {
1978 + struct clk_hw hw;
1979 + uint8_t mode;
1980 +};
1981 +
1982 +#define to_hifiberry_clk(_hw) container_of(_hw, struct clk_hifiberry_hw, hw)
1983 +
1984 +static const struct of_device_id clk_hifiberry_dacpro_dt_ids[] = {
1985 + { .compatible = "hifiberry,dacpro-clk",},
1986 + { }
1987 +};
1988 +MODULE_DEVICE_TABLE(of, clk_hifiberry_dacpro_dt_ids);
1989 +
1990 +static unsigned long clk_hifiberry_dacpro_recalc_rate(struct clk_hw *hw,
1991 + unsigned long parent_rate)
1992 +{
1993 + return (to_hifiberry_clk(hw)->mode == 0) ? CLK_44EN_RATE :
1994 + CLK_48EN_RATE;
1995 +}
1996 +
1997 +static long clk_hifiberry_dacpro_round_rate(struct clk_hw *hw,
1998 + unsigned long rate, unsigned long *parent_rate)
1999 +{
2000 + long actual_rate;
2001 +
2002 + if (rate <= CLK_44EN_RATE) {
2003 + actual_rate = (long)CLK_44EN_RATE;
2004 + } else if (rate >= CLK_48EN_RATE) {
2005 + actual_rate = (long)CLK_48EN_RATE;
2006 + } else {
2007 + long diff44Rate = (long)(rate - CLK_44EN_RATE);
2008 + long diff48Rate = (long)(CLK_48EN_RATE - rate);
2009 +
2010 + if (diff44Rate < diff48Rate)
2011 + actual_rate = (long)CLK_44EN_RATE;
2012 + else
2013 + actual_rate = (long)CLK_48EN_RATE;
2014 + }
2015 + return actual_rate;
2016 +}
2017 +
2018 +
2019 +static int clk_hifiberry_dacpro_set_rate(struct clk_hw *hw,
2020 + unsigned long rate, unsigned long parent_rate)
2021 +{
2022 + unsigned long actual_rate;
2023 + struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw);
2024 +
2025 + actual_rate = (unsigned long)clk_hifiberry_dacpro_round_rate(hw, rate,
2026 + &parent_rate);
2027 + clk->mode = (actual_rate == CLK_44EN_RATE) ? 0 : 1;
2028 + return 0;
2029 +}
2030 +
2031 +
2032 +const struct clk_ops clk_hifiberry_dacpro_rate_ops = {
2033 + .recalc_rate = clk_hifiberry_dacpro_recalc_rate,
2034 + .round_rate = clk_hifiberry_dacpro_round_rate,
2035 + .set_rate = clk_hifiberry_dacpro_set_rate,
2036 +};
2037 +
2038 +static int clk_hifiberry_dacpro_probe(struct platform_device *pdev)
2039 +{
2040 + int ret;
2041 + struct clk_hifiberry_hw *proclk;
2042 + struct clk *clk;
2043 + struct device *dev;
2044 + struct clk_init_data init;
2045 +
2046 + dev = &pdev->dev;
2047 +
2048 + proclk = kzalloc(sizeof(struct clk_hifiberry_hw), GFP_KERNEL);
2049 + if (!proclk)
2050 + return -ENOMEM;
2051 +
2052 + init.name = "clk-hifiberry-dacpro";
2053 + init.ops = &clk_hifiberry_dacpro_rate_ops;
2054 + init.flags = 0;
2055 + init.parent_names = NULL;
2056 + init.num_parents = 0;
2057 +
2058 + proclk->mode = 0;
2059 + proclk->hw.init = &init;
2060 +
2061 + clk = devm_clk_register(dev, &proclk->hw);
2062 + if (!IS_ERR(clk)) {
2063 + ret = of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
2064 + clk);
2065 + } else {
2066 + dev_err(dev, "Fail to register clock driver\n");
2067 + kfree(proclk);
2068 + ret = PTR_ERR(clk);
2069 + }
2070 + return ret;
2071 +}
2072 +
2073 +static int clk_hifiberry_dacpro_remove(struct platform_device *pdev)
2074 +{
2075 + of_clk_del_provider(pdev->dev.of_node);
2076 + return 0;
2077 +}
2078 +
2079 +static struct platform_driver clk_hifiberry_dacpro_driver = {
2080 + .probe = clk_hifiberry_dacpro_probe,
2081 + .remove = clk_hifiberry_dacpro_remove,
2082 + .driver = {
2083 + .name = "clk-hifiberry-dacpro",
2084 + .of_match_table = clk_hifiberry_dacpro_dt_ids,
2085 + },
2086 +};
2087 +
2088 +static int __init clk_hifiberry_dacpro_init(void)
2089 +{
2090 + return platform_driver_register(&clk_hifiberry_dacpro_driver);
2091 +}
2092 +core_initcall(clk_hifiberry_dacpro_init);
2093 +
2094 +static void __exit clk_hifiberry_dacpro_exit(void)
2095 +{
2096 + platform_driver_unregister(&clk_hifiberry_dacpro_driver);
2097 +}
2098 +module_exit(clk_hifiberry_dacpro_exit);
2099 +
2100 +MODULE_DESCRIPTION("HiFiBerry DAC Pro clock driver");
2101 +MODULE_LICENSE("GPL v2");
2102 +MODULE_ALIAS("platform:clk-hifiberry-dacpro");
2103 --- a/sound/soc/bcm/Kconfig
2104 +++ b/sound/soc/bcm/Kconfig
2105 @@ -26,3 +26,277 @@ config SND_BCM63XX_I2S_WHISTLER
2106 DSL/PON chips (bcm63158, bcm63178)
2107
2108 If you don't know what to do here, say N
2109 +
2110 +config SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD
2111 + tristate "Support for Google voiceHAT soundcard"
2112 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2113 + select SND_SOC_VOICEHAT
2114 + select SND_RPI_SIMPLE_SOUNDCARD
2115 + help
2116 + Say Y or M if you want to add support for voiceHAT soundcard.
2117 +
2118 +config SND_BCM2708_SOC_HIFIBERRY_DAC
2119 + tristate "Support for HifiBerry DAC"
2120 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2121 + select SND_SOC_PCM5102A
2122 + select SND_RPI_SIMPLE_SOUNDCARD
2123 + help
2124 + Say Y or M if you want to add support for HifiBerry DAC.
2125 +
2126 +config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
2127 + tristate "Support for HifiBerry DAC+"
2128 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2129 + select SND_SOC_PCM512x
2130 + select SND_SOC_TPA6130A2
2131 + select COMMON_CLK_HIFIBERRY_DACPRO
2132 + help
2133 + Say Y or M if you want to add support for HifiBerry DAC+.
2134 +
2135 +config SND_BCM2708_SOC_HIFIBERRY_DACPLUSHD
2136 + tristate "Support for HifiBerry DAC+ HD"
2137 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2138 + select SND_SOC_PCM179X_I2C
2139 + select COMMON_CLK_HIFIBERRY_DACPLUSHD
2140 + help
2141 + Say Y or M if you want to add support for HifiBerry DAC+ HD.
2142 +
2143 +config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC
2144 + tristate "Support for HifiBerry DAC+ADC"
2145 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2146 + select SND_SOC_PCM512x_I2C
2147 + select SND_SOC_DMIC
2148 + select COMMON_CLK_HIFIBERRY_DACPRO
2149 + help
2150 + Say Y or M if you want to add support for HifiBerry DAC+ADC.
2151 +
2152 +config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO
2153 + tristate "Support for HifiBerry DAC+ADC PRO"
2154 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2155 + select SND_SOC_PCM512x_I2C
2156 + select SND_SOC_PCM186X_I2C
2157 + select COMMON_CLK_HIFIBERRY_DACPRO
2158 + help
2159 + Say Y or M if you want to add support for HifiBerry DAC+ADC PRO.
2160 +
2161 +config SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP
2162 + tristate "Support for HifiBerry DAC+DSP"
2163 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2164 + select SND_RPI_SIMPLE_SOUNDCARD
2165 + help
2166 + Say Y or M if you want to add support for HifiBerry DSP-DAC.
2167 +
2168 +config SND_BCM2708_SOC_HIFIBERRY_DIGI
2169 + tristate "Support for HifiBerry Digi"
2170 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2171 + select SND_SOC_WM8804
2172 + help
2173 + Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board.
2174 +
2175 +config SND_BCM2708_SOC_HIFIBERRY_AMP
2176 + tristate "Support for the HifiBerry Amp"
2177 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2178 + select SND_SOC_TAS5713
2179 + select SND_RPI_SIMPLE_SOUNDCARD
2180 + help
2181 + Say Y or M if you want to add support for the HifiBerry Amp amplifier board.
2182 +
2183 +config SND_BCM2708_SOC_RPI_CIRRUS
2184 + tristate "Support for Cirrus Logic Audio Card"
2185 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2186 + select SND_SOC_WM5102
2187 + select SND_SOC_WM8804
2188 + help
2189 + Say Y or M if you want to add support for the Wolfson and
2190 + Cirrus Logic audio cards.
2191 +
2192 +config SND_BCM2708_SOC_RPI_DAC
2193 + tristate "Support for RPi-DAC"
2194 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2195 + select SND_SOC_PCM1794A
2196 + select SND_RPI_SIMPLE_SOUNDCARD
2197 + help
2198 + Say Y or M if you want to add support for RPi-DAC.
2199 +
2200 +config SND_BCM2708_SOC_RPI_PROTO
2201 + tristate "Support for Rpi-PROTO"
2202 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2203 + select SND_SOC_WM8731
2204 + help
2205 + Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731).
2206 +
2207 +config SND_BCM2708_SOC_JUSTBOOM_BOTH
2208 + tristate "Support for simultaneous JustBoom Digi and JustBoom DAC"
2209 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2210 + select SND_SOC_WM8804
2211 + select SND_SOC_PCM512x
2212 + help
2213 + Say Y or M if you want to add support for simultaneous
2214 + JustBoom Digi and JustBoom DAC.
2215 +
2216 + This is not the right choice if you only have one but both of
2217 + these cards.
2218 +
2219 +config SND_BCM2708_SOC_JUSTBOOM_DAC
2220 + tristate "Support for JustBoom DAC"
2221 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2222 + select SND_SOC_PCM512x
2223 + help
2224 + Say Y or M if you want to add support for JustBoom DAC.
2225 +
2226 +config SND_BCM2708_SOC_JUSTBOOM_DIGI
2227 + tristate "Support for JustBoom Digi"
2228 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2229 + select SND_SOC_WM8804
2230 + select SND_RPI_WM8804_SOUNDCARD
2231 + help
2232 + Say Y or M if you want to add support for JustBoom Digi.
2233 +
2234 +config SND_BCM2708_SOC_IQAUDIO_CODEC
2235 + tristate "Support for IQaudIO-CODEC"
2236 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2237 + select SND_SOC_DA7213
2238 + help
2239 + Say Y or M if you want to add support for IQaudIO-CODEC.
2240 +
2241 +config SND_BCM2708_SOC_IQAUDIO_DAC
2242 + tristate "Support for IQaudIO-DAC"
2243 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2244 + select SND_SOC_PCM512x_I2C
2245 + help
2246 + Say Y or M if you want to add support for IQaudIO-DAC.
2247 +
2248 +config SND_BCM2708_SOC_IQAUDIO_DIGI
2249 + tristate "Support for IQAudIO Digi"
2250 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2251 + select SND_SOC_WM8804
2252 + select SND_RPI_WM8804_SOUNDCARD
2253 + help
2254 + Say Y or M if you want to add support for IQAudIO Digital IO board.
2255 +
2256 +config SND_BCM2708_SOC_I_SABRE_Q2M
2257 + tristate "Support for Audiophonics I-Sabre Q2M DAC"
2258 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2259 + select SND_SOC_I_SABRE_CODEC
2260 + help
2261 + Say Y or M if you want to add support for Audiophonics I-SABRE Q2M DAC
2262 +
2263 +config SND_BCM2708_SOC_ADAU1977_ADC
2264 + tristate "Support for ADAU1977 ADC"
2265 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2266 + select SND_SOC_ADAU1977_I2C
2267 + select SND_RPI_SIMPLE_SOUNDCARD
2268 + help
2269 + Say Y or M if you want to add support for ADAU1977 ADC.
2270 +
2271 +config SND_AUDIOINJECTOR_PI_SOUNDCARD
2272 + tristate "Support for audioinjector.net Pi add on soundcard"
2273 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2274 + select SND_SOC_WM8731
2275 + help
2276 + Say Y or M if you want to add support for audioinjector.net Pi Hat
2277 +
2278 +config SND_AUDIOINJECTOR_OCTO_SOUNDCARD
2279 + tristate "Support for audioinjector.net Octo channel (Hat) soundcard"
2280 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2281 + select SND_SOC_CS42XX8_I2C
2282 + help
2283 + Say Y or M if you want to add support for audioinjector.net octo add on
2284 +
2285 +config SND_AUDIOINJECTOR_ISOLATED_SOUNDCARD
2286 + tristate "Support for audioinjector.net isolated DAC and ADC soundcard"
2287 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2288 + select SND_SOC_CS4271_I2C
2289 + help
2290 + Say Y or M if you want to add support for audioinjector.net isolated soundcard
2291 +
2292 +config SND_AUDIOSENSE_PI
2293 + tristate "Support for AudioSense Add-On Soundcard"
2294 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2295 + select SND_SOC_TLV320AIC32X4_I2C
2296 + help
2297 + Say Y or M if you want to add support for tlv320aic32x4 add-on
2298 +
2299 +config SND_DIGIDAC1_SOUNDCARD
2300 + tristate "Support for Red Rocks Audio DigiDAC1"
2301 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2302 + select SND_SOC_WM8804
2303 + select SND_SOC_WM8741
2304 + help
2305 + Say Y or M if you want to add support for Red Rocks Audio DigiDAC1 board.
2306 +
2307 +config SND_BCM2708_SOC_DIONAUDIO_LOCO
2308 + tristate "Support for Dion Audio LOCO DAC-AMP"
2309 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2310 + select SND_SOC_PCM5102a
2311 + help
2312 + Say Y or M if you want to add support for Dion Audio LOCO.
2313 +
2314 +config SND_BCM2708_SOC_DIONAUDIO_LOCO_V2
2315 + tristate "Support for Dion Audio LOCO-V2 DAC-AMP"
2316 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2317 + select SND_SOC_PCM5122
2318 + help
2319 + Say Y or M if you want to add support for Dion Audio LOCO-V2.
2320 +
2321 +config SND_BCM2708_SOC_ALLO_PIANO_DAC
2322 + tristate "Support for Allo Piano DAC"
2323 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2324 + select SND_SOC_PCM512x_I2C
2325 + help
2326 + Say Y or M if you want to add support for Allo Piano DAC.
2327 +
2328 +config SND_BCM2708_SOC_ALLO_PIANO_DAC_PLUS
2329 + tristate "Support for Allo Piano DAC Plus"
2330 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2331 + select SND_SOC_PCM512x_I2C
2332 + help
2333 + Say Y or M if you want to add support for Allo Piano DAC Plus.
2334 +
2335 +config SND_BCM2708_SOC_ALLO_BOSS_DAC
2336 + tristate "Support for Allo Boss DAC"
2337 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2338 + select SND_SOC_PCM512x_I2C
2339 + help
2340 + Say Y or M if you want to add support for Allo Boss DAC.
2341 +
2342 +config SND_BCM2708_SOC_ALLO_DIGIONE
2343 + tristate "Support for Allo DigiOne"
2344 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2345 + select SND_SOC_WM8804
2346 + select SND_RPI_WM8804_SOUNDCARD
2347 + help
2348 + Say Y or M if you want to add support for Allo DigiOne.
2349 +
2350 +config SND_BCM2708_SOC_ALLO_KATANA_DAC
2351 + tristate "Support for Allo Katana DAC"
2352 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2353 + depends on I2C
2354 + select REGMAP_I2C
2355 + select SND_AUDIO_GRAPH_CARD
2356 + help
2357 + Say Y or M if you want to add support for Allo Katana DAC.
2358 +
2359 +config SND_BCM2708_SOC_FE_PI_AUDIO
2360 + tristate "Support for Fe-Pi-Audio"
2361 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2362 + select SND_SOC_SGTL5000
2363 + help
2364 + Say Y or M if you want to add support for Fe-Pi-Audio.
2365 +
2366 +config SND_PISOUND
2367 + tristate "Support for Blokas Labs pisound"
2368 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
2369 + select SND_RAWMIDI
2370 + help
2371 + Say Y or M if you want to add support for Blokas Labs pisound.
2372 +
2373 +config SND_RPI_SIMPLE_SOUNDCARD
2374 + tristate "Support for Raspberry Pi simple soundcards"
2375 + help
2376 + Say Y or M if you want to add support Raspbery Pi simple soundcards
2377 +
2378 +config SND_RPI_WM8804_SOUNDCARD
2379 + tristate "Support for Raspberry Pi generic WM8804 soundcards"
2380 + help
2381 + Say Y or M if you want to add support for the Raspberry Pi
2382 + generic driver for WM8804 based soundcards.
2383 --- a/sound/soc/bcm/Makefile
2384 +++ b/sound/soc/bcm/Makefile
2385 @@ -12,4 +12,65 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-
2386 # BCM63XX Platform Support
2387 snd-soc-63xx-objs := bcm63xx-i2s-whistler.o bcm63xx-pcm-whistler.o
2388
2389 -obj-$(CONFIG_SND_BCM63XX_I2S_WHISTLER) += snd-soc-63xx.o
2390 \ No newline at end of file
2391 +obj-$(CONFIG_SND_BCM63XX_I2S_WHISTLER) += snd-soc-63xx.o
2392 +
2393 +# Google voiceHAT custom codec support
2394 +snd-soc-googlevoicehat-codec-objs := googlevoicehat-codec.o
2395 +
2396 +# BCM2708 Machine Support
2397 +snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
2398 +snd-soc-hifiberry-dacplushd-objs := hifiberry_dacplushd.o
2399 +snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
2400 +snd-soc-hifiberry-dacplusadcpro-objs := hifiberry_dacplusadcpro.o
2401 +snd-soc-hifiberry-dacplusdsp-objs := hifiberry_dacplusdsp.o
2402 +snd-soc-justboom-both-objs := justboom-both.o
2403 +snd-soc-justboom-dac-objs := justboom-dac.o
2404 +snd-soc-rpi-cirrus-objs := rpi-cirrus.o
2405 +snd-soc-rpi-proto-objs := rpi-proto.o
2406 +snd-soc-iqaudio-codec-objs := iqaudio-codec.o
2407 +snd-soc-iqaudio-dac-objs := iqaudio-dac.o
2408 + snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
2409 +snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
2410 +snd-soc-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o
2411 +snd-soc-audioinjector-isolated-soundcard-objs := audioinjector-isolated-soundcard.o
2412 +snd-soc-audiosense-pi-objs := audiosense-pi.o
2413 +snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o
2414 +snd-soc-dionaudio-loco-objs := dionaudio_loco.o
2415 +snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o
2416 +snd-soc-allo-boss-dac-objs := allo-boss-dac.o
2417 +snd-soc-allo-piano-dac-objs := allo-piano-dac.o
2418 +snd-soc-allo-piano-dac-plus-objs := allo-piano-dac-plus.o
2419 +snd-soc-allo-katana-codec-objs := allo-katana-codec.o
2420 +snd-soc-pisound-objs := pisound.o
2421 +snd-soc-fe-pi-audio-objs := fe-pi-audio.o
2422 +snd-soc-rpi-simple-soundcard-objs := rpi-simple-soundcard.o
2423 +snd-soc-rpi-wm8804-soundcard-objs := rpi-wm8804-soundcard.o
2424 +
2425 +obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD) += snd-soc-googlevoicehat-codec.o
2426 +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
2427 +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSHD) += snd-soc-hifiberry-dacplushd.o
2428 +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
2429 +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO) += snd-soc-hifiberry-dacplusadcpro.o
2430 +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP) += snd-soc-hifiberry-dacplusdsp.o
2431 +obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_BOTH) += snd-soc-justboom-both.o
2432 +obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
2433 +obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
2434 +obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
2435 +obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC) += snd-soc-iqaudio-codec.o
2436 +obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
2437 +obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.o
2438 +obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o
2439 +obj-$(CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD) += snd-soc-audioinjector-octo-soundcard.o
2440 +obj-$(CONFIG_SND_AUDIOINJECTOR_ISOLATED_SOUNDCARD) += snd-soc-audioinjector-isolated-soundcard.o
2441 +obj-$(CONFIG_SND_AUDIOSENSE_PI) += snd-soc-audiosense-pi.o
2442 +obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o
2443 +obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o
2444 +obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) += snd-soc-dionaudio-loco-v2.o
2445 +obj-$(CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC) += snd-soc-allo-boss-dac.o
2446 +obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o
2447 +obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC_PLUS) += snd-soc-allo-piano-dac-plus.o
2448 +obj-$(CONFIG_SND_BCM2708_SOC_ALLO_KATANA_DAC) += snd-soc-allo-katana-codec.o
2449 +obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o
2450 +obj-$(CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO) += snd-soc-fe-pi-audio.o
2451 +obj-$(CONFIG_SND_RPI_SIMPLE_SOUNDCARD) += snd-soc-rpi-simple-soundcard.o
2452 +obj-$(CONFIG_SND_RPI_WM8804_SOUNDCARD) += snd-soc-rpi-wm8804-soundcard.o
2453 --- /dev/null
2454 +++ b/sound/soc/bcm/allo-boss-dac.c
2455 @@ -0,0 +1,456 @@
2456 +/*
2457 + * ALSA ASoC Machine Driver for Allo Boss DAC
2458 + *
2459 + * Author: Baswaraj K <jaikumar@cem-solutions.net>
2460 + * Copyright 2017
2461 + * based on code by Daniel Matuschek,
2462 + * Stuart MacLean <stuart@hifiberry.com>
2463 + * based on code by Florian Meier <florian.meier@koalo.de>
2464 + *
2465 + * This program is free software; you can redistribute it and/or
2466 + * modify it under the terms of the GNU General Public License
2467 + * version 2 as published by the Free Software Foundation.
2468 + *
2469 + * This program is distributed in the hope that it will be useful, but
2470 + * WITHOUT ANY WARRANTY; without even the implied warranty of
2471 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2472 + * General Public License for more details.
2473 + */
2474 +
2475 +#include <linux/module.h>
2476 +#include <linux/gpio/consumer.h>
2477 +#include <linux/platform_device.h>
2478 +#include <linux/clk.h>
2479 +#include <linux/delay.h>
2480 +
2481 +#include <sound/core.h>
2482 +#include <sound/pcm.h>
2483 +#include <sound/pcm_params.h>
2484 +#include <sound/soc.h>
2485 +#include "../codecs/pcm512x.h"
2486 +
2487 +#define ALLO_BOSS_NOCLOCK 0
2488 +#define ALLO_BOSS_CLK44EN 1
2489 +#define ALLO_BOSS_CLK48EN 2
2490 +
2491 +struct pcm512x_priv {
2492 + struct regmap *regmap;
2493 + struct clk *sclk;
2494 +};
2495 +
2496 +static struct gpio_desc *mute_gpio;
2497 +
2498 +/* Clock rate of CLK44EN attached to GPIO6 pin */
2499 +#define CLK_44EN_RATE 45158400UL
2500 +/* Clock rate of CLK48EN attached to GPIO3 pin */
2501 +#define CLK_48EN_RATE 49152000UL
2502 +
2503 +static bool slave;
2504 +static bool snd_soc_allo_boss_master;
2505 +static bool digital_gain_0db_limit = true;
2506 +
2507 +static void snd_allo_boss_select_clk(struct snd_soc_component *component,
2508 + int clk_id)
2509 +{
2510 + switch (clk_id) {
2511 + case ALLO_BOSS_NOCLOCK:
2512 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
2513 + break;
2514 + case ALLO_BOSS_CLK44EN:
2515 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
2516 + break;
2517 + case ALLO_BOSS_CLK48EN:
2518 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
2519 + break;
2520 + }
2521 +}
2522 +
2523 +static void snd_allo_boss_clk_gpio(struct snd_soc_component *component)
2524 +{
2525 + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
2526 + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
2527 + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
2528 +}
2529 +
2530 +static bool snd_allo_boss_is_sclk(struct snd_soc_component *component)
2531 +{
2532 + unsigned int sck;
2533 +
2534 + sck = snd_soc_component_read(component, PCM512x_RATE_DET_4);
2535 + return (!(sck & 0x40));
2536 +}
2537 +
2538 +static bool snd_allo_boss_is_sclk_sleep(
2539 + struct snd_soc_component *component)
2540 +{
2541 + msleep(2);
2542 + return snd_allo_boss_is_sclk(component);
2543 +}
2544 +
2545 +static bool snd_allo_boss_is_master_card(struct snd_soc_component *component)
2546 +{
2547 + bool isClk44EN, isClk48En, isNoClk;
2548 +
2549 + snd_allo_boss_clk_gpio(component);
2550 +
2551 + snd_allo_boss_select_clk(component, ALLO_BOSS_CLK44EN);
2552 + isClk44EN = snd_allo_boss_is_sclk_sleep(component);
2553 +
2554 + snd_allo_boss_select_clk(component, ALLO_BOSS_NOCLOCK);
2555 + isNoClk = snd_allo_boss_is_sclk_sleep(component);
2556 +
2557 + snd_allo_boss_select_clk(component, ALLO_BOSS_CLK48EN);
2558 + isClk48En = snd_allo_boss_is_sclk_sleep(component);
2559 +
2560 + return (isClk44EN && isClk48En && !isNoClk);
2561 +}
2562 +
2563 +static int snd_allo_boss_clk_for_rate(int sample_rate)
2564 +{
2565 + int type;
2566 +
2567 + switch (sample_rate) {
2568 + case 11025:
2569 + case 22050:
2570 + case 44100:
2571 + case 88200:
2572 + case 176400:
2573 + case 352800:
2574 + type = ALLO_BOSS_CLK44EN;
2575 + break;
2576 + default:
2577 + type = ALLO_BOSS_CLK48EN;
2578 + break;
2579 + }
2580 + return type;
2581 +}
2582 +
2583 +static void snd_allo_boss_set_sclk(struct snd_soc_component *component,
2584 + int sample_rate)
2585 +{
2586 + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
2587 +
2588 + if (!IS_ERR(pcm512x->sclk)) {
2589 + int ctype;
2590 +
2591 + ctype = snd_allo_boss_clk_for_rate(sample_rate);
2592 + clk_set_rate(pcm512x->sclk, (ctype == ALLO_BOSS_CLK44EN)
2593 + ? CLK_44EN_RATE : CLK_48EN_RATE);
2594 + snd_allo_boss_select_clk(component, ctype);
2595 + }
2596 +}
2597 +
2598 +static int snd_allo_boss_init(struct snd_soc_pcm_runtime *rtd)
2599 +{
2600 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
2601 + struct pcm512x_priv *priv = snd_soc_component_get_drvdata(component);
2602 +
2603 + if (slave)
2604 + snd_soc_allo_boss_master = false;
2605 + else
2606 + snd_soc_allo_boss_master =
2607 + snd_allo_boss_is_master_card(component);
2608 +
2609 + if (snd_soc_allo_boss_master) {
2610 + struct snd_soc_dai_link *dai = rtd->dai_link;
2611 +
2612 + dai->name = "BossDAC";
2613 + dai->stream_name = "Boss DAC HiFi [Master]";
2614 + dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
2615 + | SND_SOC_DAIFMT_CBM_CFM;
2616 +
2617 + snd_soc_component_update_bits(component, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
2618 + snd_soc_component_update_bits(component, PCM512x_MASTER_MODE, 0x03, 0x03);
2619 + snd_soc_component_update_bits(component, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
2620 + /*
2621 + * Default sclk to CLK_48EN_RATE, otherwise codec
2622 + * pcm512x_dai_startup_master method could call
2623 + * snd_pcm_hw_constraint_ratnums using CLK_44EN/64
2624 + * which will mask 384k sample rate.
2625 + */
2626 + if (!IS_ERR(priv->sclk))
2627 + clk_set_rate(priv->sclk, CLK_48EN_RATE);
2628 + } else {
2629 + priv->sclk = ERR_PTR(-ENOENT);
2630 + }
2631 +
2632 + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x08, 0x08);
2633 + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
2634 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
2635 +
2636 + if (digital_gain_0db_limit) {
2637 + int ret;
2638 + struct snd_soc_card *card = rtd->card;
2639 +
2640 + ret = snd_soc_limit_volume(card, "Digital Playback Volume",
2641 + 207);
2642 + if (ret < 0)
2643 + dev_warn(card->dev, "Failed to set volume limit: %d\n",
2644 + ret);
2645 + }
2646 +
2647 + return 0;
2648 +}
2649 +
2650 +static int snd_allo_boss_update_rate_den(
2651 + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
2652 +{
2653 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
2654 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
2655 + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
2656 + struct snd_ratnum *rats_no_pll;
2657 + unsigned int num = 0, den = 0;
2658 + int err;
2659 +
2660 + rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
2661 + if (!rats_no_pll)
2662 + return -ENOMEM;
2663 +
2664 + rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
2665 + rats_no_pll->den_min = 1;
2666 + rats_no_pll->den_max = 128;
2667 + rats_no_pll->den_step = 1;
2668 +
2669 + err = snd_interval_ratnum(hw_param_interval(params,
2670 + SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
2671 + if (err >= 0 && den) {
2672 + params->rate_num = num;
2673 + params->rate_den = den;
2674 + }
2675 +
2676 + devm_kfree(rtd->dev, rats_no_pll);
2677 + return 0;
2678 +}
2679 +
2680 +static void snd_allo_boss_gpio_mute(struct snd_soc_card *card)
2681 +{
2682 + if (mute_gpio)
2683 + gpiod_set_value_cansleep(mute_gpio, 1);
2684 +}
2685 +
2686 +static void snd_allo_boss_gpio_unmute(struct snd_soc_card *card)
2687 +{
2688 + if (mute_gpio)
2689 + gpiod_set_value_cansleep(mute_gpio, 0);
2690 +}
2691 +
2692 +static int snd_allo_boss_set_bias_level(struct snd_soc_card *card,
2693 + struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
2694 +{
2695 + struct snd_soc_pcm_runtime *rtd;
2696 + struct snd_soc_dai *codec_dai;
2697 +
2698 + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
2699 + codec_dai = asoc_rtd_to_codec(rtd, 0);
2700 +
2701 + if (dapm->dev != codec_dai->dev)
2702 + return 0;
2703 +
2704 + switch (level) {
2705 + case SND_SOC_BIAS_PREPARE:
2706 + if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
2707 + break;
2708 + /* UNMUTE DAC */
2709 + snd_allo_boss_gpio_unmute(card);
2710 + break;
2711 +
2712 + case SND_SOC_BIAS_STANDBY:
2713 + if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
2714 + break;
2715 + /* MUTE DAC */
2716 + snd_allo_boss_gpio_mute(card);
2717 + break;
2718 +
2719 + default:
2720 + break;
2721 + }
2722 +
2723 + return 0;
2724 +}
2725 +
2726 +static int snd_allo_boss_hw_params(
2727 + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
2728 +{
2729 + int ret = 0;
2730 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
2731 + int channels = params_channels(params);
2732 + int width = snd_pcm_format_physical_width(params_format(params));
2733 +
2734 + if (snd_soc_allo_boss_master) {
2735 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
2736 +
2737 + snd_allo_boss_set_sclk(component,
2738 + params_rate(params));
2739 +
2740 + ret = snd_allo_boss_update_rate_den(
2741 + substream, params);
2742 + if (ret)
2743 + return ret;
2744 + }
2745 +
2746 + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), channels * width);
2747 + if (ret)
2748 + return ret;
2749 + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_codec(rtd, 0), channels * width);
2750 + return ret;
2751 +}
2752 +
2753 +static int snd_allo_boss_startup(
2754 + struct snd_pcm_substream *substream)
2755 +{
2756 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
2757 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
2758 + struct snd_soc_card *card = rtd->card;
2759 +
2760 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
2761 + snd_allo_boss_gpio_mute(card);
2762 +
2763 + if (snd_soc_allo_boss_master) {
2764 + struct pcm512x_priv *priv = snd_soc_component_get_drvdata(component);
2765 + /*
2766 + * Default sclk to CLK_48EN_RATE, otherwise codec
2767 + * pcm512x_dai_startup_master method could call
2768 + * snd_pcm_hw_constraint_ratnums using CLK_44EN/64
2769 + * which will mask 384k sample rate.
2770 + */
2771 + if (!IS_ERR(priv->sclk))
2772 + clk_set_rate(priv->sclk, CLK_48EN_RATE);
2773 + }
2774 +
2775 + return 0;
2776 +}
2777 +
2778 +static void snd_allo_boss_shutdown(
2779 + struct snd_pcm_substream *substream)
2780 +{
2781 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
2782 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
2783 +
2784 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
2785 +}
2786 +
2787 +static int snd_allo_boss_prepare(
2788 + struct snd_pcm_substream *substream)
2789 +{
2790 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
2791 + struct snd_soc_card *card = rtd->card;
2792 +
2793 + snd_allo_boss_gpio_unmute(card);
2794 + return 0;
2795 +}
2796 +/* machine stream operations */
2797 +static struct snd_soc_ops snd_allo_boss_ops = {
2798 + .hw_params = snd_allo_boss_hw_params,
2799 + .startup = snd_allo_boss_startup,
2800 + .shutdown = snd_allo_boss_shutdown,
2801 + .prepare = snd_allo_boss_prepare,
2802 +};
2803 +
2804 +SND_SOC_DAILINK_DEFS(allo_boss,
2805 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
2806 + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi")),
2807 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
2808 +
2809 +static struct snd_soc_dai_link snd_allo_boss_dai[] = {
2810 +{
2811 + .name = "Boss DAC",
2812 + .stream_name = "Boss DAC HiFi",
2813 + .dai_fmt = SND_SOC_DAIFMT_I2S |
2814 + SND_SOC_DAIFMT_NB_NF |
2815 + SND_SOC_DAIFMT_CBS_CFS,
2816 + .ops = &snd_allo_boss_ops,
2817 + .init = snd_allo_boss_init,
2818 + SND_SOC_DAILINK_REG(allo_boss),
2819 +},
2820 +};
2821 +
2822 +/* audio machine driver */
2823 +static struct snd_soc_card snd_allo_boss = {
2824 + .name = "BossDAC",
2825 + .owner = THIS_MODULE,
2826 + .dai_link = snd_allo_boss_dai,
2827 + .num_links = ARRAY_SIZE(snd_allo_boss_dai),
2828 +};
2829 +
2830 +static int snd_allo_boss_probe(struct platform_device *pdev)
2831 +{
2832 + int ret = 0;
2833 +
2834 + snd_allo_boss.dev = &pdev->dev;
2835 +
2836 + if (pdev->dev.of_node) {
2837 + struct device_node *i2s_node;
2838 + struct snd_soc_dai_link *dai;
2839 +
2840 + dai = &snd_allo_boss_dai[0];
2841 + i2s_node = of_parse_phandle(pdev->dev.of_node,
2842 + "i2s-controller", 0);
2843 +
2844 + if (i2s_node) {
2845 + dai->cpus->dai_name = NULL;
2846 + dai->cpus->of_node = i2s_node;
2847 + dai->platforms->name = NULL;
2848 + dai->platforms->of_node = i2s_node;
2849 + }
2850 +
2851 + digital_gain_0db_limit = !of_property_read_bool(
2852 + pdev->dev.of_node, "allo,24db_digital_gain");
2853 + slave = of_property_read_bool(pdev->dev.of_node,
2854 + "allo,slave");
2855 +
2856 + mute_gpio = devm_gpiod_get_optional(&pdev->dev, "mute",
2857 + GPIOD_OUT_LOW);
2858 + if (IS_ERR(mute_gpio)) {
2859 + ret = PTR_ERR(mute_gpio);
2860 + dev_err(&pdev->dev,
2861 + "failed to get mute gpio: %d\n", ret);
2862 + return ret;
2863 + }
2864 +
2865 + if (mute_gpio)
2866 + snd_allo_boss.set_bias_level =
2867 + snd_allo_boss_set_bias_level;
2868 +
2869 + ret = snd_soc_register_card(&snd_allo_boss);
2870 + if (ret) {
2871 + dev_err(&pdev->dev,
2872 + "snd_soc_register_card() failed: %d\n", ret);
2873 + return ret;
2874 + }
2875 +
2876 + if (mute_gpio)
2877 + snd_allo_boss_gpio_mute(&snd_allo_boss);
2878 +
2879 + return 0;
2880 + }
2881 +
2882 + return -EINVAL;
2883 +}
2884 +
2885 +static int snd_allo_boss_remove(struct platform_device *pdev)
2886 +{
2887 + snd_allo_boss_gpio_mute(&snd_allo_boss);
2888 + return snd_soc_unregister_card(&snd_allo_boss);
2889 +}
2890 +
2891 +static const struct of_device_id snd_allo_boss_of_match[] = {
2892 + { .compatible = "allo,boss-dac", },
2893 + { /* sentinel */ },
2894 +};
2895 +MODULE_DEVICE_TABLE(of, snd_allo_boss_of_match);
2896 +
2897 +static struct platform_driver snd_allo_boss_driver = {
2898 + .driver = {
2899 + .name = "snd-allo-boss-dac",
2900 + .owner = THIS_MODULE,
2901 + .of_match_table = snd_allo_boss_of_match,
2902 + },
2903 + .probe = snd_allo_boss_probe,
2904 + .remove = snd_allo_boss_remove,
2905 +};
2906 +
2907 +module_platform_driver(snd_allo_boss_driver);
2908 +
2909 +MODULE_AUTHOR("Baswaraj K <jaikumar@cem-solutions.net>");
2910 +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Boss DAC");
2911 +MODULE_LICENSE("GPL v2");
2912 --- /dev/null
2913 +++ b/sound/soc/bcm/allo-katana-codec.c
2914 @@ -0,0 +1,388 @@
2915 +/*
2916 + * Driver for the ALLO KATANA CODEC
2917 + *
2918 + * Author: Jaikumar <jaikumar@cem-solutions.net>
2919 + * Copyright 2018
2920 + *
2921 + * This program is free software; you can redistribute it and/or
2922 + * modify it under the terms of the GNU General Public License
2923 + * version 2 as published by the Free Software Foundation.
2924 + *
2925 + * This program is distributed in the hope that it will be useful, but
2926 + * WITHOUT ANY WARRANTY; without even the implied warranty of
2927 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2928 + * General Public License for more details.
2929 + */
2930 +
2931 +
2932 +#include <linux/init.h>
2933 +#include <linux/module.h>
2934 +#include <linux/clk.h>
2935 +#include <linux/kernel.h>
2936 +#include <linux/regmap.h>
2937 +#include <linux/regulator/consumer.h>
2938 +#include <linux/gcd.h>
2939 +#include <sound/soc.h>
2940 +#include <sound/soc-dapm.h>
2941 +#include <sound/pcm_params.h>
2942 +#include <sound/tlv.h>
2943 +#include <linux/i2c.h>
2944 +
2945 +
2946 +#define KATANA_CODEC_CHIP_ID 0x30
2947 +#define KATANA_CODEC_VIRT_BASE 0x100
2948 +#define KATANA_CODEC_PAGE 0
2949 +
2950 +#define KATANA_CODEC_CHIP_ID_REG (KATANA_CODEC_VIRT_BASE + 0)
2951 +#define KATANA_CODEC_RESET (KATANA_CODEC_VIRT_BASE + 1)
2952 +#define KATANA_CODEC_VOLUME_1 (KATANA_CODEC_VIRT_BASE + 2)
2953 +#define KATANA_CODEC_VOLUME_2 (KATANA_CODEC_VIRT_BASE + 3)
2954 +#define KATANA_CODEC_MUTE (KATANA_CODEC_VIRT_BASE + 4)
2955 +#define KATANA_CODEC_DSP_PROGRAM (KATANA_CODEC_VIRT_BASE + 5)
2956 +#define KATANA_CODEC_DEEMPHASIS (KATANA_CODEC_VIRT_BASE + 6)
2957 +#define KATANA_CODEC_DOP (KATANA_CODEC_VIRT_BASE + 7)
2958 +#define KATANA_CODEC_FORMAT (KATANA_CODEC_VIRT_BASE + 8)
2959 +#define KATANA_CODEC_COMMAND (KATANA_CODEC_VIRT_BASE + 9)
2960 +#define KATANA_CODEC_MUTE_STREAM (KATANA_CODEC_VIRT_BASE + 10)
2961 +
2962 +#define KATANA_CODEC_MAX_REGISTER (KATANA_CODEC_VIRT_BASE + 10)
2963 +
2964 +#define KATANA_CODEC_FMT 0xff
2965 +#define KATANA_CODEC_CHAN_MONO 0x00
2966 +#define KATANA_CODEC_CHAN_STEREO 0x80
2967 +#define KATANA_CODEC_ALEN_16 0x10
2968 +#define KATANA_CODEC_ALEN_24 0x20
2969 +#define KATANA_CODEC_ALEN_32 0x30
2970 +#define KATANA_CODEC_RATE_11025 0x01
2971 +#define KATANA_CODEC_RATE_22050 0x02
2972 +#define KATANA_CODEC_RATE_32000 0x03
2973 +#define KATANA_CODEC_RATE_44100 0x04
2974 +#define KATANA_CODEC_RATE_48000 0x05
2975 +#define KATANA_CODEC_RATE_88200 0x06
2976 +#define KATANA_CODEC_RATE_96000 0x07
2977 +#define KATANA_CODEC_RATE_176400 0x08
2978 +#define KATANA_CODEC_RATE_192000 0x09
2979 +#define KATANA_CODEC_RATE_352800 0x0a
2980 +#define KATANA_CODEC_RATE_384000 0x0b
2981 +
2982 +
2983 +struct katana_codec_priv {
2984 + struct regmap *regmap;
2985 + int fmt;
2986 +};
2987 +
2988 +static const struct reg_default katana_codec_reg_defaults[] = {
2989 + { KATANA_CODEC_RESET, 0x00 },
2990 + { KATANA_CODEC_VOLUME_1, 0xF0 },
2991 + { KATANA_CODEC_VOLUME_2, 0xF0 },
2992 + { KATANA_CODEC_MUTE, 0x00 },
2993 + { KATANA_CODEC_DSP_PROGRAM, 0x04 },
2994 + { KATANA_CODEC_DEEMPHASIS, 0x00 },
2995 + { KATANA_CODEC_DOP, 0x00 },
2996 + { KATANA_CODEC_FORMAT, 0xb4 },
2997 +};
2998 +
2999 +static const char * const katana_codec_dsp_program_texts[] = {
3000 + "Linear Phase Fast Roll-off Filter",
3001 + "Linear Phase Slow Roll-off Filter",
3002 + "Minimum Phase Fast Roll-off Filter",
3003 + "Minimum Phase Slow Roll-off Filter",
3004 + "Apodizing Fast Roll-off Filter",
3005 + "Corrected Minimum Phase Fast Roll-off Filter",
3006 + "Brick Wall Filter",
3007 +};
3008 +
3009 +static const unsigned int katana_codec_dsp_program_values[] = {
3010 + 0,
3011 + 1,
3012 + 2,
3013 + 3,
3014 + 4,
3015 + 6,
3016 + 7,
3017 +};
3018 +
3019 +static SOC_VALUE_ENUM_SINGLE_DECL(katana_codec_dsp_program,
3020 + KATANA_CODEC_DSP_PROGRAM, 0, 0x07,
3021 + katana_codec_dsp_program_texts,
3022 + katana_codec_dsp_program_values);
3023 +
3024 +static const char * const katana_codec_deemphasis_texts[] = {
3025 + "Bypass",
3026 + "32kHz",
3027 + "44.1kHz",
3028 + "48kHz",
3029 +};
3030 +
3031 +static const unsigned int katana_codec_deemphasis_values[] = {
3032 + 0,
3033 + 1,
3034 + 2,
3035 + 3,
3036 +};
3037 +
3038 +static SOC_VALUE_ENUM_SINGLE_DECL(katana_codec_deemphasis,
3039 + KATANA_CODEC_DEEMPHASIS, 0, 0x03,
3040 + katana_codec_deemphasis_texts,
3041 + katana_codec_deemphasis_values);
3042 +
3043 +static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(master_tlv, -12750, 0);
3044 +
3045 +static const struct snd_kcontrol_new katana_codec_controls[] = {
3046 + SOC_DOUBLE_R_TLV("Master Playback Volume", KATANA_CODEC_VOLUME_1,
3047 + KATANA_CODEC_VOLUME_2, 0, 255, 1, master_tlv),
3048 + SOC_DOUBLE("Master Playback Switch", KATANA_CODEC_MUTE, 0, 0, 1, 1),
3049 + SOC_ENUM("DSP Program Route", katana_codec_dsp_program),
3050 + SOC_ENUM("Deemphasis Route", katana_codec_deemphasis),
3051 + SOC_SINGLE("DoP Playback Switch", KATANA_CODEC_DOP, 0, 1, 1)
3052 +};
3053 +
3054 +static bool katana_codec_readable_register(struct device *dev,
3055 + unsigned int reg)
3056 +{
3057 + switch (reg) {
3058 + case KATANA_CODEC_CHIP_ID_REG:
3059 + return true;
3060 + default:
3061 + return reg < 0xff;
3062 + }
3063 +}
3064 +
3065 +static int katana_codec_hw_params(struct snd_pcm_substream *substream,
3066 + struct snd_pcm_hw_params *params,
3067 + struct snd_soc_dai *dai)
3068 +{
3069 + struct snd_soc_component *component = dai->component;
3070 + struct katana_codec_priv *katana_codec =
3071 + snd_soc_component_get_drvdata(component);
3072 + int fmt = 0;
3073 + int ret;
3074 +
3075 + dev_dbg(component->card->dev, "hw_params %u Hz, %u channels, %u bits\n",
3076 + params_rate(params),
3077 + params_channels(params),
3078 + params_width(params));
3079 +
3080 + switch (katana_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
3081 + case SND_SOC_DAIFMT_CBM_CFM: // master
3082 + if (params_channels(params) == 2)
3083 + fmt = KATANA_CODEC_CHAN_STEREO;
3084 + else
3085 + fmt = KATANA_CODEC_CHAN_MONO;
3086 +
3087 + switch (params_width(params)) {
3088 + case 16:
3089 + fmt |= KATANA_CODEC_ALEN_16;
3090 + break;
3091 + case 24:
3092 + fmt |= KATANA_CODEC_ALEN_24;
3093 + break;
3094 + case 32:
3095 + fmt |= KATANA_CODEC_ALEN_32;
3096 + break;
3097 + default:
3098 + dev_err(component->card->dev, "Bad frame size: %d\n",
3099 + params_width(params));
3100 + return -EINVAL;
3101 + }
3102 +
3103 + switch (params_rate(params)) {
3104 + case 44100:
3105 + fmt |= KATANA_CODEC_RATE_44100;
3106 + break;
3107 + case 48000:
3108 + fmt |= KATANA_CODEC_RATE_48000;
3109 + break;
3110 + case 88200:
3111 + fmt |= KATANA_CODEC_RATE_88200;
3112 + break;
3113 + case 96000:
3114 + fmt |= KATANA_CODEC_RATE_96000;
3115 + break;
3116 + case 176400:
3117 + fmt |= KATANA_CODEC_RATE_176400;
3118 + break;
3119 + case 192000:
3120 + fmt |= KATANA_CODEC_RATE_192000;
3121 + break;
3122 + case 352800:
3123 + fmt |= KATANA_CODEC_RATE_352800;
3124 + break;
3125 + case 384000:
3126 + fmt |= KATANA_CODEC_RATE_384000;
3127 + break;
3128 + default:
3129 + dev_err(component->card->dev, "Bad sample rate: %d\n",
3130 + params_rate(params));
3131 + return -EINVAL;
3132 + }
3133 +
3134 + ret = regmap_write(katana_codec->regmap, KATANA_CODEC_FORMAT,
3135 + fmt);
3136 + if (ret != 0) {
3137 + dev_err(component->card->dev, "Failed to set format: %d\n", ret);
3138 + return ret;
3139 + }
3140 + break;
3141 +
3142 + case SND_SOC_DAIFMT_CBS_CFS:
3143 + break;
3144 +
3145 + default:
3146 + return -EINVAL;
3147 + }
3148 +
3149 + return 0;
3150 +}
3151 +
3152 +static int katana_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
3153 +{
3154 + struct snd_soc_component *component = dai->component;
3155 + struct katana_codec_priv *katana_codec =
3156 + snd_soc_component_get_drvdata(component);
3157 +
3158 + katana_codec->fmt = fmt;
3159 +
3160 + return 0;
3161 +}
3162 +
3163 +int katana_codec_dai_mute_stream(struct snd_soc_dai *dai, int mute,
3164 + int stream)
3165 +{
3166 + struct snd_soc_component *component = dai->component;
3167 + struct katana_codec_priv *katana_codec =
3168 + snd_soc_component_get_drvdata(component);
3169 + int ret = 0;
3170 +
3171 + ret = regmap_write(katana_codec->regmap, KATANA_CODEC_MUTE_STREAM,
3172 + mute);
3173 + if (ret != 0) {
3174 + dev_err(component->card->dev, "Failed to set mute: %d\n", ret);
3175 + return ret;
3176 + }
3177 + return ret;
3178 +}
3179 +
3180 +static const struct snd_soc_dai_ops katana_codec_dai_ops = {
3181 + .mute_stream = katana_codec_dai_mute_stream,
3182 + .hw_params = katana_codec_hw_params,
3183 + .set_fmt = katana_codec_set_fmt,
3184 +};
3185 +
3186 +static struct snd_soc_dai_driver katana_codec_dai = {
3187 + .name = "allo-katana-codec",
3188 + .playback = {
3189 + .stream_name = "Playback",
3190 + .channels_min = 2,
3191 + .channels_max = 2,
3192 + .rates = SNDRV_PCM_RATE_CONTINUOUS,
3193 + .rate_min = 44100,
3194 + .rate_max = 384000,
3195 + .formats = SNDRV_PCM_FMTBIT_S16_LE |
3196 + SNDRV_PCM_FMTBIT_S32_LE
3197 + },
3198 + .ops = &katana_codec_dai_ops,
3199 +};
3200 +
3201 +static struct snd_soc_component_driver katana_codec_component_driver = {
3202 + .idle_bias_on = true,
3203 +
3204 + .controls = katana_codec_controls,
3205 + .num_controls = ARRAY_SIZE(katana_codec_controls),
3206 +};
3207 +
3208 +static const struct regmap_range_cfg katana_codec_range = {
3209 + .name = "Pages", .range_min = KATANA_CODEC_VIRT_BASE,
3210 + .range_max = KATANA_CODEC_MAX_REGISTER,
3211 + .selector_reg = KATANA_CODEC_PAGE,
3212 + .selector_mask = 0xff,
3213 + .window_start = 0, .window_len = 0x100,
3214 +};
3215 +
3216 +const struct regmap_config katana_codec_regmap = {
3217 + .reg_bits = 8,
3218 + .val_bits = 8,
3219 +
3220 + .ranges = &katana_codec_range,
3221 + .num_ranges = 1,
3222 +
3223 + .max_register = KATANA_CODEC_MAX_REGISTER,
3224 + .readable_reg = katana_codec_readable_register,
3225 + .reg_defaults = katana_codec_reg_defaults,
3226 + .num_reg_defaults = ARRAY_SIZE(katana_codec_reg_defaults),
3227 + .cache_type = REGCACHE_RBTREE,
3228 +};
3229 +
3230 +static int allo_katana_component_probe(struct i2c_client *i2c,
3231 + const struct i2c_device_id *id)
3232 +{
3233 + struct regmap *regmap;
3234 + struct regmap_config config = katana_codec_regmap;
3235 + struct device *dev = &i2c->dev;
3236 + struct katana_codec_priv *katana_codec;
3237 + unsigned int chip_id = 0;
3238 + int ret;
3239 +
3240 + regmap = devm_regmap_init_i2c(i2c, &config);
3241 + if (IS_ERR(regmap))
3242 + return PTR_ERR(regmap);
3243 +
3244 + katana_codec = devm_kzalloc(dev, sizeof(struct katana_codec_priv),
3245 + GFP_KERNEL);
3246 + if (!katana_codec)
3247 + return -ENOMEM;
3248 +
3249 + dev_set_drvdata(dev, katana_codec);
3250 + katana_codec->regmap = regmap;
3251 +
3252 + ret = regmap_read(regmap, KATANA_CODEC_CHIP_ID_REG, &chip_id);
3253 + if ((ret != 0) || (chip_id != KATANA_CODEC_CHIP_ID)) {
3254 + dev_err(dev, "Failed to read Chip or wrong Chip id: %d\n", ret);
3255 + return ret;
3256 + }
3257 + regmap_update_bits(regmap, KATANA_CODEC_RESET, 0x01, 0x01);
3258 + msleep(10);
3259 +
3260 + ret = snd_soc_register_component(dev, &katana_codec_component_driver,
3261 + &katana_codec_dai, 1);
3262 + if (ret != 0) {
3263 + dev_err(dev, "failed to register codec: %d\n", ret);
3264 + return ret;
3265 + }
3266 +
3267 + return 0;
3268 +}
3269 +
3270 +static int allo_katana_component_remove(struct i2c_client *i2c)
3271 +{
3272 + snd_soc_unregister_component(&i2c->dev);
3273 + return 0;
3274 +}
3275 +
3276 +static const struct i2c_device_id allo_katana_component_id[] = {
3277 + { "allo-katana-codec", },
3278 + { }
3279 +};
3280 +MODULE_DEVICE_TABLE(i2c, allo_katana_component_id);
3281 +
3282 +static const struct of_device_id allo_katana_codec_of_match[] = {
3283 + { .compatible = "allo,allo-katana-codec", },
3284 + { }
3285 +};
3286 +MODULE_DEVICE_TABLE(of, allo_katana_codec_of_match);
3287 +
3288 +static struct i2c_driver allo_katana_component_driver = {
3289 + .probe = allo_katana_component_probe,
3290 + .remove = allo_katana_component_remove,
3291 + .id_table = allo_katana_component_id,
3292 + .driver = {
3293 + .name = "allo-katana-codec",
3294 + .of_match_table = allo_katana_codec_of_match,
3295 + },
3296 +};
3297 +
3298 +module_i2c_driver(allo_katana_component_driver);
3299 +
3300 +MODULE_DESCRIPTION("ASoC Allo Katana Codec Driver");
3301 +MODULE_AUTHOR("Jaikumar <jaikumar@cem-solutions.net>");
3302 +MODULE_LICENSE("GPL v2");
3303 --- /dev/null
3304 +++ b/sound/soc/bcm/allo-piano-dac-plus.c
3305 @@ -0,0 +1,987 @@
3306 +/*
3307 + * ALSA ASoC Machine Driver for Allo Piano DAC Plus Subwoofer
3308 + *
3309 + * Author: Baswaraj K <jaikumar@cem-solutions.net>
3310 + * Copyright 2016
3311 + * based on code by Daniel Matuschek <info@crazy-audio.com>
3312 + * based on code by Florian Meier <florian.meier@koalo.de>
3313 + *
3314 + * This program is free software; you can redistribute it and/or
3315 + * modify it under the terms of the GNU General Public License
3316 + * version 2 as published by the Free Software Foundation.
3317 + *
3318 + * This program is distributed in the hope that it will be useful, but
3319 + * WITHOUT ANY WARRANTY; without even the implied warranty of
3320 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3321 + * General Public License for more details.
3322 + */
3323 +
3324 +#include <linux/module.h>
3325 +#include <linux/platform_device.h>
3326 +#include <linux/gpio/consumer.h>
3327 +#include <sound/core.h>
3328 +#include <sound/pcm.h>
3329 +#include <sound/pcm_params.h>
3330 +#include <sound/soc.h>
3331 +#include <linux/firmware.h>
3332 +#include <linux/delay.h>
3333 +#include <sound/tlv.h>
3334 +#include "../codecs/pcm512x.h"
3335 +
3336 +#define P_DAC_LEFT_MUTE 0x10
3337 +#define P_DAC_RIGHT_MUTE 0x01
3338 +#define P_DAC_MUTE 0x11
3339 +#define P_DAC_UNMUTE 0x00
3340 +#define P_MUTE 1
3341 +#define P_UNMUTE 0
3342 +
3343 +struct dsp_code {
3344 + char i2c_addr;
3345 + char offset;
3346 + char val;
3347 +};
3348 +
3349 +struct glb_pool {
3350 + struct mutex lock;
3351 + unsigned int dual_mode;
3352 + unsigned int set_lowpass;
3353 + unsigned int set_mode;
3354 + unsigned int set_rate;
3355 + unsigned int dsp_page_number;
3356 +};
3357 +
3358 +static bool digital_gain_0db_limit = true;
3359 +bool glb_mclk;
3360 +
3361 +static struct gpio_desc *mute_gpio[2];
3362 +
3363 +static const char * const allo_piano_mode_texts[] = {
3364 + "None",
3365 + "2.0",
3366 + "2.1",
3367 + "2.2",
3368 +};
3369 +
3370 +static const SOC_ENUM_SINGLE_DECL(allo_piano_mode_enum,
3371 + 0, 0, allo_piano_mode_texts);
3372 +
3373 +static const char * const allo_piano_dual_mode_texts[] = {
3374 + "None",
3375 + "Dual-Mono",
3376 + "Dual-Stereo",
3377 +};
3378 +
3379 +static const SOC_ENUM_SINGLE_DECL(allo_piano_dual_mode_enum,
3380 + 0, 0, allo_piano_dual_mode_texts);
3381 +
3382 +static const char * const allo_piano_dsp_low_pass_texts[] = {
3383 + "60",
3384 + "70",
3385 + "80",
3386 + "90",
3387 + "100",
3388 + "110",
3389 + "120",
3390 + "130",
3391 + "140",
3392 + "150",
3393 + "160",
3394 + "170",
3395 + "180",
3396 + "190",
3397 + "200",
3398 +};
3399 +
3400 +static const SOC_ENUM_SINGLE_DECL(allo_piano_enum,
3401 + 0, 0, allo_piano_dsp_low_pass_texts);
3402 +
3403 +static int __snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd,
3404 + unsigned int mode, unsigned int rate, unsigned int lowpass)
3405 +{
3406 + const struct firmware *fw;
3407 + struct snd_soc_card *card = rtd->card;
3408 + struct glb_pool *glb_ptr = card->drvdata;
3409 + char firmware_name[60];
3410 + int ret = 0, dac = 0;
3411 +
3412 + if (rate <= 46000)
3413 + rate = 44100;
3414 + else if (rate <= 68000)
3415 + rate = 48000;
3416 + else if (rate <= 92000)
3417 + rate = 88200;
3418 + else if (rate <= 136000)
3419 + rate = 96000;
3420 + else if (rate <= 184000)
3421 + rate = 176400;
3422 + else
3423 + rate = 192000;
3424 +
3425 + if (lowpass > 14)
3426 + glb_ptr->set_lowpass = lowpass = 0;
3427 +
3428 + if (mode > 3)
3429 + glb_ptr->set_mode = mode = 0;
3430 +
3431 + if (mode > 0)
3432 + glb_ptr->dual_mode = 0;
3433 +
3434 + /* same configuration loaded */
3435 + if ((rate == glb_ptr->set_rate) && (lowpass == glb_ptr->set_lowpass)
3436 + && (mode == glb_ptr->set_mode))
3437 + return 0;
3438 +
3439 + switch (mode) {
3440 + case 0: /* None */
3441 + return 1;
3442 +
3443 + case 1: /* 2.0 */
3444 + snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
3445 + PCM512x_MUTE, P_DAC_UNMUTE);
3446 + snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
3447 + PCM512x_MUTE, P_DAC_MUTE);
3448 + glb_ptr->set_rate = rate;
3449 + glb_ptr->set_mode = mode;
3450 + glb_ptr->set_lowpass = lowpass;
3451 + return 1;
3452 +
3453 + default:
3454 + snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
3455 + PCM512x_MUTE, P_DAC_UNMUTE);
3456 + snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
3457 + PCM512x_MUTE, P_DAC_UNMUTE);
3458 + }
3459 +
3460 + for (dac = 0; dac < rtd->num_codecs; dac++) {
3461 + struct dsp_code *dsp_code_read;
3462 + int i = 1;
3463 +
3464 + if (dac == 0) { /* high */
3465 + snprintf(firmware_name, sizeof(firmware_name),
3466 + "allo/piano/2.2/allo-piano-dsp-%d-%d-%d.bin",
3467 + rate, ((lowpass * 10) + 60), dac);
3468 + } else { /* low */
3469 + snprintf(firmware_name, sizeof(firmware_name),
3470 + "allo/piano/2.%d/allo-piano-dsp-%d-%d-%d.bin",
3471 + (mode - 1), rate, ((lowpass * 10) + 60), dac);
3472 + }
3473 +
3474 + dev_info(rtd->card->dev, "Dsp Firmware File Name: %s\n",
3475 + firmware_name);
3476 +
3477 + ret = request_firmware(&fw, firmware_name, rtd->card->dev);
3478 + if (ret < 0) {
3479 + dev_err(rtd->card->dev,
3480 + "Error: Allo Piano Firmware %s missing. %d\n",
3481 + firmware_name, ret);
3482 + goto err;
3483 + }
3484 +
3485 + while (i < (fw->size - 1)) {
3486 + dsp_code_read = (struct dsp_code *)&fw->data[i];
3487 +
3488 + if (dsp_code_read->offset == 0) {
3489 + glb_ptr->dsp_page_number = dsp_code_read->val;
3490 + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, dac)->component,
3491 + PCM512x_PAGE_BASE(0),
3492 + dsp_code_read->val);
3493 +
3494 + } else if (dsp_code_read->offset != 0) {
3495 + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, dac)->component,
3496 + (PCM512x_PAGE_BASE(
3497 + glb_ptr->dsp_page_number) +
3498 + dsp_code_read->offset),
3499 + dsp_code_read->val);
3500 + }
3501 + if (ret < 0) {
3502 + dev_err(rtd->card->dev,
3503 + "Failed to write Register: %d\n", ret);
3504 + release_firmware(fw);
3505 + goto err;
3506 + }
3507 + i = i + 3;
3508 + }
3509 + release_firmware(fw);
3510 + }
3511 + glb_ptr->set_rate = rate;
3512 + glb_ptr->set_mode = mode;
3513 + glb_ptr->set_lowpass = lowpass;
3514 + return 1;
3515 +
3516 +err:
3517 + return ret;
3518 +}
3519 +
3520 +static int snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd,
3521 + unsigned int mode, unsigned int rate, unsigned int lowpass)
3522 +{
3523 + struct snd_soc_card *card = rtd->card;
3524 + struct glb_pool *glb_ptr = card->drvdata;
3525 + int ret = 0;
3526 +
3527 + mutex_lock(&glb_ptr->lock);
3528 +
3529 + ret = __snd_allo_piano_dsp_program(rtd, mode, rate, lowpass);
3530 +
3531 + mutex_unlock(&glb_ptr->lock);
3532 +
3533 + return ret;
3534 +}
3535 +
3536 +static int snd_allo_piano_dual_mode_get(struct snd_kcontrol *kcontrol,
3537 + struct snd_ctl_elem_value *ucontrol)
3538 +{
3539 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3540 + struct glb_pool *glb_ptr = card->drvdata;
3541 +
3542 + ucontrol->value.integer.value[0] = glb_ptr->dual_mode;
3543 +
3544 + return 0;
3545 +}
3546 +
3547 +static int snd_allo_piano_dual_mode_put(struct snd_kcontrol *kcontrol,
3548 + struct snd_ctl_elem_value *ucontrol)
3549 +{
3550 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3551 + struct glb_pool *glb_ptr = card->drvdata;
3552 + struct snd_soc_pcm_runtime *rtd;
3553 + struct snd_card *snd_card_ptr = card->snd_card;
3554 + struct snd_kcontrol *kctl;
3555 + struct soc_mixer_control *mc;
3556 + unsigned int left_val = 0, right_val = 0;
3557 +
3558 + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
3559 +
3560 + if (ucontrol->value.integer.value[0] > 0) {
3561 + glb_ptr->dual_mode = ucontrol->value.integer.value[0];
3562 + glb_ptr->set_mode = 0;
3563 + } else {
3564 + if (glb_ptr->set_mode <= 0) {
3565 + glb_ptr->dual_mode = 1;
3566 + glb_ptr->set_mode = 0;
3567 + } else {
3568 + glb_ptr->dual_mode = 0;
3569 + return 0;
3570 + }
3571 + }
3572 +
3573 + if (glb_ptr->dual_mode == 1) { // Dual Mono
3574 + snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
3575 + PCM512x_MUTE, P_DAC_RIGHT_MUTE);
3576 + snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
3577 + PCM512x_MUTE, P_DAC_LEFT_MUTE);
3578 + snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
3579 + PCM512x_DIGITAL_VOLUME_3, 0xff);
3580 + snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
3581 + PCM512x_DIGITAL_VOLUME_2, 0xff);
3582 +
3583 + list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
3584 + if (!strncmp(kctl->id.name, "Digital Playback Volume",
3585 + sizeof(kctl->id.name))) {
3586 + mc = (struct soc_mixer_control *)
3587 + kctl->private_value;
3588 + mc->rreg = mc->reg;
3589 + break;
3590 + }
3591 + }
3592 + } else {
3593 + left_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 0)->component,
3594 + PCM512x_DIGITAL_VOLUME_2);
3595 + right_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 1)->component,
3596 + PCM512x_DIGITAL_VOLUME_3);
3597 +
3598 + list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
3599 + if (!strncmp(kctl->id.name, "Digital Playback Volume",
3600 + sizeof(kctl->id.name))) {
3601 + mc = (struct soc_mixer_control *)
3602 + kctl->private_value;
3603 + mc->rreg = PCM512x_DIGITAL_VOLUME_3;
3604 + break;
3605 + }
3606 + }
3607 +
3608 + snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
3609 + PCM512x_DIGITAL_VOLUME_3, left_val);
3610 + snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
3611 + PCM512x_DIGITAL_VOLUME_2, right_val);
3612 + snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
3613 + PCM512x_MUTE, P_DAC_UNMUTE);
3614 + snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
3615 + PCM512x_MUTE, P_DAC_UNMUTE);
3616 + }
3617 +
3618 + return 0;
3619 +}
3620 +
3621 +static int snd_allo_piano_mode_get(struct snd_kcontrol *kcontrol,
3622 + struct snd_ctl_elem_value *ucontrol)
3623 +{
3624 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3625 + struct glb_pool *glb_ptr = card->drvdata;
3626 +
3627 + ucontrol->value.integer.value[0] = glb_ptr->set_mode;
3628 + return 0;
3629 +}
3630 +
3631 +static int snd_allo_piano_mode_put(struct snd_kcontrol *kcontrol,
3632 + struct snd_ctl_elem_value *ucontrol)
3633 +{
3634 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3635 + struct snd_soc_pcm_runtime *rtd;
3636 + struct glb_pool *glb_ptr = card->drvdata;
3637 + struct snd_card *snd_card_ptr = card->snd_card;
3638 + struct snd_kcontrol *kctl;
3639 + struct soc_mixer_control *mc;
3640 + unsigned int left_val = 0, right_val = 0;
3641 +
3642 + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
3643 +
3644 + if ((glb_ptr->dual_mode == 1) &&
3645 + (ucontrol->value.integer.value[0] > 0)) {
3646 + left_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 0)->component,
3647 + PCM512x_DIGITAL_VOLUME_2);
3648 + right_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 1)->component,
3649 + PCM512x_DIGITAL_VOLUME_2);
3650 +
3651 + list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
3652 + if (!strncmp(kctl->id.name, "Digital Playback Volume",
3653 + sizeof(kctl->id.name))) {
3654 + mc = (struct soc_mixer_control *)
3655 + kctl->private_value;
3656 + mc->rreg = PCM512x_DIGITAL_VOLUME_3;
3657 + break;
3658 + }
3659 + }
3660 + snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
3661 + PCM512x_DIGITAL_VOLUME_3, left_val);
3662 + snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
3663 + PCM512x_DIGITAL_VOLUME_3, right_val);
3664 + }
3665 +
3666 + return(snd_allo_piano_dsp_program(rtd,
3667 + ucontrol->value.integer.value[0],
3668 + glb_ptr->set_rate, glb_ptr->set_lowpass));
3669 +}
3670 +
3671 +static int snd_allo_piano_lowpass_get(struct snd_kcontrol *kcontrol,
3672 + struct snd_ctl_elem_value *ucontrol)
3673 +{
3674 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3675 + struct glb_pool *glb_ptr = card->drvdata;
3676 +
3677 + ucontrol->value.integer.value[0] = glb_ptr->set_lowpass;
3678 + return 0;
3679 +}
3680 +
3681 +static int snd_allo_piano_lowpass_put(struct snd_kcontrol *kcontrol,
3682 + struct snd_ctl_elem_value *ucontrol)
3683 +{
3684 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3685 + struct snd_soc_pcm_runtime *rtd;
3686 + struct glb_pool *glb_ptr = card->drvdata;
3687 +
3688 + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
3689 + return(snd_allo_piano_dsp_program(rtd,
3690 + glb_ptr->set_mode, glb_ptr->set_rate,
3691 + ucontrol->value.integer.value[0]));
3692 +}
3693 +
3694 +static int pcm512x_get_reg_sub(struct snd_kcontrol *kcontrol,
3695 + struct snd_ctl_elem_value *ucontrol)
3696 +{
3697 + struct soc_mixer_control *mc =
3698 + (struct soc_mixer_control *)kcontrol->private_value;
3699 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3700 + struct glb_pool *glb_ptr = card->drvdata;
3701 + struct snd_soc_pcm_runtime *rtd;
3702 + unsigned int left_val = 0;
3703 + unsigned int right_val = 0;
3704 + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
3705 + right_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 1)->component,
3706 + PCM512x_DIGITAL_VOLUME_3);
3707 + if (glb_ptr->dual_mode != 1) {
3708 + left_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 1)->component,
3709 + PCM512x_DIGITAL_VOLUME_2);
3710 +
3711 + } else {
3712 + left_val = right_val;
3713 + }
3714 +
3715 + ucontrol->value.integer.value[0] =
3716 + (~(left_val >> mc->shift)) & mc->max;
3717 + ucontrol->value.integer.value[1] =
3718 + (~(right_val >> mc->shift)) & mc->max;
3719 +
3720 + return 0;
3721 +}
3722 +
3723 +static int pcm512x_set_reg_sub(struct snd_kcontrol *kcontrol,
3724 + struct snd_ctl_elem_value *ucontrol)
3725 +{
3726 + struct soc_mixer_control *mc =
3727 + (struct soc_mixer_control *)kcontrol->private_value;
3728 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3729 + struct glb_pool *glb_ptr = card->drvdata;
3730 + struct snd_soc_pcm_runtime *rtd;
3731 + unsigned int left_val = (ucontrol->value.integer.value[0] & mc->max);
3732 + unsigned int right_val = (ucontrol->value.integer.value[1] & mc->max);
3733 + int ret = 0;
3734 +
3735 + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
3736 + if (glb_ptr->dual_mode != 1) {
3737 + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
3738 + PCM512x_DIGITAL_VOLUME_2, (~left_val));
3739 + if (ret < 0)
3740 + return ret;
3741 + }
3742 +
3743 + if (digital_gain_0db_limit) {
3744 + ret = snd_soc_limit_volume(card, "Subwoofer Playback Volume",
3745 + 207);
3746 + if (ret < 0)
3747 + dev_warn(card->dev, "Failed to set volume limit: %d\n",
3748 + ret);
3749 + }
3750 +
3751 + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
3752 + PCM512x_DIGITAL_VOLUME_3, (~right_val));
3753 + if (ret < 0)
3754 + return ret;
3755 +
3756 + return 1;
3757 +}
3758 +
3759 +static int pcm512x_get_reg_sub_switch(struct snd_kcontrol *kcontrol,
3760 + struct snd_ctl_elem_value *ucontrol)
3761 +{
3762 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3763 + struct snd_soc_pcm_runtime *rtd;
3764 + int val = 0;
3765 +
3766 + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
3767 + val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 1)->component, PCM512x_MUTE);
3768 +
3769 + ucontrol->value.integer.value[0] =
3770 + (val & P_DAC_LEFT_MUTE) ? P_UNMUTE : P_MUTE;
3771 + ucontrol->value.integer.value[1] =
3772 + (val & P_DAC_RIGHT_MUTE) ? P_UNMUTE : P_MUTE;
3773 +
3774 + return val;
3775 +}
3776 +
3777 +static int pcm512x_set_reg_sub_switch(struct snd_kcontrol *kcontrol,
3778 + struct snd_ctl_elem_value *ucontrol)
3779 +{
3780 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3781 + struct snd_soc_pcm_runtime *rtd;
3782 + struct glb_pool *glb_ptr = card->drvdata;
3783 + unsigned int left_val = (ucontrol->value.integer.value[0]);
3784 + unsigned int right_val = (ucontrol->value.integer.value[1]);
3785 + int ret = 0;
3786 +
3787 + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
3788 + if (glb_ptr->set_mode != 1) {
3789 + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component, PCM512x_MUTE,
3790 + ~((left_val & 0x01)<<4 | (right_val & 0x01)));
3791 + if (ret < 0)
3792 + return ret;
3793 + }
3794 + return 1;
3795 +
3796 +}
3797 +
3798 +static int pcm512x_get_reg_master(struct snd_kcontrol *kcontrol,
3799 + struct snd_ctl_elem_value *ucontrol)
3800 +{
3801 + struct soc_mixer_control *mc =
3802 + (struct soc_mixer_control *)kcontrol->private_value;
3803 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3804 + struct glb_pool *glb_ptr = card->drvdata;
3805 + struct snd_soc_pcm_runtime *rtd;
3806 + unsigned int left_val = 0, right_val = 0;
3807 +
3808 + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
3809 +
3810 + left_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 0)->component,
3811 + PCM512x_DIGITAL_VOLUME_2);
3812 +
3813 + if (glb_ptr->dual_mode == 1) {
3814 + right_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 1)->component,
3815 + PCM512x_DIGITAL_VOLUME_3);
3816 + } else {
3817 + right_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 0)->component,
3818 + PCM512x_DIGITAL_VOLUME_3);
3819 + }
3820 +
3821 + ucontrol->value.integer.value[0] =
3822 + (~(left_val >> mc->shift)) & mc->max;
3823 + ucontrol->value.integer.value[1] =
3824 + (~(right_val >> mc->shift)) & mc->max;
3825 +
3826 + return 0;
3827 +}
3828 +
3829 +static int pcm512x_set_reg_master(struct snd_kcontrol *kcontrol,
3830 + struct snd_ctl_elem_value *ucontrol)
3831 +{
3832 + struct soc_mixer_control *mc =
3833 + (struct soc_mixer_control *)kcontrol->private_value;
3834 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3835 + struct glb_pool *glb_ptr = card->drvdata;
3836 + struct snd_soc_pcm_runtime *rtd;
3837 + unsigned int left_val = (ucontrol->value.integer.value[0] & mc->max);
3838 + unsigned int right_val = (ucontrol->value.integer.value[1] & mc->max);
3839 + int ret = 0;
3840 +
3841 + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
3842 +
3843 + if (digital_gain_0db_limit) {
3844 + ret = snd_soc_limit_volume(card, "Master Playback Volume",
3845 + 207);
3846 + if (ret < 0)
3847 + dev_warn(card->dev, "Failed to set volume limit: %d\n",
3848 + ret);
3849 + }
3850 +
3851 + if (glb_ptr->dual_mode != 1) {
3852 + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
3853 + PCM512x_DIGITAL_VOLUME_2, (~left_val));
3854 + if (ret < 0)
3855 + return ret;
3856 +
3857 + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
3858 + PCM512x_DIGITAL_VOLUME_3, (~right_val));
3859 + if (ret < 0)
3860 + return ret;
3861 +
3862 + }
3863 +
3864 + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
3865 + PCM512x_DIGITAL_VOLUME_3, (~right_val));
3866 + if (ret < 0)
3867 + return ret;
3868 +
3869 + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
3870 + PCM512x_DIGITAL_VOLUME_2, (~left_val));
3871 + if (ret < 0)
3872 + return ret;
3873 + return 1;
3874 +}
3875 +
3876 +static int pcm512x_get_reg_master_switch(struct snd_kcontrol *kcontrol,
3877 + struct snd_ctl_elem_value *ucontrol)
3878 +{
3879 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3880 + struct glb_pool *glb_ptr = card->drvdata;
3881 + struct snd_soc_pcm_runtime *rtd;
3882 + int val = 0;
3883 +
3884 + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
3885 +
3886 + val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 0)->component, PCM512x_MUTE);
3887 +
3888 + ucontrol->value.integer.value[0] =
3889 + (val & P_DAC_LEFT_MUTE) ? P_UNMUTE : P_MUTE;
3890 +
3891 + if (glb_ptr->dual_mode == 1) {
3892 + val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 1)->component, PCM512x_MUTE);
3893 + }
3894 + ucontrol->value.integer.value[1] =
3895 + (val & P_DAC_RIGHT_MUTE) ? P_UNMUTE : P_MUTE;
3896 +
3897 + return val;
3898 +}
3899 +
3900 +static int pcm512x_set_reg_master_switch(struct snd_kcontrol *kcontrol,
3901 + struct snd_ctl_elem_value *ucontrol)
3902 +{
3903 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3904 + struct snd_soc_pcm_runtime *rtd;
3905 + struct glb_pool *glb_ptr = card->drvdata;
3906 + unsigned int left_val = (ucontrol->value.integer.value[0]);
3907 + unsigned int right_val = (ucontrol->value.integer.value[1]);
3908 + int ret = 0;
3909 +
3910 + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
3911 + if (glb_ptr->dual_mode == 1) {
3912 + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component, PCM512x_MUTE,
3913 + ~((left_val & 0x01)<<4));
3914 + if (ret < 0)
3915 + return ret;
3916 + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component, PCM512x_MUTE,
3917 + ~((right_val & 0x01)));
3918 + if (ret < 0)
3919 + return ret;
3920 +
3921 + } else if (glb_ptr->set_mode == 1) {
3922 + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component, PCM512x_MUTE,
3923 + ~((left_val & 0x01)<<4 | (right_val & 0x01)));
3924 + if (ret < 0)
3925 + return ret;
3926 +
3927 + } else {
3928 + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component, PCM512x_MUTE,
3929 + ~((left_val & 0x01)<<4 | (right_val & 0x01)));
3930 + if (ret < 0)
3931 + return ret;
3932 +
3933 + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component, PCM512x_MUTE,
3934 + ~((left_val & 0x01)<<4 | (right_val & 0x01)));
3935 + if (ret < 0)
3936 + return ret;
3937 + }
3938 + return 1;
3939 +}
3940 +
3941 +static const DECLARE_TLV_DB_SCALE(digital_tlv_sub, -10350, 50, 1);
3942 +static const DECLARE_TLV_DB_SCALE(digital_tlv_master, -10350, 50, 1);
3943 +
3944 +static const struct snd_kcontrol_new allo_piano_controls[] = {
3945 + SOC_ENUM_EXT("Subwoofer mode Route",
3946 + allo_piano_mode_enum,
3947 + snd_allo_piano_mode_get,
3948 + snd_allo_piano_mode_put),
3949 +
3950 + SOC_ENUM_EXT("Dual Mode Route",
3951 + allo_piano_dual_mode_enum,
3952 + snd_allo_piano_dual_mode_get,
3953 + snd_allo_piano_dual_mode_put),
3954 +
3955 + SOC_ENUM_EXT("Lowpass Route", allo_piano_enum,
3956 + snd_allo_piano_lowpass_get,
3957 + snd_allo_piano_lowpass_put),
3958 +
3959 + SOC_DOUBLE_R_EXT_TLV("Subwoofer Playback Volume",
3960 + PCM512x_DIGITAL_VOLUME_2,
3961 + PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
3962 + pcm512x_get_reg_sub,
3963 + pcm512x_set_reg_sub,
3964 + digital_tlv_sub),
3965 +
3966 + SOC_DOUBLE_EXT("Subwoofer Playback Switch",
3967 + PCM512x_MUTE,
3968 + PCM512x_RQML_SHIFT,
3969 + PCM512x_RQMR_SHIFT, 1, 1,
3970 + pcm512x_get_reg_sub_switch,
3971 + pcm512x_set_reg_sub_switch),
3972 +
3973 + SOC_DOUBLE_R_EXT_TLV("Master Playback Volume",
3974 + PCM512x_DIGITAL_VOLUME_2,
3975 + PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
3976 + pcm512x_get_reg_master,
3977 + pcm512x_set_reg_master,
3978 + digital_tlv_master),
3979 +
3980 + SOC_DOUBLE_EXT("Master Playback Switch",
3981 + PCM512x_MUTE,
3982 + PCM512x_RQML_SHIFT,
3983 + PCM512x_RQMR_SHIFT, 1, 1,
3984 + pcm512x_get_reg_master_switch,
3985 + pcm512x_set_reg_master_switch),
3986 +};
3987 +
3988 +static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd)
3989 +{
3990 + struct snd_soc_card *card = rtd->card;
3991 + struct glb_pool *glb_ptr;
3992 +
3993 + glb_ptr = kzalloc(sizeof(struct glb_pool), GFP_KERNEL);
3994 + if (!glb_ptr)
3995 + return -ENOMEM;
3996 +
3997 + card->drvdata = glb_ptr;
3998 + glb_ptr->dual_mode = 2;
3999 + glb_ptr->set_mode = 0;
4000 +
4001 + mutex_init(&glb_ptr->lock);
4002 +
4003 + if (digital_gain_0db_limit) {
4004 + int ret;
4005 +
4006 + ret = snd_soc_limit_volume(card, "Digital Playback Volume",
4007 + 207);
4008 + if (ret < 0)
4009 + dev_warn(card->dev, "Failed to set volume limit: %d\n",
4010 + ret);
4011 + }
4012 + return 0;
4013 +}
4014 +
4015 +static void snd_allo_piano_gpio_mute(struct snd_soc_card *card)
4016 +{
4017 + if (mute_gpio[0])
4018 + gpiod_set_value_cansleep(mute_gpio[0], P_MUTE);
4019 +
4020 + if (mute_gpio[1])
4021 + gpiod_set_value_cansleep(mute_gpio[1], P_MUTE);
4022 +}
4023 +
4024 +static void snd_allo_piano_gpio_unmute(struct snd_soc_card *card)
4025 +{
4026 + if (mute_gpio[0])
4027 + gpiod_set_value_cansleep(mute_gpio[0], P_UNMUTE);
4028 +
4029 + if (mute_gpio[1])
4030 + gpiod_set_value_cansleep(mute_gpio[1], P_UNMUTE);
4031 +}
4032 +
4033 +static int snd_allo_piano_set_bias_level(struct snd_soc_card *card,
4034 + struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
4035 +{
4036 + struct snd_soc_pcm_runtime *rtd;
4037 + struct snd_soc_dai *codec_dai;
4038 +
4039 + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
4040 + codec_dai = asoc_rtd_to_codec(rtd, 0);
4041 +
4042 + if (dapm->dev != codec_dai->dev)
4043 + return 0;
4044 +
4045 + switch (level) {
4046 + case SND_SOC_BIAS_PREPARE:
4047 + if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
4048 + break;
4049 + /* UNMUTE DAC */
4050 + snd_allo_piano_gpio_unmute(card);
4051 + break;
4052 +
4053 + case SND_SOC_BIAS_STANDBY:
4054 + if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
4055 + break;
4056 + /* MUTE DAC */
4057 + snd_allo_piano_gpio_mute(card);
4058 + break;
4059 +
4060 + default:
4061 + break;
4062 + }
4063 +
4064 + return 0;
4065 +}
4066 +
4067 +static int snd_allo_piano_dac_startup(
4068 + struct snd_pcm_substream *substream)
4069 +{
4070 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
4071 + struct snd_soc_card *card = rtd->card;
4072 +
4073 + snd_allo_piano_gpio_mute(card);
4074 +
4075 + return 0;
4076 +}
4077 +
4078 +static int snd_allo_piano_dac_hw_params(
4079 + struct snd_pcm_substream *substream,
4080 + struct snd_pcm_hw_params *params)
4081 +{
4082 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
4083 + unsigned int rate = params_rate(params);
4084 + struct snd_soc_card *card = rtd->card;
4085 + struct glb_pool *glb_ptr = card->drvdata;
4086 + int ret = 0, val = 0, dac;
4087 +
4088 + for (dac = 0; (glb_mclk && dac < 2); dac++) {
4089 + /* Configure the PLL clock reference for both the Codecs */
4090 + val = snd_soc_component_read(asoc_rtd_to_codec(rtd, dac)->component,
4091 + PCM512x_RATE_DET_4);
4092 +
4093 + if (val & 0x40) {
4094 + snd_soc_component_write(asoc_rtd_to_codec(rtd, dac)->component,
4095 + PCM512x_PLL_REF,
4096 + PCM512x_SREF_BCK);
4097 +
4098 + dev_info(asoc_rtd_to_codec(rtd, dac)->component->dev,
4099 + "Setting BCLK as input clock & Enable PLL\n");
4100 + } else {
4101 + snd_soc_component_write(asoc_rtd_to_codec(rtd, dac)->component,
4102 + PCM512x_PLL_EN,
4103 + 0x00);
4104 +
4105 + snd_soc_component_write(asoc_rtd_to_codec(rtd, dac)->component,
4106 + PCM512x_PLL_REF,
4107 + PCM512x_SREF_SCK);
4108 +
4109 + dev_info(asoc_rtd_to_codec(rtd, dac)->component->dev,
4110 + "Setting SCLK as input clock & disabled PLL\n");
4111 + }
4112 + }
4113 +
4114 + ret = snd_allo_piano_dsp_program(rtd, glb_ptr->set_mode, rate,
4115 + glb_ptr->set_lowpass);
4116 + if (ret < 0)
4117 + return ret;
4118 +
4119 + return ret;
4120 +}
4121 +
4122 +static int snd_allo_piano_dac_prepare(
4123 + struct snd_pcm_substream *substream)
4124 +{
4125 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
4126 + struct snd_soc_card *card = rtd->card;
4127 +
4128 + snd_allo_piano_gpio_unmute(card);
4129 +
4130 + return 0;
4131 +}
4132 +
4133 +/* machine stream operations */
4134 +static struct snd_soc_ops snd_allo_piano_dac_ops = {
4135 + .startup = snd_allo_piano_dac_startup,
4136 + .hw_params = snd_allo_piano_dac_hw_params,
4137 + .prepare = snd_allo_piano_dac_prepare,
4138 +};
4139 +
4140 +static struct snd_soc_dai_link_component allo_piano_2_1_codecs[] = {
4141 + {
4142 + .dai_name = "pcm512x-hifi",
4143 + },
4144 + {
4145 + .dai_name = "pcm512x-hifi",
4146 + },
4147 +};
4148 +
4149 +SND_SOC_DAILINK_DEFS(allo_piano_dai_plus,
4150 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
4151 + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "pcm512x-hifi"),
4152 + COMP_CODEC(NULL, "pcm512x-hifi")),
4153 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
4154 +
4155 +static struct snd_soc_dai_link snd_allo_piano_dac_dai[] = {
4156 + {
4157 + .name = "PianoDACPlus",
4158 + .stream_name = "PianoDACPlus",
4159 + .dai_fmt = SND_SOC_DAIFMT_I2S |
4160 + SND_SOC_DAIFMT_NB_NF |
4161 + SND_SOC_DAIFMT_CBS_CFS,
4162 + .ops = &snd_allo_piano_dac_ops,
4163 + .init = snd_allo_piano_dac_init,
4164 + SND_SOC_DAILINK_REG(allo_piano_dai_plus),
4165 + },
4166 +};
4167 +
4168 +/* audio machine driver */
4169 +static struct snd_soc_card snd_allo_piano_dac = {
4170 + .name = "PianoDACPlus",
4171 + .owner = THIS_MODULE,
4172 + .dai_link = snd_allo_piano_dac_dai,
4173 + .num_links = ARRAY_SIZE(snd_allo_piano_dac_dai),
4174 + .controls = allo_piano_controls,
4175 + .num_controls = ARRAY_SIZE(allo_piano_controls),
4176 +};
4177 +
4178 +static int snd_allo_piano_dac_probe(struct platform_device *pdev)
4179 +{
4180 + struct snd_soc_card *card = &snd_allo_piano_dac;
4181 + int ret = 0, i = 0;
4182 +
4183 + card->dev = &pdev->dev;
4184 + platform_set_drvdata(pdev, &snd_allo_piano_dac);
4185 +
4186 + if (pdev->dev.of_node) {
4187 + struct device_node *i2s_node;
4188 + struct snd_soc_dai_link *dai;
4189 +
4190 + dai = &snd_allo_piano_dac_dai[0];
4191 + i2s_node = of_parse_phandle(pdev->dev.of_node,
4192 + "i2s-controller", 0);
4193 + if (i2s_node) {
4194 + for (i = 0; i < card->num_links; i++) {
4195 + dai->cpus->dai_name = NULL;
4196 + dai->cpus->of_node = i2s_node;
4197 + dai->platforms->name = NULL;
4198 + dai->platforms->of_node = i2s_node;
4199 + }
4200 + }
4201 + digital_gain_0db_limit =
4202 + !of_property_read_bool(pdev->dev.of_node,
4203 + "allo,24db_digital_gain");
4204 +
4205 + glb_mclk = of_property_read_bool(pdev->dev.of_node,
4206 + "allo,glb_mclk");
4207 +
4208 + allo_piano_2_1_codecs[0].of_node =
4209 + of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
4210 + if (!allo_piano_2_1_codecs[0].of_node) {
4211 + dev_err(&pdev->dev,
4212 + "Property 'audio-codec' missing or invalid\n");
4213 + return -EINVAL;
4214 + }
4215 +
4216 + allo_piano_2_1_codecs[1].of_node =
4217 + of_parse_phandle(pdev->dev.of_node, "audio-codec", 1);
4218 + if (!allo_piano_2_1_codecs[1].of_node) {
4219 + dev_err(&pdev->dev,
4220 + "Property 'audio-codec' missing or invalid\n");
4221 + return -EINVAL;
4222 + }
4223 +
4224 + mute_gpio[0] = devm_gpiod_get_optional(&pdev->dev, "mute1",
4225 + GPIOD_OUT_LOW);
4226 + if (IS_ERR(mute_gpio[0])) {
4227 + ret = PTR_ERR(mute_gpio[0]);
4228 + dev_err(&pdev->dev,
4229 + "failed to get mute1 gpio6: %d\n", ret);
4230 + return ret;
4231 + }
4232 +
4233 + mute_gpio[1] = devm_gpiod_get_optional(&pdev->dev, "mute2",
4234 + GPIOD_OUT_LOW);
4235 + if (IS_ERR(mute_gpio[1])) {
4236 + ret = PTR_ERR(mute_gpio[1]);
4237 + dev_err(&pdev->dev,
4238 + "failed to get mute2 gpio25: %d\n", ret);
4239 + return ret;
4240 + }
4241 +
4242 + if (mute_gpio[0] && mute_gpio[1])
4243 + snd_allo_piano_dac.set_bias_level =
4244 + snd_allo_piano_set_bias_level;
4245 +
4246 + ret = snd_soc_register_card(&snd_allo_piano_dac);
4247 + if (ret < 0) {
4248 + dev_err(&pdev->dev,
4249 + "snd_soc_register_card() failed: %d\n", ret);
4250 + return ret;
4251 + }
4252 +
4253 + if ((mute_gpio[0]) && (mute_gpio[1]))
4254 + snd_allo_piano_gpio_mute(&snd_allo_piano_dac);
4255 +
4256 + return 0;
4257 + }
4258 +
4259 + return -EINVAL;
4260 +}
4261 +
4262 +static int snd_allo_piano_dac_remove(struct platform_device *pdev)
4263 +{
4264 + struct snd_soc_card *card = platform_get_drvdata(pdev);
4265 +
4266 + kfree(&card->drvdata);
4267 + snd_allo_piano_gpio_mute(&snd_allo_piano_dac);
4268 + return snd_soc_unregister_card(&snd_allo_piano_dac);
4269 +}
4270 +
4271 +static const struct of_device_id snd_allo_piano_dac_of_match[] = {
4272 + { .compatible = "allo,piano-dac-plus", },
4273 + { /* sentinel */ },
4274 +};
4275 +
4276 +MODULE_DEVICE_TABLE(of, snd_allo_piano_dac_of_match);
4277 +
4278 +static struct platform_driver snd_allo_piano_dac_driver = {
4279 + .driver = {
4280 + .name = "snd-allo-piano-dac-plus",
4281 + .owner = THIS_MODULE,
4282 + .of_match_table = snd_allo_piano_dac_of_match,
4283 + },
4284 + .probe = snd_allo_piano_dac_probe,
4285 + .remove = snd_allo_piano_dac_remove,
4286 +};
4287 +
4288 +module_platform_driver(snd_allo_piano_dac_driver);
4289 +
4290 +MODULE_AUTHOR("Baswaraj K <jaikumar@cem-solutions.net>");
4291 +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Piano DAC Plus");
4292 +MODULE_LICENSE("GPL v2");
4293 --- /dev/null
4294 +++ b/sound/soc/bcm/allo-piano-dac.c
4295 @@ -0,0 +1,122 @@
4296 +/*
4297 + * ALSA ASoC Machine Driver for Allo Piano DAC
4298 + *
4299 + * Author: Baswaraj K <jaikumar@cem-solutions.net>
4300 + * Copyright 2016
4301 + * based on code by Daniel Matuschek <info@crazy-audio.com>
4302 + * based on code by Florian Meier <florian.meier@koalo.de>
4303 + *
4304 + * This program is free software; you can redistribute it and/or
4305 + * modify it under the terms of the GNU General Public License
4306 + * version 2 as published by the Free Software Foundation.
4307 + *
4308 + * This program is distributed in the hope that it will be useful, but
4309 + * WITHOUT ANY WARRANTY; without even the implied warranty of
4310 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4311 + * General Public License for more details.
4312 + */
4313 +
4314 +#include <linux/module.h>
4315 +#include <linux/platform_device.h>
4316 +
4317 +#include <sound/core.h>
4318 +#include <sound/pcm.h>
4319 +#include <sound/pcm_params.h>
4320 +#include <sound/soc.h>
4321 +
4322 +static bool digital_gain_0db_limit = true;
4323 +
4324 +static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd)
4325 +{
4326 + if (digital_gain_0db_limit) {
4327 + int ret;
4328 + struct snd_soc_card *card = rtd->card;
4329 +
4330 + ret = snd_soc_limit_volume(card, "Digital Playback Volume",
4331 + 207);
4332 + if (ret < 0)
4333 + dev_warn(card->dev, "Failed to set volume limit: %d\n",
4334 + ret);
4335 + }
4336 +
4337 + return 0;
4338 +}
4339 +
4340 +SND_SOC_DAILINK_DEFS(allo_piano_dai,
4341 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
4342 + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004c", "pcm512x-hifi")),
4343 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
4344 +
4345 +static struct snd_soc_dai_link snd_allo_piano_dac_dai[] = {
4346 +{
4347 + .name = "Piano DAC",
4348 + .stream_name = "Piano DAC HiFi",
4349 + .dai_fmt = SND_SOC_DAIFMT_I2S |
4350 + SND_SOC_DAIFMT_NB_NF |
4351 + SND_SOC_DAIFMT_CBS_CFS,
4352 + .init = snd_allo_piano_dac_init,
4353 + SND_SOC_DAILINK_REG(allo_piano_dai),
4354 +},
4355 +};
4356 +
4357 +/* audio machine driver */
4358 +static struct snd_soc_card snd_allo_piano_dac = {
4359 + .name = "PianoDAC",
4360 + .owner = THIS_MODULE,
4361 + .dai_link = snd_allo_piano_dac_dai,
4362 + .num_links = ARRAY_SIZE(snd_allo_piano_dac_dai),
4363 +};
4364 +
4365 +static int snd_allo_piano_dac_probe(struct platform_device *pdev)
4366 +{
4367 + int ret = 0;
4368 +
4369 + snd_allo_piano_dac.dev = &pdev->dev;
4370 +
4371 + if (pdev->dev.of_node) {
4372 + struct device_node *i2s_node;
4373 + struct snd_soc_dai_link *dai;
4374 +
4375 + dai = &snd_allo_piano_dac_dai[0];
4376 + i2s_node = of_parse_phandle(pdev->dev.of_node,
4377 + "i2s-controller", 0);
4378 +
4379 + if (i2s_node) {
4380 + dai->cpus->dai_name = NULL;
4381 + dai->cpus->of_node = i2s_node;
4382 + dai->platforms->name = NULL;
4383 + dai->platforms->of_node = i2s_node;
4384 + }
4385 +
4386 + digital_gain_0db_limit = !of_property_read_bool(
4387 + pdev->dev.of_node, "allo,24db_digital_gain");
4388 + }
4389 +
4390 + ret = devm_snd_soc_register_card(&pdev->dev, &snd_allo_piano_dac);
4391 + if (ret && ret != -EPROBE_DEFER)
4392 + dev_err(&pdev->dev,
4393 + "snd_soc_register_card() failed: %d\n", ret);
4394 +
4395 + return ret;
4396 +}
4397 +
4398 +static const struct of_device_id snd_allo_piano_dac_of_match[] = {
4399 + { .compatible = "allo,piano-dac", },
4400 + { /* sentinel */ },
4401 +};
4402 +MODULE_DEVICE_TABLE(of, snd_allo_piano_dac_of_match);
4403 +
4404 +static struct platform_driver snd_allo_piano_dac_driver = {
4405 + .driver = {
4406 + .name = "snd-allo-piano-dac",
4407 + .owner = THIS_MODULE,
4408 + .of_match_table = snd_allo_piano_dac_of_match,
4409 + },
4410 + .probe = snd_allo_piano_dac_probe,
4411 +};
4412 +
4413 +module_platform_driver(snd_allo_piano_dac_driver);
4414 +
4415 +MODULE_AUTHOR("Baswaraj K <jaikumar@cem-solutions.net>");
4416 +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Piano DAC");
4417 +MODULE_LICENSE("GPL v2");
4418 --- /dev/null
4419 +++ b/sound/soc/bcm/audioinjector-isolated-soundcard.c
4420 @@ -0,0 +1,183 @@
4421 +/*
4422 + * ASoC Driver for AudioInjector.net isolated soundcard
4423 + *
4424 + * Created on: 20-February-2020
4425 + * Author: flatmax@flatmax.org
4426 + * based on audioinjector-octo-soundcard.c
4427 + *
4428 + * Copyright (C) 2020 Flatmax Pty. Ltd.
4429 + *
4430 + * This program is free software; you can redistribute it and/or
4431 + * modify it under the terms of the GNU General Public License
4432 + * version 2 as published by the Free Software Foundation.
4433 + *
4434 + * This program is distributed in the hope that it will be useful, but
4435 + * WITHOUT ANY WARRANTY; without even the implied warranty of
4436 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4437 + * General Public License for more details.
4438 + */
4439 +
4440 +#include <linux/module.h>
4441 +#include <linux/types.h>
4442 +#include <linux/gpio/consumer.h>
4443 +
4444 +#include <sound/core.h>
4445 +#include <sound/soc.h>
4446 +#include <sound/pcm_params.h>
4447 +#include <sound/control.h>
4448 +
4449 +static struct gpio_desc *mute_gpio;
4450 +
4451 +static const unsigned int audioinjector_isolated_rates[] = {
4452 + 192000, 96000, 48000, 32000, 24000, 16000, 8000
4453 +};
4454 +
4455 +static struct snd_pcm_hw_constraint_list audioinjector_isolated_constraints = {
4456 + .list = audioinjector_isolated_rates,
4457 + .count = ARRAY_SIZE(audioinjector_isolated_rates),
4458 +};
4459 +
4460 +static int audioinjector_isolated_dai_init(struct snd_soc_pcm_runtime *rtd)
4461 +{
4462 + int ret=snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 24576000, 0);
4463 + if (ret)
4464 + return ret;
4465 +
4466 + return snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), 64);
4467 +}
4468 +
4469 +static int audioinjector_isolated_startup(struct snd_pcm_substream *substream)
4470 +{
4471 + snd_pcm_hw_constraint_list(substream->runtime, 0,
4472 + SNDRV_PCM_HW_PARAM_RATE, &audioinjector_isolated_constraints);
4473 +
4474 + return 0;
4475 +}
4476 +
4477 +static int audioinjector_isolated_trigger(struct snd_pcm_substream *substream,
4478 + int cmd){
4479 +
4480 + switch (cmd) {
4481 + case SNDRV_PCM_TRIGGER_STOP:
4482 + case SNDRV_PCM_TRIGGER_SUSPEND:
4483 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
4484 + gpiod_set_value(mute_gpio, 0);
4485 + break;
4486 + case SNDRV_PCM_TRIGGER_START:
4487 + case SNDRV_PCM_TRIGGER_RESUME:
4488 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
4489 + gpiod_set_value(mute_gpio, 1);
4490 + break;
4491 + default:
4492 + return -EINVAL;
4493 + }
4494 + return 0;
4495 +}
4496 +
4497 +static struct snd_soc_ops audioinjector_isolated_ops = {
4498 + .startup = audioinjector_isolated_startup,
4499 + .trigger = audioinjector_isolated_trigger,
4500 +};
4501 +
4502 +SND_SOC_DAILINK_DEFS(audioinjector_isolated,
4503 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
4504 + DAILINK_COMP_ARRAY(COMP_CODEC("cs4271.1-0010", "cs4271-hifi")),
4505 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
4506 +
4507 +static struct snd_soc_dai_link audioinjector_isolated_dai[] = {
4508 + {
4509 + .name = "AudioInjector ISO",
4510 + .stream_name = "AI-HIFI",
4511 + .ops = &audioinjector_isolated_ops,
4512 + .init = audioinjector_isolated_dai_init,
4513 + .symmetric_rates = 1,
4514 + .symmetric_channels = 1,
4515 + .dai_fmt = SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF,
4516 + SND_SOC_DAILINK_REG(audioinjector_isolated),
4517 + }
4518 +};
4519 +
4520 +static const struct snd_soc_dapm_widget audioinjector_isolated_widgets[] = {
4521 + SND_SOC_DAPM_OUTPUT("OUTPUTS"),
4522 + SND_SOC_DAPM_INPUT("INPUTS"),
4523 +};
4524 +
4525 +static const struct snd_soc_dapm_route audioinjector_isolated_route[] = {
4526 + /* Balanced outputs */
4527 + {"OUTPUTS", NULL, "AOUTA+"},
4528 + {"OUTPUTS", NULL, "AOUTA-"},
4529 + {"OUTPUTS", NULL, "AOUTB+"},
4530 + {"OUTPUTS", NULL, "AOUTB-"},
4531 +
4532 + /* Balanced inputs */
4533 + {"AINA", NULL, "INPUTS"},
4534 + {"AINB", NULL, "INPUTS"},
4535 +};
4536 +
4537 +static struct snd_soc_card snd_soc_audioinjector_isolated = {
4538 + .name = "audioinjector-isolated-soundcard",
4539 + .dai_link = audioinjector_isolated_dai,
4540 + .num_links = ARRAY_SIZE(audioinjector_isolated_dai),
4541 +
4542 + .dapm_widgets = audioinjector_isolated_widgets,
4543 + .num_dapm_widgets = ARRAY_SIZE(audioinjector_isolated_widgets),
4544 + .dapm_routes = audioinjector_isolated_route,
4545 + .num_dapm_routes = ARRAY_SIZE(audioinjector_isolated_route),
4546 +};
4547 +
4548 +static int audioinjector_isolated_probe(struct platform_device *pdev)
4549 +{
4550 + struct snd_soc_card *card = &snd_soc_audioinjector_isolated;
4551 + int ret;
4552 +
4553 + card->dev = &pdev->dev;
4554 +
4555 + if (pdev->dev.of_node) {
4556 + struct snd_soc_dai_link *dai = &audioinjector_isolated_dai[0];
4557 + struct device_node *i2s_node =
4558 + of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0);
4559 +
4560 + if (i2s_node) {
4561 + dai->cpus->dai_name = NULL;
4562 + dai->cpus->of_node = i2s_node;
4563 + dai->platforms->name = NULL;
4564 + dai->platforms->of_node = i2s_node;
4565 + } else {
4566 + dev_err(&pdev->dev,
4567 + "i2s-controller missing or invalid in DT\n");
4568 + return -EINVAL;
4569 + }
4570 +
4571 + mute_gpio = devm_gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_LOW);
4572 + if (IS_ERR(mute_gpio)){
4573 + dev_err(&pdev->dev, "mute gpio not found in dt overlay\n");
4574 + return PTR_ERR(mute_gpio);
4575 + }
4576 + }
4577 +
4578 + ret = devm_snd_soc_register_card(&pdev->dev, card);
4579 + if (ret && ret != -EPROBE_DEFER)
4580 + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
4581 + return ret;
4582 +}
4583 +
4584 +static const struct of_device_id audioinjector_isolated_of_match[] = {
4585 + { .compatible = "ai,audioinjector-isolated-soundcard", },
4586 + {},
4587 +};
4588 +MODULE_DEVICE_TABLE(of, audioinjector_isolated_of_match);
4589 +
4590 +static struct platform_driver audioinjector_isolated_driver = {
4591 + .driver = {
4592 + .name = "audioinjector-isolated",
4593 + .owner = THIS_MODULE,
4594 + .of_match_table = audioinjector_isolated_of_match,
4595 + },
4596 + .probe = audioinjector_isolated_probe,
4597 +};
4598 +
4599 +module_platform_driver(audioinjector_isolated_driver);
4600 +MODULE_AUTHOR("Matt Flax <flatmax@flatmax.org>");
4601 +MODULE_DESCRIPTION("AudioInjector.net isolated Soundcard");
4602 +MODULE_LICENSE("GPL v2");
4603 +MODULE_ALIAS("platform:audioinjector-isolated-soundcard");
4604 --- /dev/null
4605 +++ b/sound/soc/bcm/audioinjector-octo-soundcard.c
4606 @@ -0,0 +1,346 @@
4607 +/*
4608 + * ASoC Driver for AudioInjector Pi octo channel soundcard (hat)
4609 + *
4610 + * Created on: 27-October-2016
4611 + * Author: flatmax@flatmax.org
4612 + * based on audioinjector-pi-soundcard.c
4613 + *
4614 + * Copyright (C) 2016 Flatmax Pty. Ltd.
4615 + *
4616 + * This program is free software; you can redistribute it and/or
4617 + * modify it under the terms of the GNU General Public License
4618 + * version 2 as published by the Free Software Foundation.
4619 + *
4620 + * This program is distributed in the hope that it will be useful, but
4621 + * WITHOUT ANY WARRANTY; without even the implied warranty of
4622 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4623 + * General Public License for more details.
4624 + */
4625 +
4626 +#include <linux/module.h>
4627 +#include <linux/types.h>
4628 +#include <linux/gpio/consumer.h>
4629 +
4630 +#include <sound/core.h>
4631 +#include <sound/soc.h>
4632 +#include <sound/pcm_params.h>
4633 +#include <sound/control.h>
4634 +
4635 +static struct gpio_descs *mult_gpios;
4636 +static struct gpio_desc *codec_rst_gpio;
4637 +static unsigned int audioinjector_octo_rate;
4638 +static bool non_stop_clocks;
4639 +
4640 +static const unsigned int audioinjector_octo_rates[] = {
4641 + 96000, 48000, 32000, 24000, 16000, 8000, 88200, 44100, 29400, 22050, 14700,
4642 +};
4643 +
4644 +static struct snd_pcm_hw_constraint_list audioinjector_octo_constraints = {
4645 + .list = audioinjector_octo_rates,
4646 + .count = ARRAY_SIZE(audioinjector_octo_rates),
4647 +};
4648 +
4649 +static int audioinjector_octo_dai_init(struct snd_soc_pcm_runtime *rtd)
4650 +{
4651 + return snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), 64);
4652 +}
4653 +
4654 +static int audioinjector_octo_startup(struct snd_pcm_substream *substream)
4655 +{
4656 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
4657 + asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = 8;
4658 + asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = 8;
4659 + asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = 8;
4660 + asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_max = 8;
4661 + asoc_rtd_to_codec(rtd, 0)->driver->capture.channels_max = 8;
4662 +
4663 + snd_pcm_hw_constraint_list(substream->runtime, 0,
4664 + SNDRV_PCM_HW_PARAM_RATE,
4665 + &audioinjector_octo_constraints);
4666 +
4667 + return 0;
4668 +}
4669 +
4670 +static void audioinjector_octo_shutdown(struct snd_pcm_substream *substream)
4671 +{
4672 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
4673 + asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = 2;
4674 + asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = 2;
4675 + asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = 2;
4676 + asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_max = 2;
4677 + asoc_rtd_to_codec(rtd, 0)->driver->capture.channels_max = 6;
4678 +}
4679 +
4680 +static int audioinjector_octo_hw_params(struct snd_pcm_substream *substream,
4681 + struct snd_pcm_hw_params *params)
4682 +{
4683 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
4684 +
4685 + // set codec DAI configuration
4686 + int ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 0),
4687 + SND_SOC_DAIFMT_CBS_CFS|SND_SOC_DAIFMT_DSP_A|
4688 + SND_SOC_DAIFMT_NB_NF);
4689 + if (ret < 0)
4690 + return ret;
4691 +
4692 + // set cpu DAI configuration
4693 + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
4694 + SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S|
4695 + SND_SOC_DAIFMT_NB_NF);
4696 + if (ret < 0)
4697 + return ret;
4698 +
4699 + audioinjector_octo_rate = params_rate(params);
4700 +
4701 + // Set the correct sysclock for the codec
4702 + switch (audioinjector_octo_rate) {
4703 + case 96000:
4704 + case 48000:
4705 + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 49152000,
4706 + 0);
4707 + break;
4708 + case 24000:
4709 + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 49152000/2,
4710 + 0);
4711 + break;
4712 + case 32000:
4713 + case 16000:
4714 + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 49152000/3,
4715 + 0);
4716 + break;
4717 + case 8000:
4718 + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 49152000/6,
4719 + 0);
4720 + break;
4721 + case 88200:
4722 + case 44100:
4723 + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 45185400,
4724 + 0);
4725 + break;
4726 + case 22050:
4727 + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 45185400/2,
4728 + 0);
4729 + break;
4730 + case 29400:
4731 + case 14700:
4732 + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 45185400/3,
4733 + 0);
4734 + break;
4735 + default:
4736 + return -EINVAL;
4737 + }
4738 +}
4739 +
4740 +static int audioinjector_octo_trigger(struct snd_pcm_substream *substream,
4741 + int cmd){
4742 + DECLARE_BITMAP(mult, 4);
4743 +
4744 + memset(mult, 0, sizeof(mult));
4745 +
4746 + switch (cmd) {
4747 + case SNDRV_PCM_TRIGGER_STOP:
4748 + case SNDRV_PCM_TRIGGER_SUSPEND:
4749 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
4750 + if (!non_stop_clocks)
4751 + break;
4752 + /* fall through */
4753 + case SNDRV_PCM_TRIGGER_START:
4754 + case SNDRV_PCM_TRIGGER_RESUME:
4755 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
4756 + switch (audioinjector_octo_rate) {
4757 + case 96000:
4758 + __assign_bit(3, mult, 1);
4759 + /* fall through */
4760 + case 88200:
4761 + __assign_bit(1, mult, 1);
4762 + __assign_bit(2, mult, 1);
4763 + break;
4764 + case 48000:
4765 + __assign_bit(3, mult, 1);
4766 + /* fall through */
4767 + case 44100:
4768 + __assign_bit(2, mult, 1);
4769 + break;
4770 + case 32000:
4771 + __assign_bit(3, mult, 1);
4772 + /* fall through */
4773 + case 29400:
4774 + __assign_bit(0, mult, 1);
4775 + __assign_bit(1, mult, 1);
4776 + break;
4777 + case 24000:
4778 + __assign_bit(3, mult, 1);
4779 + /* fall through */
4780 + case 22050:
4781 + __assign_bit(1, mult, 1);
4782 + break;
4783 + case 16000:
4784 + __assign_bit(3, mult, 1);
4785 + /* fall through */
4786 + case 14700:
4787 + __assign_bit(0, mult, 1);
4788 + break;
4789 + case 8000:
4790 + __assign_bit(3, mult, 1);
4791 + break;
4792 + default:
4793 + return -EINVAL;
4794 + }
4795 + break;
4796 + default:
4797 + return -EINVAL;
4798 + }
4799 + gpiod_set_array_value_cansleep(mult_gpios->ndescs, mult_gpios->desc,
4800 + NULL, mult);
4801 +
4802 + return 0;
4803 +}
4804 +
4805 +static struct snd_soc_ops audioinjector_octo_ops = {
4806 + .startup = audioinjector_octo_startup,
4807 + .shutdown = audioinjector_octo_shutdown,
4808 + .hw_params = audioinjector_octo_hw_params,
4809 + .trigger = audioinjector_octo_trigger,
4810 +};
4811 +
4812 +SND_SOC_DAILINK_DEFS(audioinjector_octo,
4813 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
4814 + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42448")),
4815 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
4816 +
4817 +static struct snd_soc_dai_link audioinjector_octo_dai[] = {
4818 + {
4819 + .name = "AudioInjector Octo",
4820 + .stream_name = "AudioInject-HIFI",
4821 + .ops = &audioinjector_octo_ops,
4822 + .init = audioinjector_octo_dai_init,
4823 + .symmetric_rates = 1,
4824 + .symmetric_channels = 1,
4825 + SND_SOC_DAILINK_REG(audioinjector_octo),
4826 + },
4827 +};
4828 +
4829 +static const struct snd_soc_dapm_widget audioinjector_octo_widgets[] = {
4830 + SND_SOC_DAPM_OUTPUT("OUTPUTS0"),
4831 + SND_SOC_DAPM_OUTPUT("OUTPUTS1"),
4832 + SND_SOC_DAPM_OUTPUT("OUTPUTS2"),
4833 + SND_SOC_DAPM_OUTPUT("OUTPUTS3"),
4834 + SND_SOC_DAPM_INPUT("INPUTS0"),
4835 + SND_SOC_DAPM_INPUT("INPUTS1"),
4836 + SND_SOC_DAPM_INPUT("INPUTS2"),
4837 +};
4838 +
4839 +static const struct snd_soc_dapm_route audioinjector_octo_route[] = {
4840 + /* Balanced outputs */
4841 + {"OUTPUTS0", NULL, "AOUT1L"},
4842 + {"OUTPUTS0", NULL, "AOUT1R"},
4843 + {"OUTPUTS1", NULL, "AOUT2L"},
4844 + {"OUTPUTS1", NULL, "AOUT2R"},
4845 + {"OUTPUTS2", NULL, "AOUT3L"},
4846 + {"OUTPUTS2", NULL, "AOUT3R"},
4847 + {"OUTPUTS3", NULL, "AOUT4L"},
4848 + {"OUTPUTS3", NULL, "AOUT4R"},
4849 +
4850 + /* Balanced inputs */
4851 + {"AIN1L", NULL, "INPUTS0"},
4852 + {"AIN1R", NULL, "INPUTS0"},
4853 + {"AIN2L", NULL, "INPUTS1"},
4854 + {"AIN2R", NULL, "INPUTS1"},
4855 + {"AIN3L", NULL, "INPUTS2"},
4856 + {"AIN3R", NULL, "INPUTS2"},
4857 +};
4858 +
4859 +static struct snd_soc_card snd_soc_audioinjector_octo = {
4860 + .name = "audioinjector-octo-soundcard",
4861 + .dai_link = audioinjector_octo_dai,
4862 + .num_links = ARRAY_SIZE(audioinjector_octo_dai),
4863 +
4864 + .dapm_widgets = audioinjector_octo_widgets,
4865 + .num_dapm_widgets = ARRAY_SIZE(audioinjector_octo_widgets),
4866 + .dapm_routes = audioinjector_octo_route,
4867 + .num_dapm_routes = ARRAY_SIZE(audioinjector_octo_route),
4868 +};
4869 +
4870 +static int audioinjector_octo_probe(struct platform_device *pdev)
4871 +{
4872 + struct snd_soc_card *card = &snd_soc_audioinjector_octo;
4873 + int ret;
4874 +
4875 + card->dev = &pdev->dev;
4876 +
4877 + if (pdev->dev.of_node) {
4878 + struct snd_soc_dai_link *dai = &audioinjector_octo_dai[0];
4879 + struct device_node *i2s_node =
4880 + of_parse_phandle(pdev->dev.of_node,
4881 + "i2s-controller", 0);
4882 + struct device_node *codec_node =
4883 + of_parse_phandle(pdev->dev.of_node,
4884 + "codec", 0);
4885 +
4886 + mult_gpios = devm_gpiod_get_array_optional(&pdev->dev, "mult",
4887 + GPIOD_OUT_LOW);
4888 + if (IS_ERR(mult_gpios))
4889 + return PTR_ERR(mult_gpios);
4890 +
4891 + codec_rst_gpio = devm_gpiod_get_optional(&pdev->dev, "reset",
4892 + GPIOD_OUT_LOW);
4893 + if (IS_ERR(codec_rst_gpio))
4894 + return PTR_ERR(codec_rst_gpio);
4895 +
4896 + non_stop_clocks = of_property_read_bool(pdev->dev.of_node, "non-stop-clocks");
4897 +
4898 + if (codec_rst_gpio)
4899 + gpiod_set_value(codec_rst_gpio, 1);
4900 + msleep(500);
4901 + if (codec_rst_gpio)
4902 + gpiod_set_value(codec_rst_gpio, 0);
4903 + msleep(500);
4904 + if (codec_rst_gpio)
4905 + gpiod_set_value(codec_rst_gpio, 1);
4906 + msleep(500);
4907 +
4908 + if (i2s_node && codec_node) {
4909 + dai->cpus->dai_name = NULL;
4910 + dai->cpus->of_node = i2s_node;
4911 + dai->platforms->name = NULL;
4912 + dai->platforms->of_node = i2s_node;
4913 + dai->codecs->name = NULL;
4914 + dai->codecs->of_node = codec_node;
4915 + } else
4916 + if (!i2s_node) {
4917 + dev_err(&pdev->dev,
4918 + "i2s-controller missing or invalid in DT\n");
4919 + return -EINVAL;
4920 + } else {
4921 + dev_err(&pdev->dev,
4922 + "Property 'codec' missing or invalid\n");
4923 + return -EINVAL;
4924 + }
4925 + }
4926 +
4927 + ret = devm_snd_soc_register_card(&pdev->dev, card);
4928 + if (ret != 0)
4929 + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
4930 + return ret;
4931 +}
4932 +
4933 +static const struct of_device_id audioinjector_octo_of_match[] = {
4934 + { .compatible = "ai,audioinjector-octo-soundcard", },
4935 + {},
4936 +};
4937 +MODULE_DEVICE_TABLE(of, audioinjector_octo_of_match);
4938 +
4939 +static struct platform_driver audioinjector_octo_driver = {
4940 + .driver = {
4941 + .name = "audioinjector-octo",
4942 + .owner = THIS_MODULE,
4943 + .of_match_table = audioinjector_octo_of_match,
4944 + },
4945 + .probe = audioinjector_octo_probe,
4946 +};
4947 +
4948 +module_platform_driver(audioinjector_octo_driver);
4949 +MODULE_AUTHOR("Matt Flax <flatmax@flatmax.org>");
4950 +MODULE_DESCRIPTION("AudioInjector.net octo Soundcard");
4951 +MODULE_LICENSE("GPL v2");
4952 +MODULE_ALIAS("platform:audioinjector-octo-soundcard");
4953 --- /dev/null
4954 +++ b/sound/soc/bcm/audioinjector-pi-soundcard.c
4955 @@ -0,0 +1,187 @@
4956 +/*
4957 + * ASoC Driver for AudioInjector Pi add on soundcard
4958 + *
4959 + * Created on: 13-May-2016
4960 + * Author: flatmax@flatmax.org
4961 + * based on code by Cliff Cai <Cliff.Cai@analog.com> for the ssm2602 machine blackfin.
4962 + * with help from Lars-Peter Clausen for simplifying the original code to use the dai_fmt field.
4963 + * i2s_node code taken from the other sound/soc/bcm machine drivers.
4964 + *
4965 + * Copyright (C) 2016 Flatmax Pty. Ltd.
4966 + *
4967 + * This program is free software; you can redistribute it and/or
4968 + * modify it under the terms of the GNU General Public License
4969 + * version 2 as published by the Free Software Foundation.
4970 + *
4971 + * This program is distributed in the hope that it will be useful, but
4972 + * WITHOUT ANY WARRANTY; without even the implied warranty of
4973 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4974 + * General Public License for more details.
4975 + */
4976 +
4977 +#include <linux/module.h>
4978 +#include <linux/types.h>
4979 +
4980 +#include <sound/core.h>
4981 +#include <sound/soc.h>
4982 +#include <sound/pcm_params.h>
4983 +#include <sound/control.h>
4984 +
4985 +#include "../codecs/wm8731.h"
4986 +
4987 +static const unsigned int bcm2835_rates_12000000[] = {
4988 + 8000, 16000, 32000, 44100, 48000, 96000, 88200,
4989 +};
4990 +
4991 +static struct snd_pcm_hw_constraint_list bcm2835_constraints_12000000 = {
4992 + .list = bcm2835_rates_12000000,
4993 + .count = ARRAY_SIZE(bcm2835_rates_12000000),
4994 +};
4995 +
4996 +static int snd_audioinjector_pi_soundcard_startup(struct snd_pcm_substream *substream)
4997 +{
4998 + /* Setup constraints, because there is a 12 MHz XTAL on the board */
4999 + snd_pcm_hw_constraint_list(substream->runtime, 0,
5000 + SNDRV_PCM_HW_PARAM_RATE,
5001 + &bcm2835_constraints_12000000);
5002 + return 0;
5003 +}
5004 +
5005 +static int snd_audioinjector_pi_soundcard_hw_params(struct snd_pcm_substream *substream,
5006 + struct snd_pcm_hw_params *params)
5007 +{
5008 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
5009 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
5010 +
5011 + switch (params_rate(params)){
5012 + case 8000:
5013 + return snd_soc_dai_set_bclk_ratio(cpu_dai, 1);
5014 + case 16000:
5015 + return snd_soc_dai_set_bclk_ratio(cpu_dai, 750);
5016 + case 32000:
5017 + return snd_soc_dai_set_bclk_ratio(cpu_dai, 375);
5018 + case 44100:
5019 + return snd_soc_dai_set_bclk_ratio(cpu_dai, 272);
5020 + case 48000:
5021 + return snd_soc_dai_set_bclk_ratio(cpu_dai, 250);
5022 + case 88200:
5023 + return snd_soc_dai_set_bclk_ratio(cpu_dai, 136);
5024 + case 96000:
5025 + return snd_soc_dai_set_bclk_ratio(cpu_dai, 125);
5026 + default:
5027 + return snd_soc_dai_set_bclk_ratio(cpu_dai, 125);
5028 + }
5029 +}
5030 +
5031 +/* machine stream operations */
5032 +static struct snd_soc_ops snd_audioinjector_pi_soundcard_ops = {
5033 + .startup = snd_audioinjector_pi_soundcard_startup,
5034 + .hw_params = snd_audioinjector_pi_soundcard_hw_params,
5035 +};
5036 +
5037 +static int audioinjector_pi_soundcard_dai_init(struct snd_soc_pcm_runtime *rtd)
5038 +{
5039 + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), WM8731_SYSCLK_XTAL, 12000000, SND_SOC_CLOCK_IN);
5040 +}
5041 +
5042 +SND_SOC_DAILINK_DEFS(audioinjector_pi,
5043 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
5044 + DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.1-001a", "wm8731-hifi")),
5045 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2835-i2s.0")));
5046 +
5047 +static struct snd_soc_dai_link audioinjector_pi_soundcard_dai[] = {
5048 + {
5049 + .name = "AudioInjector audio",
5050 + .stream_name = "AudioInjector audio",
5051 + .ops = &snd_audioinjector_pi_soundcard_ops,
5052 + .init = audioinjector_pi_soundcard_dai_init,
5053 + .dai_fmt = SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF,
5054 + SND_SOC_DAILINK_REG(audioinjector_pi),
5055 + },
5056 +};
5057 +
5058 +static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
5059 + SND_SOC_DAPM_HP("Headphone Jack", NULL),
5060 + SND_SOC_DAPM_SPK("Ext Spk", NULL),
5061 + SND_SOC_DAPM_LINE("Line In Jacks", NULL),
5062 + SND_SOC_DAPM_MIC("Microphone", NULL),
5063 +};
5064 +
5065 +static const struct snd_soc_dapm_route audioinjector_audio_map[] = {
5066 + /* headphone connected to LHPOUT, RHPOUT */
5067 + {"Headphone Jack", NULL, "LHPOUT"},
5068 + {"Headphone Jack", NULL, "RHPOUT"},
5069 +
5070 + /* speaker connected to LOUT, ROUT */
5071 + {"Ext Spk", NULL, "ROUT"},
5072 + {"Ext Spk", NULL, "LOUT"},
5073 +
5074 + /* line inputs */
5075 + {"Line In Jacks", NULL, "Line Input"},
5076 +
5077 + /* mic is connected to Mic Jack, with WM8731 Mic Bias */
5078 + {"Microphone", NULL, "Mic Bias"},
5079 +};
5080 +
5081 +static struct snd_soc_card snd_soc_audioinjector = {
5082 + .name = "audioinjector-pi-soundcard",
5083 + .dai_link = audioinjector_pi_soundcard_dai,
5084 + .num_links = ARRAY_SIZE(audioinjector_pi_soundcard_dai),
5085 +
5086 + .dapm_widgets = wm8731_dapm_widgets,
5087 + .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets),
5088 + .dapm_routes = audioinjector_audio_map,
5089 + .num_dapm_routes = ARRAY_SIZE(audioinjector_audio_map),
5090 +};
5091 +
5092 +static int audioinjector_pi_soundcard_probe(struct platform_device *pdev)
5093 +{
5094 + struct snd_soc_card *card = &snd_soc_audioinjector;
5095 + int ret;
5096 +
5097 + card->dev = &pdev->dev;
5098 +
5099 + if (pdev->dev.of_node) {
5100 + struct snd_soc_dai_link *dai = &audioinjector_pi_soundcard_dai[0];
5101 + struct device_node *i2s_node = of_parse_phandle(pdev->dev.of_node,
5102 + "i2s-controller", 0);
5103 +
5104 + if (i2s_node) {
5105 + dai->cpus->dai_name = NULL;
5106 + dai->cpus->of_node = i2s_node;
5107 + dai->platforms->name = NULL;
5108 + dai->platforms->of_node = i2s_node;
5109 + } else
5110 + if (!dai->cpus->of_node) {
5111 + dev_err(&pdev->dev, "Property 'i2s-controller' missing or invalid\n");
5112 + return -EINVAL;
5113 + }
5114 + }
5115 +
5116 + if ((ret = devm_snd_soc_register_card(&pdev->dev, card))) {
5117 + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
5118 + }
5119 + return ret;
5120 +}
5121 +
5122 +static const struct of_device_id audioinjector_pi_soundcard_of_match[] = {
5123 + { .compatible = "ai,audioinjector-pi-soundcard", },
5124 + {},
5125 +};
5126 +MODULE_DEVICE_TABLE(of, audioinjector_pi_soundcard_of_match);
5127 +
5128 +static struct platform_driver audioinjector_pi_soundcard_driver = {
5129 + .driver = {
5130 + .name = "audioinjector-stereo",
5131 + .owner = THIS_MODULE,
5132 + .of_match_table = audioinjector_pi_soundcard_of_match,
5133 + },
5134 + .probe = audioinjector_pi_soundcard_probe,
5135 +};
5136 +
5137 +module_platform_driver(audioinjector_pi_soundcard_driver);
5138 +MODULE_AUTHOR("Matt Flax <flatmax@flatmax.org>");
5139 +MODULE_DESCRIPTION("AudioInjector.net Pi Soundcard");
5140 +MODULE_LICENSE("GPL v2");
5141 +MODULE_ALIAS("platform:audioinjector-pi-soundcard");
5142 +
5143 --- /dev/null
5144 +++ b/sound/soc/bcm/audiosense-pi.c
5145 @@ -0,0 +1,248 @@
5146 +/*
5147 + * ASoC Driver for AudioSense add on soundcard
5148 + * Author:
5149 + * Bhargav A K <anur.bhargav@gmail.com>
5150 + * Copyright 2017
5151 + *
5152 + * This program is free software; you can redistribute it and/or
5153 + * modify it under the terms of the GNU General Public License
5154 + * version 2 as published by the Free Software Foundation.
5155 + *
5156 + * This program is distributed in the hope that it will be useful, but
5157 + * WITHOUT ANY WARRANTY; without even the implied warranty of
5158 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5159 + * General Public License for more details.
5160 + */
5161 +
5162 +#include <linux/module.h>
5163 +#include <linux/platform_device.h>
5164 +#include <linux/clk.h>
5165 +#include <linux/i2c.h>
5166 +#include <sound/core.h>
5167 +#include <sound/pcm.h>
5168 +#include <sound/pcm_params.h>
5169 +#include <sound/soc.h>
5170 +#include <sound/jack.h>
5171 +#include <sound/control.h>
5172 +
5173 +#include <sound/tlv320aic32x4.h>
5174 +#include "../codecs/tlv320aic32x4.h"
5175 +
5176 +#define AIC32X4_SYSCLK_XTAL 0x00
5177 +
5178 +/*
5179 + * Setup Codec Sample Rates and Channels
5180 + * Supported Rates:
5181 + * 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000,
5182 + */
5183 +static const unsigned int audiosense_pi_rate[] = {
5184 + 48000,
5185 +};
5186 +
5187 +static struct snd_pcm_hw_constraint_list audiosense_constraints_rates = {
5188 + .list = audiosense_pi_rate,
5189 + .count = ARRAY_SIZE(audiosense_pi_rate),
5190 +};
5191 +
5192 +static const unsigned int audiosense_pi_channels[] = {
5193 + 2,
5194 +};
5195 +
5196 +static struct snd_pcm_hw_constraint_list audiosense_constraints_ch = {
5197 + .count = ARRAY_SIZE(audiosense_pi_channels),
5198 + .list = audiosense_pi_channels,
5199 + .mask = 0,
5200 +};
5201 +
5202 +/* Setup DAPM widgets and paths */
5203 +static const struct snd_soc_dapm_widget audiosense_pi_dapm_widgets[] = {
5204 + SND_SOC_DAPM_HP("Headphone Jack", NULL),
5205 + SND_SOC_DAPM_LINE("Line Out", NULL),
5206 + SND_SOC_DAPM_LINE("Line In", NULL),
5207 + SND_SOC_DAPM_INPUT("CM_L"),
5208 + SND_SOC_DAPM_INPUT("CM_R"),
5209 +};
5210 +
5211 +static const struct snd_soc_dapm_route audiosense_pi_audio_map[] = {
5212 + /* Line Inputs are connected to
5213 + * (IN1_L | IN1_R)
5214 + * (IN2_L | IN2_R)
5215 + * (IN3_L | IN3_R)
5216 + */
5217 + {"IN1_L", NULL, "Line In"},
5218 + {"IN1_R", NULL, "Line In"},
5219 + {"IN2_L", NULL, "Line In"},
5220 + {"IN2_R", NULL, "Line In"},
5221 + {"IN3_L", NULL, "Line In"},
5222 + {"IN3_R", NULL, "Line In"},
5223 +
5224 + /* Mic is connected to IN2_L and IN2_R */
5225 + {"Left ADC", NULL, "Mic Bias"},
5226 + {"Right ADC", NULL, "Mic Bias"},
5227 +
5228 + /* Headphone connected to HPL, HPR */
5229 + {"Headphone Jack", NULL, "HPL"},
5230 + {"Headphone Jack", NULL, "HPR"},
5231 +
5232 + /* Speakers connected to LOL and LOR */
5233 + {"Line Out", NULL, "LOL"},
5234 + {"Line Out", NULL, "LOR"},
5235 +};
5236 +
5237 +static int audiosense_pi_card_init(struct snd_soc_pcm_runtime *rtd)
5238 +{
5239 + /* TODO: init of the codec specific dapm data, ignore suspend/resume */
5240 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
5241 +
5242 + snd_soc_component_update_bits(component, AIC32X4_MICBIAS, 0x78,
5243 + AIC32X4_MICBIAS_LDOIN |
5244 + AIC32X4_MICBIAS_2075V);
5245 + snd_soc_component_update_bits(component, AIC32X4_PWRCFG, 0x08,
5246 + AIC32X4_AVDDWEAKDISABLE);
5247 + snd_soc_component_update_bits(component, AIC32X4_LDOCTL, 0x01,
5248 + AIC32X4_LDOCTLEN);
5249 +
5250 + return 0;
5251 +}
5252 +
5253 +static int audiosense_pi_card_hw_params(
5254 + struct snd_pcm_substream *substream,
5255 + struct snd_pcm_hw_params *params)
5256 +{
5257 + int ret = 0;
5258 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
5259 + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
5260 +
5261 + /* Set the codec system clock, there is a 12 MHz XTAL on the board */
5262 + ret = snd_soc_dai_set_sysclk(codec_dai, AIC32X4_SYSCLK_XTAL,
5263 + 12000000, SND_SOC_CLOCK_IN);
5264 + if (ret) {
5265 + dev_err(rtd->card->dev,
5266 + "could not set codec driver clock params\n");
5267 + return ret;
5268 + }
5269 + return 0;
5270 +}
5271 +
5272 +static int audiosense_pi_card_startup(struct snd_pcm_substream *substream)
5273 +{
5274 + struct snd_pcm_runtime *runtime = substream->runtime;
5275 +
5276 + /*
5277 + * Set codec to 48Khz Sampling, Stereo I/O and 16 bit audio
5278 + */
5279 + runtime->hw.channels_max = 2;
5280 + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5281 + &audiosense_constraints_ch);
5282 +
5283 + runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
5284 + snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
5285 +
5286 +
5287 + snd_pcm_hw_constraint_list(substream->runtime, 0,
5288 + SNDRV_PCM_HW_PARAM_RATE,
5289 + &audiosense_constraints_rates);
5290 + return 0;
5291 +}
5292 +
5293 +static struct snd_soc_ops audiosense_pi_card_ops = {
5294 + .startup = audiosense_pi_card_startup,
5295 + .hw_params = audiosense_pi_card_hw_params,
5296 +};
5297 +
5298 +SND_SOC_DAILINK_DEFS(audiosense_pi,
5299 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
5300 + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic32x4.1-0018", "tlv320aic32x4-hifi")),
5301 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
5302 +
5303 +static struct snd_soc_dai_link audiosense_pi_card_dai[] = {
5304 + {
5305 + .name = "TLV320AIC3204 Audio",
5306 + .stream_name = "TLV320AIC3204 Hifi Audio",
5307 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
5308 + SND_SOC_DAIFMT_CBM_CFM,
5309 + .ops = &audiosense_pi_card_ops,
5310 + .init = audiosense_pi_card_init,
5311 + SND_SOC_DAILINK_REG(audiosense_pi),
5312 + },
5313 +};
5314 +
5315 +static struct snd_soc_card audiosense_pi_card = {
5316 + .name = "audiosense-pi",
5317 + .driver_name = "audiosense-pi",
5318 + .dai_link = audiosense_pi_card_dai,
5319 + .owner = THIS_MODULE,
5320 + .num_links = ARRAY_SIZE(audiosense_pi_card_dai),
5321 + .dapm_widgets = audiosense_pi_dapm_widgets,
5322 + .num_dapm_widgets = ARRAY_SIZE(audiosense_pi_dapm_widgets),
5323 + .dapm_routes = audiosense_pi_audio_map,
5324 + .num_dapm_routes = ARRAY_SIZE(audiosense_pi_audio_map),
5325 +};
5326 +
5327 +static int audiosense_pi_card_probe(struct platform_device *pdev)
5328 +{
5329 + int ret = 0;
5330 + struct snd_soc_card *card = &audiosense_pi_card;
5331 + struct snd_soc_dai_link *dai = &audiosense_pi_card_dai[0];
5332 + struct device_node *i2s_node = pdev->dev.of_node;
5333 +
5334 + card->dev = &pdev->dev;
5335 +
5336 + if (!dai) {
5337 + dev_err(&pdev->dev, "DAI not found. Missing or Invalid\n");
5338 + return -EINVAL;
5339 + }
5340 +
5341 + i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0);
5342 + if (!i2s_node) {
5343 + dev_err(&pdev->dev,
5344 + "Property 'i2s-controller' missing or invalid\n");
5345 + return -EINVAL;
5346 + }
5347 +
5348 + dai->cpus->dai_name = NULL;
5349 + dai->cpus->of_node = i2s_node;
5350 + dai->platforms->name = NULL;
5351 + dai->platforms->of_node = i2s_node;
5352 +
5353 + of_node_put(i2s_node);
5354 +
5355 + ret = snd_soc_register_card(card);
5356 + if (ret && ret != -EPROBE_DEFER)
5357 + dev_err(&pdev->dev,
5358 + "snd_soc_register_card() failed: %d\n", ret);
5359 +
5360 + return ret;
5361 +}
5362 +
5363 +static int audiosense_pi_card_remove(struct platform_device *pdev)
5364 +{
5365 + struct snd_soc_card *card = platform_get_drvdata(pdev);
5366 +
5367 + return snd_soc_unregister_card(card);
5368 +
5369 +}
5370 +
5371 +static const struct of_device_id audiosense_pi_card_of_match[] = {
5372 + { .compatible = "as,audiosense-pi", },
5373 + {},
5374 +};
5375 +MODULE_DEVICE_TABLE(of, audiosense_pi_card_of_match);
5376 +
5377 +static struct platform_driver audiosense_pi_card_driver = {
5378 + .driver = {
5379 + .name = "audiosense-snd-card",
5380 + .owner = THIS_MODULE,
5381 + .of_match_table = audiosense_pi_card_of_match,
5382 + },
5383 + .probe = audiosense_pi_card_probe,
5384 + .remove = audiosense_pi_card_remove,
5385 +};
5386 +
5387 +module_platform_driver(audiosense_pi_card_driver);
5388 +
5389 +MODULE_AUTHOR("Bhargav AK <anur.bhargav@gmail.com>");
5390 +MODULE_DESCRIPTION("ASoC Driver for TLV320AIC3204 Audio");
5391 +MODULE_LICENSE("GPL v2");
5392 +MODULE_ALIAS("platform:audiosense-pi");
5393 +
5394 --- /dev/null
5395 +++ b/sound/soc/bcm/digidac1-soundcard.c
5396 @@ -0,0 +1,421 @@
5397 +/*
5398 + * ASoC Driver for RRA DigiDAC1
5399 + * Copyright 2016
5400 + * Author: José M. Tasende <vintage@redrocksaudio.es>
5401 + * based on the HifiBerry DAC driver by Florian Meier <florian.meier@koalo.de>
5402 + * and the Wolfson card driver by Nikesh Oswal, <Nikesh.Oswal@wolfsonmicro.com>
5403 + * This program is free software; you can redistribute it and/or
5404 + * modify it under the terms of the GNU General Public License
5405 + * version 2 as published by the Free Software Foundation.
5406 + *
5407 + * This program is distributed in the hope that it will be useful, but
5408 + * WITHOUT ANY WARRANTY; without even the implied warranty of
5409 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5410 + * General Public License for more details.
5411 + */
5412 +
5413 +#include <linux/module.h>
5414 +#include <linux/platform_device.h>
5415 +#include <linux/i2c.h>
5416 +#include <sound/core.h>
5417 +#include <sound/pcm.h>
5418 +#include <sound/pcm_params.h>
5419 +#include <sound/soc.h>
5420 +#include <sound/jack.h>
5421 +#include <sound/soc-dapm.h>
5422 +#include <sound/tlv.h>
5423 +#include <linux/regulator/consumer.h>
5424 +
5425 +#include "../codecs/wm8804.h"
5426 +#include "../codecs/wm8741.h"
5427 +
5428 +#define WM8741_NUM_SUPPLIES 2
5429 +
5430 +/* codec private data */
5431 +struct wm8741_priv {
5432 + struct wm8741_platform_data pdata;
5433 + struct regmap *regmap;
5434 + struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];
5435 + unsigned int sysclk;
5436 + const struct snd_pcm_hw_constraint_list *sysclk_constraints;
5437 +};
5438 +
5439 +static int samplerate = 44100;
5440 +
5441 +/* New Alsa Controls not exposed by original wm8741 codec driver */
5442 +/* in actual driver the att. adjustment is wrong because */
5443 +/* this DAC has a coarse attenuation register with 4dB steps */
5444 +/* and a fine level register with 0.125dB steps */
5445 +/* each register has 32 steps so combining both we have 1024 steps */
5446 +/* of 0.125 dB. */
5447 +/* The original level controls from driver are removed at startup */
5448 +/* and replaced by the corrected ones. */
5449 +/* The same wm8741 driver can be used for wm8741 and wm8742 devices */
5450 +
5451 +static const DECLARE_TLV_DB_SCALE(dac_tlv_fine, 0, 13, 0);
5452 +static const DECLARE_TLV_DB_SCALE(dac_tlv_coarse, -12700, 400, 1);
5453 +static const char *w8741_dither[4] = {"Off", "RPDF", "TPDF", "HPDF"};
5454 +static const char *w8741_filter[5] = {
5455 + "Type 1", "Type 2", "Type 3", "Type 4", "Type 5"};
5456 +static const char *w8741_switch[2] = {"Off", "On"};
5457 +static const struct soc_enum w8741_enum[] = {
5458 +SOC_ENUM_SINGLE(WM8741_MODE_CONTROL_2, 0, 4, w8741_dither),/* dithering type */
5459 +SOC_ENUM_SINGLE(WM8741_FILTER_CONTROL, 0, 5, w8741_filter),/* filter type */
5460 +SOC_ENUM_SINGLE(WM8741_FORMAT_CONTROL, 6, 2, w8741_switch),/* phase invert */
5461 +SOC_ENUM_SINGLE(WM8741_VOLUME_CONTROL, 0, 2, w8741_switch),/* volume ramp */
5462 +SOC_ENUM_SINGLE(WM8741_VOLUME_CONTROL, 3, 2, w8741_switch),/* soft mute */
5463 +};
5464 +
5465 +static const struct snd_kcontrol_new w8741_snd_controls_stereo[] = {
5466 +SOC_DOUBLE_R_TLV("DAC Fine Playback Volume", WM8741_DACLLSB_ATTENUATION,
5467 + WM8741_DACRLSB_ATTENUATION, 0, 31, 1, dac_tlv_fine),
5468 +SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8741_DACLMSB_ATTENUATION,
5469 + WM8741_DACRMSB_ATTENUATION, 0, 31, 1, dac_tlv_coarse),
5470 +SOC_ENUM("DAC Dither", w8741_enum[0]),
5471 +SOC_ENUM("DAC Digital Filter", w8741_enum[1]),
5472 +SOC_ENUM("DAC Phase Invert", w8741_enum[2]),
5473 +SOC_ENUM("DAC Volume Ramp", w8741_enum[3]),
5474 +SOC_ENUM("DAC Soft Mute", w8741_enum[4]),
5475 +};
5476 +
5477 +static const struct snd_kcontrol_new w8741_snd_controls_mono_left[] = {
5478 +SOC_SINGLE_TLV("DAC Fine Playback Volume", WM8741_DACLLSB_ATTENUATION,
5479 + 0, 31, 0, dac_tlv_fine),
5480 +SOC_SINGLE_TLV("Digital Playback Volume", WM8741_DACLMSB_ATTENUATION,
5481 + 0, 31, 1, dac_tlv_coarse),
5482 +SOC_ENUM("DAC Dither", w8741_enum[0]),
5483 +SOC_ENUM("DAC Digital Filter", w8741_enum[1]),
5484 +SOC_ENUM("DAC Phase Invert", w8741_enum[2]),
5485 +SOC_ENUM("DAC Volume Ramp", w8741_enum[3]),
5486 +SOC_ENUM("DAC Soft Mute", w8741_enum[4]),
5487 +};
5488 +
5489 +static const struct snd_kcontrol_new w8741_snd_controls_mono_right[] = {
5490 +SOC_SINGLE_TLV("DAC Fine Playback Volume", WM8741_DACRLSB_ATTENUATION,
5491 + 0, 31, 0, dac_tlv_fine),
5492 +SOC_SINGLE_TLV("Digital Playback Volume", WM8741_DACRMSB_ATTENUATION,
5493 + 0, 31, 1, dac_tlv_coarse),
5494 +SOC_ENUM("DAC Dither", w8741_enum[0]),
5495 +SOC_ENUM("DAC Digital Filter", w8741_enum[1]),
5496 +SOC_ENUM("DAC Phase Invert", w8741_enum[2]),
5497 +SOC_ENUM("DAC Volume Ramp", w8741_enum[3]),
5498 +SOC_ENUM("DAC Soft Mute", w8741_enum[4]),
5499 +};
5500 +
5501 +static int w8741_add_controls(struct snd_soc_component *component)
5502 +{
5503 + struct wm8741_priv *wm8741 = snd_soc_component_get_drvdata(component);
5504 +
5505 + switch (wm8741->pdata.diff_mode) {
5506 + case WM8741_DIFF_MODE_STEREO:
5507 + case WM8741_DIFF_MODE_STEREO_REVERSED:
5508 + snd_soc_add_component_controls(component,
5509 + w8741_snd_controls_stereo,
5510 + ARRAY_SIZE(w8741_snd_controls_stereo));
5511 + break;
5512 + case WM8741_DIFF_MODE_MONO_LEFT:
5513 + snd_soc_add_component_controls(component,
5514 + w8741_snd_controls_mono_left,
5515 + ARRAY_SIZE(w8741_snd_controls_mono_left));
5516 + break;
5517 + case WM8741_DIFF_MODE_MONO_RIGHT:
5518 + snd_soc_add_component_controls(component,
5519 + w8741_snd_controls_mono_right,
5520 + ARRAY_SIZE(w8741_snd_controls_mono_right));
5521 + break;
5522 + default:
5523 + return -EINVAL;
5524 + }
5525 +
5526 + return 0;
5527 +}
5528 +
5529 +static int digidac1_soundcard_init(struct snd_soc_pcm_runtime *rtd)
5530 +{
5531 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
5532 + struct snd_soc_card *card = rtd->card;
5533 + struct snd_soc_pcm_runtime *wm8741_rtd;
5534 + struct snd_soc_component *wm8741_component;
5535 + struct snd_card *sound_card = card->snd_card;
5536 + struct snd_kcontrol *kctl;
5537 + int ret;
5538 +
5539 + wm8741_rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[1]);
5540 + if (!wm8741_rtd) {
5541 + dev_warn(card->dev, "digidac1_soundcard_init: couldn't get wm8741 rtd\n");
5542 + return -EFAULT;
5543 + }
5544 + wm8741_component = asoc_rtd_to_codec(wm8741_rtd, 0)->component;
5545 + ret = w8741_add_controls(wm8741_component);
5546 + if (ret < 0)
5547 + dev_warn(card->dev, "Failed to add new wm8741 controls: %d\n",
5548 + ret);
5549 +
5550 + /* enable TX output */
5551 + snd_soc_component_update_bits(component, WM8804_PWRDN, 0x4, 0x0);
5552 +
5553 + kctl = snd_soc_card_get_kcontrol(card,
5554 + "Playback Volume");
5555 + if (kctl) {
5556 + kctl->vd[0].access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
5557 + snd_ctl_remove(sound_card, kctl);
5558 + }
5559 + kctl = snd_soc_card_get_kcontrol(card,
5560 + "Fine Playback Volume");
5561 + if (kctl) {
5562 + kctl->vd[0].access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
5563 + snd_ctl_remove(sound_card, kctl);
5564 + }
5565 + return 0;
5566 +}
5567 +
5568 +static int digidac1_soundcard_startup(struct snd_pcm_substream *substream)
5569 +{
5570 + /* turn on wm8804 digital output */
5571 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
5572 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
5573 + struct snd_soc_card *card = rtd->card;
5574 + struct snd_soc_pcm_runtime *wm8741_rtd;
5575 + struct snd_soc_component *wm8741_component;
5576 +
5577 + snd_soc_component_update_bits(component, WM8804_PWRDN, 0x3c, 0x00);
5578 + wm8741_rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[1]);
5579 + if (!wm8741_rtd) {
5580 + dev_warn(card->dev, "digidac1_soundcard_startup: couldn't get WM8741 rtd\n");
5581 + return -EFAULT;
5582 + }
5583 + wm8741_component = asoc_rtd_to_codec(wm8741_rtd, 0)->component;
5584 +
5585 + /* latch wm8741 level */
5586 + snd_soc_component_update_bits(wm8741_component, WM8741_DACLLSB_ATTENUATION,
5587 + WM8741_UPDATELL, WM8741_UPDATELL);
5588 + snd_soc_component_update_bits(wm8741_component, WM8741_DACLMSB_ATTENUATION,
5589 + WM8741_UPDATELM, WM8741_UPDATELM);
5590 + snd_soc_component_update_bits(wm8741_component, WM8741_DACRLSB_ATTENUATION,
5591 + WM8741_UPDATERL, WM8741_UPDATERL);
5592 + snd_soc_component_update_bits(wm8741_component, WM8741_DACRMSB_ATTENUATION,
5593 + WM8741_UPDATERM, WM8741_UPDATERM);
5594 +
5595 + return 0;
5596 +}
5597 +
5598 +static void digidac1_soundcard_shutdown(struct snd_pcm_substream *substream)
5599 +{
5600 + /* turn off wm8804 digital output */
5601 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
5602 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
5603 +
5604 + snd_soc_component_update_bits(component, WM8804_PWRDN, 0x3c, 0x3c);
5605 +}
5606 +
5607 +static int digidac1_soundcard_hw_params(struct snd_pcm_substream *substream,
5608 + struct snd_pcm_hw_params *params)
5609 +{
5610 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
5611 + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
5612 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
5613 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
5614 + struct snd_soc_card *card = rtd->card;
5615 + struct snd_soc_pcm_runtime *wm8741_rtd;
5616 + struct snd_soc_component *wm8741_component;
5617 +
5618 + int sysclk = 27000000;
5619 + long mclk_freq = 0;
5620 + int mclk_div = 1;
5621 + int sampling_freq = 1;
5622 + int ret;
5623 +
5624 + wm8741_rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[1]);
5625 + if (!wm8741_rtd) {
5626 + dev_warn(card->dev, "digidac1_soundcard_hw_params: couldn't get WM8741 rtd\n");
5627 + return -EFAULT;
5628 + }
5629 + wm8741_component = asoc_rtd_to_codec(wm8741_rtd, 0)->component;
5630 + samplerate = params_rate(params);
5631 +
5632 + if (samplerate <= 96000) {
5633 + mclk_freq = samplerate*256;
5634 + mclk_div = WM8804_MCLKDIV_256FS;
5635 + } else {
5636 + mclk_freq = samplerate*128;
5637 + mclk_div = WM8804_MCLKDIV_128FS;
5638 + }
5639 +
5640 + switch (samplerate) {
5641 + case 32000:
5642 + sampling_freq = 0x03;
5643 + break;
5644 + case 44100:
5645 + sampling_freq = 0x00;
5646 + break;
5647 + case 48000:
5648 + sampling_freq = 0x02;
5649 + break;
5650 + case 88200:
5651 + sampling_freq = 0x08;
5652 + break;
5653 + case 96000:
5654 + sampling_freq = 0x0a;
5655 + break;
5656 + case 176400:
5657 + sampling_freq = 0x0c;
5658 + break;
5659 + case 192000:
5660 + sampling_freq = 0x0e;
5661 + break;
5662 + default:
5663 + dev_err(card->dev,
5664 + "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n",
5665 + samplerate);
5666 + }
5667 +
5668 + snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div);
5669 + snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq);
5670 +
5671 + ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL,
5672 + sysclk, SND_SOC_CLOCK_OUT);
5673 + if (ret < 0) {
5674 + dev_err(card->dev,
5675 + "Failed to set WM8804 SYSCLK: %d\n", ret);
5676 + return ret;
5677 + }
5678 + /* Enable wm8804 TX output */
5679 + snd_soc_component_update_bits(component, WM8804_PWRDN, 0x4, 0x0);
5680 +
5681 + /* wm8804 Power on */
5682 + snd_soc_component_update_bits(component, WM8804_PWRDN, 0x9, 0);
5683 +
5684 + /* wm8804 set sampling frequency status bits */
5685 + snd_soc_component_update_bits(component, WM8804_SPDTX4, 0x0f, sampling_freq);
5686 +
5687 + /* Now update wm8741 registers for the correct oversampling */
5688 + if (samplerate <= 48000)
5689 + snd_soc_component_update_bits(wm8741_component, WM8741_MODE_CONTROL_1,
5690 + WM8741_OSR_MASK, 0x00);
5691 + else if (samplerate <= 96000)
5692 + snd_soc_component_update_bits(wm8741_component, WM8741_MODE_CONTROL_1,
5693 + WM8741_OSR_MASK, 0x20);
5694 + else
5695 + snd_soc_component_update_bits(wm8741_component, WM8741_MODE_CONTROL_1,
5696 + WM8741_OSR_MASK, 0x40);
5697 +
5698 + /* wm8741 bit size */
5699 + switch (params_width(params)) {
5700 + case 16:
5701 + snd_soc_component_update_bits(wm8741_component, WM8741_FORMAT_CONTROL,
5702 + WM8741_IWL_MASK, 0x00);
5703 + break;
5704 + case 20:
5705 + snd_soc_component_update_bits(wm8741_component, WM8741_FORMAT_CONTROL,
5706 + WM8741_IWL_MASK, 0x01);
5707 + break;
5708 + case 24:
5709 + snd_soc_component_update_bits(wm8741_component, WM8741_FORMAT_CONTROL,
5710 + WM8741_IWL_MASK, 0x02);
5711 + break;
5712 + case 32:
5713 + snd_soc_component_update_bits(wm8741_component, WM8741_FORMAT_CONTROL,
5714 + WM8741_IWL_MASK, 0x03);
5715 + break;
5716 + default:
5717 + dev_dbg(card->dev, "wm8741_hw_params: Unsupported bit size param = %d",
5718 + params_width(params));
5719 + return -EINVAL;
5720 + }
5721 +
5722 + return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
5723 +}
5724 +/* machine stream operations */
5725 +static struct snd_soc_ops digidac1_soundcard_ops = {
5726 + .hw_params = digidac1_soundcard_hw_params,
5727 + .startup = digidac1_soundcard_startup,
5728 + .shutdown = digidac1_soundcard_shutdown,
5729 +};
5730 +
5731 +SND_SOC_DAILINK_DEFS(digidac1,
5732 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
5733 + DAILINK_COMP_ARRAY(COMP_CODEC("wm8804.1-003b", "wm8804-spdif")),
5734 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2835-i2s.0")));
5735 +
5736 +SND_SOC_DAILINK_DEFS(digidac11,
5737 + DAILINK_COMP_ARRAY(COMP_CPU("wm8804-spdif")),
5738 + DAILINK_COMP_ARRAY(COMP_CODEC("wm8741.1-001a", "wm8741")),
5739 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
5740 +
5741 +static struct snd_soc_dai_link digidac1_soundcard_dai[] = {
5742 + {
5743 + .name = "RRA DigiDAC1",
5744 + .stream_name = "RRA DigiDAC1 HiFi",
5745 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
5746 + SND_SOC_DAIFMT_CBM_CFM,
5747 + .ops = &digidac1_soundcard_ops,
5748 + .init = digidac1_soundcard_init,
5749 + SND_SOC_DAILINK_REG(digidac1),
5750 + },
5751 + {
5752 + .name = "RRA DigiDAC11",
5753 + .stream_name = "RRA DigiDAC11 HiFi",
5754 + .dai_fmt = SND_SOC_DAIFMT_I2S
5755 + | SND_SOC_DAIFMT_NB_NF
5756 + | SND_SOC_DAIFMT_CBS_CFS,
5757 + SND_SOC_DAILINK_REG(digidac11),
5758 + },
5759 +};
5760 +
5761 +/* audio machine driver */
5762 +static struct snd_soc_card digidac1_soundcard = {
5763 + .name = "digidac1-soundcard",
5764 + .owner = THIS_MODULE,
5765 + .dai_link = digidac1_soundcard_dai,
5766 + .num_links = ARRAY_SIZE(digidac1_soundcard_dai),
5767 +};
5768 +
5769 +static int digidac1_soundcard_probe(struct platform_device *pdev)
5770 +{
5771 + int ret = 0;
5772 +
5773 + digidac1_soundcard.dev = &pdev->dev;
5774 +
5775 + if (pdev->dev.of_node) {
5776 + struct device_node *i2s_node;
5777 + struct snd_soc_dai_link *dai = &digidac1_soundcard_dai[0];
5778 +
5779 + i2s_node = of_parse_phandle(pdev->dev.of_node,
5780 + "i2s-controller", 0);
5781 +
5782 + if (i2s_node) {
5783 + dai->cpus->dai_name = NULL;
5784 + dai->cpus->of_node = i2s_node;
5785 + dai->platforms->name = NULL;
5786 + dai->platforms->of_node = i2s_node;
5787 + }
5788 + }
5789 +
5790 + ret = devm_snd_soc_register_card(&pdev->dev, &digidac1_soundcard);
5791 + if (ret && ret != -EPROBE_DEFER)
5792 + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
5793 + ret);
5794 +
5795 + return ret;
5796 +}
5797 +
5798 +static const struct of_device_id digidac1_soundcard_of_match[] = {
5799 + { .compatible = "rra,digidac1-soundcard", },
5800 + {},
5801 +};
5802 +MODULE_DEVICE_TABLE(of, digidac1_soundcard_of_match);
5803 +
5804 +static struct platform_driver digidac1_soundcard_driver = {
5805 + .driver = {
5806 + .name = "digidac1-audio",
5807 + .owner = THIS_MODULE,
5808 + .of_match_table = digidac1_soundcard_of_match,
5809 + },
5810 + .probe = digidac1_soundcard_probe,
5811 +};
5812 +
5813 +module_platform_driver(digidac1_soundcard_driver);
5814 +
5815 +MODULE_AUTHOR("José M. Tasende <vintage@redrocksaudio.es>");
5816 +MODULE_DESCRIPTION("ASoC Driver for RRA DigiDAC1");
5817 +MODULE_LICENSE("GPL v2");
5818 --- /dev/null
5819 +++ b/sound/soc/bcm/dionaudio_loco-v2.c
5820 @@ -0,0 +1,117 @@
5821 +/*
5822 + * ASoC Driver for Dion Audio LOCO-V2 DAC-AMP
5823 + *
5824 + * Author: Miquel Blauw <info@dionaudio.nl>
5825 + * Copyright 2017
5826 + *
5827 + * Based on the software of the RPi-DAC writen by Florian Meier
5828 + *
5829 + * This program is free software; you can redistribute it and/or
5830 + * modify it under the terms of the GNU General Public License
5831 + * version 2 as published by the Free Software Foundation.
5832 + *
5833 + * This program is distributed in the hope that it will be useful, but
5834 + * WITHOUT ANY WARRANTY; without even the implied warranty of
5835 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5836 + * General Public License for more details.
5837 + */
5838 +
5839 +#include <linux/module.h>
5840 +#include <linux/platform_device.h>
5841 +
5842 +#include <sound/core.h>
5843 +#include <sound/pcm.h>
5844 +#include <sound/pcm_params.h>
5845 +#include <sound/soc.h>
5846 +#include <sound/jack.h>
5847 +
5848 +static bool digital_gain_0db_limit = true;
5849 +
5850 +static int snd_rpi_dionaudio_loco_v2_init(struct snd_soc_pcm_runtime *rtd)
5851 +{
5852 + if (digital_gain_0db_limit) {
5853 + int ret;
5854 + struct snd_soc_card *card = rtd->card;
5855 +
5856 + ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
5857 + if (ret < 0)
5858 + dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
5859 + }
5860 +
5861 + return 0;
5862 +}
5863 +
5864 +SND_SOC_DAILINK_DEFS(dionaudio_loco_v2,
5865 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
5866 + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi")),
5867 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
5868 +
5869 +static struct snd_soc_dai_link snd_rpi_dionaudio_loco_v2_dai[] = {
5870 +{
5871 + .name = "DionAudio LOCO-V2",
5872 + .stream_name = "DionAudio LOCO-V2 DAC-AMP",
5873 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
5874 + SND_SOC_DAIFMT_CBS_CFS,
5875 + .init = snd_rpi_dionaudio_loco_v2_init,
5876 + SND_SOC_DAILINK_REG(dionaudio_loco_v2),
5877 +},};
5878 +
5879 +/* audio machine driver */
5880 +static struct snd_soc_card snd_rpi_dionaudio_loco_v2 = {
5881 + .name = "Dion Audio LOCO-V2",
5882 + .dai_link = snd_rpi_dionaudio_loco_v2_dai,
5883 + .num_links = ARRAY_SIZE(snd_rpi_dionaudio_loco_v2_dai),
5884 +};
5885 +
5886 +static int snd_rpi_dionaudio_loco_v2_probe(struct platform_device *pdev)
5887 +{
5888 + int ret = 0;
5889 +
5890 + snd_rpi_dionaudio_loco_v2.dev = &pdev->dev;
5891 +
5892 + if (pdev->dev.of_node) {
5893 + struct device_node *i2s_node;
5894 + struct snd_soc_dai_link *dai =
5895 + &snd_rpi_dionaudio_loco_v2_dai[0];
5896 +
5897 + i2s_node = of_parse_phandle(pdev->dev.of_node,
5898 + "i2s-controller", 0);
5899 + if (i2s_node) {
5900 + dai->cpus->dai_name = NULL;
5901 + dai->cpus->of_node = i2s_node;
5902 + dai->platforms->name = NULL;
5903 + dai->platforms->of_node = i2s_node;
5904 + }
5905 +
5906 + digital_gain_0db_limit = !of_property_read_bool(
5907 + pdev->dev.of_node, "dionaudio,24db_digital_gain");
5908 + }
5909 +
5910 + ret = devm_snd_soc_register_card(&pdev->dev, &snd_rpi_dionaudio_loco_v2);
5911 + if (ret)
5912 + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
5913 + ret);
5914 +
5915 + return ret;
5916 +}
5917 +
5918 +static const struct of_device_id dionaudio_of_match[] = {
5919 + { .compatible = "dionaudio,dionaudio-loco-v2", },
5920 + {},
5921 +};
5922 +MODULE_DEVICE_TABLE(of, dionaudio_of_match);
5923 +
5924 +static struct platform_driver snd_rpi_dionaudio_loco_v2_driver = {
5925 + .driver = {
5926 + .name = "snd-rpi-dionaudio-loco-v2",
5927 + .owner = THIS_MODULE,
5928 + .of_match_table = dionaudio_of_match,
5929 + },
5930 + .probe = snd_rpi_dionaudio_loco_v2_probe,
5931 +};
5932 +
5933 +module_platform_driver(snd_rpi_dionaudio_loco_v2_driver);
5934 +
5935 +MODULE_AUTHOR("Miquel Blauw <info@dionaudio.nl>");
5936 +MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO-V2");
5937 +MODULE_LICENSE("GPL v2");
5938 --- /dev/null
5939 +++ b/sound/soc/bcm/dionaudio_loco.c
5940 @@ -0,0 +1,117 @@
5941 +/*
5942 + * ASoC Driver for Dion Audio LOCO DAC-AMP
5943 + *
5944 + * Author: Miquel Blauw <info@dionaudio.nl>
5945 + * Copyright 2016
5946 + *
5947 + * Based on the software of the RPi-DAC writen by Florian Meier
5948 + *
5949 + * This program is free software; you can redistribute it and/or
5950 + * modify it under the terms of the GNU General Public License
5951 + * version 2 as published by the Free Software Foundation.
5952 + *
5953 + * This program is distributed in the hope that it will be useful, but
5954 + * WITHOUT ANY WARRANTY; without even the implied warranty of
5955 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5956 + * General Public License for more details.
5957 + */
5958 +
5959 +#include <linux/module.h>
5960 +#include <linux/platform_device.h>
5961 +
5962 +#include <sound/core.h>
5963 +#include <sound/pcm.h>
5964 +#include <sound/pcm_params.h>
5965 +#include <sound/soc.h>
5966 +#include <sound/jack.h>
5967 +
5968 +static int snd_rpi_dionaudio_loco_hw_params(
5969 + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
5970 +{
5971 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
5972 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
5973 +
5974 + unsigned int sample_bits =
5975 + snd_pcm_format_physical_width(params_format(params));
5976 +
5977 + return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2);
5978 +}
5979 +
5980 +/* machine stream operations */
5981 +static struct snd_soc_ops snd_rpi_dionaudio_loco_ops = {
5982 + .hw_params = snd_rpi_dionaudio_loco_hw_params,
5983 +};
5984 +
5985 +SND_SOC_DAILINK_DEFS(dionaudio_loco,
5986 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
5987 + DAILINK_COMP_ARRAY(COMP_CODEC("pcm5102a-codec", "pcm5102a-hifi")),
5988 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
5989 +
5990 +static struct snd_soc_dai_link snd_rpi_dionaudio_loco_dai[] = {
5991 +{
5992 + .name = "DionAudio LOCO",
5993 + .stream_name = "DionAudio LOCO DAC-AMP",
5994 + .dai_fmt = SND_SOC_DAIFMT_I2S |
5995 + SND_SOC_DAIFMT_NB_NF |
5996 + SND_SOC_DAIFMT_CBS_CFS,
5997 + .ops = &snd_rpi_dionaudio_loco_ops,
5998 + SND_SOC_DAILINK_REG(dionaudio_loco),
5999 +},
6000 +};
6001 +
6002 +/* audio machine driver */
6003 +static struct snd_soc_card snd_rpi_dionaudio_loco = {
6004 + .name = "snd_rpi_dionaudio_loco",
6005 + .dai_link = snd_rpi_dionaudio_loco_dai,
6006 + .num_links = ARRAY_SIZE(snd_rpi_dionaudio_loco_dai),
6007 +};
6008 +
6009 +static int snd_rpi_dionaudio_loco_probe(struct platform_device *pdev)
6010 +{
6011 + struct device_node *np;
6012 + int ret = 0;
6013 +
6014 + snd_rpi_dionaudio_loco.dev = &pdev->dev;
6015 +
6016 + np = pdev->dev.of_node;
6017 + if (np) {
6018 + struct snd_soc_dai_link *dai = &snd_rpi_dionaudio_loco_dai[0];
6019 + struct device_node *i2s_np;
6020 +
6021 + i2s_np = of_parse_phandle(np, "i2s-controller", 0);
6022 + if (i2s_np) {
6023 + dai->cpus->dai_name = NULL;
6024 + dai->cpus->of_node = i2s_np;
6025 + dai->platforms->name = NULL;
6026 + dai->platforms->of_node = i2s_np;
6027 + }
6028 + }
6029 +
6030 + ret = devm_snd_soc_register_card(&pdev->dev, &snd_rpi_dionaudio_loco);
6031 + if (ret && ret != -EPROBE_DEFER)
6032 + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
6033 + ret);
6034 +
6035 + return ret;
6036 +}
6037 +
6038 +static const struct of_device_id snd_rpi_dionaudio_loco_of_match[] = {
6039 + { .compatible = "dionaudio,loco-pcm5242-tpa3118", },
6040 + { /* sentinel */ },
6041 +};
6042 +MODULE_DEVICE_TABLE(of, snd_rpi_dionaudio_loco_of_match);
6043 +
6044 +static struct platform_driver snd_rpi_dionaudio_loco_driver = {
6045 + .driver = {
6046 + .name = "snd-dionaudio-loco",
6047 + .owner = THIS_MODULE,
6048 + .of_match_table = snd_rpi_dionaudio_loco_of_match,
6049 + },
6050 + .probe = snd_rpi_dionaudio_loco_probe,
6051 +};
6052 +
6053 +module_platform_driver(snd_rpi_dionaudio_loco_driver);
6054 +
6055 +MODULE_AUTHOR("Miquel Blauw <info@dionaudio.nl>");
6056 +MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO");
6057 +MODULE_LICENSE("GPL v2");
6058 --- /dev/null
6059 +++ b/sound/soc/bcm/fe-pi-audio.c
6060 @@ -0,0 +1,154 @@
6061 +/*
6062 + * ASoC Driver for Fe-Pi Audio Sound Card
6063 + *
6064 + * Author: Henry Kupis <kuupaz@gmail.com>
6065 + * Copyright 2016
6066 + * based on code by Florian Meier <florian.meier@koalo.de>
6067 + * based on code by Shawn Guo <shawn.guo@linaro.org>
6068 + *
6069 + * This program is free software; you can redistribute it and/or
6070 + * modify it under the terms of the GNU General Public License
6071 + * version 2 as published by the Free Software Foundation.
6072 + *
6073 + * This program is distributed in the hope that it will be useful, but
6074 + * WITHOUT ANY WARRANTY; without even the implied warranty of
6075 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6076 + * General Public License for more details.
6077 + */
6078 +
6079 +#include <linux/module.h>
6080 +#include <linux/platform_device.h>
6081 +#include <linux/io.h>
6082 +
6083 +#include <sound/core.h>
6084 +#include <sound/pcm.h>
6085 +#include <sound/pcm_params.h>
6086 +#include <sound/soc.h>
6087 +#include <sound/jack.h>
6088 +
6089 +#include "../codecs/sgtl5000.h"
6090 +
6091 +static int snd_fe_pi_audio_init(struct snd_soc_pcm_runtime *rtd)
6092 +{
6093 + struct snd_soc_card *card = rtd->card;
6094 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
6095 +
6096 + snd_soc_dapm_force_enable_pin(&card->dapm, "LO");
6097 + snd_soc_dapm_force_enable_pin(&card->dapm, "ADC");
6098 + snd_soc_dapm_force_enable_pin(&card->dapm, "DAC");
6099 + snd_soc_dapm_force_enable_pin(&card->dapm, "HP");
6100 + snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER,
6101 + SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP);
6102 +
6103 + return 0;
6104 +}
6105 +
6106 +static int snd_fe_pi_audio_hw_params(struct snd_pcm_substream *substream,
6107 + struct snd_pcm_hw_params *params)
6108 +{
6109 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
6110 + struct device *dev = rtd->card->dev;
6111 + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
6112 +
6113 + int ret;
6114 +
6115 + /* Set SGTL5000's SYSCLK */
6116 + ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, 12288000, SND_SOC_CLOCK_IN);
6117 + if (ret) {
6118 + dev_err(dev, "could not set codec driver clock params\n");
6119 + return ret;
6120 + }
6121 +
6122 + return 0;
6123 +}
6124 +
6125 +
6126 +static struct snd_soc_ops snd_fe_pi_audio_ops = {
6127 + .hw_params = snd_fe_pi_audio_hw_params,
6128 +};
6129 +
6130 +SND_SOC_DAILINK_DEFS(fe_pi,
6131 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
6132 + DAILINK_COMP_ARRAY(COMP_CODEC("sgtl5000.1-000a", "sgtl5000")),
6133 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
6134 +
6135 +static struct snd_soc_dai_link snd_fe_pi_audio_dai[] = {
6136 + {
6137 + .name = "FE-PI",
6138 + .stream_name = "Fe-Pi HiFi",
6139 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
6140 + SND_SOC_DAIFMT_CBM_CFM,
6141 + .ops = &snd_fe_pi_audio_ops,
6142 + .init = snd_fe_pi_audio_init,
6143 + SND_SOC_DAILINK_REG(fe_pi),
6144 + },
6145 +};
6146 +
6147 +static const struct snd_soc_dapm_route fe_pi_audio_dapm_routes[] = {
6148 + {"ADC", NULL, "Mic Bias"},
6149 +};
6150 +
6151 +
6152 +static struct snd_soc_card fe_pi_audio = {
6153 + .name = "Fe-Pi Audio",
6154 + .owner = THIS_MODULE,
6155 + .dai_link = snd_fe_pi_audio_dai,
6156 + .num_links = ARRAY_SIZE(snd_fe_pi_audio_dai),
6157 +
6158 + .dapm_routes = fe_pi_audio_dapm_routes,
6159 + .num_dapm_routes = ARRAY_SIZE(fe_pi_audio_dapm_routes),
6160 +};
6161 +
6162 +static int snd_fe_pi_audio_probe(struct platform_device *pdev)
6163 +{
6164 + int ret = 0;
6165 + struct snd_soc_card *card = &fe_pi_audio;
6166 + struct device_node *np = pdev->dev.of_node;
6167 + struct device_node *i2s_node;
6168 + struct snd_soc_dai_link *dai = &snd_fe_pi_audio_dai[0];
6169 +
6170 + fe_pi_audio.dev = &pdev->dev;
6171 +
6172 + i2s_node = of_parse_phandle(np, "i2s-controller", 0);
6173 + if (!i2s_node) {
6174 + dev_err(&pdev->dev, "i2s_node phandle missing or invalid\n");
6175 + return -EINVAL;
6176 + }
6177 +
6178 + dai->cpus->dai_name = NULL;
6179 + dai->cpus->of_node = i2s_node;
6180 + dai->platforms->name = NULL;
6181 + dai->platforms->of_node = i2s_node;
6182 +
6183 + of_node_put(i2s_node);
6184 +
6185 + card->dev = &pdev->dev;
6186 + platform_set_drvdata(pdev, card);
6187 +
6188 + ret = devm_snd_soc_register_card(&pdev->dev, card);
6189 + if (ret && ret != -EPROBE_DEFER)
6190 + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret);
6191 +
6192 + return ret;
6193 +}
6194 +
6195 +static const struct of_device_id snd_fe_pi_audio_of_match[] = {
6196 + { .compatible = "fe-pi,fe-pi-audio", },
6197 + {},
6198 +};
6199 +MODULE_DEVICE_TABLE(of, snd_fe_pi_audio_of_match);
6200 +
6201 +static struct platform_driver snd_fe_pi_audio_driver = {
6202 + .driver = {
6203 + .name = "snd-fe-pi-audio",
6204 + .owner = THIS_MODULE,
6205 + .of_match_table = snd_fe_pi_audio_of_match,
6206 + },
6207 + .probe = snd_fe_pi_audio_probe,
6208 +};
6209 +
6210 +module_platform_driver(snd_fe_pi_audio_driver);
6211 +
6212 +MODULE_AUTHOR("Henry Kupis <fe-pi@cox.net>");
6213 +MODULE_DESCRIPTION("ASoC Driver for Fe-Pi Audio");
6214 +MODULE_LICENSE("GPL v2");
6215 --- /dev/null
6216 +++ b/sound/soc/bcm/googlevoicehat-codec.c
6217 @@ -0,0 +1,214 @@
6218 +/*
6219 + * Driver for the Google voiceHAT audio codec for Raspberry Pi.
6220 + *
6221 + * Author: Peter Malkin <petermalkin@google.com>
6222 + * Copyright 2016
6223 + *
6224 + * This program is free software; you can redistribute it and/or
6225 + * modify it under the terms of the GNU General Public License
6226 + * version 2 as published by the Free Software Foundation.
6227 + *
6228 + * This program is distributed in the hope that it will be useful, but
6229 + * WITHOUT ANY WARRANTY; without even the implied warranty of
6230 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6231 + * General Public License for more details.
6232 + */
6233 +
6234 +#include <linux/device.h>
6235 +#include <linux/err.h>
6236 +#include <linux/gpio.h>
6237 +#include <linux/gpio/consumer.h>
6238 +#include <linux/init.h>
6239 +#include <linux/kernel.h>
6240 +#include <linux/mod_devicetable.h>
6241 +#include <linux/module.h>
6242 +#include <linux/of.h>
6243 +#include <linux/platform_device.h>
6244 +#include <linux/version.h>
6245 +#include <sound/pcm.h>
6246 +#include <sound/soc.h>
6247 +#include <sound/soc-dai.h>
6248 +#include <sound/soc-dapm.h>
6249 +
6250 +#define ICS43432_RATE_MIN_HZ 7190 /* from data sheet */
6251 +#define ICS43432_RATE_MAX_HZ 52800 /* from data sheet */
6252 +/* Delay in enabling SDMODE after clock settles to remove pop */
6253 +#define SDMODE_DELAY_MS 5
6254 +
6255 +struct voicehat_priv {
6256 + struct delayed_work enable_sdmode_work;
6257 + struct gpio_desc *sdmode_gpio;
6258 + unsigned long sdmode_delay_jiffies;
6259 +};
6260 +
6261 +static void voicehat_enable_sdmode_work(struct work_struct *work)
6262 +{
6263 + struct voicehat_priv *voicehat = container_of(work,
6264 + struct voicehat_priv,
6265 + enable_sdmode_work.work);
6266 + gpiod_set_value(voicehat->sdmode_gpio, 1);
6267 +}
6268 +
6269 +static int voicehat_component_probe(struct snd_soc_component *component)
6270 +{
6271 + struct voicehat_priv *voicehat =
6272 + snd_soc_component_get_drvdata(component);
6273 +
6274 + voicehat->sdmode_gpio = devm_gpiod_get(component->dev, "sdmode",
6275 + GPIOD_OUT_LOW);
6276 + if (IS_ERR(voicehat->sdmode_gpio)) {
6277 + dev_err(component->dev, "Unable to allocate GPIO pin\n");
6278 + return PTR_ERR(voicehat->sdmode_gpio);
6279 + }
6280 +
6281 + INIT_DELAYED_WORK(&voicehat->enable_sdmode_work,
6282 + voicehat_enable_sdmode_work);
6283 + return 0;
6284 +}
6285 +
6286 +static void voicehat_component_remove(struct snd_soc_component *component)
6287 +{
6288 + struct voicehat_priv *voicehat =
6289 + snd_soc_component_get_drvdata(component);
6290 +
6291 + cancel_delayed_work_sync(&voicehat->enable_sdmode_work);
6292 +}
6293 +
6294 +static const struct snd_soc_dapm_widget voicehat_dapm_widgets[] = {
6295 + SND_SOC_DAPM_OUTPUT("Speaker"),
6296 +};
6297 +
6298 +static const struct snd_soc_dapm_route voicehat_dapm_routes[] = {
6299 + {"Speaker", NULL, "HiFi Playback"},
6300 +};
6301 +
6302 +static const struct snd_soc_component_driver voicehat_component_driver = {
6303 + .probe = voicehat_component_probe,
6304 + .remove = voicehat_component_remove,
6305 + .dapm_widgets = voicehat_dapm_widgets,
6306 + .num_dapm_widgets = ARRAY_SIZE(voicehat_dapm_widgets),
6307 + .dapm_routes = voicehat_dapm_routes,
6308 + .num_dapm_routes = ARRAY_SIZE(voicehat_dapm_routes),
6309 +};
6310 +
6311 +static int voicehat_daiops_trigger(struct snd_pcm_substream *substream, int cmd,
6312 + struct snd_soc_dai *dai)
6313 +{
6314 + struct snd_soc_component *component = dai->component;
6315 + struct voicehat_priv *voicehat =
6316 + snd_soc_component_get_drvdata(component);
6317 +
6318 + if (voicehat->sdmode_delay_jiffies == 0)
6319 + return 0;
6320 +
6321 + dev_dbg(dai->dev, "CMD %d", cmd);
6322 + dev_dbg(dai->dev, "Playback Active %d", dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK]);
6323 + dev_dbg(dai->dev, "Capture Active %d", dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]);
6324 +
6325 + switch (cmd) {
6326 + case SNDRV_PCM_TRIGGER_START:
6327 + case SNDRV_PCM_TRIGGER_RESUME:
6328 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
6329 + if (dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK]) {
6330 + dev_info(dai->dev, "Enabling audio amp...\n");
6331 + queue_delayed_work(
6332 + system_power_efficient_wq,
6333 + &voicehat->enable_sdmode_work,
6334 + voicehat->sdmode_delay_jiffies);
6335 + }
6336 + break;
6337 + case SNDRV_PCM_TRIGGER_STOP:
6338 + case SNDRV_PCM_TRIGGER_SUSPEND:
6339 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
6340 + if (dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK]) {
6341 + cancel_delayed_work(&voicehat->enable_sdmode_work);
6342 + dev_info(dai->dev, "Disabling audio amp...\n");
6343 + gpiod_set_value(voicehat->sdmode_gpio, 0);
6344 + }
6345 + break;
6346 + }
6347 + return 0;
6348 +}
6349 +
6350 +static const struct snd_soc_dai_ops voicehat_dai_ops = {
6351 + .trigger = voicehat_daiops_trigger,
6352 +};
6353 +
6354 +static struct snd_soc_dai_driver voicehat_dai = {
6355 + .name = "voicehat-hifi",
6356 + .capture = {
6357 + .stream_name = "HiFi Capture",
6358 + .channels_min = 2,
6359 + .channels_max = 2,
6360 + .rates = SNDRV_PCM_RATE_48000,
6361 + .formats = SNDRV_PCM_FMTBIT_S32_LE
6362 + },
6363 + .playback = {
6364 + .stream_name = "HiFi Playback",
6365 + .channels_min = 2,
6366 + .channels_max = 2,
6367 + .rates = SNDRV_PCM_RATE_48000,
6368 + .formats = SNDRV_PCM_FMTBIT_S32_LE
6369 + },
6370 + .ops = &voicehat_dai_ops,
6371 + .symmetric_rates = 1
6372 +};
6373 +
6374 +#ifdef CONFIG_OF
6375 +static const struct of_device_id voicehat_ids[] = {
6376 + { .compatible = "google,voicehat", }, {}
6377 + };
6378 + MODULE_DEVICE_TABLE(of, voicehat_ids);
6379 +#endif
6380 +
6381 +static int voicehat_platform_probe(struct platform_device *pdev)
6382 +{
6383 + struct voicehat_priv *voicehat;
6384 + unsigned int sdmode_delay;
6385 + int ret;
6386 +
6387 + voicehat = devm_kzalloc(&pdev->dev, sizeof(*voicehat), GFP_KERNEL);
6388 + if (!voicehat)
6389 + return -ENOMEM;
6390 +
6391 + ret = device_property_read_u32(&pdev->dev, "voicehat_sdmode_delay",
6392 + &sdmode_delay);
6393 +
6394 + if (ret) {
6395 + sdmode_delay = SDMODE_DELAY_MS;
6396 + dev_info(&pdev->dev,
6397 + "property 'voicehat_sdmode_delay' not found default 5 mS");
6398 + } else {
6399 + dev_info(&pdev->dev, "property 'voicehat_sdmode_delay' found delay= %d mS",
6400 + sdmode_delay);
6401 + }
6402 + voicehat->sdmode_delay_jiffies = msecs_to_jiffies(sdmode_delay);
6403 +
6404 + dev_set_drvdata(&pdev->dev, voicehat);
6405 +
6406 + return snd_soc_register_component(&pdev->dev,
6407 + &voicehat_component_driver,
6408 + &voicehat_dai,
6409 + 1);
6410 +}
6411 +
6412 +static int voicehat_platform_remove(struct platform_device *pdev)
6413 +{
6414 + snd_soc_unregister_component(&pdev->dev);
6415 + return 0;
6416 +}
6417 +
6418 +static struct platform_driver voicehat_driver = {
6419 + .driver = {
6420 + .name = "voicehat-codec",
6421 + .of_match_table = of_match_ptr(voicehat_ids),
6422 + },
6423 + .probe = voicehat_platform_probe,
6424 + .remove = voicehat_platform_remove,
6425 +};
6426 +
6427 +module_platform_driver(voicehat_driver);
6428 +
6429 +MODULE_DESCRIPTION("Google voiceHAT Codec driver");
6430 +MODULE_AUTHOR("Peter Malkin <petermalkin@google.com>");
6431 +MODULE_LICENSE("GPL v2");
6432 --- /dev/null
6433 +++ b/sound/soc/bcm/hifiberry_dacplus.c
6434 @@ -0,0 +1,424 @@
6435 +/*
6436 + * ASoC Driver for HiFiBerry DAC+ / DAC Pro
6437 + *
6438 + * Author: Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
6439 + * Copyright 2014-2015
6440 + * based on code by Florian Meier <florian.meier@koalo.de>
6441 + * Headphone added by Joerg Schambacher, joerg@i2audio.com
6442 + *
6443 + * This program is free software; you can redistribute it and/or
6444 + * modify it under the terms of the GNU General Public License
6445 + * version 2 as published by the Free Software Foundation.
6446 + *
6447 + * This program is distributed in the hope that it will be useful, but
6448 + * WITHOUT ANY WARRANTY; without even the implied warranty of
6449 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6450 + * General Public License for more details.
6451 + */
6452 +
6453 +#include <linux/module.h>
6454 +#include <linux/platform_device.h>
6455 +#include <linux/kernel.h>
6456 +#include <linux/clk.h>
6457 +#include <linux/kernel.h>
6458 +#include <linux/module.h>
6459 +#include <linux/of.h>
6460 +#include <linux/slab.h>
6461 +#include <linux/delay.h>
6462 +#include <linux/i2c.h>
6463 +
6464 +#include <sound/core.h>
6465 +#include <sound/pcm.h>
6466 +#include <sound/pcm_params.h>
6467 +#include <sound/soc.h>
6468 +#include <sound/jack.h>
6469 +
6470 +#include "../codecs/pcm512x.h"
6471 +
6472 +#define HIFIBERRY_DACPRO_NOCLOCK 0
6473 +#define HIFIBERRY_DACPRO_CLK44EN 1
6474 +#define HIFIBERRY_DACPRO_CLK48EN 2
6475 +
6476 +struct pcm512x_priv {
6477 + struct regmap *regmap;
6478 + struct clk *sclk;
6479 +};
6480 +
6481 +/* Clock rate of CLK44EN attached to GPIO6 pin */
6482 +#define CLK_44EN_RATE 22579200UL
6483 +/* Clock rate of CLK48EN attached to GPIO3 pin */
6484 +#define CLK_48EN_RATE 24576000UL
6485 +
6486 +static bool slave;
6487 +static bool snd_rpi_hifiberry_is_dacpro;
6488 +static bool digital_gain_0db_limit = true;
6489 +static bool leds_off;
6490 +
6491 +static void snd_rpi_hifiberry_dacplus_select_clk(struct snd_soc_component *component,
6492 + int clk_id)
6493 +{
6494 + switch (clk_id) {
6495 + case HIFIBERRY_DACPRO_NOCLOCK:
6496 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
6497 + break;
6498 + case HIFIBERRY_DACPRO_CLK44EN:
6499 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
6500 + break;
6501 + case HIFIBERRY_DACPRO_CLK48EN:
6502 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
6503 + break;
6504 + }
6505 +}
6506 +
6507 +static void snd_rpi_hifiberry_dacplus_clk_gpio(struct snd_soc_component *component)
6508 +{
6509 + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
6510 + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
6511 + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
6512 +}
6513 +
6514 +static bool snd_rpi_hifiberry_dacplus_is_sclk(struct snd_soc_component *component)
6515 +{
6516 + unsigned int sck;
6517 +
6518 + sck = snd_soc_component_read(component, PCM512x_RATE_DET_4);
6519 + return (!(sck & 0x40));
6520 +}
6521 +
6522 +static bool snd_rpi_hifiberry_dacplus_is_sclk_sleep(
6523 + struct snd_soc_component *component)
6524 +{
6525 + msleep(2);
6526 + return snd_rpi_hifiberry_dacplus_is_sclk(component);
6527 +}
6528 +
6529 +static bool snd_rpi_hifiberry_dacplus_is_pro_card(struct snd_soc_component *component)
6530 +{
6531 + bool isClk44EN, isClk48En, isNoClk;
6532 +
6533 + snd_rpi_hifiberry_dacplus_clk_gpio(component);
6534 +
6535 + snd_rpi_hifiberry_dacplus_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
6536 + isClk44EN = snd_rpi_hifiberry_dacplus_is_sclk_sleep(component);
6537 +
6538 + snd_rpi_hifiberry_dacplus_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
6539 + isNoClk = snd_rpi_hifiberry_dacplus_is_sclk_sleep(component);
6540 +
6541 + snd_rpi_hifiberry_dacplus_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
6542 + isClk48En = snd_rpi_hifiberry_dacplus_is_sclk_sleep(component);
6543 +
6544 + return (isClk44EN && isClk48En && !isNoClk);
6545 +}
6546 +
6547 +static int snd_rpi_hifiberry_dacplus_clk_for_rate(int sample_rate)
6548 +{
6549 + int type;
6550 +
6551 + switch (sample_rate) {
6552 + case 11025:
6553 + case 22050:
6554 + case 44100:
6555 + case 88200:
6556 + case 176400:
6557 + case 352800:
6558 + type = HIFIBERRY_DACPRO_CLK44EN;
6559 + break;
6560 + default:
6561 + type = HIFIBERRY_DACPRO_CLK48EN;
6562 + break;
6563 + }
6564 + return type;
6565 +}
6566 +
6567 +static void snd_rpi_hifiberry_dacplus_set_sclk(struct snd_soc_component *component,
6568 + int sample_rate)
6569 +{
6570 + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
6571 +
6572 + if (!IS_ERR(pcm512x->sclk)) {
6573 + int ctype;
6574 +
6575 + ctype = snd_rpi_hifiberry_dacplus_clk_for_rate(sample_rate);
6576 + clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN)
6577 + ? CLK_44EN_RATE : CLK_48EN_RATE);
6578 + snd_rpi_hifiberry_dacplus_select_clk(component, ctype);
6579 + }
6580 +}
6581 +
6582 +static int snd_rpi_hifiberry_dacplus_init(struct snd_soc_pcm_runtime *rtd)
6583 +{
6584 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
6585 + struct pcm512x_priv *priv;
6586 +
6587 + if (slave)
6588 + snd_rpi_hifiberry_is_dacpro = false;
6589 + else
6590 + snd_rpi_hifiberry_is_dacpro =
6591 + snd_rpi_hifiberry_dacplus_is_pro_card(component);
6592 +
6593 + if (snd_rpi_hifiberry_is_dacpro) {
6594 + struct snd_soc_dai_link *dai = rtd->dai_link;
6595 +
6596 + dai->name = "HiFiBerry DAC+ Pro";
6597 + dai->stream_name = "HiFiBerry DAC+ Pro HiFi";
6598 + dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
6599 + | SND_SOC_DAIFMT_CBM_CFM;
6600 +
6601 + snd_soc_component_update_bits(component, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
6602 + snd_soc_component_update_bits(component, PCM512x_MASTER_MODE, 0x03, 0x03);
6603 + snd_soc_component_update_bits(component, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
6604 + } else {
6605 + priv = snd_soc_component_get_drvdata(component);
6606 + priv->sclk = ERR_PTR(-ENOENT);
6607 + }
6608 +
6609 + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x08, 0x08);
6610 + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
6611 + if (leds_off)
6612 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
6613 + else
6614 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
6615 +
6616 + if (digital_gain_0db_limit) {
6617 + int ret;
6618 + struct snd_soc_card *card = rtd->card;
6619 +
6620 + ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
6621 + if (ret < 0)
6622 + dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
6623 + }
6624 +
6625 + return 0;
6626 +}
6627 +
6628 +static int snd_rpi_hifiberry_dacplus_update_rate_den(
6629 + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
6630 +{
6631 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
6632 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
6633 + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
6634 + struct snd_ratnum *rats_no_pll;
6635 + unsigned int num = 0, den = 0;
6636 + int err;
6637 +
6638 + rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
6639 + if (!rats_no_pll)
6640 + return -ENOMEM;
6641 +
6642 + rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
6643 + rats_no_pll->den_min = 1;
6644 + rats_no_pll->den_max = 128;
6645 + rats_no_pll->den_step = 1;
6646 +
6647 + err = snd_interval_ratnum(hw_param_interval(params,
6648 + SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
6649 + if (err >= 0 && den) {
6650 + params->rate_num = num;
6651 + params->rate_den = den;
6652 + }
6653 +
6654 + devm_kfree(rtd->dev, rats_no_pll);
6655 + return 0;
6656 +}
6657 +
6658 +static int snd_rpi_hifiberry_dacplus_hw_params(
6659 + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
6660 +{
6661 + int ret = 0;
6662 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
6663 + int channels = params_channels(params);
6664 + int width = 32;
6665 +
6666 + if (snd_rpi_hifiberry_is_dacpro) {
6667 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
6668 +
6669 + width = snd_pcm_format_physical_width(params_format(params));
6670 +
6671 + snd_rpi_hifiberry_dacplus_set_sclk(component,
6672 + params_rate(params));
6673 +
6674 + ret = snd_rpi_hifiberry_dacplus_update_rate_den(
6675 + substream, params);
6676 + }
6677 +
6678 + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), channels * width);
6679 + if (ret)
6680 + return ret;
6681 + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_codec(rtd, 0), channels * width);
6682 + return ret;
6683 +}
6684 +
6685 +static int snd_rpi_hifiberry_dacplus_startup(
6686 + struct snd_pcm_substream *substream)
6687 +{
6688 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
6689 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
6690 +
6691 + if (leds_off)
6692 + return 0;
6693 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
6694 + return 0;
6695 +}
6696 +
6697 +static void snd_rpi_hifiberry_dacplus_shutdown(
6698 + struct snd_pcm_substream *substream)
6699 +{
6700 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
6701 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
6702 +
6703 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
6704 +}
6705 +
6706 +/* machine stream operations */
6707 +static struct snd_soc_ops snd_rpi_hifiberry_dacplus_ops = {
6708 + .hw_params = snd_rpi_hifiberry_dacplus_hw_params,
6709 + .startup = snd_rpi_hifiberry_dacplus_startup,
6710 + .shutdown = snd_rpi_hifiberry_dacplus_shutdown,
6711 +};
6712 +
6713 +SND_SOC_DAILINK_DEFS(rpi_hifiberry_dacplus,
6714 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
6715 + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi")),
6716 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
6717 +
6718 +static struct snd_soc_dai_link snd_rpi_hifiberry_dacplus_dai[] = {
6719 +{
6720 + .name = "HiFiBerry DAC+",
6721 + .stream_name = "HiFiBerry DAC+ HiFi",
6722 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
6723 + SND_SOC_DAIFMT_CBS_CFS,
6724 + .ops = &snd_rpi_hifiberry_dacplus_ops,
6725 + .init = snd_rpi_hifiberry_dacplus_init,
6726 + SND_SOC_DAILINK_REG(rpi_hifiberry_dacplus),
6727 +},
6728 +};
6729 +
6730 +/* aux device for optional headphone amp */
6731 +static struct snd_soc_aux_dev hifiberry_dacplus_aux_devs[] = {
6732 + {
6733 + .dlc = {
6734 + .name = "tpa6130a2.1-0060",
6735 + },
6736 + },
6737 +};
6738 +
6739 +/* audio machine driver */
6740 +static struct snd_soc_card snd_rpi_hifiberry_dacplus = {
6741 + .name = "snd_rpi_hifiberry_dacplus",
6742 + .driver_name = "HifiberryDacp",
6743 + .owner = THIS_MODULE,
6744 + .dai_link = snd_rpi_hifiberry_dacplus_dai,
6745 + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai),
6746 +};
6747 +
6748 +static int hb_hp_detect(void)
6749 +{
6750 + struct i2c_adapter *adap = i2c_get_adapter(1);
6751 + int ret;
6752 +
6753 + struct i2c_client tpa_i2c_client = {
6754 + .addr = 0x60,
6755 + .adapter = adap,
6756 + };
6757 +
6758 + ret = i2c_smbus_read_byte(&tpa_i2c_client) >= 0;
6759 + i2c_put_adapter(adap);
6760 + return ret;
6761 +};
6762 +
6763 +static struct property tpa_enable_prop = {
6764 + .name = "status",
6765 + .length = 4 + 1, /* length 'okay' + 1 */
6766 + .value = "okay",
6767 + };
6768 +
6769 +static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev)
6770 +{
6771 + int ret = 0;
6772 + struct snd_soc_card *card = &snd_rpi_hifiberry_dacplus;
6773 + int len;
6774 + struct device_node *tpa_node;
6775 + struct property *tpa_prop;
6776 + struct of_changeset ocs;
6777 +
6778 + /* probe for head phone amp */
6779 + if (hb_hp_detect()) {
6780 + card->aux_dev = hifiberry_dacplus_aux_devs;
6781 + card->num_aux_devs =
6782 + ARRAY_SIZE(hifiberry_dacplus_aux_devs);
6783 + tpa_node = of_find_compatible_node(NULL, NULL, "ti,tpa6130a2");
6784 + tpa_prop = of_find_property(tpa_node, "status", &len);
6785 +
6786 + if (strcmp((char *)tpa_prop->value, "okay")) {
6787 + /* and activate headphone using change_sets */
6788 + dev_info(&pdev->dev, "activating headphone amplifier");
6789 + of_changeset_init(&ocs);
6790 + ret = of_changeset_update_property(&ocs, tpa_node,
6791 + &tpa_enable_prop);
6792 + if (ret) {
6793 + dev_err(&pdev->dev,
6794 + "cannot activate headphone amplifier\n");
6795 + return -ENODEV;
6796 + }
6797 + ret = of_changeset_apply(&ocs);
6798 + if (ret) {
6799 + dev_err(&pdev->dev,
6800 + "cannot activate headphone amplifier\n");
6801 + return -ENODEV;
6802 + }
6803 + }
6804 + }
6805 +
6806 + snd_rpi_hifiberry_dacplus.dev = &pdev->dev;
6807 + if (pdev->dev.of_node) {
6808 + struct device_node *i2s_node;
6809 + struct snd_soc_dai_link *dai;
6810 +
6811 + dai = &snd_rpi_hifiberry_dacplus_dai[0];
6812 + i2s_node = of_parse_phandle(pdev->dev.of_node,
6813 + "i2s-controller", 0);
6814 +
6815 + if (i2s_node) {
6816 + dai->cpus->dai_name = NULL;
6817 + dai->cpus->of_node = i2s_node;
6818 + dai->platforms->name = NULL;
6819 + dai->platforms->of_node = i2s_node;
6820 + }
6821 +
6822 + digital_gain_0db_limit = !of_property_read_bool(
6823 + pdev->dev.of_node, "hifiberry,24db_digital_gain");
6824 + slave = of_property_read_bool(pdev->dev.of_node,
6825 + "hifiberry-dacplus,slave");
6826 + leds_off = of_property_read_bool(pdev->dev.of_node,
6827 + "hifiberry-dacplus,leds_off");
6828 + }
6829 +
6830 + ret = devm_snd_soc_register_card(&pdev->dev,
6831 + &snd_rpi_hifiberry_dacplus);
6832 + if (ret && ret != -EPROBE_DEFER)
6833 + dev_err(&pdev->dev,
6834 + "snd_soc_register_card() failed: %d\n", ret);
6835 +
6836 + return ret;
6837 +}
6838 +
6839 +static const struct of_device_id snd_rpi_hifiberry_dacplus_of_match[] = {
6840 + { .compatible = "hifiberry,hifiberry-dacplus", },
6841 + {},
6842 +};
6843 +MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplus_of_match);
6844 +
6845 +static struct platform_driver snd_rpi_hifiberry_dacplus_driver = {
6846 + .driver = {
6847 + .name = "snd-rpi-hifiberry-dacplus",
6848 + .owner = THIS_MODULE,
6849 + .of_match_table = snd_rpi_hifiberry_dacplus_of_match,
6850 + },
6851 + .probe = snd_rpi_hifiberry_dacplus_probe,
6852 +};
6853 +
6854 +module_platform_driver(snd_rpi_hifiberry_dacplus_driver);
6855 +
6856 +MODULE_AUTHOR("Daniel Matuschek <daniel@hifiberry.com>");
6857 +MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+");
6858 +MODULE_LICENSE("GPL v2");
6859 --- /dev/null
6860 +++ b/sound/soc/bcm/hifiberry_dacplusadc.c
6861 @@ -0,0 +1,398 @@
6862 +/*
6863 + * ASoC Driver for HiFiBerry DAC+ / DAC Pro with ADC
6864 + *
6865 + * Author: Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
6866 + * Copyright 2014-2015
6867 + * based on code by Florian Meier <florian.meier@koalo.de>
6868 + * ADC added by Joerg Schambacher <joscha@schambacher.com>
6869 + * Copyright 2018
6870 + *
6871 + * This program is free software; you can redistribute it and/or
6872 + * modify it under the terms of the GNU General Public License
6873 + * version 2 as published by the Free Software Foundation.
6874 + *
6875 + * This program is distributed in the hope that it will be useful, but
6876 + * WITHOUT ANY WARRANTY; without even the implied warranty of
6877 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6878 + * General Public License for more details.
6879 + */
6880 +
6881 +#include <linux/module.h>
6882 +#include <linux/platform_device.h>
6883 +#include <linux/kernel.h>
6884 +#include <linux/clk.h>
6885 +#include <linux/kernel.h>
6886 +#include <linux/module.h>
6887 +#include <linux/of.h>
6888 +#include <linux/slab.h>
6889 +#include <linux/delay.h>
6890 +
6891 +#include <sound/core.h>
6892 +#include <sound/pcm.h>
6893 +#include <sound/pcm_params.h>
6894 +#include <sound/soc.h>
6895 +#include <sound/jack.h>
6896 +
6897 +#include "../codecs/pcm512x.h"
6898 +
6899 +#define HIFIBERRY_DACPRO_NOCLOCK 0
6900 +#define HIFIBERRY_DACPRO_CLK44EN 1
6901 +#define HIFIBERRY_DACPRO_CLK48EN 2
6902 +
6903 +struct platform_device *dmic_codec_dev;
6904 +
6905 +struct pcm512x_priv {
6906 + struct regmap *regmap;
6907 + struct clk *sclk;
6908 +};
6909 +
6910 +/* Clock rate of CLK44EN attached to GPIO6 pin */
6911 +#define CLK_44EN_RATE 22579200UL
6912 +/* Clock rate of CLK48EN attached to GPIO3 pin */
6913 +#define CLK_48EN_RATE 24576000UL
6914 +
6915 +static bool slave;
6916 +static bool snd_rpi_hifiberry_is_dacpro;
6917 +static bool digital_gain_0db_limit = true;
6918 +static bool leds_off;
6919 +
6920 +static void snd_rpi_hifiberry_dacplusadc_select_clk(struct snd_soc_component *component,
6921 + int clk_id)
6922 +{
6923 + switch (clk_id) {
6924 + case HIFIBERRY_DACPRO_NOCLOCK:
6925 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
6926 + break;
6927 + case HIFIBERRY_DACPRO_CLK44EN:
6928 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
6929 + break;
6930 + case HIFIBERRY_DACPRO_CLK48EN:
6931 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
6932 + break;
6933 + }
6934 +}
6935 +
6936 +static void snd_rpi_hifiberry_dacplusadc_clk_gpio(struct snd_soc_component *component)
6937 +{
6938 + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
6939 + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
6940 + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
6941 +}
6942 +
6943 +static bool snd_rpi_hifiberry_dacplusadc_is_sclk(struct snd_soc_component *component)
6944 +{
6945 + unsigned int sck;
6946 +
6947 + sck = snd_soc_component_read(component, PCM512x_RATE_DET_4);
6948 + return (!(sck & 0x40));
6949 +}
6950 +
6951 +static bool snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(
6952 + struct snd_soc_component *component)
6953 +{
6954 + msleep(2);
6955 + return snd_rpi_hifiberry_dacplusadc_is_sclk(component);
6956 +}
6957 +
6958 +static bool snd_rpi_hifiberry_dacplusadc_is_pro_card(struct snd_soc_component *component)
6959 +{
6960 + bool isClk44EN, isClk48En, isNoClk;
6961 +
6962 + snd_rpi_hifiberry_dacplusadc_clk_gpio(component);
6963 +
6964 + snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
6965 + isClk44EN = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
6966 +
6967 + snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
6968 + isNoClk = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
6969 +
6970 + snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
6971 + isClk48En = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
6972 +
6973 + return (isClk44EN && isClk48En && !isNoClk);
6974 +}
6975 +
6976 +static int snd_rpi_hifiberry_dacplusadc_clk_for_rate(int sample_rate)
6977 +{
6978 + int type;
6979 +
6980 + switch (sample_rate) {
6981 + case 11025:
6982 + case 22050:
6983 + case 44100:
6984 + case 88200:
6985 + case 176400:
6986 + case 352800:
6987 + type = HIFIBERRY_DACPRO_CLK44EN;
6988 + break;
6989 + default:
6990 + type = HIFIBERRY_DACPRO_CLK48EN;
6991 + break;
6992 + }
6993 + return type;
6994 +}
6995 +
6996 +static void snd_rpi_hifiberry_dacplusadc_set_sclk(struct snd_soc_component *component,
6997 + int sample_rate)
6998 +{
6999 + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
7000 +
7001 + if (!IS_ERR(pcm512x->sclk)) {
7002 + int ctype;
7003 +
7004 + ctype = snd_rpi_hifiberry_dacplusadc_clk_for_rate(sample_rate);
7005 + clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN)
7006 + ? CLK_44EN_RATE : CLK_48EN_RATE);
7007 + snd_rpi_hifiberry_dacplusadc_select_clk(component, ctype);
7008 + }
7009 +}
7010 +
7011 +static int snd_rpi_hifiberry_dacplusadc_init(struct snd_soc_pcm_runtime *rtd)
7012 +{
7013 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
7014 + struct pcm512x_priv *priv;
7015 +
7016 + if (slave)
7017 + snd_rpi_hifiberry_is_dacpro = false;
7018 + else
7019 + snd_rpi_hifiberry_is_dacpro =
7020 + snd_rpi_hifiberry_dacplusadc_is_pro_card(component);
7021 +
7022 + if (snd_rpi_hifiberry_is_dacpro) {
7023 + struct snd_soc_dai_link *dai = rtd->dai_link;
7024 +
7025 + dai->name = "HiFiBerry ADCDAC+ Pro";
7026 + dai->stream_name = "HiFiBerry ADCDAC+ Pro HiFi";
7027 + dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
7028 + | SND_SOC_DAIFMT_CBM_CFM;
7029 +
7030 + snd_soc_component_update_bits(component, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
7031 + snd_soc_component_update_bits(component, PCM512x_MASTER_MODE, 0x03, 0x03);
7032 + snd_soc_component_update_bits(component, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
7033 + } else {
7034 + priv = snd_soc_component_get_drvdata(component);
7035 + priv->sclk = ERR_PTR(-ENOENT);
7036 + }
7037 +
7038 + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x08, 0x08);
7039 + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
7040 + if (leds_off)
7041 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
7042 + else
7043 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
7044 +
7045 + if (digital_gain_0db_limit) {
7046 + int ret;
7047 + struct snd_soc_card *card = rtd->card;
7048 +
7049 + ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
7050 + if (ret < 0)
7051 + dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
7052 + }
7053 +
7054 + return 0;
7055 +}
7056 +
7057 +static int snd_rpi_hifiberry_dacplusadc_update_rate_den(
7058 + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
7059 +{
7060 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
7061 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
7062 + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
7063 + struct snd_ratnum *rats_no_pll;
7064 + unsigned int num = 0, den = 0;
7065 + int err;
7066 +
7067 + rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
7068 + if (!rats_no_pll)
7069 + return -ENOMEM;
7070 +
7071 + rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
7072 + rats_no_pll->den_min = 1;
7073 + rats_no_pll->den_max = 128;
7074 + rats_no_pll->den_step = 1;
7075 +
7076 + err = snd_interval_ratnum(hw_param_interval(params,
7077 + SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
7078 + if (err >= 0 && den) {
7079 + params->rate_num = num;
7080 + params->rate_den = den;
7081 + }
7082 +
7083 + devm_kfree(rtd->dev, rats_no_pll);
7084 + return 0;
7085 +}
7086 +
7087 +static int snd_rpi_hifiberry_dacplusadc_hw_params(
7088 + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
7089 +{
7090 + int ret = 0;
7091 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
7092 + int channels = params_channels(params);
7093 + int width = 32;
7094 +
7095 + if (snd_rpi_hifiberry_is_dacpro) {
7096 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
7097 +
7098 + width = snd_pcm_format_physical_width(params_format(params));
7099 +
7100 + snd_rpi_hifiberry_dacplusadc_set_sclk(component,
7101 + params_rate(params));
7102 +
7103 + ret = snd_rpi_hifiberry_dacplusadc_update_rate_den(
7104 + substream, params);
7105 + }
7106 +
7107 + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), channels * width);
7108 + if (ret)
7109 + return ret;
7110 + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_codec(rtd, 0), channels * width);
7111 + return ret;
7112 +}
7113 +
7114 +static int hifiberry_dacplusadc_LED_cnt;
7115 +
7116 +static int snd_rpi_hifiberry_dacplusadc_startup(
7117 + struct snd_pcm_substream *substream)
7118 +{
7119 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
7120 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
7121 +
7122 + if (leds_off)
7123 + return 0;
7124 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1,
7125 + 0x08, 0x08);
7126 + hifiberry_dacplusadc_LED_cnt++;
7127 + return 0;
7128 +}
7129 +
7130 +static void snd_rpi_hifiberry_dacplusadc_shutdown(
7131 + struct snd_pcm_substream *substream)
7132 +{
7133 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
7134 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
7135 +
7136 + hifiberry_dacplusadc_LED_cnt--;
7137 + if (!hifiberry_dacplusadc_LED_cnt)
7138 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1,
7139 + 0x08, 0x00);
7140 +}
7141 +
7142 +/* machine stream operations */
7143 +static struct snd_soc_ops snd_rpi_hifiberry_dacplusadc_ops = {
7144 + .hw_params = snd_rpi_hifiberry_dacplusadc_hw_params,
7145 + .startup = snd_rpi_hifiberry_dacplusadc_startup,
7146 + .shutdown = snd_rpi_hifiberry_dacplusadc_shutdown,
7147 +};
7148 +
7149 +SND_SOC_DAILINK_DEFS(hifi,
7150 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
7151 + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi"),
7152 + COMP_CODEC("dmic-codec", "dmic-hifi")),
7153 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
7154 +
7155 +static struct snd_soc_dai_link snd_rpi_hifiberry_dacplusadc_dai[] = {
7156 +{
7157 + .name = "HiFiBerry DAC+ADC",
7158 + .stream_name = "HiFiBerry DAC+ADC HiFi",
7159 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
7160 + SND_SOC_DAIFMT_CBS_CFS,
7161 + .ops = &snd_rpi_hifiberry_dacplusadc_ops,
7162 + .init = snd_rpi_hifiberry_dacplusadc_init,
7163 + SND_SOC_DAILINK_REG(hifi),
7164 +},
7165 +};
7166 +
7167 +/* audio machine driver */
7168 +static struct snd_soc_card snd_rpi_hifiberry_dacplusadc = {
7169 + .name = "snd_rpi_hifiberry_dacplusadc",
7170 + .driver_name = "HifiberryDacpAdc",
7171 + .owner = THIS_MODULE,
7172 + .dai_link = snd_rpi_hifiberry_dacplusadc_dai,
7173 + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplusadc_dai),
7174 +};
7175 +
7176 +
7177 +static int snd_rpi_hifiberry_dacplusadc_probe(struct platform_device *pdev)
7178 +{
7179 + int ret = 0;
7180 +
7181 + snd_rpi_hifiberry_dacplusadc.dev = &pdev->dev;
7182 + if (pdev->dev.of_node) {
7183 + struct device_node *i2s_node;
7184 + struct snd_soc_dai_link *dai;
7185 +
7186 + dai = &snd_rpi_hifiberry_dacplusadc_dai[0];
7187 + i2s_node = of_parse_phandle(pdev->dev.of_node,
7188 + "i2s-controller", 0);
7189 + if (i2s_node) {
7190 + dai->cpus->of_node = i2s_node;
7191 + dai->platforms->of_node = i2s_node;
7192 + dai->cpus->dai_name = NULL;
7193 + dai->platforms->name = NULL;
7194 + }
7195 + }
7196 + digital_gain_0db_limit = !of_property_read_bool(
7197 + pdev->dev.of_node, "hifiberry,24db_digital_gain");
7198 + slave = of_property_read_bool(pdev->dev.of_node,
7199 + "hifiberry-dacplusadc,slave");
7200 + leds_off = of_property_read_bool(pdev->dev.of_node,
7201 + "hifiberry-dacplusadc,leds_off");
7202 +
7203 + ret = devm_snd_soc_register_card(&pdev->dev,
7204 + &snd_rpi_hifiberry_dacplusadc);
7205 + if (ret && ret != -EPROBE_DEFER)
7206 + dev_err(&pdev->dev,
7207 + "snd_soc_register_card() failed: %d\n", ret);
7208 +
7209 + return ret;
7210 +}
7211 +
7212 +static const struct of_device_id snd_rpi_hifiberry_dacplusadc_of_match[] = {
7213 + { .compatible = "hifiberry,hifiberry-dacplusadc", },
7214 + {},
7215 +};
7216 +
7217 +MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplusadc_of_match);
7218 +
7219 +static struct platform_driver snd_rpi_hifiberry_dacplusadc_driver = {
7220 + .driver = {
7221 + .name = "snd-rpi-hifiberry-dacplusadc",
7222 + .owner = THIS_MODULE,
7223 + .of_match_table = snd_rpi_hifiberry_dacplusadc_of_match,
7224 + },
7225 + .probe = snd_rpi_hifiberry_dacplusadc_probe,
7226 +};
7227 +
7228 +static int __init hifiberry_dacplusadc_init(void)
7229 +{
7230 + int ret;
7231 +
7232 + dmic_codec_dev = platform_device_register_simple("dmic-codec", -1, NULL,
7233 + 0);
7234 + if (IS_ERR(dmic_codec_dev)) {
7235 + pr_err("%s: dmic-codec device registration failed\n", __func__);
7236 + return PTR_ERR(dmic_codec_dev);
7237 + }
7238 +
7239 + ret = platform_driver_register(&snd_rpi_hifiberry_dacplusadc_driver);
7240 + if (ret) {
7241 + pr_err("%s: platform driver registration failed\n", __func__);
7242 + platform_device_unregister(dmic_codec_dev);
7243 + }
7244 +
7245 + return ret;
7246 +}
7247 +module_init(hifiberry_dacplusadc_init);
7248 +
7249 +static void __exit hifiberry_dacplusadc_exit(void)
7250 +{
7251 + platform_driver_unregister(&snd_rpi_hifiberry_dacplusadc_driver);
7252 + platform_device_unregister(dmic_codec_dev);
7253 +}
7254 +module_exit(hifiberry_dacplusadc_exit);
7255 +
7256 +MODULE_AUTHOR("Joerg Schambacher <joscha@schambacher.com>");
7257 +MODULE_AUTHOR("Daniel Matuschek <daniel@hifiberry.com>");
7258 +MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ADC");
7259 +MODULE_LICENSE("GPL v2");
7260 --- /dev/null
7261 +++ b/sound/soc/bcm/hifiberry_dacplusadcpro.c
7262 @@ -0,0 +1,543 @@
7263 +/*
7264 + * ASoC Driver for HiFiBerry DAC+ / DAC Pro with ADC PRO Version (SW control)
7265 + *
7266 + * Author: Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
7267 + * Copyright 2014-2015
7268 + * based on code by Florian Meier <florian.meier@koalo.de>
7269 + * ADC added by Joerg Schambacher <joerg@i2audio.com>
7270 + * Copyright 2018-19
7271 + *
7272 + * This program is free software; you can redistribute it and/or
7273 + * modify it under the terms of the GNU General Public License
7274 + * version 2 as published by the Free Software Foundation.
7275 + *
7276 + * This program is distributed in the hope that it will be useful, but
7277 + * WITHOUT ANY WARRANTY; without even the implied warranty of
7278 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
7279 + * General Public License for more details.
7280 + */
7281 +
7282 +#include <linux/module.h>
7283 +#include <linux/platform_device.h>
7284 +#include <linux/kernel.h>
7285 +#include <linux/clk.h>
7286 +#include <linux/kernel.h>
7287 +#include <linux/module.h>
7288 +#include <linux/of.h>
7289 +#include <linux/slab.h>
7290 +#include <linux/delay.h>
7291 +
7292 +#include <sound/core.h>
7293 +#include <sound/pcm.h>
7294 +#include <sound/pcm_params.h>
7295 +#include <sound/soc.h>
7296 +#include <sound/jack.h>
7297 +#include <sound/tlv.h>
7298 +
7299 +#include "../codecs/pcm512x.h"
7300 +#include "../codecs/pcm186x.h"
7301 +
7302 +#define HIFIBERRY_DACPRO_NOCLOCK 0
7303 +#define HIFIBERRY_DACPRO_CLK44EN 1
7304 +#define HIFIBERRY_DACPRO_CLK48EN 2
7305 +
7306 +struct pcm512x_priv {
7307 + struct regmap *regmap;
7308 + struct clk *sclk;
7309 +};
7310 +
7311 +/* Clock rate of CLK44EN attached to GPIO6 pin */
7312 +#define CLK_44EN_RATE 22579200UL
7313 +/* Clock rate of CLK48EN attached to GPIO3 pin */
7314 +#define CLK_48EN_RATE 24576000UL
7315 +
7316 +static bool slave;
7317 +static bool snd_rpi_hifiberry_is_dacpro;
7318 +static bool digital_gain_0db_limit = true;
7319 +static bool leds_off;
7320 +
7321 +static const unsigned int pcm186x_adc_input_channel_sel_value[] = {
7322 + 0x00, 0x01, 0x02, 0x03, 0x10
7323 +};
7324 +
7325 +static const char * const pcm186x_adcl_input_channel_sel_text[] = {
7326 + "No Select",
7327 + "VINL1[SE]", /* Default for ADCL */
7328 + "VINL2[SE]",
7329 + "VINL2[SE] + VINL1[SE]",
7330 + "{VIN1P, VIN1M}[DIFF]"
7331 +};
7332 +
7333 +static const char * const pcm186x_adcr_input_channel_sel_text[] = {
7334 + "No Select",
7335 + "VINR1[SE]", /* Default for ADCR */
7336 + "VINR2[SE]",
7337 + "VINR2[SE] + VINR1[SE]",
7338 + "{VIN2P, VIN2M}[DIFF]"
7339 +};
7340 +
7341 +static const struct soc_enum pcm186x_adc_input_channel_sel[] = {
7342 + SOC_VALUE_ENUM_SINGLE(PCM186X_ADC1_INPUT_SEL_L, 0,
7343 + PCM186X_ADC_INPUT_SEL_MASK,
7344 + ARRAY_SIZE(pcm186x_adcl_input_channel_sel_text),
7345 + pcm186x_adcl_input_channel_sel_text,
7346 + pcm186x_adc_input_channel_sel_value),
7347 + SOC_VALUE_ENUM_SINGLE(PCM186X_ADC1_INPUT_SEL_R, 0,
7348 + PCM186X_ADC_INPUT_SEL_MASK,
7349 + ARRAY_SIZE(pcm186x_adcr_input_channel_sel_text),
7350 + pcm186x_adcr_input_channel_sel_text,
7351 + pcm186x_adc_input_channel_sel_value),
7352 +};
7353 +
7354 +static const unsigned int pcm186x_mic_bias_sel_value[] = {
7355 + 0x00, 0x01, 0x11
7356 +};
7357 +
7358 +static const char * const pcm186x_mic_bias_sel_text[] = {
7359 + "Mic Bias off",
7360 + "Mic Bias on",
7361 + "Mic Bias with Bypass Resistor"
7362 +};
7363 +
7364 +static const struct soc_enum pcm186x_mic_bias_sel[] = {
7365 + SOC_VALUE_ENUM_SINGLE(PCM186X_MIC_BIAS_CTRL, 0,
7366 + GENMASK(4, 0),
7367 + ARRAY_SIZE(pcm186x_mic_bias_sel_text),
7368 + pcm186x_mic_bias_sel_text,
7369 + pcm186x_mic_bias_sel_value),
7370 +};
7371 +
7372 +static const unsigned int pcm186x_gain_sel_value[] = {
7373 + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
7374 + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
7375 + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
7376 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
7377 + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
7378 + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
7379 + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
7380 + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
7381 + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
7382 + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
7383 + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
7384 + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
7385 + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
7386 + 0x50
7387 +};
7388 +
7389 +static const char * const pcm186x_gain_sel_text[] = {
7390 + "-12.0dB", "-11.5dB", "-11.0dB", "-10.5dB", "-10.0dB", "-9.5dB",
7391 + "-9.0dB", "-8.5dB", "-8.0dB", "-7.5dB", "-7.0dB", "-6.5dB",
7392 + "-6.0dB", "-5.5dB", "-5.0dB", "-4.5dB", "-4.0dB", "-3.5dB",
7393 + "-3.0dB", "-2.5dB", "-2.0dB", "-1.5dB", "-1.0dB", "-0.5dB",
7394 + "0.0dB", "0.5dB", "1.0dB", "1.5dB", "2.0dB", "2.5dB",
7395 + "3.0dB", "3.5dB", "4.0dB", "4.5dB", "5.0dB", "5.5dB",
7396 + "6.0dB", "6.5dB", "7.0dB", "7.5dB", "8.0dB", "8.5dB",
7397 + "9.0dB", "9.5dB", "10.0dB", "10.5dB", "11.0dB", "11.5dB",
7398 + "12.0dB", "12.5dB", "13.0dB", "13.5dB", "14.0dB", "14.5dB",
7399 + "15.0dB", "15.5dB", "16.0dB", "16.5dB", "17.0dB", "17.5dB",
7400 + "18.0dB", "18.5dB", "19.0dB", "19.5dB", "20.0dB", "20.5dB",
7401 + "21.0dB", "21.5dB", "22.0dB", "22.5dB", "23.0dB", "23.5dB",
7402 + "24.0dB", "24.5dB", "25.0dB", "25.5dB", "26.0dB", "26.5dB",
7403 + "27.0dB", "27.5dB", "28.0dB", "28.5dB", "29.0dB", "29.5dB",
7404 + "30.0dB", "30.5dB", "31.0dB", "31.5dB", "32.0dB", "32.5dB",
7405 + "33.0dB", "33.5dB", "34.0dB", "34.5dB", "35.0dB", "35.5dB",
7406 + "36.0dB", "36.5dB", "37.0dB", "37.5dB", "38.0dB", "38.5dB",
7407 + "39.0dB", "39.5dB", "40.0dB"};
7408 +
7409 +static const struct soc_enum pcm186x_gain_sel[] = {
7410 + SOC_VALUE_ENUM_SINGLE(PCM186X_PGA_VAL_CH1_L, 0,
7411 + 0xff,
7412 + ARRAY_SIZE(pcm186x_gain_sel_text),
7413 + pcm186x_gain_sel_text,
7414 + pcm186x_gain_sel_value),
7415 + SOC_VALUE_ENUM_SINGLE(PCM186X_PGA_VAL_CH1_R, 0,
7416 + 0xff,
7417 + ARRAY_SIZE(pcm186x_gain_sel_text),
7418 + pcm186x_gain_sel_text,
7419 + pcm186x_gain_sel_value),
7420 +};
7421 +
7422 +static const struct snd_kcontrol_new pcm1863_snd_controls_card[] = {
7423 + SOC_ENUM("ADC Left Input", pcm186x_adc_input_channel_sel[0]),
7424 + SOC_ENUM("ADC Right Input", pcm186x_adc_input_channel_sel[1]),
7425 + SOC_ENUM("ADC Mic Bias", pcm186x_mic_bias_sel),
7426 + SOC_ENUM("PGA Gain Left", pcm186x_gain_sel[0]),
7427 + SOC_ENUM("PGA Gain Right", pcm186x_gain_sel[1]),
7428 +};
7429 +
7430 +static int pcm1863_add_controls(struct snd_soc_component *component)
7431 +{
7432 + snd_soc_add_component_controls(component,
7433 + pcm1863_snd_controls_card,
7434 + ARRAY_SIZE(pcm1863_snd_controls_card));
7435 + return 0;
7436 +}
7437 +
7438 +static void snd_rpi_hifiberry_dacplusadcpro_select_clk(
7439 + struct snd_soc_component *component, int clk_id)
7440 +{
7441 + switch (clk_id) {
7442 + case HIFIBERRY_DACPRO_NOCLOCK:
7443 + snd_soc_component_update_bits(component,
7444 + PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
7445 + break;
7446 + case HIFIBERRY_DACPRO_CLK44EN:
7447 + snd_soc_component_update_bits(component,
7448 + PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
7449 + break;
7450 + case HIFIBERRY_DACPRO_CLK48EN:
7451 + snd_soc_component_update_bits(component,
7452 + PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
7453 + break;
7454 + }
7455 +}
7456 +
7457 +static void snd_rpi_hifiberry_dacplusadcpro_clk_gpio(struct snd_soc_component *component)
7458 +{
7459 + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
7460 + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
7461 + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
7462 +}
7463 +
7464 +static bool snd_rpi_hifiberry_dacplusadcpro_is_sclk(struct snd_soc_component *component)
7465 +{
7466 + unsigned int sck;
7467 +
7468 + sck = snd_soc_component_read(component, PCM512x_RATE_DET_4);
7469 + return (!(sck & 0x40));
7470 +}
7471 +
7472 +static bool snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(
7473 + struct snd_soc_component *component)
7474 +{
7475 + msleep(2);
7476 + return snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
7477 +}
7478 +
7479 +static bool snd_rpi_hifiberry_dacplusadcpro_is_pro_card(struct snd_soc_component *component)
7480 +{
7481 + bool isClk44EN, isClk48En, isNoClk;
7482 +
7483 + snd_rpi_hifiberry_dacplusadcpro_clk_gpio(component);
7484 +
7485 + snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
7486 + isClk44EN = snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(component);
7487 +
7488 + snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
7489 + isNoClk = snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(component);
7490 +
7491 + snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
7492 + isClk48En = snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(component);
7493 +
7494 + return (isClk44EN && isClk48En && !isNoClk);
7495 +}
7496 +
7497 +static int snd_rpi_hifiberry_dacplusadcpro_clk_for_rate(int sample_rate)
7498 +{
7499 + int type;
7500 +
7501 + switch (sample_rate) {
7502 + case 11025:
7503 + case 22050:
7504 + case 44100:
7505 + case 88200:
7506 + case 176400:
7507 + case 352800:
7508 + type = HIFIBERRY_DACPRO_CLK44EN;
7509 + break;
7510 + default:
7511 + type = HIFIBERRY_DACPRO_CLK48EN;
7512 + break;
7513 + }
7514 + return type;
7515 +}
7516 +
7517 +static void snd_rpi_hifiberry_dacplusadcpro_set_sclk(struct snd_soc_component *component,
7518 + int sample_rate)
7519 +{
7520 + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
7521 +
7522 + if (!IS_ERR(pcm512x->sclk)) {
7523 + int ctype;
7524 +
7525 + ctype = snd_rpi_hifiberry_dacplusadcpro_clk_for_rate(sample_rate);
7526 + clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN)
7527 + ? CLK_44EN_RATE : CLK_48EN_RATE);
7528 + snd_rpi_hifiberry_dacplusadcpro_select_clk(component, ctype);
7529 + }
7530 +}
7531 +
7532 +static int snd_rpi_hifiberry_dacplusadcpro_init(struct snd_soc_pcm_runtime *rtd)
7533 +{
7534 + struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 0)->component;
7535 + struct snd_soc_component *adc = asoc_rtd_to_codec(rtd, 1)->component;
7536 + struct snd_soc_dai_driver *adc_driver = asoc_rtd_to_codec(rtd, 1)->driver;
7537 + struct pcm512x_priv *priv;
7538 + int ret;
7539 +
7540 + if (slave)
7541 + snd_rpi_hifiberry_is_dacpro = false;
7542 + else
7543 + snd_rpi_hifiberry_is_dacpro =
7544 + snd_rpi_hifiberry_dacplusadcpro_is_pro_card(dac);
7545 +
7546 + if (snd_rpi_hifiberry_is_dacpro) {
7547 + struct snd_soc_dai_link *dai = rtd->dai_link;
7548 +
7549 + dai->name = "HiFiBerry DAC+ADC Pro";
7550 + dai->stream_name = "HiFiBerry DAC+ADC Pro HiFi";
7551 + dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
7552 + | SND_SOC_DAIFMT_CBM_CFM;
7553 +
7554 + // set DAC DAI configuration
7555 + ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 0),
7556 + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
7557 + | SND_SOC_DAIFMT_CBM_CFM);
7558 + if (ret < 0)
7559 + return ret;
7560 +
7561 + // set ADC DAI configuration
7562 + ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 1),
7563 + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
7564 + | SND_SOC_DAIFMT_CBS_CFS);
7565 + if (ret < 0)
7566 + return ret;
7567 +
7568 + // set CPU DAI configuration
7569 + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
7570 + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
7571 + if (ret < 0)
7572 + return ret;
7573 +
7574 + snd_soc_component_update_bits(dac, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
7575 + snd_soc_component_update_bits(dac, PCM512x_MASTER_MODE, 0x03, 0x03);
7576 + snd_soc_component_update_bits(dac, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
7577 + } else {
7578 + priv = snd_soc_component_get_drvdata(dac);
7579 + priv->sclk = ERR_PTR(-ENOENT);
7580 + }
7581 +
7582 + /* disable 24bit mode as long as I2S module does not have sign extension fixed */
7583 + adc_driver->capture.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE;
7584 +
7585 + snd_soc_component_update_bits(dac, PCM512x_GPIO_EN, 0x08, 0x08);
7586 + snd_soc_component_update_bits(dac, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
7587 + if (leds_off)
7588 + snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
7589 + else
7590 + snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
7591 +
7592 + ret = pcm1863_add_controls(adc);
7593 + if (ret < 0)
7594 + dev_warn(rtd->dev, "Failed to add pcm1863 controls: %d\n",
7595 + ret);
7596 +
7597 + /* set GPIO2 to output, GPIO3 input */
7598 + snd_soc_component_write(adc, PCM186X_GPIO3_2_CTRL, 0x00);
7599 + snd_soc_component_write(adc, PCM186X_GPIO3_2_DIR_CTRL, 0x04);
7600 + if (leds_off)
7601 + snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x00);
7602 + else
7603 + snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
7604 +
7605 + if (digital_gain_0db_limit) {
7606 + int ret;
7607 + struct snd_soc_card *card = rtd->card;
7608 +
7609 + ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
7610 + if (ret < 0)
7611 + dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
7612 + }
7613 +
7614 + return 0;
7615 +}
7616 +
7617 +static int snd_rpi_hifiberry_dacplusadcpro_update_rate_den(
7618 + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
7619 +{
7620 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
7621 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; /* only use DAC */
7622 + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
7623 + struct snd_ratnum *rats_no_pll;
7624 + unsigned int num = 0, den = 0;
7625 + int err;
7626 +
7627 + rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
7628 + if (!rats_no_pll)
7629 + return -ENOMEM;
7630 +
7631 + rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
7632 + rats_no_pll->den_min = 1;
7633 + rats_no_pll->den_max = 128;
7634 + rats_no_pll->den_step = 1;
7635 +
7636 + err = snd_interval_ratnum(hw_param_interval(params,
7637 + SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
7638 + if (err >= 0 && den) {
7639 + params->rate_num = num;
7640 + params->rate_den = den;
7641 + }
7642 +
7643 + devm_kfree(rtd->dev, rats_no_pll);
7644 + return 0;
7645 +}
7646 +
7647 +static int snd_rpi_hifiberry_dacplusadcpro_hw_params(
7648 + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
7649 +{
7650 + int ret = 0;
7651 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
7652 + int channels = params_channels(params);
7653 + int width = 32;
7654 + struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 0)->component;
7655 + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
7656 + struct snd_soc_dai_driver *drv = dai->driver;
7657 + const struct snd_soc_dai_ops *ops = drv->ops;
7658 +
7659 + if (snd_rpi_hifiberry_is_dacpro) {
7660 + width = snd_pcm_format_physical_width(params_format(params));
7661 +
7662 + snd_rpi_hifiberry_dacplusadcpro_set_sclk(dac,
7663 + params_rate(params));
7664 +
7665 + ret = snd_rpi_hifiberry_dacplusadcpro_update_rate_den(
7666 + substream, params);
7667 + if (ret)
7668 + return ret;
7669 + }
7670 +
7671 + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), channels * width);
7672 + if (ret)
7673 + return ret;
7674 + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_codec(rtd, 0), channels * width);
7675 + if (ret)
7676 + return ret;
7677 + if (snd_rpi_hifiberry_is_dacpro && ops->hw_params)
7678 + ret = ops->hw_params(substream, params, dai);
7679 + return ret;
7680 +}
7681 +
7682 +static int snd_rpi_hifiberry_dacplusadcpro_startup(
7683 + struct snd_pcm_substream *substream)
7684 +{
7685 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
7686 + struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 0)->component;
7687 + struct snd_soc_component *adc = asoc_rtd_to_codec(rtd, 1)->component;
7688 +
7689 + if (leds_off)
7690 + return 0;
7691 + /* switch on respective LED */
7692 + if (!substream->stream)
7693 + snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
7694 + else
7695 + snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
7696 + return 0;
7697 +}
7698 +
7699 +static void snd_rpi_hifiberry_dacplusadcpro_shutdown(
7700 + struct snd_pcm_substream *substream)
7701 +{
7702 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
7703 + struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 0)->component;
7704 + struct snd_soc_component *adc = asoc_rtd_to_codec(rtd, 1)->component;
7705 +
7706 + /* switch off respective LED */
7707 + if (!substream->stream)
7708 + snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
7709 + else
7710 + snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x00);
7711 +}
7712 +
7713 +
7714 +/* machine stream operations */
7715 +static struct snd_soc_ops snd_rpi_hifiberry_dacplusadcpro_ops = {
7716 + .hw_params = snd_rpi_hifiberry_dacplusadcpro_hw_params,
7717 + .startup = snd_rpi_hifiberry_dacplusadcpro_startup,
7718 + .shutdown = snd_rpi_hifiberry_dacplusadcpro_shutdown,
7719 +};
7720 +
7721 +SND_SOC_DAILINK_DEFS(hifi,
7722 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
7723 + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi"),
7724 + COMP_CODEC("pcm186x.1-004a", "pcm1863-aif")),
7725 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
7726 +
7727 +static struct snd_soc_dai_link snd_rpi_hifiberry_dacplusadcpro_dai[] = {
7728 +{
7729 + .name = "HiFiBerry DAC+ADC PRO",
7730 + .stream_name = "HiFiBerry DAC+ADC PRO HiFi",
7731 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
7732 + SND_SOC_DAIFMT_CBS_CFS,
7733 + .ops = &snd_rpi_hifiberry_dacplusadcpro_ops,
7734 + .init = snd_rpi_hifiberry_dacplusadcpro_init,
7735 + SND_SOC_DAILINK_REG(hifi),
7736 +},
7737 +};
7738 +
7739 +/* audio machine driver */
7740 +static struct snd_soc_card snd_rpi_hifiberry_dacplusadcpro = {
7741 + .name = "snd_rpi_hifiberry_dacplusadcpro",
7742 + .driver_name = "HifiberryDacpAdcPro",
7743 + .owner = THIS_MODULE,
7744 + .dai_link = snd_rpi_hifiberry_dacplusadcpro_dai,
7745 + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplusadcpro_dai),
7746 +};
7747 +
7748 +static int snd_rpi_hifiberry_dacplusadcpro_probe(struct platform_device *pdev)
7749 +{
7750 + int ret = 0, i = 0;
7751 + struct snd_soc_card *card = &snd_rpi_hifiberry_dacplusadcpro;
7752 +
7753 + snd_rpi_hifiberry_dacplusadcpro.dev = &pdev->dev;
7754 + if (pdev->dev.of_node) {
7755 + struct device_node *i2s_node;
7756 + struct snd_soc_dai_link *dai;
7757 +
7758 + dai = &snd_rpi_hifiberry_dacplusadcpro_dai[0];
7759 + i2s_node = of_parse_phandle(pdev->dev.of_node,
7760 + "i2s-controller", 0);
7761 + if (i2s_node) {
7762 + for (i = 0; i < card->num_links; i++) {
7763 + dai->cpus->dai_name = NULL;
7764 + dai->cpus->of_node = i2s_node;
7765 + dai->platforms->name = NULL;
7766 + dai->platforms->of_node = i2s_node;
7767 + }
7768 + }
7769 + }
7770 + digital_gain_0db_limit = !of_property_read_bool(
7771 + pdev->dev.of_node, "hifiberry-dacplusadcpro,24db_digital_gain");
7772 + slave = of_property_read_bool(pdev->dev.of_node,
7773 + "hifiberry-dacplusadcpro,slave");
7774 + leds_off = of_property_read_bool(pdev->dev.of_node,
7775 + "hifiberry-dacplusadcpro,leds_off");
7776 + ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplusadcpro);
7777 + if (ret && ret != -EPROBE_DEFER)
7778 + dev_err(&pdev->dev,
7779 + "snd_soc_register_card() failed: %d\n", ret);
7780 +
7781 + return ret;
7782 +}
7783 +
7784 +static const struct of_device_id snd_rpi_hifiberry_dacplusadcpro_of_match[] = {
7785 + { .compatible = "hifiberry,hifiberry-dacplusadcpro", },
7786 + {},
7787 +};
7788 +
7789 +MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplusadcpro_of_match);
7790 +
7791 +static struct platform_driver snd_rpi_hifiberry_dacplusadcpro_driver = {
7792 + .driver = {
7793 + .name = "snd-rpi-hifiberry-dacplusadcpro",
7794 + .owner = THIS_MODULE,
7795 + .of_match_table = snd_rpi_hifiberry_dacplusadcpro_of_match,
7796 + },
7797 + .probe = snd_rpi_hifiberry_dacplusadcpro_probe,
7798 +};
7799 +
7800 +module_platform_driver(snd_rpi_hifiberry_dacplusadcpro_driver);
7801 +
7802 +MODULE_AUTHOR("Joerg Schambacher <joerg@i2audio.com>");
7803 +MODULE_AUTHOR("Daniel Matuschek <daniel@hifiberry.com>");
7804 +MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ADC");
7805 +MODULE_LICENSE("GPL v2");
7806 --- /dev/null
7807 +++ b/sound/soc/bcm/hifiberry_dacplusdsp.c
7808 @@ -0,0 +1,90 @@
7809 +// SPDX-License-Identifier: GPL-2.0
7810 +/*
7811 + * ASoC Driver for HiFiBerry DAC + DSP
7812 + *
7813 + * Author: Joerg Schambacher <joscha@schambacher.com>
7814 + * Copyright 2018
7815 + *
7816 + * This program is free software; you can redistribute it and/or
7817 + * modify it under the terms of the GNU General Public License
7818 + * version 2 as published by the Free Software Foundation.
7819 + *
7820 + * This program is distributed in the hope that it will be useful, but
7821 + * WITHOUT ANY WARRANTY; without even the implied warranty of
7822 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
7823 + * General Public License for more details.
7824 + */
7825 +
7826 +#include <linux/init.h>
7827 +#include <linux/module.h>
7828 +#include <linux/of.h>
7829 +#include <linux/platform_device.h>
7830 +#include <sound/soc.h>
7831 +
7832 +static struct snd_soc_component_driver dacplusdsp_component_driver;
7833 +
7834 +static struct snd_soc_dai_driver dacplusdsp_dai = {
7835 + .name = "dacplusdsp-hifi",
7836 + .capture = {
7837 + .stream_name = "DAC+DSP Capture",
7838 + .channels_min = 2,
7839 + .channels_max = 2,
7840 + .rates = SNDRV_PCM_RATE_CONTINUOUS,
7841 + .formats = SNDRV_PCM_FMTBIT_S16_LE |
7842 + SNDRV_PCM_FMTBIT_S24_LE |
7843 + SNDRV_PCM_FMTBIT_S32_LE,
7844 + },
7845 + .playback = {
7846 + .stream_name = "DACP+DSP Playback",
7847 + .channels_min = 2,
7848 + .channels_max = 2,
7849 + .rates = SNDRV_PCM_RATE_CONTINUOUS,
7850 + .formats = SNDRV_PCM_FMTBIT_S16_LE |
7851 + SNDRV_PCM_FMTBIT_S24_LE |
7852 + SNDRV_PCM_FMTBIT_S32_LE,
7853 + },
7854 + .symmetric_rates = 1};
7855 +
7856 +#ifdef CONFIG_OF
7857 +static const struct of_device_id dacplusdsp_ids[] = {
7858 + {
7859 + .compatible = "hifiberry,dacplusdsp",
7860 + },
7861 + {} };
7862 +MODULE_DEVICE_TABLE(of, dacplusdsp_ids);
7863 +#endif
7864 +
7865 +static int dacplusdsp_platform_probe(struct platform_device *pdev)
7866 +{
7867 + int ret;
7868 +
7869 + ret = snd_soc_register_component(&pdev->dev,
7870 + &dacplusdsp_component_driver, &dacplusdsp_dai, 1);
7871 + if (ret) {
7872 + pr_alert("snd_soc_register_component failed\n");
7873 + return ret;
7874 + }
7875 +
7876 + return 0;
7877 +}
7878 +
7879 +static int dacplusdsp_platform_remove(struct platform_device *pdev)
7880 +{
7881 + snd_soc_unregister_component(&pdev->dev);
7882 + return 0;
7883 +}
7884 +
7885 +static struct platform_driver dacplusdsp_driver = {
7886 + .driver = {
7887 + .name = "hifiberry-dacplusdsp-codec",
7888 + .of_match_table = of_match_ptr(dacplusdsp_ids),
7889 + },
7890 + .probe = dacplusdsp_platform_probe,
7891 + .remove = dacplusdsp_platform_remove,
7892 +};
7893 +
7894 +module_platform_driver(dacplusdsp_driver);
7895 +
7896 +MODULE_AUTHOR("Joerg Schambacher <joerg@i2audio.com>");
7897 +MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+DSP");
7898 +MODULE_LICENSE("GPL v2");
7899 --- /dev/null
7900 +++ b/sound/soc/bcm/hifiberry_dacplushd.c
7901 @@ -0,0 +1,238 @@
7902 +// SPDX-License-Identifier: GPL-2.0
7903 +/*
7904 + * ASoC Driver for HiFiBerry DAC+ HD
7905 + *
7906 + * Author: Joerg Schambacher, i2Audio GmbH for HiFiBerry
7907 + * Copyright 2020
7908 + *
7909 + * This program is free software; you can redistribute it and/or
7910 + * modify it under the terms of the GNU General Public License
7911 + * version 2 as published by the Free Software Foundation.
7912 + *
7913 + * This program is distributed in the hope that it will be useful, but
7914 + * WITHOUT ANY WARRANTY; without even the implied warranty of
7915 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
7916 + * General Public License for more details.
7917 + */
7918 +
7919 +#include <linux/module.h>
7920 +#include <linux/platform_device.h>
7921 +#include <linux/kernel.h>
7922 +#include <linux/delay.h>
7923 +#include <linux/module.h>
7924 +#include <linux/of.h>
7925 +#include <linux/delay.h>
7926 +#include <linux/gpio.h>
7927 +#include <linux/gpio/consumer.h>
7928 +#include <sound/core.h>
7929 +#include <sound/pcm.h>
7930 +#include <sound/pcm_params.h>
7931 +#include <sound/soc.h>
7932 +#include <linux/i2c.h>
7933 +#include <linux/clk.h>
7934 +
7935 +#include "../codecs/pcm179x.h"
7936 +
7937 +#define DEFAULT_RATE 44100
7938 +
7939 +struct brd_drv_data {
7940 + struct regmap *regmap;
7941 + struct clk *sclk;
7942 +};
7943 +
7944 +static struct brd_drv_data drvdata;
7945 +static struct gpio_desc *reset_gpio;
7946 +static const unsigned int hb_dacplushd_rates[] = {
7947 + 192000, 96000, 48000, 176400, 88200, 44100,
7948 +};
7949 +
7950 +static struct snd_pcm_hw_constraint_list hb_dacplushd_constraints = {
7951 + .list = hb_dacplushd_rates,
7952 + .count = ARRAY_SIZE(hb_dacplushd_rates),
7953 +};
7954 +
7955 +static int snd_rpi_hb_dacplushd_startup(struct snd_pcm_substream *substream)
7956 +{
7957 + /* constraints for standard sample rates */
7958 + snd_pcm_hw_constraint_list(substream->runtime, 0,
7959 + SNDRV_PCM_HW_PARAM_RATE,
7960 + &hb_dacplushd_constraints);
7961 + return 0;
7962 +}
7963 +
7964 +static void snd_rpi_hifiberry_dacplushd_set_sclk(
7965 + struct snd_soc_component *component,
7966 + int sample_rate)
7967 +{
7968 + if (!IS_ERR(drvdata.sclk))
7969 + clk_set_rate(drvdata.sclk, sample_rate);
7970 +}
7971 +
7972 +static int snd_rpi_hifiberry_dacplushd_init(struct snd_soc_pcm_runtime *rtd)
7973 +{
7974 + struct snd_soc_dai_link *dai = rtd->dai_link;
7975 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
7976 +
7977 + dai->name = "HiFiBerry DAC+ HD";
7978 + dai->stream_name = "HiFiBerry DAC+ HD HiFi";
7979 + dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
7980 + | SND_SOC_DAIFMT_CBM_CFM;
7981 +
7982 + /* allow only fixed 32 clock counts per channel */
7983 + snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2);
7984 +
7985 + return 0;
7986 +}
7987 +
7988 +static int snd_rpi_hifiberry_dacplushd_hw_params(
7989 + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
7990 +{
7991 + int ret = 0;
7992 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
7993 +
7994 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
7995 +
7996 + snd_rpi_hifiberry_dacplushd_set_sclk(component, params_rate(params));
7997 + return ret;
7998 +}
7999 +
8000 +/* machine stream operations */
8001 +static struct snd_soc_ops snd_rpi_hifiberry_dacplushd_ops = {
8002 + .startup = snd_rpi_hb_dacplushd_startup,
8003 + .hw_params = snd_rpi_hifiberry_dacplushd_hw_params,
8004 +};
8005 +
8006 +SND_SOC_DAILINK_DEFS(hifi,
8007 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
8008 + DAILINK_COMP_ARRAY(COMP_CODEC("pcm179x.1-004c", "pcm179x-hifi")),
8009 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
8010 +
8011 +
8012 +static struct snd_soc_dai_link snd_rpi_hifiberry_dacplushd_dai[] = {
8013 +{
8014 + .name = "HiFiBerry DAC+ HD",
8015 + .stream_name = "HiFiBerry DAC+ HD HiFi",
8016 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
8017 + SND_SOC_DAIFMT_CBS_CFS,
8018 + .ops = &snd_rpi_hifiberry_dacplushd_ops,
8019 + .init = snd_rpi_hifiberry_dacplushd_init,
8020 + SND_SOC_DAILINK_REG(hifi),
8021 +},
8022 +};
8023 +
8024 +/* audio machine driver */
8025 +static struct snd_soc_card snd_rpi_hifiberry_dacplushd = {
8026 + .name = "snd_rpi_hifiberry_dacplushd",
8027 + .driver_name = "HifiberryDacplusHD",
8028 + .owner = THIS_MODULE,
8029 + .dai_link = snd_rpi_hifiberry_dacplushd_dai,
8030 + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplushd_dai),
8031 +};
8032 +
8033 +static int snd_rpi_hifiberry_dacplushd_probe(struct platform_device *pdev)
8034 +{
8035 + int ret = 0;
8036 + static int dac_reset_done;
8037 + struct device *dev = &pdev->dev;
8038 + struct device_node *dev_node = dev->of_node;
8039 +
8040 + snd_rpi_hifiberry_dacplushd.dev = &pdev->dev;
8041 +
8042 + /* get GPIO and release DAC from RESET */
8043 + if (!dac_reset_done) {
8044 + reset_gpio = gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW);
8045 + if (IS_ERR(reset_gpio)) {
8046 + dev_err(&pdev->dev, "gpiod_get() failed\n");
8047 + return -EINVAL;
8048 + }
8049 + dac_reset_done = 1;
8050 + }
8051 + if (!IS_ERR(reset_gpio))
8052 + gpiod_set_value(reset_gpio, 0);
8053 + msleep(1);
8054 + if (!IS_ERR(reset_gpio))
8055 + gpiod_set_value(reset_gpio, 1);
8056 + msleep(1);
8057 + if (!IS_ERR(reset_gpio))
8058 + gpiod_set_value(reset_gpio, 0);
8059 +
8060 + if (pdev->dev.of_node) {
8061 + struct device_node *i2s_node;
8062 + struct snd_soc_dai_link *dai;
8063 +
8064 + dai = &snd_rpi_hifiberry_dacplushd_dai[0];
8065 + i2s_node = of_parse_phandle(pdev->dev.of_node,
8066 + "i2s-controller", 0);
8067 +
8068 + if (i2s_node) {
8069 + dai->cpus->of_node = i2s_node;
8070 + dai->platforms->of_node = i2s_node;
8071 + dai->cpus->dai_name = NULL;
8072 + dai->platforms->name = NULL;
8073 + } else {
8074 + return -EPROBE_DEFER;
8075 + }
8076 +
8077 + }
8078 +
8079 + ret = devm_snd_soc_register_card(&pdev->dev,
8080 + &snd_rpi_hifiberry_dacplushd);
8081 + if (ret && ret != -EPROBE_DEFER) {
8082 + dev_err(&pdev->dev,
8083 + "snd_soc_register_card() failed: %d\n", ret);
8084 + return ret;
8085 + }
8086 + if (ret == -EPROBE_DEFER)
8087 + return ret;
8088 +
8089 + dev_set_drvdata(dev, &drvdata);
8090 + if (dev_node == NULL) {
8091 + dev_err(&pdev->dev, "Device tree node not found\n");
8092 + return -ENODEV;
8093 + }
8094 +
8095 + drvdata.sclk = devm_clk_get(dev, NULL);
8096 + if (IS_ERR(drvdata.sclk)) {
8097 + drvdata.sclk = ERR_PTR(-ENOENT);
8098 + return -ENODEV;
8099 + }
8100 +
8101 + clk_set_rate(drvdata.sclk, DEFAULT_RATE);
8102 +
8103 + return ret;
8104 +}
8105 +
8106 +static int snd_rpi_hifiberry_dacplushd_remove(struct platform_device *pdev)
8107 +{
8108 + if (IS_ERR(reset_gpio))
8109 + return -EINVAL;
8110 +
8111 + /* put DAC into RESET and release GPIO */
8112 + gpiod_set_value(reset_gpio, 0);
8113 + gpiod_put(reset_gpio);
8114 +
8115 + return 0;
8116 +}
8117 +
8118 +static const struct of_device_id snd_rpi_hifiberry_dacplushd_of_match[] = {
8119 + { .compatible = "hifiberry,hifiberry-dacplushd", },
8120 + {},
8121 +};
8122 +
8123 +MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplushd_of_match);
8124 +
8125 +static struct platform_driver snd_rpi_hifiberry_dacplushd_driver = {
8126 + .driver = {
8127 + .name = "snd-rpi-hifiberry-dacplushd",
8128 + .owner = THIS_MODULE,
8129 + .of_match_table = snd_rpi_hifiberry_dacplushd_of_match,
8130 + },
8131 + .probe = snd_rpi_hifiberry_dacplushd_probe,
8132 + .remove = snd_rpi_hifiberry_dacplushd_remove,
8133 +};
8134 +
8135 +module_platform_driver(snd_rpi_hifiberry_dacplushd_driver);
8136 +
8137 +MODULE_AUTHOR("Joerg Schambacher <joerg@i2audio.com>");
8138 +MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ HD");
8139 +MODULE_LICENSE("GPL v2");
8140 --- /dev/null
8141 +++ b/sound/soc/bcm/i-sabre-q2m.c
8142 @@ -0,0 +1,158 @@
8143 +/*
8144 + * ASoC Driver for I-Sabre Q2M
8145 + *
8146 + * Author: Satoru Kawase
8147 + * Modified by: Xiao Qingyong
8148 + * Update kernel v4.18+ by : Audiophonics
8149 + * Copyright 2018 Audiophonics
8150 + *
8151 + * This program is free software; you can redistribute it and/or
8152 + * modify it under the terms of the GNU General Public License
8153 + * version 2 as published by the Free Software Foundation.
8154 + *
8155 + * This program is distributed in the hope that it will be useful, but
8156 + * WITHOUT ANY WARRANTY; without even the implied warranty of
8157 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8158 + * General Public License for more details.
8159 + */
8160 +
8161 +#include <linux/kernel.h>
8162 +#include <linux/init.h>
8163 +#include <linux/module.h>
8164 +#include <linux/delay.h>
8165 +#include <linux/fs.h>
8166 +#include <asm/uaccess.h>
8167 +#include <sound/core.h>
8168 +#include <sound/soc.h>
8169 +#include <sound/pcm.h>
8170 +#include <sound/pcm_params.h>
8171 +
8172 +#include "../codecs/i-sabre-codec.h"
8173 +
8174 +
8175 +static int snd_rpi_i_sabre_q2m_init(struct snd_soc_pcm_runtime *rtd)
8176 +{
8177 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
8178 + unsigned int value;
8179 +
8180 + /* Device ID */
8181 + value = snd_soc_component_read(component, ISABRECODEC_REG_01);
8182 + dev_info(component->card->dev, "Audiophonics Device ID : %02X\n", value);
8183 +
8184 + /* API revision */
8185 + value = snd_soc_component_read(component, ISABRECODEC_REG_02);
8186 + dev_info(component->card->dev, "Audiophonics API revision : %02X\n", value);
8187 +
8188 + return 0;
8189 +}
8190 +
8191 +static int snd_rpi_i_sabre_q2m_hw_params(
8192 + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
8193 +{
8194 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
8195 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
8196 + int bclk_ratio;
8197 +
8198 + bclk_ratio = snd_pcm_format_physical_width(
8199 + params_format(params)) * params_channels(params);
8200 + return snd_soc_dai_set_bclk_ratio(cpu_dai, bclk_ratio);
8201 +}
8202 +
8203 +/* machine stream operations */
8204 +static struct snd_soc_ops snd_rpi_i_sabre_q2m_ops = {
8205 + .hw_params = snd_rpi_i_sabre_q2m_hw_params,
8206 +};
8207 +
8208 +SND_SOC_DAILINK_DEFS(rpi_i_sabre_q2m,
8209 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
8210 + DAILINK_COMP_ARRAY(COMP_CODEC("i-sabre-codec-i2c.1-0048", "i-sabre-codec-dai")),
8211 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
8212 +
8213 +static struct snd_soc_dai_link snd_rpi_i_sabre_q2m_dai[] = {
8214 + {
8215 + .name = "I-Sabre Q2M",
8216 + .stream_name = "I-Sabre Q2M DAC",
8217 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
8218 + | SND_SOC_DAIFMT_CBS_CFS,
8219 + .init = snd_rpi_i_sabre_q2m_init,
8220 + .ops = &snd_rpi_i_sabre_q2m_ops,
8221 + SND_SOC_DAILINK_REG(rpi_i_sabre_q2m),
8222 + }
8223 +};
8224 +
8225 +/* audio machine driver */
8226 +static struct snd_soc_card snd_rpi_i_sabre_q2m = {
8227 + .name = "I-Sabre Q2M DAC",
8228 + .owner = THIS_MODULE,
8229 + .dai_link = snd_rpi_i_sabre_q2m_dai,
8230 + .num_links = ARRAY_SIZE(snd_rpi_i_sabre_q2m_dai)
8231 +};
8232 +
8233 +
8234 +static int snd_rpi_i_sabre_q2m_probe(struct platform_device *pdev)
8235 +{
8236 + int ret = 0;
8237 +
8238 + snd_rpi_i_sabre_q2m.dev = &pdev->dev;
8239 + if (pdev->dev.of_node) {
8240 + struct device_node *i2s_node;
8241 + struct snd_soc_dai_link *dai;
8242 +
8243 + dai = &snd_rpi_i_sabre_q2m_dai[0];
8244 + i2s_node = of_parse_phandle(pdev->dev.of_node,
8245 + "i2s-controller", 0);
8246 + if (i2s_node) {
8247 + dai->cpus->dai_name = NULL;
8248 + dai->cpus->of_node = i2s_node;
8249 + dai->platforms->name = NULL;
8250 + dai->platforms->of_node = i2s_node;
8251 + } else {
8252 + dev_err(&pdev->dev,
8253 + "Property 'i2s-controller' missing or invalid\n");
8254 + return (-EINVAL);
8255 + }
8256 +
8257 + dai->name = "I-Sabre Q2M";
8258 + dai->stream_name = "I-Sabre Q2M DAC";
8259 + dai->dai_fmt = SND_SOC_DAIFMT_I2S
8260 + | SND_SOC_DAIFMT_NB_NF
8261 + | SND_SOC_DAIFMT_CBS_CFS;
8262 + }
8263 +
8264 + /* Wait for registering codec driver */
8265 + mdelay(50);
8266 +
8267 + ret = snd_soc_register_card(&snd_rpi_i_sabre_q2m);
8268 + if (ret) {
8269 + dev_err(&pdev->dev,
8270 + "snd_soc_register_card() failed: %d\n", ret);
8271 + }
8272 +
8273 + return ret;
8274 +}
8275 +
8276 +static int snd_rpi_i_sabre_q2m_remove(struct platform_device *pdev)
8277 +{
8278 + return snd_soc_unregister_card(&snd_rpi_i_sabre_q2m);
8279 +}
8280 +
8281 +static const struct of_device_id snd_rpi_i_sabre_q2m_of_match[] = {
8282 + { .compatible = "audiophonics,i-sabre-q2m", },
8283 + {}
8284 +};
8285 +MODULE_DEVICE_TABLE(of, snd_rpi_i_sabre_q2m_of_match);
8286 +
8287 +static struct platform_driver snd_rpi_i_sabre_q2m_driver = {
8288 + .driver = {
8289 + .name = "snd-rpi-i-sabre-q2m",
8290 + .owner = THIS_MODULE,
8291 + .of_match_table = snd_rpi_i_sabre_q2m_of_match,
8292 + },
8293 + .probe = snd_rpi_i_sabre_q2m_probe,
8294 + .remove = snd_rpi_i_sabre_q2m_remove,
8295 +};
8296 +module_platform_driver(snd_rpi_i_sabre_q2m_driver);
8297 +
8298 +MODULE_DESCRIPTION("ASoC Driver for I-Sabre Q2M");
8299 +MODULE_AUTHOR("Audiophonics <http://www.audiophonics.fr>");
8300 +MODULE_LICENSE("GPL");
8301 --- /dev/null
8302 +++ b/sound/soc/bcm/iqaudio-codec.c
8303 @@ -0,0 +1,274 @@
8304 +/*
8305 + * ASoC Driver for IQaudIO Raspberry Pi Codec board
8306 + *
8307 + * Author: Gordon Garrity <gordon@iqaudio.com>
8308 + * (C) Copyright IQaudio Limited, 2017-2019
8309 + *
8310 + * This program is free software; you can redistribute it and/or
8311 + * modify it under the terms of the GNU General Public License
8312 + * version 2 as published by the Free Software Foundation.
8313 + *
8314 + * This program is distributed in the hope that it will be useful, but
8315 + * WITHOUT ANY WARRANTY; without even the implied warranty of
8316 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8317 + * General Public License for more details.
8318 + */
8319 +
8320 +#include <linux/module.h>
8321 +#include <linux/gpio/consumer.h>
8322 +#include <linux/platform_device.h>
8323 +
8324 +#include <sound/core.h>
8325 +#include <sound/pcm.h>
8326 +#include <sound/pcm_params.h>
8327 +#include <sound/soc.h>
8328 +#include <sound/jack.h>
8329 +
8330 +#include <linux/acpi.h>
8331 +#include <linux/slab.h>
8332 +#include "../codecs/da7213.h"
8333 +
8334 +static int pll_out = DA7213_PLL_FREQ_OUT_90316800;
8335 +
8336 +static int snd_rpi_iqaudio_pll_control(struct snd_soc_dapm_widget *w,
8337 + struct snd_kcontrol *k, int event)
8338 +{
8339 + int ret = 0;
8340 + struct snd_soc_dapm_context *dapm = w->dapm;
8341 + struct snd_soc_card *card = dapm->card;
8342 + struct snd_soc_pcm_runtime *rtd =
8343 + snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
8344 + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
8345 +
8346 + if (SND_SOC_DAPM_EVENT_OFF(event)) {
8347 + ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_MCLK, 0,
8348 + 0);
8349 + if (ret)
8350 + dev_err(card->dev, "Failed to bypass PLL: %d\n", ret);
8351 + /* Allow PLL time to bypass */
8352 + msleep(100);
8353 + } else if (SND_SOC_DAPM_EVENT_ON(event)) {
8354 + ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_PLL, 0,
8355 + pll_out);
8356 + if (ret)
8357 + dev_err(card->dev, "Failed to enable PLL: %d\n", ret);
8358 + /* Allow PLL time to lock */
8359 + msleep(100);
8360 + }
8361 +
8362 + return ret;
8363 +}
8364 +
8365 +static int snd_rpi_iqaudio_post_dapm_event(struct snd_soc_dapm_widget *w,
8366 + struct snd_kcontrol *kcontrol,
8367 + int event)
8368 +{
8369 + switch (event) {
8370 + case SND_SOC_DAPM_POST_PMU:
8371 + /* Delay for mic bias ramp */
8372 + msleep(1000);
8373 + break;
8374 + default:
8375 + break;
8376 + }
8377 +
8378 + return 0;
8379 +}
8380 +
8381 +static const struct snd_kcontrol_new dapm_controls[] = {
8382 + SOC_DAPM_PIN_SWITCH("HP Jack"),
8383 + SOC_DAPM_PIN_SWITCH("MIC Jack"),
8384 + SOC_DAPM_PIN_SWITCH("Onboard MIC"),
8385 + SOC_DAPM_PIN_SWITCH("AUX Jack"),
8386 +};
8387 +
8388 +static const struct snd_soc_dapm_widget dapm_widgets[] = {
8389 + SND_SOC_DAPM_HP("HP Jack", NULL),
8390 + SND_SOC_DAPM_MIC("MIC Jack", NULL),
8391 + SND_SOC_DAPM_MIC("Onboard MIC", NULL),
8392 + SND_SOC_DAPM_LINE("AUX Jack", NULL),
8393 + SND_SOC_DAPM_SUPPLY("PLL Control", SND_SOC_NOPM, 0, 0,
8394 + snd_rpi_iqaudio_pll_control,
8395 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
8396 + SND_SOC_DAPM_POST("Post Power Up Event", snd_rpi_iqaudio_post_dapm_event),
8397 +};
8398 +
8399 +static const struct snd_soc_dapm_route audio_map[] = {
8400 + {"HP Jack", NULL, "HPL"},
8401 + {"HP Jack", NULL, "HPR"},
8402 + {"HP Jack", NULL, "PLL Control"},
8403 +
8404 + {"AUXR", NULL, "AUX Jack"},
8405 + {"AUXL", NULL, "AUX Jack"},
8406 + {"AUX Jack", NULL, "PLL Control"},
8407 +
8408 + /* Assume Mic1 is linked to Headset and Mic2 to on-board mic */
8409 + {"MIC1", NULL, "MIC Jack"},
8410 + {"MIC Jack", NULL, "PLL Control"},
8411 + {"MIC2", NULL, "Onboard MIC"},
8412 + {"Onboard MIC", NULL, "PLL Control"},
8413 +};
8414 +
8415 +/* machine stream operations */
8416 +
8417 +static int snd_rpi_iqaudio_codec_init(struct snd_soc_pcm_runtime *rtd)
8418 +{
8419 + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
8420 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
8421 + int ret;
8422 +
8423 + /*
8424 + * Disable AUX Jack Pin by default to prevent PLL being enabled at
8425 + * startup. This avoids holding the PLL to a fixed SR config for
8426 + * subsequent streams.
8427 + *
8428 + * This pin can still be enabled later, as required by user-space.
8429 + */
8430 + snd_soc_dapm_disable_pin(&rtd->card->dapm, "AUX Jack");
8431 + snd_soc_dapm_sync(&rtd->card->dapm);
8432 +
8433 + /* Set bclk ratio to align with codec's BCLK rate */
8434 + ret = snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
8435 + if (ret) {
8436 + dev_err(rtd->dev, "Failed to set CPU BLCK ratio\n");
8437 + return ret;
8438 + }
8439 +
8440 + /* Set MCLK frequency to codec, onboard 11.2896MHz clock */
8441 + return snd_soc_dai_set_sysclk(codec_dai, DA7213_CLKSRC_MCLK, 11289600,
8442 + SND_SOC_CLOCK_OUT);
8443 +}
8444 +
8445 +static int snd_rpi_iqaudio_codec_hw_params(struct snd_pcm_substream *substream,
8446 + struct snd_pcm_hw_params *params)
8447 +{
8448 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
8449 + unsigned int samplerate = params_rate(params);
8450 +
8451 + switch (samplerate) {
8452 + case 8000:
8453 + case 16000:
8454 + case 32000:
8455 + case 48000:
8456 + case 96000:
8457 + pll_out = DA7213_PLL_FREQ_OUT_98304000;
8458 + return 0;
8459 + case 44100:
8460 + case 88200:
8461 + pll_out = DA7213_PLL_FREQ_OUT_90316800;
8462 + return 0;
8463 + default:
8464 + dev_err(rtd->dev,"Unsupported samplerate %d\n", samplerate);
8465 + return -EINVAL;
8466 + }
8467 +}
8468 +
8469 +static const struct snd_soc_ops snd_rpi_iqaudio_codec_ops = {
8470 + .hw_params = snd_rpi_iqaudio_codec_hw_params,
8471 +};
8472 +
8473 +SND_SOC_DAILINK_DEFS(rpi_iqaudio,
8474 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
8475 + DAILINK_COMP_ARRAY(COMP_CODEC("da7213.1-001a", "da7213-hifi")),
8476 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2835-i2s.0")));
8477 +
8478 +static struct snd_soc_dai_link snd_rpi_iqaudio_codec_dai[] = {
8479 +{
8480 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
8481 + SND_SOC_DAIFMT_CBM_CFM,
8482 + .init = snd_rpi_iqaudio_codec_init,
8483 + .ops = &snd_rpi_iqaudio_codec_ops,
8484 + .symmetric_rates = 1,
8485 + .symmetric_channels = 1,
8486 + .symmetric_samplebits = 1,
8487 + SND_SOC_DAILINK_REG(rpi_iqaudio),
8488 +},
8489 +};
8490 +
8491 +/* audio machine driver */
8492 +static struct snd_soc_card snd_rpi_iqaudio_codec = {
8493 + .owner = THIS_MODULE,
8494 + .dai_link = snd_rpi_iqaudio_codec_dai,
8495 + .num_links = ARRAY_SIZE(snd_rpi_iqaudio_codec_dai),
8496 + .controls = dapm_controls,
8497 + .num_controls = ARRAY_SIZE(dapm_controls),
8498 + .dapm_widgets = dapm_widgets,
8499 + .num_dapm_widgets = ARRAY_SIZE(dapm_widgets),
8500 + .dapm_routes = audio_map,
8501 + .num_dapm_routes = ARRAY_SIZE(audio_map),
8502 +};
8503 +
8504 +static int snd_rpi_iqaudio_codec_probe(struct platform_device *pdev)
8505 +{
8506 + int ret = 0;
8507 +
8508 + snd_rpi_iqaudio_codec.dev = &pdev->dev;
8509 +
8510 + if (pdev->dev.of_node) {
8511 + struct device_node *i2s_node;
8512 + struct snd_soc_card *card = &snd_rpi_iqaudio_codec;
8513 + struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_codec_dai[0];
8514 +
8515 + i2s_node = of_parse_phandle(pdev->dev.of_node,
8516 + "i2s-controller", 0);
8517 + if (i2s_node) {
8518 + dai->cpus->dai_name = NULL;
8519 + dai->cpus->of_node = i2s_node;
8520 + dai->platforms->name = NULL;
8521 + dai->platforms->of_node = i2s_node;
8522 + }
8523 +
8524 + if (of_property_read_string(pdev->dev.of_node, "card_name",
8525 + &card->name))
8526 + card->name = "IQaudIOCODEC";
8527 +
8528 + if (of_property_read_string(pdev->dev.of_node, "dai_name",
8529 + &dai->name))
8530 + dai->name = "IQaudIO CODEC";
8531 +
8532 + if (of_property_read_string(pdev->dev.of_node,
8533 + "dai_stream_name", &dai->stream_name))
8534 + dai->stream_name = "IQaudIO CODEC HiFi v1.2";
8535 +
8536 + }
8537 +
8538 + ret = snd_soc_register_card(&snd_rpi_iqaudio_codec);
8539 + if (ret) {
8540 + if (ret != -EPROBE_DEFER)
8541 + dev_err(&pdev->dev,
8542 + "snd_soc_register_card() failed: %d\n", ret);
8543 + return ret;
8544 + }
8545 +
8546 + return 0;
8547 +}
8548 +
8549 +static int snd_rpi_iqaudio_codec_remove(struct platform_device *pdev)
8550 +{
8551 + return snd_soc_unregister_card(&snd_rpi_iqaudio_codec);
8552 +}
8553 +
8554 +static const struct of_device_id iqaudio_of_match[] = {
8555 + { .compatible = "iqaudio,iqaudio-codec", },
8556 + {},
8557 +};
8558 +
8559 +MODULE_DEVICE_TABLE(of, iqaudio_of_match);
8560 +
8561 +static struct platform_driver snd_rpi_iqaudio_codec_driver = {
8562 + .driver = {
8563 + .name = "snd-rpi-iqaudio-codec",
8564 + .owner = THIS_MODULE,
8565 + .of_match_table = iqaudio_of_match,
8566 + },
8567 + .probe = snd_rpi_iqaudio_codec_probe,
8568 + .remove = snd_rpi_iqaudio_codec_remove,
8569 +};
8570 +
8571 +
8572 +
8573 +module_platform_driver(snd_rpi_iqaudio_codec_driver);
8574 +
8575 +MODULE_AUTHOR("Gordon Garrity <gordon@iqaudio.com>");
8576 +MODULE_DESCRIPTION("ASoC Driver for IQaudIO CODEC");
8577 +MODULE_LICENSE("GPL v2");
8578 --- /dev/null
8579 +++ b/sound/soc/bcm/iqaudio-dac.c
8580 @@ -0,0 +1,223 @@
8581 +/*
8582 + * ASoC Driver for IQaudIO DAC
8583 + *
8584 + * Author: Florian Meier <florian.meier@koalo.de>
8585 + * Copyright 2013
8586 + *
8587 + * This program is free software; you can redistribute it and/or
8588 + * modify it under the terms of the GNU General Public License
8589 + * version 2 as published by the Free Software Foundation.
8590 + *
8591 + * This program is distributed in the hope that it will be useful, but
8592 + * WITHOUT ANY WARRANTY; without even the implied warranty of
8593 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8594 + * General Public License for more details.
8595 + */
8596 +
8597 +#include <linux/module.h>
8598 +#include <linux/gpio/consumer.h>
8599 +#include <linux/platform_device.h>
8600 +
8601 +#include <sound/core.h>
8602 +#include <sound/pcm.h>
8603 +#include <sound/pcm_params.h>
8604 +#include <sound/soc.h>
8605 +#include <sound/jack.h>
8606 +
8607 +static bool digital_gain_0db_limit = true;
8608 +
8609 +static struct gpio_desc *mute_gpio;
8610 +
8611 +static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd)
8612 +{
8613 + if (digital_gain_0db_limit)
8614 + {
8615 + int ret;
8616 + struct snd_soc_card *card = rtd->card;
8617 +
8618 + ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
8619 + if (ret < 0)
8620 + dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
8621 + }
8622 +
8623 + return 0;
8624 +}
8625 +
8626 +static void snd_rpi_iqaudio_gpio_mute(struct snd_soc_card *card)
8627 +{
8628 + if (mute_gpio) {
8629 + dev_info(card->dev, "%s: muting amp using GPIO22\n",
8630 + __func__);
8631 + gpiod_set_value_cansleep(mute_gpio, 0);
8632 + }
8633 +}
8634 +
8635 +static void snd_rpi_iqaudio_gpio_unmute(struct snd_soc_card *card)
8636 +{
8637 + if (mute_gpio) {
8638 + dev_info(card->dev, "%s: un-muting amp using GPIO22\n",
8639 + __func__);
8640 + gpiod_set_value_cansleep(mute_gpio, 1);
8641 + }
8642 +}
8643 +
8644 +static int snd_rpi_iqaudio_set_bias_level(struct snd_soc_card *card,
8645 + struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
8646 +{
8647 + struct snd_soc_pcm_runtime *rtd;
8648 + struct snd_soc_dai *codec_dai;
8649 +
8650 + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
8651 + codec_dai = asoc_rtd_to_codec(rtd, 0);
8652 +
8653 + if (dapm->dev != codec_dai->dev)
8654 + return 0;
8655 +
8656 + switch (level) {
8657 + case SND_SOC_BIAS_PREPARE:
8658 + if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
8659 + break;
8660 +
8661 + /* UNMUTE AMP */
8662 + snd_rpi_iqaudio_gpio_unmute(card);
8663 +
8664 + break;
8665 + case SND_SOC_BIAS_STANDBY:
8666 + if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
8667 + break;
8668 +
8669 + /* MUTE AMP */
8670 + snd_rpi_iqaudio_gpio_mute(card);
8671 +
8672 + break;
8673 + default:
8674 + break;
8675 + }
8676 +
8677 + return 0;
8678 +}
8679 +
8680 +SND_SOC_DAILINK_DEFS(hifi,
8681 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
8682 + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004c", "pcm512x-hifi")),
8683 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
8684 +
8685 +static struct snd_soc_dai_link snd_rpi_iqaudio_dac_dai[] = {
8686 +{
8687 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
8688 + SND_SOC_DAIFMT_CBS_CFS,
8689 + .init = snd_rpi_iqaudio_dac_init,
8690 + SND_SOC_DAILINK_REG(hifi),
8691 +},
8692 +};
8693 +
8694 +/* audio machine driver */
8695 +static struct snd_soc_card snd_rpi_iqaudio_dac = {
8696 + .owner = THIS_MODULE,
8697 + .dai_link = snd_rpi_iqaudio_dac_dai,
8698 + .num_links = ARRAY_SIZE(snd_rpi_iqaudio_dac_dai),
8699 +};
8700 +
8701 +static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev)
8702 +{
8703 + int ret = 0;
8704 + bool gpio_unmute = false;
8705 +
8706 + snd_rpi_iqaudio_dac.dev = &pdev->dev;
8707 +
8708 + if (pdev->dev.of_node) {
8709 + struct device_node *i2s_node;
8710 + struct snd_soc_card *card = &snd_rpi_iqaudio_dac;
8711 + struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_dac_dai[0];
8712 + bool auto_gpio_mute = false;
8713 +
8714 + i2s_node = of_parse_phandle(pdev->dev.of_node,
8715 + "i2s-controller", 0);
8716 + if (i2s_node) {
8717 + dai->cpus->dai_name = NULL;
8718 + dai->cpus->of_node = i2s_node;
8719 + dai->platforms->name = NULL;
8720 + dai->platforms->of_node = i2s_node;
8721 + }
8722 +
8723 + digital_gain_0db_limit = !of_property_read_bool(
8724 + pdev->dev.of_node, "iqaudio,24db_digital_gain");
8725 +
8726 + if (of_property_read_string(pdev->dev.of_node, "card_name",
8727 + &card->name))
8728 + card->name = "IQaudIODAC";
8729 +
8730 + if (of_property_read_string(pdev->dev.of_node, "dai_name",
8731 + &dai->name))
8732 + dai->name = "IQaudIO DAC";
8733 +
8734 + if (of_property_read_string(pdev->dev.of_node,
8735 + "dai_stream_name", &dai->stream_name))
8736 + dai->stream_name = "IQaudIO DAC HiFi";
8737 +
8738 + /* gpio_unmute - one time unmute amp using GPIO */
8739 + gpio_unmute = of_property_read_bool(pdev->dev.of_node,
8740 + "iqaudio-dac,unmute-amp");
8741 +
8742 + /* auto_gpio_mute - mute/unmute amp using GPIO */
8743 + auto_gpio_mute = of_property_read_bool(pdev->dev.of_node,
8744 + "iqaudio-dac,auto-mute-amp");
8745 +
8746 + if (auto_gpio_mute || gpio_unmute) {
8747 + mute_gpio = devm_gpiod_get_optional(&pdev->dev, "mute",
8748 + GPIOD_OUT_LOW);
8749 + if (IS_ERR(mute_gpio)) {
8750 + ret = PTR_ERR(mute_gpio);
8751 + dev_err(&pdev->dev,
8752 + "Failed to get mute gpio: %d\n", ret);
8753 + return ret;
8754 + }
8755 +
8756 + if (auto_gpio_mute && mute_gpio)
8757 + snd_rpi_iqaudio_dac.set_bias_level =
8758 + snd_rpi_iqaudio_set_bias_level;
8759 + }
8760 + }
8761 +
8762 + ret = snd_soc_register_card(&snd_rpi_iqaudio_dac);
8763 + if (ret) {
8764 + if (ret != -EPROBE_DEFER)
8765 + dev_err(&pdev->dev,
8766 + "snd_soc_register_card() failed: %d\n", ret);
8767 + return ret;
8768 + }
8769 +
8770 + if (gpio_unmute && mute_gpio)
8771 + snd_rpi_iqaudio_gpio_unmute(&snd_rpi_iqaudio_dac);
8772 +
8773 + return 0;
8774 +}
8775 +
8776 +static int snd_rpi_iqaudio_dac_remove(struct platform_device *pdev)
8777 +{
8778 + snd_rpi_iqaudio_gpio_mute(&snd_rpi_iqaudio_dac);
8779 +
8780 + return snd_soc_unregister_card(&snd_rpi_iqaudio_dac);
8781 +}
8782 +
8783 +static const struct of_device_id iqaudio_of_match[] = {
8784 + { .compatible = "iqaudio,iqaudio-dac", },
8785 + {},
8786 +};
8787 +MODULE_DEVICE_TABLE(of, iqaudio_of_match);
8788 +
8789 +static struct platform_driver snd_rpi_iqaudio_dac_driver = {
8790 + .driver = {
8791 + .name = "snd-rpi-iqaudio-dac",
8792 + .owner = THIS_MODULE,
8793 + .of_match_table = iqaudio_of_match,
8794 + },
8795 + .probe = snd_rpi_iqaudio_dac_probe,
8796 + .remove = snd_rpi_iqaudio_dac_remove,
8797 +};
8798 +
8799 +module_platform_driver(snd_rpi_iqaudio_dac_driver);
8800 +
8801 +MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
8802 +MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC");
8803 +MODULE_LICENSE("GPL v2");
8804 --- /dev/null
8805 +++ b/sound/soc/bcm/justboom-both.c
8806 @@ -0,0 +1,266 @@
8807 +// SPDX-License-Identifier: GPL-2.0
8808 +/*
8809 + * rpi--wm8804.c -- ALSA SoC Raspberry Pi soundcard.
8810 + *
8811 + * Authors: Johannes Krude <johannes@krude.de
8812 + *
8813 + * Driver for when connecting simultaneously justboom-digi and justboom-dac
8814 + *
8815 + * Based upon code from:
8816 + * justboom-digi.c
8817 + * by Milan Neskovic <info@justboom.co>
8818 + * justboom-dac.c
8819 + * by Milan Neskovic <info@justboom.co>
8820 + *
8821 + * This program is free software; you can redistribute it and/or
8822 + * modify it under the terms of the GNU General Public License
8823 + * version 2 as published by the Free Software Foundation.
8824 + *
8825 + * This program is distributed in the hope that it will be useful, but
8826 + * WITHOUT ANY WARRANTY; without even the implied warranty of
8827 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8828 + * General Public License for more details.
8829 + */
8830 +
8831 +#include <linux/module.h>
8832 +#include <linux/platform_device.h>
8833 +
8834 +#include <sound/core.h>
8835 +#include <sound/pcm.h>
8836 +#include <sound/pcm_params.h>
8837 +#include <sound/soc.h>
8838 +#include <sound/jack.h>
8839 +
8840 +#include "../codecs/wm8804.h"
8841 +#include "../codecs/pcm512x.h"
8842 +
8843 +
8844 +static bool digital_gain_0db_limit = true;
8845 +
8846 +static int snd_rpi_justboom_both_init(struct snd_soc_pcm_runtime *rtd)
8847 +{
8848 + struct snd_soc_component *digi = asoc_rtd_to_codec(rtd, 0)->component;
8849 + struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 1)->component;
8850 +
8851 + /* enable TX output */
8852 + snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x4, 0x0);
8853 +
8854 + snd_soc_component_update_bits(dac, PCM512x_GPIO_EN, 0x08, 0x08);
8855 + snd_soc_component_update_bits(dac, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02);
8856 + snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
8857 +
8858 + if (digital_gain_0db_limit) {
8859 + int ret;
8860 + struct snd_soc_card *card = rtd->card;
8861 +
8862 + ret = snd_soc_limit_volume(card, "Digital Playback Volume",
8863 + 207);
8864 + if (ret < 0)
8865 + dev_warn(card->dev, "Failed to set volume limit: %d\n",
8866 + ret);
8867 + }
8868 +
8869 + return 0;
8870 +}
8871 +
8872 +static int snd_rpi_justboom_both_hw_params(struct snd_pcm_substream *substream,
8873 + struct snd_pcm_hw_params *params)
8874 +{
8875 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
8876 + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
8877 + struct snd_soc_component *digi = asoc_rtd_to_codec(rtd, 0)->component;
8878 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
8879 +
8880 + int sysclk = 27000000; /* This is fixed on this board */
8881 +
8882 + long mclk_freq = 0;
8883 + int mclk_div = 1;
8884 + int sampling_freq = 1;
8885 +
8886 + int ret;
8887 +
8888 + int samplerate = params_rate(params);
8889 +
8890 + if (samplerate <= 96000) {
8891 + mclk_freq = samplerate*256;
8892 + mclk_div = WM8804_MCLKDIV_256FS;
8893 + } else {
8894 + mclk_freq = samplerate*128;
8895 + mclk_div = WM8804_MCLKDIV_128FS;
8896 + }
8897 +
8898 + switch (samplerate) {
8899 + case 32000:
8900 + sampling_freq = 0x03;
8901 + break;
8902 + case 44100:
8903 + sampling_freq = 0x00;
8904 + break;
8905 + case 48000:
8906 + sampling_freq = 0x02;
8907 + break;
8908 + case 88200:
8909 + sampling_freq = 0x08;
8910 + break;
8911 + case 96000:
8912 + sampling_freq = 0x0a;
8913 + break;
8914 + case 176400:
8915 + sampling_freq = 0x0c;
8916 + break;
8917 + case 192000:
8918 + sampling_freq = 0x0e;
8919 + break;
8920 + default:
8921 + dev_err(rtd->card->dev,
8922 + "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n",
8923 + samplerate);
8924 + }
8925 +
8926 + snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div);
8927 + snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq);
8928 +
8929 + ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL,
8930 + sysclk, SND_SOC_CLOCK_OUT);
8931 + if (ret < 0) {
8932 + dev_err(rtd->card->dev,
8933 + "Failed to set WM8804 SYSCLK: %d\n", ret);
8934 + return ret;
8935 + }
8936 +
8937 + /* Enable TX output */
8938 + snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x4, 0x0);
8939 +
8940 + /* Power on */
8941 + snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x9, 0);
8942 +
8943 + /* set sampling frequency status bits */
8944 + snd_soc_component_update_bits(digi, WM8804_SPDTX4, 0x0f, sampling_freq);
8945 +
8946 + return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
8947 +}
8948 +
8949 +static int snd_rpi_justboom_both_startup(struct snd_pcm_substream *substream)
8950 +{
8951 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
8952 + struct snd_soc_component *digi = asoc_rtd_to_codec(rtd, 0)->component;
8953 + struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 1)->component;
8954 +
8955 + /* turn on digital output */
8956 + snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x3c, 0x00);
8957 +
8958 + snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
8959 +
8960 + return 0;
8961 +}
8962 +
8963 +static void snd_rpi_justboom_both_shutdown(struct snd_pcm_substream *substream)
8964 +{
8965 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
8966 + struct snd_soc_component *digi = asoc_rtd_to_codec(rtd, 0)->component;
8967 + struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 1)->component;
8968 +
8969 + snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
8970 +
8971 + /* turn off output */
8972 + snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x3c, 0x3c);
8973 +}
8974 +
8975 +/* machine stream operations */
8976 +static struct snd_soc_ops snd_rpi_justboom_both_ops = {
8977 + .hw_params = snd_rpi_justboom_both_hw_params,
8978 + .startup = snd_rpi_justboom_both_startup,
8979 + .shutdown = snd_rpi_justboom_both_shutdown,
8980 +};
8981 +
8982 +SND_SOC_DAILINK_DEFS(rpi_justboom_both,
8983 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
8984 + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi"),
8985 + COMP_CODEC("wm8804.1-003b", "wm8804-spdif")),
8986 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
8987 +
8988 +static struct snd_soc_dai_link snd_rpi_justboom_both_dai[] = {
8989 +{
8990 + .name = "JustBoom Digi",
8991 + .stream_name = "JustBoom Digi HiFi",
8992 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
8993 + SND_SOC_DAIFMT_CBM_CFM,
8994 + .ops = &snd_rpi_justboom_both_ops,
8995 + .init = snd_rpi_justboom_both_init,
8996 + SND_SOC_DAILINK_REG(rpi_justboom_both),
8997 +},
8998 +};
8999 +
9000 +/* audio machine driver */
9001 +static struct snd_soc_card snd_rpi_justboom_both = {
9002 + .name = "snd_rpi_justboom_both",
9003 + .driver_name = "JustBoomBoth",
9004 + .owner = THIS_MODULE,
9005 + .dai_link = snd_rpi_justboom_both_dai,
9006 + .num_links = ARRAY_SIZE(snd_rpi_justboom_both_dai),
9007 +};
9008 +
9009 +static int snd_rpi_justboom_both_probe(struct platform_device *pdev)
9010 +{
9011 + int ret = 0;
9012 + struct snd_soc_card *card = &snd_rpi_justboom_both;
9013 +
9014 + snd_rpi_justboom_both.dev = &pdev->dev;
9015 +
9016 + if (pdev->dev.of_node) {
9017 + struct device_node *i2s_node;
9018 + struct snd_soc_dai_link *dai = &snd_rpi_justboom_both_dai[0];
9019 +
9020 + i2s_node = of_parse_phandle(pdev->dev.of_node,
9021 + "i2s-controller", 0);
9022 +
9023 + if (i2s_node) {
9024 + int i;
9025 +
9026 + for (i = 0; i < card->num_links; i++) {
9027 + dai->cpus->dai_name = NULL;
9028 + dai->cpus->of_node = i2s_node;
9029 + dai->platforms->name = NULL;
9030 + dai->platforms->of_node = i2s_node;
9031 + }
9032 + }
9033 +
9034 + digital_gain_0db_limit = !of_property_read_bool(
9035 + pdev->dev.of_node, "justboom,24db_digital_gain");
9036 + }
9037 +
9038 + ret = snd_soc_register_card(card);
9039 + if (ret && ret != -EPROBE_DEFER) {
9040 + dev_err(&pdev->dev,
9041 + "snd_soc_register_card() failed: %d\n", ret);
9042 + }
9043 +
9044 + return ret;
9045 +}
9046 +
9047 +static int snd_rpi_justboom_both_remove(struct platform_device *pdev)
9048 +{
9049 + return snd_soc_unregister_card(&snd_rpi_justboom_both);
9050 +}
9051 +
9052 +static const struct of_device_id snd_rpi_justboom_both_of_match[] = {
9053 + { .compatible = "justboom,justboom-both", },
9054 + {},
9055 +};
9056 +MODULE_DEVICE_TABLE(of, snd_rpi_justboom_both_of_match);
9057 +
9058 +static struct platform_driver snd_rpi_justboom_both_driver = {
9059 + .driver = {
9060 + .name = "snd-rpi-justboom-both",
9061 + .owner = THIS_MODULE,
9062 + .of_match_table = snd_rpi_justboom_both_of_match,
9063 + },
9064 + .probe = snd_rpi_justboom_both_probe,
9065 + .remove = snd_rpi_justboom_both_remove,
9066 +};
9067 +
9068 +module_platform_driver(snd_rpi_justboom_both_driver);
9069 +
9070 +MODULE_AUTHOR("Johannes Krude <johannes@krude.de>");
9071 +MODULE_DESCRIPTION("ASoC Driver for simultaneous use of JustBoom PI Digi & DAC HAT Sound Cards");
9072 +MODULE_LICENSE("GPL v2");
9073 --- /dev/null
9074 +++ b/sound/soc/bcm/justboom-dac.c
9075 @@ -0,0 +1,147 @@
9076 +/*
9077 + * ASoC Driver for JustBoom DAC Raspberry Pi HAT Sound Card
9078 + *
9079 + * Author: Milan Neskovic
9080 + * Copyright 2016
9081 + * based on code by Daniel Matuschek <info@crazy-audio.com>
9082 + * based on code by Florian Meier <florian.meier@koalo.de>
9083 + *
9084 + * This program is free software; you can redistribute it and/or
9085 + * modify it under the terms of the GNU General Public License
9086 + * version 2 as published by the Free Software Foundation.
9087 + *
9088 + * This program is distributed in the hope that it will be useful, but
9089 + * WITHOUT ANY WARRANTY; without even the implied warranty of
9090 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9091 + * General Public License for more details.
9092 + */
9093 +
9094 +#include <linux/module.h>
9095 +#include <linux/platform_device.h>
9096 +
9097 +#include <sound/core.h>
9098 +#include <sound/pcm.h>
9099 +#include <sound/pcm_params.h>
9100 +#include <sound/soc.h>
9101 +#include <sound/jack.h>
9102 +
9103 +#include "../codecs/pcm512x.h"
9104 +
9105 +static bool digital_gain_0db_limit = true;
9106 +
9107 +static int snd_rpi_justboom_dac_init(struct snd_soc_pcm_runtime *rtd)
9108 +{
9109 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
9110 + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x08, 0x08);
9111 + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02);
9112 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08,0x08);
9113 +
9114 + if (digital_gain_0db_limit)
9115 + {
9116 + int ret;
9117 + struct snd_soc_card *card = rtd->card;
9118 +
9119 + ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
9120 + if (ret < 0)
9121 + dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
9122 + }
9123 +
9124 + return 0;
9125 +}
9126 +
9127 +static int snd_rpi_justboom_dac_startup(struct snd_pcm_substream *substream) {
9128 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
9129 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
9130 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08,0x08);
9131 + return 0;
9132 +}
9133 +
9134 +static void snd_rpi_justboom_dac_shutdown(struct snd_pcm_substream *substream) {
9135 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
9136 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
9137 + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08,0x00);
9138 +}
9139 +
9140 +/* machine stream operations */
9141 +static struct snd_soc_ops snd_rpi_justboom_dac_ops = {
9142 + .startup = snd_rpi_justboom_dac_startup,
9143 + .shutdown = snd_rpi_justboom_dac_shutdown,
9144 +};
9145 +
9146 +SND_SOC_DAILINK_DEFS(hifi,
9147 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
9148 + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi")),
9149 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
9150 +
9151 +static struct snd_soc_dai_link snd_rpi_justboom_dac_dai[] = {
9152 +{
9153 + .name = "JustBoom DAC",
9154 + .stream_name = "JustBoom DAC HiFi",
9155 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
9156 + SND_SOC_DAIFMT_CBS_CFS,
9157 + .ops = &snd_rpi_justboom_dac_ops,
9158 + .init = snd_rpi_justboom_dac_init,
9159 + SND_SOC_DAILINK_REG(hifi),
9160 +},
9161 +};
9162 +
9163 +/* audio machine driver */
9164 +static struct snd_soc_card snd_rpi_justboom_dac = {
9165 + .name = "snd_rpi_justboom_dac",
9166 + .driver_name = "JustBoomDac",
9167 + .owner = THIS_MODULE,
9168 + .dai_link = snd_rpi_justboom_dac_dai,
9169 + .num_links = ARRAY_SIZE(snd_rpi_justboom_dac_dai),
9170 +};
9171 +
9172 +static int snd_rpi_justboom_dac_probe(struct platform_device *pdev)
9173 +{
9174 + int ret = 0;
9175 +
9176 + snd_rpi_justboom_dac.dev = &pdev->dev;
9177 +
9178 + if (pdev->dev.of_node) {
9179 + struct device_node *i2s_node;
9180 + struct snd_soc_dai_link *dai = &snd_rpi_justboom_dac_dai[0];
9181 + i2s_node = of_parse_phandle(pdev->dev.of_node,
9182 + "i2s-controller", 0);
9183 +
9184 + if (i2s_node) {
9185 + dai->cpus->dai_name = NULL;
9186 + dai->cpus->of_node = i2s_node;
9187 + dai->platforms->name = NULL;
9188 + dai->platforms->of_node = i2s_node;
9189 + }
9190 +
9191 + digital_gain_0db_limit = !of_property_read_bool(
9192 + pdev->dev.of_node, "justboom,24db_digital_gain");
9193 + }
9194 +
9195 + ret = devm_snd_soc_register_card(&pdev->dev, &snd_rpi_justboom_dac);
9196 + if (ret && ret != -EPROBE_DEFER)
9197 + dev_err(&pdev->dev,
9198 + "snd_soc_register_card() failed: %d\n", ret);
9199 +
9200 + return ret;
9201 +}
9202 +
9203 +static const struct of_device_id snd_rpi_justboom_dac_of_match[] = {
9204 + { .compatible = "justboom,justboom-dac", },
9205 + {},
9206 +};
9207 +MODULE_DEVICE_TABLE(of, snd_rpi_justboom_dac_of_match);
9208 +
9209 +static struct platform_driver snd_rpi_justboom_dac_driver = {
9210 + .driver = {
9211 + .name = "snd-rpi-justboom-dac",
9212 + .owner = THIS_MODULE,
9213 + .of_match_table = snd_rpi_justboom_dac_of_match,
9214 + },
9215 + .probe = snd_rpi_justboom_dac_probe,
9216 +};
9217 +
9218 +module_platform_driver(snd_rpi_justboom_dac_driver);
9219 +
9220 +MODULE_AUTHOR("Milan Neskovic <info@justboom.co>");
9221 +MODULE_DESCRIPTION("ASoC Driver for JustBoom PI DAC HAT Sound Card");
9222 +MODULE_LICENSE("GPL v2");
9223 --- /dev/null
9224 +++ b/sound/soc/bcm/pisound.c
9225 @@ -0,0 +1,1238 @@
9226 +/*
9227 + * Pisound Linux kernel module.
9228 + * Copyright (C) 2016-2020 Vilniaus Blokas UAB, https://blokas.io/pisound
9229 + *
9230 + * This program is free software; you can redistribute it and/or
9231 + * modify it under the terms of the GNU General Public License
9232 + * as published by the Free Software Foundation; version 2 of the
9233 + * License.
9234 + *
9235 + * This program is distributed in the hope that it will be useful,
9236 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9237 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9238 + * GNU General Public License for more details.
9239 + *
9240 + * You should have received a copy of the GNU General Public License
9241 + * along with this program; if not, write to the Free Software
9242 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
9243 + * MA 02110-1301, USA.
9244 + */
9245 +
9246 +#include <linux/init.h>
9247 +#include <linux/module.h>
9248 +#include <linux/platform_device.h>
9249 +#include <linux/gpio.h>
9250 +#include <linux/kobject.h>
9251 +#include <linux/sysfs.h>
9252 +#include <linux/delay.h>
9253 +#include <linux/spi/spi.h>
9254 +#include <linux/interrupt.h>
9255 +#include <linux/kfifo.h>
9256 +#include <linux/jiffies.h>
9257 +
9258 +#include <sound/core.h>
9259 +#include <sound/pcm.h>
9260 +#include <sound/pcm_params.h>
9261 +#include <sound/soc.h>
9262 +#include <sound/jack.h>
9263 +#include <sound/rawmidi.h>
9264 +#include <sound/asequencer.h>
9265 +#include <sound/control.h>
9266 +
9267 +static int pisnd_spi_init(struct device *dev);
9268 +static void pisnd_spi_uninit(void);
9269 +
9270 +static void pisnd_spi_flush(void);
9271 +static void pisnd_spi_start(void);
9272 +static uint8_t pisnd_spi_recv(uint8_t *buffer, uint8_t length);
9273 +
9274 +typedef void (*pisnd_spi_recv_cb)(void *data);
9275 +static void pisnd_spi_set_callback(pisnd_spi_recv_cb cb, void *data);
9276 +
9277 +static const char *pisnd_spi_get_serial(void);
9278 +static const char *pisnd_spi_get_id(void);
9279 +static const char *pisnd_spi_get_fw_version(void);
9280 +static const char *pisnd_spi_get_hw_version(void);
9281 +
9282 +static int pisnd_midi_init(struct snd_card *card);
9283 +static void pisnd_midi_uninit(void);
9284 +
9285 +enum task_e {
9286 + TASK_PROCESS = 0,
9287 +};
9288 +
9289 +static void pisnd_schedule_process(enum task_e task);
9290 +
9291 +#define PISOUND_LOG_PREFIX "pisound: "
9292 +
9293 +#ifdef PISOUND_DEBUG
9294 +# define printd(...) pr_alert(PISOUND_LOG_PREFIX __VA_ARGS__)
9295 +#else
9296 +# define printd(...) do {} while (0)
9297 +#endif
9298 +
9299 +#define printe(...) pr_err(PISOUND_LOG_PREFIX __VA_ARGS__)
9300 +#define printi(...) pr_info(PISOUND_LOG_PREFIX __VA_ARGS__)
9301 +
9302 +static struct snd_rawmidi *g_rmidi;
9303 +static struct snd_rawmidi_substream *g_midi_output_substream;
9304 +
9305 +static int pisnd_output_open(struct snd_rawmidi_substream *substream)
9306 +{
9307 + g_midi_output_substream = substream;
9308 + return 0;
9309 +}
9310 +
9311 +static int pisnd_output_close(struct snd_rawmidi_substream *substream)
9312 +{
9313 + g_midi_output_substream = NULL;
9314 + return 0;
9315 +}
9316 +
9317 +static void pisnd_output_trigger(
9318 + struct snd_rawmidi_substream *substream,
9319 + int up
9320 + )
9321 +{
9322 + if (substream != g_midi_output_substream) {
9323 + printe("MIDI output trigger called for an unexpected stream!");
9324 + return;
9325 + }
9326 +
9327 + if (!up)
9328 + return;
9329 +
9330 + pisnd_spi_start();
9331 +}
9332 +
9333 +static void pisnd_output_drain(struct snd_rawmidi_substream *substream)
9334 +{
9335 + pisnd_spi_flush();
9336 +}
9337 +
9338 +static int pisnd_input_open(struct snd_rawmidi_substream *substream)
9339 +{
9340 + return 0;
9341 +}
9342 +
9343 +static int pisnd_input_close(struct snd_rawmidi_substream *substream)
9344 +{
9345 + return 0;
9346 +}
9347 +
9348 +static void pisnd_midi_recv_callback(void *substream)
9349 +{
9350 + uint8_t data[128];
9351 + uint8_t n = 0;
9352 +
9353 + while ((n = pisnd_spi_recv(data, sizeof(data)))) {
9354 + int res = snd_rawmidi_receive(substream, data, n);
9355 + (void)res;
9356 + printd("midi recv %u bytes, res = %d\n", n, res);
9357 + }
9358 +}
9359 +
9360 +static void pisnd_input_trigger(struct snd_rawmidi_substream *substream, int up)
9361 +{
9362 + if (up) {
9363 + pisnd_spi_set_callback(pisnd_midi_recv_callback, substream);
9364 + pisnd_schedule_process(TASK_PROCESS);
9365 + } else {
9366 + pisnd_spi_set_callback(NULL, NULL);
9367 + }
9368 +}
9369 +
9370 +static struct snd_rawmidi_ops pisnd_output_ops = {
9371 + .open = pisnd_output_open,
9372 + .close = pisnd_output_close,
9373 + .trigger = pisnd_output_trigger,
9374 + .drain = pisnd_output_drain,
9375 +};
9376 +
9377 +static struct snd_rawmidi_ops pisnd_input_ops = {
9378 + .open = pisnd_input_open,
9379 + .close = pisnd_input_close,
9380 + .trigger = pisnd_input_trigger,
9381 +};
9382 +
9383 +static void pisnd_get_port_info(
9384 + struct snd_rawmidi *rmidi,
9385 + int number,
9386 + struct snd_seq_port_info *seq_port_info
9387 + )
9388 +{
9389 + seq_port_info->type =
9390 + SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
9391 + SNDRV_SEQ_PORT_TYPE_HARDWARE |
9392 + SNDRV_SEQ_PORT_TYPE_PORT;
9393 + seq_port_info->midi_voices = 0;
9394 +}
9395 +
9396 +static struct snd_rawmidi_global_ops pisnd_global_ops = {
9397 + .get_port_info = pisnd_get_port_info,
9398 +};
9399 +
9400 +static int pisnd_midi_init(struct snd_card *card)
9401 +{
9402 + int err;
9403 +
9404 + g_midi_output_substream = NULL;
9405 +
9406 + err = snd_rawmidi_new(card, "pisound MIDI", 0, 1, 1, &g_rmidi);
9407 +
9408 + if (err < 0) {
9409 + printe("snd_rawmidi_new failed: %d\n", err);
9410 + return err;
9411 + }
9412 +
9413 + strcpy(g_rmidi->name, "pisound MIDI ");
9414 + strcat(g_rmidi->name, pisnd_spi_get_serial());
9415 +
9416 + g_rmidi->info_flags =
9417 + SNDRV_RAWMIDI_INFO_OUTPUT |
9418 + SNDRV_RAWMIDI_INFO_INPUT |
9419 + SNDRV_RAWMIDI_INFO_DUPLEX;
9420 +
9421 + g_rmidi->ops = &pisnd_global_ops;
9422 +
9423 + g_rmidi->private_data = (void *)0;
9424 +
9425 + snd_rawmidi_set_ops(
9426 + g_rmidi,
9427 + SNDRV_RAWMIDI_STREAM_OUTPUT,
9428 + &pisnd_output_ops
9429 + );
9430 +
9431 + snd_rawmidi_set_ops(
9432 + g_rmidi,
9433 + SNDRV_RAWMIDI_STREAM_INPUT,
9434 + &pisnd_input_ops
9435 + );
9436 +
9437 + return 0;
9438 +}
9439 +
9440 +static void pisnd_midi_uninit(void)
9441 +{
9442 +}
9443 +
9444 +static void *g_recvData;
9445 +static pisnd_spi_recv_cb g_recvCallback;
9446 +
9447 +#define FIFO_SIZE 4096
9448 +
9449 +static char g_serial_num[11];
9450 +static char g_id[25];
9451 +enum { MAX_VERSION_STR_LEN = 6 };
9452 +static char g_fw_version[MAX_VERSION_STR_LEN];
9453 +static char g_hw_version[MAX_VERSION_STR_LEN];
9454 +
9455 +static uint8_t g_ledFlashDuration;
9456 +static bool g_ledFlashDurationChanged;
9457 +
9458 +DEFINE_KFIFO(spi_fifo_in, uint8_t, FIFO_SIZE);
9459 +DEFINE_KFIFO(spi_fifo_out, uint8_t, FIFO_SIZE);
9460 +
9461 +static struct gpio_desc *data_available;
9462 +static struct gpio_desc *spi_reset;
9463 +
9464 +static struct spi_device *pisnd_spi_device;
9465 +
9466 +static struct workqueue_struct *pisnd_workqueue;
9467 +static struct work_struct pisnd_work_process;
9468 +
9469 +static void pisnd_work_handler(struct work_struct *work);
9470 +
9471 +static void spi_transfer(const uint8_t *txbuf, uint8_t *rxbuf, int len);
9472 +static uint16_t spi_transfer16(uint16_t val);
9473 +
9474 +static int pisnd_init_workqueues(void)
9475 +{
9476 + pisnd_workqueue = create_singlethread_workqueue("pisnd_workqueue");
9477 + INIT_WORK(&pisnd_work_process, pisnd_work_handler);
9478 +
9479 + return 0;
9480 +}
9481 +
9482 +static void pisnd_uninit_workqueues(void)
9483 +{
9484 + flush_workqueue(pisnd_workqueue);
9485 + destroy_workqueue(pisnd_workqueue);
9486 +
9487 + pisnd_workqueue = NULL;
9488 +}
9489 +
9490 +static bool pisnd_spi_has_more(void)
9491 +{
9492 + return gpiod_get_value(data_available);
9493 +}
9494 +
9495 +static void pisnd_schedule_process(enum task_e task)
9496 +{
9497 + if (pisnd_spi_device != NULL &&
9498 + pisnd_workqueue != NULL &&
9499 + !work_pending(&pisnd_work_process)
9500 + ) {
9501 + printd("schedule: has more = %d\n", pisnd_spi_has_more());
9502 + if (task == TASK_PROCESS)
9503 + queue_work(pisnd_workqueue, &pisnd_work_process);
9504 + }
9505 +}
9506 +
9507 +static irqreturn_t data_available_interrupt_handler(int irq, void *dev_id)
9508 +{
9509 + if (irq == gpiod_to_irq(data_available) && pisnd_spi_has_more()) {
9510 + printd("schedule from irq\n");
9511 + pisnd_schedule_process(TASK_PROCESS);
9512 + }
9513 +
9514 + return IRQ_HANDLED;
9515 +}
9516 +
9517 +static uint16_t spi_transfer16(uint16_t val)
9518 +{
9519 + uint8_t txbuf[2];
9520 + uint8_t rxbuf[2];
9521 +
9522 + if (!pisnd_spi_device) {
9523 + printe("pisnd_spi_device null, returning\n");
9524 + return 0;
9525 + }
9526 +
9527 + txbuf[0] = val >> 8;
9528 + txbuf[1] = val & 0xff;
9529 +
9530 + spi_transfer(txbuf, rxbuf, sizeof(txbuf));
9531 +
9532 + printd("received: %02x%02x\n", rxbuf[0], rxbuf[1]);
9533 +
9534 + return (rxbuf[0] << 8) | rxbuf[1];
9535 +}
9536 +
9537 +static void spi_transfer(const uint8_t *txbuf, uint8_t *rxbuf, int len)
9538 +{
9539 + int err;
9540 + struct spi_transfer transfer;
9541 + struct spi_message msg;
9542 +
9543 + memset(rxbuf, 0, len);
9544 +
9545 + if (!pisnd_spi_device) {
9546 + printe("pisnd_spi_device null, returning\n");
9547 + return;
9548 + }
9549 +
9550 + spi_message_init(&msg);
9551 +
9552 + memset(&transfer, 0, sizeof(transfer));
9553 +
9554 + transfer.tx_buf = txbuf;
9555 + transfer.rx_buf = rxbuf;
9556 + transfer.len = len;
9557 + transfer.speed_hz = 150000;
9558 + transfer.delay_usecs = 10;
9559 + spi_message_add_tail(&transfer, &msg);
9560 +
9561 + err = spi_sync(pisnd_spi_device, &msg);
9562 +
9563 + if (err < 0) {
9564 + printe("spi_sync error %d\n", err);
9565 + return;
9566 + }
9567 +
9568 + printd("hasMore %d\n", pisnd_spi_has_more());
9569 +}
9570 +
9571 +static int spi_read_bytes(char *dst, size_t length, uint8_t *bytesRead)
9572 +{
9573 + uint16_t rx;
9574 + uint8_t size;
9575 + uint8_t i;
9576 +
9577 + memset(dst, 0, length);
9578 + *bytesRead = 0;
9579 +
9580 + rx = spi_transfer16(0);
9581 + if (!(rx >> 8))
9582 + return -EINVAL;
9583 +
9584 + size = rx & 0xff;
9585 +
9586 + if (size > length)
9587 + return -EINVAL;
9588 +
9589 + for (i = 0; i < size; ++i) {
9590 + rx = spi_transfer16(0);
9591 + if (!(rx >> 8))
9592 + return -EINVAL;
9593 +
9594 + dst[i] = rx & 0xff;
9595 + }
9596 +
9597 + *bytesRead = i;
9598 +
9599 + return 0;
9600 +}
9601 +
9602 +static int spi_device_match(struct device *dev, const void *data)
9603 +{
9604 + struct spi_device *spi = container_of(dev, struct spi_device, dev);
9605 +
9606 + printd(" %s %s %dkHz %d bits mode=0x%02X\n",
9607 + spi->modalias, dev_name(dev), spi->max_speed_hz/1000,
9608 + spi->bits_per_word, spi->mode);
9609 +
9610 + if (strcmp("pisound-spi", spi->modalias) == 0) {
9611 + printi("\tFound!\n");
9612 + return 1;
9613 + }
9614 +
9615 + printe("\tNot found!\n");
9616 + return 0;
9617 +}
9618 +
9619 +static struct spi_device *pisnd_spi_find_device(void)
9620 +{
9621 + struct device *dev;
9622 +
9623 + printi("Searching for spi device...\n");
9624 + dev = bus_find_device(&spi_bus_type, NULL, NULL, spi_device_match);
9625 + if (dev != NULL)
9626 + return container_of(dev, struct spi_device, dev);
9627 + else
9628 + return NULL;
9629 +}
9630 +
9631 +static void pisnd_work_handler(struct work_struct *work)
9632 +{
9633 + enum { TRANSFER_SIZE = 4 };
9634 + enum { PISOUND_OUTPUT_BUFFER_SIZE_MILLIBYTES = 127 * 1000 };
9635 + enum { MIDI_MILLIBYTES_PER_JIFFIE = (3125 * 1000) / HZ };
9636 + int out_buffer_used_millibytes = 0;
9637 + unsigned long now;
9638 + uint8_t val;
9639 + uint8_t txbuf[TRANSFER_SIZE];
9640 + uint8_t rxbuf[TRANSFER_SIZE];
9641 + uint8_t midibuf[TRANSFER_SIZE];
9642 + int i, n;
9643 + bool had_data;
9644 +
9645 + unsigned long last_transfer_at = jiffies;
9646 +
9647 + if (work == &pisnd_work_process) {
9648 + if (pisnd_spi_device == NULL)
9649 + return;
9650 +
9651 + do {
9652 + if (g_midi_output_substream &&
9653 + kfifo_avail(&spi_fifo_out) >= sizeof(midibuf)) {
9654 +
9655 + n = snd_rawmidi_transmit_peek(
9656 + g_midi_output_substream,
9657 + midibuf, sizeof(midibuf)
9658 + );
9659 +
9660 + if (n > 0) {
9661 + for (i = 0; i < n; ++i)
9662 + kfifo_put(
9663 + &spi_fifo_out,
9664 + midibuf[i]
9665 + );
9666 + snd_rawmidi_transmit_ack(
9667 + g_midi_output_substream,
9668 + i
9669 + );
9670 + }
9671 + }
9672 +
9673 + had_data = false;
9674 + memset(txbuf, 0, sizeof(txbuf));
9675 + for (i = 0; i < sizeof(txbuf) &&
9676 + ((out_buffer_used_millibytes+1000 <
9677 + PISOUND_OUTPUT_BUFFER_SIZE_MILLIBYTES) ||
9678 + g_ledFlashDurationChanged);
9679 + i += 2) {
9680 +
9681 + val = 0;
9682 +
9683 + if (g_ledFlashDurationChanged) {
9684 + txbuf[i+0] = 0xf0;
9685 + txbuf[i+1] = g_ledFlashDuration;
9686 + g_ledFlashDuration = 0;
9687 + g_ledFlashDurationChanged = false;
9688 + } else if (kfifo_get(&spi_fifo_out, &val)) {
9689 + txbuf[i+0] = 0x0f;
9690 + txbuf[i+1] = val;
9691 + out_buffer_used_millibytes += 1000;
9692 + }
9693 + }
9694 +
9695 + spi_transfer(txbuf, rxbuf, sizeof(txbuf));
9696 + /* Estimate the Pisound's MIDI output buffer usage, so
9697 + * that we don't overflow it. Space in the buffer should
9698 + * be becoming available at the UART MIDI byte transfer
9699 + * rate.
9700 + */
9701 + now = jiffies;
9702 + if (now != last_transfer_at) {
9703 + out_buffer_used_millibytes -=
9704 + (now - last_transfer_at) *
9705 + MIDI_MILLIBYTES_PER_JIFFIE;
9706 + if (out_buffer_used_millibytes < 0)
9707 + out_buffer_used_millibytes = 0;
9708 + last_transfer_at = now;
9709 + }
9710 +
9711 + for (i = 0; i < sizeof(rxbuf); i += 2) {
9712 + if (rxbuf[i]) {
9713 + kfifo_put(&spi_fifo_in, rxbuf[i+1]);
9714 + if (kfifo_len(&spi_fifo_in) > 16 &&
9715 + g_recvCallback)
9716 + g_recvCallback(g_recvData);
9717 + had_data = true;
9718 + }
9719 + }
9720 + } while (had_data
9721 + || !kfifo_is_empty(&spi_fifo_out)
9722 + || pisnd_spi_has_more()
9723 + || g_ledFlashDurationChanged
9724 + || out_buffer_used_millibytes != 0
9725 + );
9726 +
9727 + if (!kfifo_is_empty(&spi_fifo_in) && g_recvCallback)
9728 + g_recvCallback(g_recvData);
9729 + }
9730 +}
9731 +
9732 +static int pisnd_spi_gpio_init(struct device *dev)
9733 +{
9734 + spi_reset = gpiod_get_index(dev, "reset", 1, GPIOD_ASIS);
9735 + data_available = gpiod_get_index(dev, "data_available", 0, GPIOD_ASIS);
9736 +
9737 + gpiod_direction_output(spi_reset, 1);
9738 + gpiod_direction_input(data_available);
9739 +
9740 + /* Reset the slave. */
9741 + gpiod_set_value(spi_reset, false);
9742 + mdelay(1);
9743 + gpiod_set_value(spi_reset, true);
9744 +
9745 + /* Give time for spi slave to start. */
9746 + mdelay(64);
9747 +
9748 + return 0;
9749 +}
9750 +
9751 +static void pisnd_spi_gpio_uninit(void)
9752 +{
9753 + gpiod_set_value(spi_reset, false);
9754 + gpiod_put(spi_reset);
9755 + spi_reset = NULL;
9756 +
9757 + gpiod_put(data_available);
9758 + data_available = NULL;
9759 +}
9760 +
9761 +static int pisnd_spi_gpio_irq_init(struct device *dev)
9762 +{
9763 + return request_threaded_irq(
9764 + gpiod_to_irq(data_available), NULL,
9765 + data_available_interrupt_handler,
9766 + IRQF_TIMER | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
9767 + "data_available_int",
9768 + NULL
9769 + );
9770 +}
9771 +
9772 +static void pisnd_spi_gpio_irq_uninit(void)
9773 +{
9774 + free_irq(gpiod_to_irq(data_available), NULL);
9775 +}
9776 +
9777 +static int spi_read_info(void)
9778 +{
9779 + uint16_t tmp;
9780 + uint8_t count;
9781 + uint8_t n;
9782 + uint8_t i;
9783 + uint8_t j;
9784 + char buffer[257];
9785 + int ret;
9786 + char *p;
9787 +
9788 + memset(g_serial_num, 0, sizeof(g_serial_num));
9789 + memset(g_fw_version, 0, sizeof(g_fw_version));
9790 + strcpy(g_hw_version, "1.0"); // Assume 1.0 hw version.
9791 + memset(g_id, 0, sizeof(g_id));
9792 +
9793 + tmp = spi_transfer16(0);
9794 +
9795 + if (!(tmp >> 8))
9796 + return -EINVAL;
9797 +
9798 + count = tmp & 0xff;
9799 +
9800 + for (i = 0; i < count; ++i) {
9801 + memset(buffer, 0, sizeof(buffer));
9802 + ret = spi_read_bytes(buffer, sizeof(buffer)-1, &n);
9803 +
9804 + if (ret < 0)
9805 + return ret;
9806 +
9807 + switch (i) {
9808 + case 0:
9809 + if (n != 2)
9810 + return -EINVAL;
9811 +
9812 + snprintf(
9813 + g_fw_version,
9814 + MAX_VERSION_STR_LEN,
9815 + "%x.%02x",
9816 + buffer[0],
9817 + buffer[1]
9818 + );
9819 +
9820 + g_fw_version[MAX_VERSION_STR_LEN-1] = '\0';
9821 + break;
9822 + case 3:
9823 + if (n != 2)
9824 + return -EINVAL;
9825 +
9826 + snprintf(
9827 + g_hw_version,
9828 + MAX_VERSION_STR_LEN,
9829 + "%x.%x",
9830 + buffer[0],
9831 + buffer[1]
9832 + );
9833 +
9834 + g_hw_version[MAX_VERSION_STR_LEN-1] = '\0';
9835 + break;
9836 + case 1:
9837 + if (n >= sizeof(g_serial_num))
9838 + return -EINVAL;
9839 +
9840 + memcpy(g_serial_num, buffer, sizeof(g_serial_num));
9841 + break;
9842 + case 2:
9843 + {
9844 + if (n*2 >= sizeof(g_id))
9845 + return -EINVAL;
9846 +
9847 + p = g_id;
9848 + for (j = 0; j < n; ++j)
9849 + p += sprintf(p, "%02x", buffer[j]);
9850 +
9851 + *p = '\0';
9852 + }
9853 + break;
9854 + default:
9855 + break;
9856 + }
9857 + }
9858 +
9859 + return 0;
9860 +}
9861 +
9862 +static int pisnd_spi_init(struct device *dev)
9863 +{
9864 + int ret;
9865 + struct spi_device *spi;
9866 +
9867 + memset(g_serial_num, 0, sizeof(g_serial_num));
9868 + memset(g_id, 0, sizeof(g_id));
9869 + memset(g_fw_version, 0, sizeof(g_fw_version));
9870 + memset(g_hw_version, 0, sizeof(g_hw_version));
9871 +
9872 + spi = pisnd_spi_find_device();
9873 +
9874 + if (spi != NULL) {
9875 + printd("initializing spi!\n");
9876 + pisnd_spi_device = spi;
9877 + ret = spi_setup(pisnd_spi_device);
9878 + } else {
9879 + printe("SPI device not found, deferring!\n");
9880 + return -EPROBE_DEFER;
9881 + }
9882 +
9883 + ret = pisnd_spi_gpio_init(dev);
9884 +
9885 + if (ret < 0) {
9886 + printe("SPI GPIO init failed: %d\n", ret);
9887 + spi_dev_put(pisnd_spi_device);
9888 + pisnd_spi_device = NULL;
9889 + pisnd_spi_gpio_uninit();
9890 + return ret;
9891 + }
9892 +
9893 + ret = spi_read_info();
9894 +
9895 + if (ret < 0) {
9896 + printe("Reading card info failed: %d\n", ret);
9897 + spi_dev_put(pisnd_spi_device);
9898 + pisnd_spi_device = NULL;
9899 + pisnd_spi_gpio_uninit();
9900 + return ret;
9901 + }
9902 +
9903 + /* Flash the LEDs. */
9904 + spi_transfer16(0xf008);
9905 +
9906 + ret = pisnd_spi_gpio_irq_init(dev);
9907 + if (ret < 0) {
9908 + printe("SPI irq request failed: %d\n", ret);
9909 + spi_dev_put(pisnd_spi_device);
9910 + pisnd_spi_device = NULL;
9911 + pisnd_spi_gpio_irq_uninit();
9912 + pisnd_spi_gpio_uninit();
9913 + }
9914 +
9915 + ret = pisnd_init_workqueues();
9916 + if (ret != 0) {
9917 + printe("Workqueue initialization failed: %d\n", ret);
9918 + spi_dev_put(pisnd_spi_device);
9919 + pisnd_spi_device = NULL;
9920 + pisnd_spi_gpio_irq_uninit();
9921 + pisnd_spi_gpio_uninit();
9922 + pisnd_uninit_workqueues();
9923 + return ret;
9924 + }
9925 +
9926 + if (pisnd_spi_has_more()) {
9927 + printd("data is available, scheduling from init\n");
9928 + pisnd_schedule_process(TASK_PROCESS);
9929 + }
9930 +
9931 + return 0;
9932 +}
9933 +
9934 +static void pisnd_spi_uninit(void)
9935 +{
9936 + pisnd_uninit_workqueues();
9937 +
9938 + spi_dev_put(pisnd_spi_device);
9939 + pisnd_spi_device = NULL;
9940 +
9941 + pisnd_spi_gpio_irq_uninit();
9942 + pisnd_spi_gpio_uninit();
9943 +}
9944 +
9945 +static void pisnd_spi_flash_leds(uint8_t duration)
9946 +{
9947 + g_ledFlashDuration = duration;
9948 + g_ledFlashDurationChanged = true;
9949 + printd("schedule from spi_flash_leds\n");
9950 + pisnd_schedule_process(TASK_PROCESS);
9951 +}
9952 +
9953 +static void pisnd_spi_flush(void)
9954 +{
9955 + while (!kfifo_is_empty(&spi_fifo_out)) {
9956 + pisnd_spi_start();
9957 + flush_workqueue(pisnd_workqueue);
9958 + }
9959 +}
9960 +
9961 +static void pisnd_spi_start(void)
9962 +{
9963 + printd("schedule from spi_start\n");
9964 + pisnd_schedule_process(TASK_PROCESS);
9965 +}
9966 +
9967 +static uint8_t pisnd_spi_recv(uint8_t *buffer, uint8_t length)
9968 +{
9969 + return kfifo_out(&spi_fifo_in, buffer, length);
9970 +}
9971 +
9972 +static void pisnd_spi_set_callback(pisnd_spi_recv_cb cb, void *data)
9973 +{
9974 + g_recvData = data;
9975 + g_recvCallback = cb;
9976 +}
9977 +
9978 +static const char *pisnd_spi_get_serial(void)
9979 +{
9980 + return g_serial_num;
9981 +}
9982 +
9983 +static const char *pisnd_spi_get_id(void)
9984 +{
9985 + return g_id;
9986 +}
9987 +
9988 +static const char *pisnd_spi_get_fw_version(void)
9989 +{
9990 + return g_fw_version;
9991 +}
9992 +
9993 +static const char *pisnd_spi_get_hw_version(void)
9994 +{
9995 + return g_hw_version;
9996 +}
9997 +
9998 +static const struct of_device_id pisound_of_match[] = {
9999 + { .compatible = "blokaslabs,pisound", },
10000 + { .compatible = "blokaslabs,pisound-spi", },
10001 + {},
10002 +};
10003 +
10004 +enum {
10005 + SWITCH = 0,
10006 + VOLUME = 1,
10007 +};
10008 +
10009 +static int pisnd_ctl_info(struct snd_kcontrol *kcontrol,
10010 + struct snd_ctl_elem_info *uinfo)
10011 +{
10012 + if (kcontrol->private_value == SWITCH) {
10013 + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
10014 + uinfo->count = 1;
10015 + uinfo->value.integer.min = 0;
10016 + uinfo->value.integer.max = 1;
10017 + return 0;
10018 + } else if (kcontrol->private_value == VOLUME) {
10019 + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
10020 + uinfo->count = 1;
10021 + uinfo->value.integer.min = 0;
10022 + uinfo->value.integer.max = 100;
10023 + return 0;
10024 + }
10025 + return -EINVAL;
10026 +}
10027 +
10028 +static int pisnd_ctl_get(struct snd_kcontrol *kcontrol,
10029 + struct snd_ctl_elem_value *ucontrol)
10030 +{
10031 + if (kcontrol->private_value == SWITCH) {
10032 + ucontrol->value.integer.value[0] = 1;
10033 + return 0;
10034 + } else if (kcontrol->private_value == VOLUME) {
10035 + ucontrol->value.integer.value[0] = 100;
10036 + return 0;
10037 + }
10038 +
10039 + return -EINVAL;
10040 +}
10041 +
10042 +static struct snd_kcontrol_new pisnd_ctl[] = {
10043 + {
10044 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10045 + .name = "PCM Playback Switch",
10046 + .index = 0,
10047 + .private_value = SWITCH,
10048 + .access = SNDRV_CTL_ELEM_ACCESS_READ,
10049 + .info = pisnd_ctl_info,
10050 + .get = pisnd_ctl_get,
10051 + },
10052 + {
10053 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10054 + .name = "PCM Playback Volume",
10055 + .index = 0,
10056 + .private_value = VOLUME,
10057 + .access = SNDRV_CTL_ELEM_ACCESS_READ,
10058 + .info = pisnd_ctl_info,
10059 + .get = pisnd_ctl_get,
10060 + },
10061 +};
10062 +
10063 +static int pisnd_ctl_init(struct snd_card *card)
10064 +{
10065 + int err, i;
10066 +
10067 + for (i = 0; i < ARRAY_SIZE(pisnd_ctl); ++i) {
10068 + err = snd_ctl_add(card, snd_ctl_new1(&pisnd_ctl[i], NULL));
10069 + if (err < 0)
10070 + return err;
10071 + }
10072 +
10073 + return 0;
10074 +}
10075 +
10076 +static int pisnd_ctl_uninit(void)
10077 +{
10078 + return 0;
10079 +}
10080 +
10081 +static struct gpio_desc *osr0, *osr1, *osr2;
10082 +static struct gpio_desc *reset;
10083 +static struct gpio_desc *button;
10084 +
10085 +static int pisnd_hw_params(
10086 + struct snd_pcm_substream *substream,
10087 + struct snd_pcm_hw_params *params
10088 + )
10089 +{
10090 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
10091 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
10092 +
10093 + /* Pisound runs on fixed 32 clock counts per channel,
10094 + * as generated by the master ADC.
10095 + */
10096 + snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2);
10097 +
10098 + printd("rate = %d\n", params_rate(params));
10099 + printd("ch = %d\n", params_channels(params));
10100 + printd("bits = %u\n",
10101 + snd_pcm_format_physical_width(params_format(params)));
10102 + printd("format = %d\n", params_format(params));
10103 +
10104 + gpiod_set_value(reset, false);
10105 +
10106 + switch (params_rate(params)) {
10107 + case 48000:
10108 + gpiod_set_value(osr0, true);
10109 + gpiod_set_value(osr1, false);
10110 + gpiod_set_value(osr2, false);
10111 + break;
10112 + case 96000:
10113 + gpiod_set_value(osr0, true);
10114 + gpiod_set_value(osr1, false);
10115 + gpiod_set_value(osr2, true);
10116 + break;
10117 + case 192000:
10118 + gpiod_set_value(osr0, true);
10119 + gpiod_set_value(osr1, true);
10120 + gpiod_set_value(osr2, true);
10121 + break;
10122 + default:
10123 + printe("Unsupported rate %u!\n", params_rate(params));
10124 + return -EINVAL;
10125 + }
10126 +
10127 + gpiod_set_value(reset, true);
10128 +
10129 + return 0;
10130 +}
10131 +
10132 +static unsigned int rates[3] = {
10133 + 48000, 96000, 192000
10134 +};
10135 +
10136 +static struct snd_pcm_hw_constraint_list constraints_rates = {
10137 + .count = ARRAY_SIZE(rates),
10138 + .list = rates,
10139 + .mask = 0,
10140 +};
10141 +
10142 +static int pisnd_startup(struct snd_pcm_substream *substream)
10143 +{
10144 + int err = snd_pcm_hw_constraint_list(
10145 + substream->runtime,
10146 + 0,
10147 + SNDRV_PCM_HW_PARAM_RATE,
10148 + &constraints_rates
10149 + );
10150 +
10151 + if (err < 0)
10152 + return err;
10153 +
10154 + err = snd_pcm_hw_constraint_single(
10155 + substream->runtime,
10156 + SNDRV_PCM_HW_PARAM_CHANNELS,
10157 + 2
10158 + );
10159 +
10160 + if (err < 0)
10161 + return err;
10162 +
10163 + err = snd_pcm_hw_constraint_mask64(
10164 + substream->runtime,
10165 + SNDRV_PCM_HW_PARAM_FORMAT,
10166 + SNDRV_PCM_FMTBIT_S16_LE |
10167 + SNDRV_PCM_FMTBIT_S24_LE |
10168 + SNDRV_PCM_FMTBIT_S32_LE
10169 + );
10170 +
10171 + if (err < 0)
10172 + return err;
10173 +
10174 + return 0;
10175 +}
10176 +
10177 +static struct snd_soc_ops pisnd_ops = {
10178 + .startup = pisnd_startup,
10179 + .hw_params = pisnd_hw_params,
10180 +};
10181 +
10182 +SND_SOC_DAILINK_DEFS(pisnd,
10183 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
10184 + DAILINK_COMP_ARRAY(COMP_DUMMY()),
10185 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
10186 +
10187 +static struct snd_soc_dai_link pisnd_dai[] = {
10188 + {
10189 + .name = "pisound",
10190 + .stream_name = "pisound",
10191 + .dai_fmt =
10192 + SND_SOC_DAIFMT_I2S |
10193 + SND_SOC_DAIFMT_NB_NF |
10194 + SND_SOC_DAIFMT_CBM_CFM,
10195 + .ops = &pisnd_ops,
10196 + SND_SOC_DAILINK_REG(pisnd),
10197 + },
10198 +};
10199 +
10200 +static int pisnd_card_probe(struct snd_soc_card *card)
10201 +{
10202 + int err = pisnd_midi_init(card->snd_card);
10203 +
10204 + if (err < 0) {
10205 + printe("pisnd_midi_init failed: %d\n", err);
10206 + return err;
10207 + }
10208 +
10209 + err = pisnd_ctl_init(card->snd_card);
10210 + if (err < 0) {
10211 + printe("pisnd_ctl_init failed: %d\n", err);
10212 + return err;
10213 + }
10214 +
10215 + return 0;
10216 +}
10217 +
10218 +static int pisnd_card_remove(struct snd_soc_card *card)
10219 +{
10220 + pisnd_ctl_uninit();
10221 + pisnd_midi_uninit();
10222 + return 0;
10223 +}
10224 +
10225 +static struct snd_soc_card pisnd_card = {
10226 + .name = "pisound",
10227 + .owner = THIS_MODULE,
10228 + .dai_link = pisnd_dai,
10229 + .num_links = ARRAY_SIZE(pisnd_dai),
10230 + .probe = pisnd_card_probe,
10231 + .remove = pisnd_card_remove,
10232 +};
10233 +
10234 +static int pisnd_init_gpio(struct device *dev)
10235 +{
10236 + osr0 = gpiod_get_index(dev, "osr", 0, GPIOD_ASIS);
10237 + osr1 = gpiod_get_index(dev, "osr", 1, GPIOD_ASIS);
10238 + osr2 = gpiod_get_index(dev, "osr", 2, GPIOD_ASIS);
10239 +
10240 + reset = gpiod_get_index(dev, "reset", 0, GPIOD_ASIS);
10241 +
10242 + button = gpiod_get_index(dev, "button", 0, GPIOD_ASIS);
10243 +
10244 + gpiod_direction_output(osr0, 1);
10245 + gpiod_direction_output(osr1, 1);
10246 + gpiod_direction_output(osr2, 1);
10247 + gpiod_direction_output(reset, 1);
10248 +
10249 + gpiod_set_value(reset, false);
10250 + gpiod_set_value(osr0, true);
10251 + gpiod_set_value(osr1, false);
10252 + gpiod_set_value(osr2, false);
10253 + gpiod_set_value(reset, true);
10254 +
10255 + gpiod_export(button, false);
10256 +
10257 + return 0;
10258 +}
10259 +
10260 +static int pisnd_uninit_gpio(void)
10261 +{
10262 + int i;
10263 +
10264 + struct gpio_desc **gpios[] = {
10265 + &osr0, &osr1, &osr2, &reset, &button,
10266 + };
10267 +
10268 + gpiod_unexport(button);
10269 +
10270 + for (i = 0; i < ARRAY_SIZE(gpios); ++i) {
10271 + if (*gpios[i] == NULL) {
10272 + printd("weird, GPIO[%d] is NULL already\n", i);
10273 + continue;
10274 + }
10275 +
10276 + gpiod_put(*gpios[i]);
10277 + *gpios[i] = NULL;
10278 + }
10279 +
10280 + return 0;
10281 +}
10282 +
10283 +static struct kobject *pisnd_kobj;
10284 +
10285 +static ssize_t pisnd_serial_show(
10286 + struct kobject *kobj,
10287 + struct kobj_attribute *attr,
10288 + char *buf
10289 + )
10290 +{
10291 + return sprintf(buf, "%s\n", pisnd_spi_get_serial());
10292 +}
10293 +
10294 +static ssize_t pisnd_id_show(
10295 + struct kobject *kobj,
10296 + struct kobj_attribute *attr,
10297 + char *buf
10298 + )
10299 +{
10300 + return sprintf(buf, "%s\n", pisnd_spi_get_id());
10301 +}
10302 +
10303 +static ssize_t pisnd_fw_version_show(
10304 + struct kobject *kobj,
10305 + struct kobj_attribute *attr,
10306 + char *buf
10307 + )
10308 +{
10309 + return sprintf(buf, "%s\n", pisnd_spi_get_fw_version());
10310 +}
10311 +
10312 +static ssize_t pisnd_hw_version_show(
10313 + struct kobject *kobj,
10314 + struct kobj_attribute *attr,
10315 + char *buf
10316 +)
10317 +{
10318 + return sprintf(buf, "%s\n", pisnd_spi_get_hw_version());
10319 +}
10320 +
10321 +static ssize_t pisnd_led_store(
10322 + struct kobject *kobj,
10323 + struct kobj_attribute *attr,
10324 + const char *buf,
10325 + size_t length
10326 + )
10327 +{
10328 + uint32_t timeout;
10329 + int err;
10330 +
10331 + err = kstrtou32(buf, 10, &timeout);
10332 +
10333 + if (err == 0 && timeout <= 255)
10334 + pisnd_spi_flash_leds(timeout);
10335 +
10336 + return length;
10337 +}
10338 +
10339 +static struct kobj_attribute pisnd_serial_attribute =
10340 + __ATTR(serial, 0444, pisnd_serial_show, NULL);
10341 +static struct kobj_attribute pisnd_id_attribute =
10342 + __ATTR(id, 0444, pisnd_id_show, NULL);
10343 +static struct kobj_attribute pisnd_fw_version_attribute =
10344 + __ATTR(version, 0444, pisnd_fw_version_show, NULL);
10345 +static struct kobj_attribute pisnd_hw_version_attribute =
10346 +__ATTR(hw_version, 0444, pisnd_hw_version_show, NULL);
10347 +static struct kobj_attribute pisnd_led_attribute =
10348 + __ATTR(led, 0644, NULL, pisnd_led_store);
10349 +
10350 +static struct attribute *attrs[] = {
10351 + &pisnd_serial_attribute.attr,
10352 + &pisnd_id_attribute.attr,
10353 + &pisnd_fw_version_attribute.attr,
10354 + &pisnd_hw_version_attribute.attr,
10355 + &pisnd_led_attribute.attr,
10356 + NULL
10357 +};
10358 +
10359 +static struct attribute_group attr_group = { .attrs = attrs };
10360 +
10361 +static int pisnd_probe(struct platform_device *pdev)
10362 +{
10363 + int ret = 0;
10364 + int i;
10365 +
10366 + ret = pisnd_spi_init(&pdev->dev);
10367 + if (ret < 0) {
10368 + printe("pisnd_spi_init failed: %d\n", ret);
10369 + return ret;
10370 + }
10371 +
10372 + printi("Detected Pisound card:\n");
10373 + printi("\tSerial: %s\n", pisnd_spi_get_serial());
10374 + printi("\tFirmware Version: %s\n", pisnd_spi_get_fw_version());
10375 + printi("\tHardware Version: %s\n", pisnd_spi_get_hw_version());
10376 + printi("\tId: %s\n", pisnd_spi_get_id());
10377 +
10378 + pisnd_kobj = kobject_create_and_add("pisound", kernel_kobj);
10379 + if (!pisnd_kobj) {
10380 + pisnd_spi_uninit();
10381 + return -ENOMEM;
10382 + }
10383 +
10384 + ret = sysfs_create_group(pisnd_kobj, &attr_group);
10385 + if (ret < 0) {
10386 + pisnd_spi_uninit();
10387 + kobject_put(pisnd_kobj);
10388 + return -ENOMEM;
10389 + }
10390 +
10391 + pisnd_init_gpio(&pdev->dev);
10392 + pisnd_card.dev = &pdev->dev;
10393 +
10394 + if (pdev->dev.of_node) {
10395 + struct device_node *i2s_node;
10396 +
10397 + i2s_node = of_parse_phandle(
10398 + pdev->dev.of_node,
10399 + "i2s-controller",
10400 + 0
10401 + );
10402 +
10403 + for (i = 0; i < pisnd_card.num_links; ++i) {
10404 + struct snd_soc_dai_link *dai = &pisnd_dai[i];
10405 +
10406 + if (i2s_node) {
10407 + dai->cpus->dai_name = NULL;
10408 + dai->cpus->of_node = i2s_node;
10409 + dai->platforms->name = NULL;
10410 + dai->platforms->of_node = i2s_node;
10411 + dai->stream_name = pisnd_spi_get_serial();
10412 + }
10413 + }
10414 + }
10415 +
10416 + ret = snd_soc_register_card(&pisnd_card);
10417 +
10418 + if (ret < 0) {
10419 + if (ret != -EPROBE_DEFER)
10420 + printe("snd_soc_register_card() failed: %d\n", ret);
10421 + pisnd_uninit_gpio();
10422 + kobject_put(pisnd_kobj);
10423 + pisnd_spi_uninit();
10424 + }
10425 +
10426 + return ret;
10427 +}
10428 +
10429 +static int pisnd_remove(struct platform_device *pdev)
10430 +{
10431 + printi("Unloading.\n");
10432 +
10433 + if (pisnd_kobj) {
10434 + kobject_put(pisnd_kobj);
10435 + pisnd_kobj = NULL;
10436 + }
10437 +
10438 + pisnd_spi_uninit();
10439 +
10440 + /* Turn off */
10441 + gpiod_set_value(reset, false);
10442 + pisnd_uninit_gpio();
10443 +
10444 + return snd_soc_unregister_card(&pisnd_card);
10445 +}
10446 +
10447 +MODULE_DEVICE_TABLE(of, pisound_of_match);
10448 +
10449 +static struct platform_driver pisnd_driver = {
10450 + .driver = {
10451 + .name = "snd-rpi-pisound",
10452 + .owner = THIS_MODULE,
10453 + .of_match_table = pisound_of_match,
10454 + },
10455 + .probe = pisnd_probe,
10456 + .remove = pisnd_remove,
10457 +};
10458 +
10459 +module_platform_driver(pisnd_driver);
10460 +
10461 +MODULE_AUTHOR("Giedrius Trainavicius <giedrius@blokas.io>");
10462 +MODULE_DESCRIPTION("ASoC Driver for Pisound, https://blokas.io/pisound");
10463 +MODULE_LICENSE("GPL v2");
10464 --- /dev/null
10465 +++ b/sound/soc/bcm/rpi-cirrus.c
10466 @@ -0,0 +1,1025 @@
10467 +/*
10468 + * ASoC machine driver for Cirrus Logic Audio Card
10469 + * (with WM5102 and WM8804 codecs)
10470 + *
10471 + * Copyright 2015-2017 Matthias Reichl <hias@horus.com>
10472 + *
10473 + * Based on rpi-cirrus-sound-pi driver (c) Wolfson / Cirrus Logic Inc.
10474 + *
10475 + * This program is free software; you can redistribute it and/or modify
10476 + * it under the terms of the GNU General Public License version 2 as
10477 + * published by the Free Software Foundation.
10478 + */
10479 +
10480 +#include <linux/module.h>
10481 +#include <linux/mutex.h>
10482 +#include <linux/slab.h>
10483 +#include <linux/list.h>
10484 +#include <linux/delay.h>
10485 +#include <sound/pcm_params.h>
10486 +
10487 +#include <linux/mfd/arizona/registers.h>
10488 +
10489 +#include "../codecs/wm5102.h"
10490 +#include "../codecs/wm8804.h"
10491 +
10492 +#define WM8804_CLKOUT_HZ 12000000
10493 +
10494 +#define RPI_CIRRUS_DEFAULT_RATE 44100
10495 +#define WM5102_MAX_SYSCLK_1 49152000 /* max sysclk for 4K family */
10496 +#define WM5102_MAX_SYSCLK_2 45158400 /* max sysclk for 11.025K family */
10497 +
10498 +static inline unsigned int calc_sysclk(unsigned int rate)
10499 +{
10500 + return (rate % 4000) ? WM5102_MAX_SYSCLK_2 : WM5102_MAX_SYSCLK_1;
10501 +}
10502 +
10503 +enum {
10504 + DAI_WM5102 = 0,
10505 + DAI_WM8804,
10506 +};
10507 +
10508 +struct rpi_cirrus_priv {
10509 + /* mutex for synchronzing FLL1 access with DAPM */
10510 + struct mutex lock;
10511 + unsigned int card_rate;
10512 + int sync_path_enable;
10513 + int fll1_freq; /* negative means RefClock in spdif rx case */
10514 +
10515 + /* track hw params/free for substreams */
10516 + unsigned int params_set;
10517 + unsigned int min_rate_idx, max_rate_idx;
10518 + unsigned char iec958_status[4];
10519 +};
10520 +
10521 +/* helper functions */
10522 +static inline struct snd_soc_pcm_runtime *get_wm5102_runtime(
10523 + struct snd_soc_card *card) {
10524 + return snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_WM5102]);
10525 +}
10526 +
10527 +static inline struct snd_soc_pcm_runtime *get_wm8804_runtime(
10528 + struct snd_soc_card *card) {
10529 + return snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_WM8804]);
10530 +}
10531 +
10532 +
10533 +struct rate_info {
10534 + unsigned int value;
10535 + char *text;
10536 +};
10537 +
10538 +static struct rate_info min_rates[] = {
10539 + { 0, "off"},
10540 + { 32000, "32kHz"},
10541 + { 44100, "44.1kHz"}
10542 +};
10543 +
10544 +#define NUM_MIN_RATES ARRAY_SIZE(min_rates)
10545 +
10546 +static int rpi_cirrus_min_rate_info(struct snd_kcontrol *kcontrol,
10547 + struct snd_ctl_elem_info *uinfo)
10548 +{
10549 + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
10550 + uinfo->count = 1;
10551 + uinfo->value.enumerated.items = NUM_MIN_RATES;
10552 +
10553 + if (uinfo->value.enumerated.item >= NUM_MIN_RATES)
10554 + uinfo->value.enumerated.item = NUM_MIN_RATES - 1;
10555 + strcpy(uinfo->value.enumerated.name,
10556 + min_rates[uinfo->value.enumerated.item].text);
10557 + return 0;
10558 +}
10559 +
10560 +static int rpi_cirrus_min_rate_get(struct snd_kcontrol *kcontrol,
10561 + struct snd_ctl_elem_value *ucontrol)
10562 +{
10563 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
10564 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
10565 +
10566 + ucontrol->value.enumerated.item[0] = priv->min_rate_idx;
10567 + return 0;
10568 +}
10569 +
10570 +static int rpi_cirrus_min_rate_put(struct snd_kcontrol *kcontrol,
10571 + struct snd_ctl_elem_value *ucontrol)
10572 +{
10573 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
10574 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
10575 + int changed = 0;
10576 +
10577 + if (priv->min_rate_idx != ucontrol->value.enumerated.item[0]) {
10578 + changed = 1;
10579 + priv->min_rate_idx = ucontrol->value.enumerated.item[0];
10580 + }
10581 +
10582 + return changed;
10583 +}
10584 +
10585 +static struct rate_info max_rates[] = {
10586 + { 0, "off"},
10587 + { 48000, "48kHz"},
10588 + { 96000, "96kHz"}
10589 +};
10590 +
10591 +#define NUM_MAX_RATES ARRAY_SIZE(max_rates)
10592 +
10593 +static int rpi_cirrus_max_rate_info(struct snd_kcontrol *kcontrol,
10594 + struct snd_ctl_elem_info *uinfo)
10595 +{
10596 + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
10597 + uinfo->count = 1;
10598 + uinfo->value.enumerated.items = NUM_MAX_RATES;
10599 + if (uinfo->value.enumerated.item >= NUM_MAX_RATES)
10600 + uinfo->value.enumerated.item = NUM_MAX_RATES - 1;
10601 + strcpy(uinfo->value.enumerated.name,
10602 + max_rates[uinfo->value.enumerated.item].text);
10603 + return 0;
10604 +}
10605 +
10606 +static int rpi_cirrus_max_rate_get(struct snd_kcontrol *kcontrol,
10607 + struct snd_ctl_elem_value *ucontrol)
10608 +{
10609 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
10610 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
10611 +
10612 + ucontrol->value.enumerated.item[0] = priv->max_rate_idx;
10613 + return 0;
10614 +}
10615 +
10616 +static int rpi_cirrus_max_rate_put(struct snd_kcontrol *kcontrol,
10617 + struct snd_ctl_elem_value *ucontrol)
10618 +{
10619 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
10620 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
10621 + int changed = 0;
10622 +
10623 + if (priv->max_rate_idx != ucontrol->value.enumerated.item[0]) {
10624 + changed = 1;
10625 + priv->max_rate_idx = ucontrol->value.enumerated.item[0];
10626 + }
10627 +
10628 + return changed;
10629 +}
10630 +
10631 +static int rpi_cirrus_spdif_info(struct snd_kcontrol *kcontrol,
10632 + struct snd_ctl_elem_info *uinfo)
10633 +{
10634 + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
10635 + uinfo->count = 1;
10636 + return 0;
10637 +}
10638 +
10639 +static int rpi_cirrus_spdif_playback_get(struct snd_kcontrol *kcontrol,
10640 + struct snd_ctl_elem_value *ucontrol)
10641 +{
10642 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
10643 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
10644 + int i;
10645 +
10646 + for (i = 0; i < 4; i++)
10647 + ucontrol->value.iec958.status[i] = priv->iec958_status[i];
10648 +
10649 + return 0;
10650 +}
10651 +
10652 +static int rpi_cirrus_spdif_playback_put(struct snd_kcontrol *kcontrol,
10653 + struct snd_ctl_elem_value *ucontrol)
10654 +{
10655 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
10656 + struct snd_soc_component *wm8804_component =
10657 + asoc_rtd_to_codec(get_wm8804_runtime(card), 0)->component;
10658 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
10659 + unsigned char *stat = priv->iec958_status;
10660 + unsigned char *ctrl_stat = ucontrol->value.iec958.status;
10661 + unsigned int mask;
10662 + int i, changed = 0;
10663 +
10664 + for (i = 0; i < 4; i++) {
10665 + mask = (i == 3) ? 0x3f : 0xff;
10666 + if ((ctrl_stat[i] & mask) != (stat[i] & mask)) {
10667 + changed = 1;
10668 + stat[i] = ctrl_stat[i] & mask;
10669 + snd_soc_component_update_bits(wm8804_component,
10670 + WM8804_SPDTX1 + i, mask, stat[i]);
10671 + }
10672 + }
10673 +
10674 + return changed;
10675 +}
10676 +
10677 +static int rpi_cirrus_spdif_mask_get(struct snd_kcontrol *kcontrol,
10678 + struct snd_ctl_elem_value *ucontrol)
10679 +{
10680 + ucontrol->value.iec958.status[0] = 0xff;
10681 + ucontrol->value.iec958.status[1] = 0xff;
10682 + ucontrol->value.iec958.status[2] = 0xff;
10683 + ucontrol->value.iec958.status[3] = 0x3f;
10684 +
10685 + return 0;
10686 +}
10687 +
10688 +static int rpi_cirrus_spdif_capture_get(struct snd_kcontrol *kcontrol,
10689 + struct snd_ctl_elem_value *ucontrol)
10690 +{
10691 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
10692 + struct snd_soc_component *wm8804_component =
10693 + asoc_rtd_to_codec(get_wm8804_runtime(card), 0)->component;
10694 + unsigned int val, mask;
10695 + int i;
10696 +
10697 + for (i = 0; i < 4; i++) {
10698 + val = snd_soc_component_read(wm8804_component,
10699 + WM8804_RXCHAN1 + i);
10700 + mask = (i == 3) ? 0x3f : 0xff;
10701 + ucontrol->value.iec958.status[i] = val & mask;
10702 + }
10703 +
10704 + return 0;
10705 +}
10706 +
10707 +#define SPDIF_FLAG_CTRL(desc, reg, bit, invert) \
10708 +{ \
10709 + .access = SNDRV_CTL_ELEM_ACCESS_READ \
10710 + | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
10711 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
10712 + .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) \
10713 + desc " Flag", \
10714 + .info = snd_ctl_boolean_mono_info, \
10715 + .get = rpi_cirrus_spdif_status_flag_get, \
10716 + .private_value = \
10717 + (bit) | ((reg) << 8) | ((invert) << 16) \
10718 +}
10719 +
10720 +static int rpi_cirrus_spdif_status_flag_get(struct snd_kcontrol *kcontrol,
10721 + struct snd_ctl_elem_value *ucontrol)
10722 +{
10723 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
10724 + struct snd_soc_component *wm8804_component =
10725 + asoc_rtd_to_codec(get_wm8804_runtime(card), 0)->component;
10726 +
10727 + unsigned int bit = kcontrol->private_value & 0xff;
10728 + unsigned int reg = (kcontrol->private_value >> 8) & 0xff;
10729 + unsigned int invert = (kcontrol->private_value >> 16) & 0xff;
10730 + unsigned int val;
10731 + bool flag;
10732 +
10733 + val = snd_soc_component_read(wm8804_component, reg);
10734 +
10735 + flag = val & (1 << bit);
10736 +
10737 + ucontrol->value.integer.value[0] = invert ? !flag : flag;
10738 +
10739 + return 0;
10740 +}
10741 +
10742 +static const char * const recovered_frequency_texts[] = {
10743 + "176.4/192 kHz",
10744 + "88.2/96 kHz",
10745 + "44.1/48 kHz",
10746 + "32 kHz"
10747 +};
10748 +
10749 +#define NUM_RECOVERED_FREQUENCIES \
10750 + ARRAY_SIZE(recovered_frequency_texts)
10751 +
10752 +static int rpi_cirrus_recovered_frequency_info(struct snd_kcontrol *kcontrol,
10753 + struct snd_ctl_elem_info *uinfo)
10754 +{
10755 + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
10756 + uinfo->count = 1;
10757 + uinfo->value.enumerated.items = NUM_RECOVERED_FREQUENCIES;
10758 + if (uinfo->value.enumerated.item >= NUM_RECOVERED_FREQUENCIES)
10759 + uinfo->value.enumerated.item = NUM_RECOVERED_FREQUENCIES - 1;
10760 + strcpy(uinfo->value.enumerated.name,
10761 + recovered_frequency_texts[uinfo->value.enumerated.item]);
10762 + return 0;
10763 +}
10764 +
10765 +static int rpi_cirrus_recovered_frequency_get(struct snd_kcontrol *kcontrol,
10766 + struct snd_ctl_elem_value *ucontrol)
10767 +{
10768 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
10769 + struct snd_soc_component *wm8804_component =
10770 + asoc_rtd_to_codec(get_wm8804_runtime(card), 0)->component;
10771 + unsigned int val;
10772 +
10773 + val = snd_soc_component_read(wm8804_component, WM8804_SPDSTAT);
10774 +
10775 + ucontrol->value.enumerated.item[0] = (val >> 4) & 0x03;
10776 + return 0;
10777 +}
10778 +
10779 +static const struct snd_kcontrol_new rpi_cirrus_controls[] = {
10780 + {
10781 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10782 + .name = "Min Sample Rate",
10783 + .info = rpi_cirrus_min_rate_info,
10784 + .get = rpi_cirrus_min_rate_get,
10785 + .put = rpi_cirrus_min_rate_put,
10786 + },
10787 + {
10788 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10789 + .name = "Max Sample Rate",
10790 + .info = rpi_cirrus_max_rate_info,
10791 + .get = rpi_cirrus_max_rate_get,
10792 + .put = rpi_cirrus_max_rate_put,
10793 + },
10794 + {
10795 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10796 + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
10797 + .info = rpi_cirrus_spdif_info,
10798 + .get = rpi_cirrus_spdif_playback_get,
10799 + .put = rpi_cirrus_spdif_playback_put,
10800 + },
10801 + {
10802 + .access = SNDRV_CTL_ELEM_ACCESS_READ
10803 + | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
10804 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10805 + .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
10806 + .info = rpi_cirrus_spdif_info,
10807 + .get = rpi_cirrus_spdif_capture_get,
10808 + },
10809 + {
10810 + .access = SNDRV_CTL_ELEM_ACCESS_READ,
10811 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10812 + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
10813 + .info = rpi_cirrus_spdif_info,
10814 + .get = rpi_cirrus_spdif_mask_get,
10815 + },
10816 + {
10817 + .access = SNDRV_CTL_ELEM_ACCESS_READ
10818 + | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
10819 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10820 + .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE)
10821 + "Recovered Frequency",
10822 + .info = rpi_cirrus_recovered_frequency_info,
10823 + .get = rpi_cirrus_recovered_frequency_get,
10824 + },
10825 + SPDIF_FLAG_CTRL("Audio", WM8804_SPDSTAT, 0, 1),
10826 + SPDIF_FLAG_CTRL("Non-PCM", WM8804_SPDSTAT, 1, 0),
10827 + SPDIF_FLAG_CTRL("Copyright", WM8804_SPDSTAT, 2, 1),
10828 + SPDIF_FLAG_CTRL("De-Emphasis", WM8804_SPDSTAT, 3, 0),
10829 + SPDIF_FLAG_CTRL("Lock", WM8804_SPDSTAT, 6, 1),
10830 + SPDIF_FLAG_CTRL("Invalid", WM8804_INTSTAT, 1, 0),
10831 + SPDIF_FLAG_CTRL("TransErr", WM8804_INTSTAT, 3, 0),
10832 +};
10833 +
10834 +static const char * const linein_micbias_texts[] = {
10835 + "off", "on",
10836 +};
10837 +
10838 +static SOC_ENUM_SINGLE_VIRT_DECL(linein_micbias_enum,
10839 + linein_micbias_texts);
10840 +
10841 +static const struct snd_kcontrol_new linein_micbias_mux =
10842 + SOC_DAPM_ENUM("Route", linein_micbias_enum);
10843 +
10844 +static int rpi_cirrus_spdif_rx_enable_event(struct snd_soc_dapm_widget *w,
10845 + struct snd_kcontrol *kcontrol, int event);
10846 +
10847 +const struct snd_soc_dapm_widget rpi_cirrus_dapm_widgets[] = {
10848 + SND_SOC_DAPM_MIC("DMIC", NULL),
10849 + SND_SOC_DAPM_MIC("Headset Mic", NULL),
10850 + SND_SOC_DAPM_INPUT("Line Input"),
10851 + SND_SOC_DAPM_MIC("Line Input with Micbias", NULL),
10852 + SND_SOC_DAPM_MUX("Line Input Micbias", SND_SOC_NOPM, 0, 0,
10853 + &linein_micbias_mux),
10854 + SND_SOC_DAPM_INPUT("dummy SPDIF in"),
10855 + SND_SOC_DAPM_PGA_E("dummy SPDIFRX", SND_SOC_NOPM, 0, 0, NULL, 0,
10856 + rpi_cirrus_spdif_rx_enable_event,
10857 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
10858 + SND_SOC_DAPM_INPUT("Dummy Input"),
10859 + SND_SOC_DAPM_OUTPUT("Dummy Output"),
10860 +};
10861 +
10862 +const struct snd_soc_dapm_route rpi_cirrus_dapm_routes[] = {
10863 + { "IN1L", NULL, "Headset Mic" },
10864 + { "IN1R", NULL, "Headset Mic" },
10865 + { "Headset Mic", NULL, "MICBIAS1" },
10866 +
10867 + { "IN2L", NULL, "DMIC" },
10868 + { "IN2R", NULL, "DMIC" },
10869 + { "DMIC", NULL, "MICBIAS2" },
10870 +
10871 + { "IN3L", NULL, "Line Input Micbias" },
10872 + { "IN3R", NULL, "Line Input Micbias" },
10873 +
10874 + { "Line Input Micbias", "off", "Line Input" },
10875 + { "Line Input Micbias", "on", "Line Input with Micbias" },
10876 +
10877 + /* Make sure MICVDD is enabled, otherwise we get noise */
10878 + { "Line Input", NULL, "MICVDD" },
10879 + { "Line Input with Micbias", NULL, "MICBIAS3" },
10880 +
10881 + /* Dummy routes to check whether SPDIF RX is enabled or not */
10882 + {"dummy SPDIFRX", NULL, "dummy SPDIF in"},
10883 + {"AIFTX", NULL, "dummy SPDIFRX"},
10884 +
10885 + /*
10886 + * Dummy routes to keep wm5102 from staying off on
10887 + * playback/capture if all mixers are off.
10888 + */
10889 + { "Dummy Output", NULL, "AIF1RX1" },
10890 + { "Dummy Output", NULL, "AIF1RX2" },
10891 + { "AIF1TX1", NULL, "Dummy Input" },
10892 + { "AIF1TX2", NULL, "Dummy Input" },
10893 +};
10894 +
10895 +static int rpi_cirrus_clear_flls(struct snd_soc_card *card,
10896 + struct snd_soc_component *wm5102_component) {
10897 +
10898 + int ret1, ret2;
10899 +
10900 + ret1 = snd_soc_component_set_pll(wm5102_component,
10901 + WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0);
10902 + ret2 = snd_soc_component_set_pll(wm5102_component,
10903 + WM5102_FLL1_REFCLK, ARIZONA_FLL_SRC_NONE, 0, 0);
10904 +
10905 + if (ret1) {
10906 + dev_warn(card->dev,
10907 + "setting FLL1 to zero failed: %d\n", ret1);
10908 + return ret1;
10909 + }
10910 + if (ret2) {
10911 + dev_warn(card->dev,
10912 + "setting FLL1_REFCLK to zero failed: %d\n", ret2);
10913 + return ret2;
10914 + }
10915 + return 0;
10916 +}
10917 +
10918 +static int rpi_cirrus_set_fll(struct snd_soc_card *card,
10919 + struct snd_soc_component *wm5102_component, unsigned int clk_freq)
10920 +{
10921 + int ret = snd_soc_component_set_pll(wm5102_component,
10922 + WM5102_FLL1,
10923 + ARIZONA_CLK_SRC_MCLK1,
10924 + WM8804_CLKOUT_HZ,
10925 + clk_freq);
10926 + if (ret)
10927 + dev_err(card->dev, "Failed to set FLL1 to %d: %d\n",
10928 + clk_freq, ret);
10929 +
10930 + usleep_range(1000, 2000);
10931 + return ret;
10932 +}
10933 +
10934 +static int rpi_cirrus_set_fll_refclk(struct snd_soc_card *card,
10935 + struct snd_soc_component *wm5102_component,
10936 + unsigned int clk_freq, unsigned int aif2_freq)
10937 +{
10938 + int ret = snd_soc_component_set_pll(wm5102_component,
10939 + WM5102_FLL1_REFCLK,
10940 + ARIZONA_CLK_SRC_MCLK1,
10941 + WM8804_CLKOUT_HZ,
10942 + clk_freq);
10943 + if (ret) {
10944 + dev_err(card->dev,
10945 + "Failed to set FLL1_REFCLK to %d: %d\n",
10946 + clk_freq, ret);
10947 + return ret;
10948 + }
10949 +
10950 + ret = snd_soc_component_set_pll(wm5102_component,
10951 + WM5102_FLL1,
10952 + ARIZONA_CLK_SRC_AIF2BCLK,
10953 + aif2_freq, clk_freq);
10954 + if (ret)
10955 + dev_err(card->dev,
10956 + "Failed to set FLL1 with Sync Clock %d to %d: %d\n",
10957 + aif2_freq, clk_freq, ret);
10958 +
10959 + usleep_range(1000, 2000);
10960 + return ret;
10961 +}
10962 +
10963 +static int rpi_cirrus_spdif_rx_enable_event(struct snd_soc_dapm_widget *w,
10964 + struct snd_kcontrol *kcontrol, int event)
10965 +{
10966 + struct snd_soc_card *card = w->dapm->card;
10967 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
10968 + struct snd_soc_component *wm5102_component =
10969 + asoc_rtd_to_codec(get_wm5102_runtime(card), 0)->component;
10970 +
10971 + unsigned int clk_freq, aif2_freq;
10972 + int ret = 0;
10973 +
10974 + switch (event) {
10975 + case SND_SOC_DAPM_POST_PMU:
10976 + mutex_lock(&priv->lock);
10977 +
10978 + /* Enable sync path in case of SPDIF capture use case */
10979 +
10980 + clk_freq = calc_sysclk(priv->card_rate);
10981 + aif2_freq = 64 * priv->card_rate;
10982 +
10983 + dev_dbg(card->dev,
10984 + "spdif_rx: changing FLL1 to use Ref Clock clk: %d spdif: %d\n",
10985 + clk_freq, aif2_freq);
10986 +
10987 + ret = rpi_cirrus_clear_flls(card, wm5102_component);
10988 + if (ret) {
10989 + dev_err(card->dev, "spdif_rx: failed to clear FLLs\n");
10990 + goto out;
10991 + }
10992 +
10993 + ret = rpi_cirrus_set_fll_refclk(card, wm5102_component,
10994 + clk_freq, aif2_freq);
10995 +
10996 + if (ret) {
10997 + dev_err(card->dev, "spdif_rx: failed to set FLLs\n");
10998 + goto out;
10999 + }
11000 +
11001 + /* set to negative to indicate we're doing spdif rx */
11002 + priv->fll1_freq = -clk_freq;
11003 + priv->sync_path_enable = 1;
11004 + break;
11005 +
11006 + case SND_SOC_DAPM_POST_PMD:
11007 + mutex_lock(&priv->lock);
11008 + priv->sync_path_enable = 0;
11009 + break;
11010 +
11011 + default:
11012 + return 0;
11013 + }
11014 +
11015 +out:
11016 + mutex_unlock(&priv->lock);
11017 + return ret;
11018 +}
11019 +
11020 +static int rpi_cirrus_set_bias_level(struct snd_soc_card *card,
11021 + struct snd_soc_dapm_context *dapm,
11022 + enum snd_soc_bias_level level)
11023 +{
11024 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
11025 + struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card);
11026 + struct snd_soc_component *wm5102_component =
11027 + asoc_rtd_to_codec(wm5102_runtime, 0)->component;
11028 +
11029 + int ret = 0;
11030 + unsigned int clk_freq;
11031 +
11032 + if (dapm->dev != asoc_rtd_to_codec(wm5102_runtime, 0)->dev)
11033 + return 0;
11034 +
11035 + switch (level) {
11036 + case SND_SOC_BIAS_PREPARE:
11037 + if (dapm->bias_level == SND_SOC_BIAS_ON)
11038 + break;
11039 +
11040 + mutex_lock(&priv->lock);
11041 +
11042 + if (!priv->sync_path_enable) {
11043 + clk_freq = calc_sysclk(priv->card_rate);
11044 +
11045 + dev_dbg(card->dev,
11046 + "set_bias: changing FLL1 from %d to %d\n",
11047 + priv->fll1_freq, clk_freq);
11048 +
11049 + ret = rpi_cirrus_set_fll(card,
11050 + wm5102_component, clk_freq);
11051 + if (ret)
11052 + dev_err(card->dev,
11053 + "set_bias: Failed to set FLL1\n");
11054 + else
11055 + priv->fll1_freq = clk_freq;
11056 + }
11057 + mutex_unlock(&priv->lock);
11058 + break;
11059 + default:
11060 + break;
11061 + }
11062 +
11063 + return ret;
11064 +}
11065 +
11066 +static int rpi_cirrus_set_bias_level_post(struct snd_soc_card *card,
11067 + struct snd_soc_dapm_context *dapm,
11068 + enum snd_soc_bias_level level)
11069 +{
11070 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
11071 + struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card);
11072 + struct snd_soc_component *wm5102_component =
11073 + asoc_rtd_to_codec(wm5102_runtime, 0)->component;
11074 +
11075 + if (dapm->dev != asoc_rtd_to_codec(wm5102_runtime, 0)->dev)
11076 + return 0;
11077 +
11078 + switch (level) {
11079 + case SND_SOC_BIAS_STANDBY:
11080 + mutex_lock(&priv->lock);
11081 +
11082 + dev_dbg(card->dev,
11083 + "set_bias_post: changing FLL1 from %d to off\n",
11084 + priv->fll1_freq);
11085 +
11086 + if (rpi_cirrus_clear_flls(card, wm5102_component))
11087 + dev_err(card->dev,
11088 + "set_bias_post: failed to clear FLLs\n");
11089 + else
11090 + priv->fll1_freq = 0;
11091 +
11092 + mutex_unlock(&priv->lock);
11093 +
11094 + break;
11095 + default:
11096 + break;
11097 + }
11098 +
11099 + return 0;
11100 +}
11101 +
11102 +static int rpi_cirrus_set_wm8804_pll(struct snd_soc_card *card,
11103 + struct snd_soc_dai *wm8804_dai, unsigned int rate)
11104 +{
11105 + int ret;
11106 +
11107 + /* use 256fs */
11108 + unsigned int clk_freq = rate * 256;
11109 +
11110 + ret = snd_soc_dai_set_pll(wm8804_dai, 0, 0,
11111 + WM8804_CLKOUT_HZ, clk_freq);
11112 + if (ret) {
11113 + dev_err(card->dev,
11114 + "Failed to set WM8804 PLL to %d: %d\n", clk_freq, ret);
11115 + return ret;
11116 + }
11117 +
11118 + /* Set MCLK as PLL Output */
11119 + ret = snd_soc_dai_set_sysclk(wm8804_dai,
11120 + WM8804_TX_CLKSRC_PLL, clk_freq, 0);
11121 + if (ret) {
11122 + dev_err(card->dev,
11123 + "Failed to set MCLK as PLL Output: %d\n", ret);
11124 + return ret;
11125 + }
11126 +
11127 + return ret;
11128 +}
11129 +
11130 +static int rpi_cirrus_startup(struct snd_pcm_substream *substream)
11131 +{
11132 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
11133 + struct snd_soc_card *card = rtd->card;
11134 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
11135 + unsigned int min_rate = min_rates[priv->min_rate_idx].value;
11136 + unsigned int max_rate = max_rates[priv->max_rate_idx].value;
11137 +
11138 + if (min_rate || max_rate) {
11139 + if (max_rate == 0)
11140 + max_rate = UINT_MAX;
11141 +
11142 + dev_dbg(card->dev,
11143 + "startup: limiting rate to %u-%u\n",
11144 + min_rate, max_rate);
11145 +
11146 + snd_pcm_hw_constraint_minmax(substream->runtime,
11147 + SNDRV_PCM_HW_PARAM_RATE, min_rate, max_rate);
11148 + }
11149 +
11150 + return 0;
11151 +}
11152 +
11153 +static struct snd_soc_pcm_stream rpi_cirrus_dai_link2_params = {
11154 + .formats = SNDRV_PCM_FMTBIT_S24_LE,
11155 + .channels_min = 2,
11156 + .channels_max = 2,
11157 + .rate_min = RPI_CIRRUS_DEFAULT_RATE,
11158 + .rate_max = RPI_CIRRUS_DEFAULT_RATE,
11159 +};
11160 +
11161 +static int rpi_cirrus_hw_params(struct snd_pcm_substream *substream,
11162 + struct snd_pcm_hw_params *params)
11163 +{
11164 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
11165 + struct snd_soc_card *card = rtd->card;
11166 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
11167 + struct snd_soc_dai *bcm_i2s_dai = asoc_rtd_to_cpu(rtd, 0);
11168 + struct snd_soc_component *wm5102_component = asoc_rtd_to_codec(rtd, 0)->component;
11169 + struct snd_soc_dai *wm8804_dai = asoc_rtd_to_codec(get_wm8804_runtime(card), 0);
11170 +
11171 + int ret;
11172 +
11173 + unsigned int width = snd_pcm_format_physical_width(
11174 + params_format(params));
11175 + unsigned int rate = params_rate(params);
11176 + unsigned int clk_freq = calc_sysclk(rate);
11177 +
11178 + mutex_lock(&priv->lock);
11179 +
11180 + dev_dbg(card->dev, "hw_params: setting rate to %d\n", rate);
11181 +
11182 + ret = snd_soc_dai_set_bclk_ratio(bcm_i2s_dai, 2 * width);
11183 + if (ret) {
11184 + dev_err(card->dev, "set_bclk_ratio failed: %d\n", ret);
11185 + goto out;
11186 + }
11187 +
11188 + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 0x03, 0x03, 2, width);
11189 + if (ret) {
11190 + dev_err(card->dev, "set_tdm_slot failed: %d\n", ret);
11191 + goto out;
11192 + }
11193 +
11194 + /* WM8804 supports sample rates from 32k only */
11195 + if (rate >= 32000) {
11196 + ret = rpi_cirrus_set_wm8804_pll(card, wm8804_dai, rate);
11197 + if (ret)
11198 + goto out;
11199 + }
11200 +
11201 + ret = snd_soc_component_set_sysclk(wm5102_component,
11202 + ARIZONA_CLK_SYSCLK,
11203 + ARIZONA_CLK_SRC_FLL1,
11204 + clk_freq,
11205 + SND_SOC_CLOCK_IN);
11206 + if (ret) {
11207 + dev_err(card->dev, "Failed to set SYSCLK: %d\n", ret);
11208 + goto out;
11209 + }
11210 +
11211 + if ((priv->fll1_freq > 0) && (priv->fll1_freq != clk_freq)) {
11212 + dev_dbg(card->dev,
11213 + "hw_params: changing FLL1 from %d to %d\n",
11214 + priv->fll1_freq, clk_freq);
11215 +
11216 + if (rpi_cirrus_clear_flls(card, wm5102_component)) {
11217 + dev_err(card->dev, "hw_params: failed to clear FLLs\n");
11218 + goto out;
11219 + }
11220 +
11221 + if (rpi_cirrus_set_fll(card, wm5102_component, clk_freq)) {
11222 + dev_err(card->dev, "hw_params: failed to set FLL\n");
11223 + goto out;
11224 + }
11225 +
11226 + priv->fll1_freq = clk_freq;
11227 + }
11228 +
11229 + priv->card_rate = rate;
11230 + rpi_cirrus_dai_link2_params.rate_min = rate;
11231 + rpi_cirrus_dai_link2_params.rate_max = rate;
11232 +
11233 + priv->params_set |= 1 << substream->stream;
11234 +
11235 +out:
11236 + mutex_unlock(&priv->lock);
11237 +
11238 + return ret;
11239 +}
11240 +
11241 +static int rpi_cirrus_hw_free(struct snd_pcm_substream *substream)
11242 +{
11243 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
11244 + struct snd_soc_card *card = rtd->card;
11245 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
11246 + struct snd_soc_component *wm5102_component = asoc_rtd_to_codec(rtd, 0)->component;
11247 + int ret;
11248 + unsigned int old_params_set = priv->params_set;
11249 +
11250 + priv->params_set &= ~(1 << substream->stream);
11251 +
11252 + /* disable sysclk if this was the last open stream */
11253 + if (priv->params_set == 0 && old_params_set) {
11254 + dev_dbg(card->dev,
11255 + "hw_free: Setting SYSCLK to Zero\n");
11256 +
11257 + ret = snd_soc_component_set_sysclk(wm5102_component,
11258 + ARIZONA_CLK_SYSCLK,
11259 + ARIZONA_CLK_SRC_FLL1,
11260 + 0,
11261 + SND_SOC_CLOCK_IN);
11262 + if (ret)
11263 + dev_err(card->dev,
11264 + "hw_free: Failed to set SYSCLK to Zero: %d\n",
11265 + ret);
11266 + }
11267 + return 0;
11268 +}
11269 +
11270 +static int rpi_cirrus_init_wm5102(struct snd_soc_pcm_runtime *rtd)
11271 +{
11272 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
11273 + int ret;
11274 +
11275 + /* no 32kHz input, derive it from sysclk if needed */
11276 + snd_soc_component_update_bits(component,
11277 + ARIZONA_CLOCK_32K_1, ARIZONA_CLK_32K_SRC_MASK, 2);
11278 +
11279 + if (rpi_cirrus_clear_flls(rtd->card, component))
11280 + dev_warn(rtd->card->dev,
11281 + "init_wm5102: failed to clear FLLs\n");
11282 +
11283 + ret = snd_soc_component_set_sysclk(component,
11284 + ARIZONA_CLK_SYSCLK, ARIZONA_CLK_SRC_FLL1,
11285 + 0, SND_SOC_CLOCK_IN);
11286 + if (ret) {
11287 + dev_err(rtd->card->dev,
11288 + "Failed to set SYSCLK to Zero: %d\n", ret);
11289 + return ret;
11290 + }
11291 +
11292 + return 0;
11293 +}
11294 +
11295 +static int rpi_cirrus_init_wm8804(struct snd_soc_pcm_runtime *rtd)
11296 +{
11297 + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
11298 + struct snd_soc_component *component = codec_dai->component;
11299 + struct snd_soc_card *card = rtd->card;
11300 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
11301 + unsigned int val, mask;
11302 + int i, ret;
11303 +
11304 + for (i = 0; i < 4; i++) {
11305 + val = snd_soc_component_read(component,
11306 + WM8804_SPDTX1 + i);
11307 + mask = (i == 3) ? 0x3f : 0xff;
11308 + priv->iec958_status[i] = val & mask;
11309 + }
11310 +
11311 + /* Setup for 256fs */
11312 + ret = snd_soc_dai_set_clkdiv(codec_dai,
11313 + WM8804_MCLK_DIV, WM8804_MCLKDIV_256FS);
11314 + if (ret) {
11315 + dev_err(card->dev,
11316 + "init_wm8804: Failed to set MCLK_DIV to 256fs: %d\n",
11317 + ret);
11318 + return ret;
11319 + }
11320 +
11321 + /* Output OSC on CLKOUT */
11322 + ret = snd_soc_dai_set_sysclk(codec_dai,
11323 + WM8804_CLKOUT_SRC_OSCCLK, WM8804_CLKOUT_HZ, 0);
11324 + if (ret)
11325 + dev_err(card->dev,
11326 + "init_wm8804: Failed to set CLKOUT as OSC Frequency: %d\n",
11327 + ret);
11328 +
11329 + /* Init PLL with default samplerate */
11330 + ret = rpi_cirrus_set_wm8804_pll(card, codec_dai,
11331 + RPI_CIRRUS_DEFAULT_RATE);
11332 + if (ret)
11333 + dev_err(card->dev,
11334 + "init_wm8804: Failed to setup PLL for %dHz: %d\n",
11335 + RPI_CIRRUS_DEFAULT_RATE, ret);
11336 +
11337 + return ret;
11338 +}
11339 +
11340 +static struct snd_soc_ops rpi_cirrus_ops = {
11341 + .startup = rpi_cirrus_startup,
11342 + .hw_params = rpi_cirrus_hw_params,
11343 + .hw_free = rpi_cirrus_hw_free,
11344 +};
11345 +
11346 +SND_SOC_DAILINK_DEFS(wm5102,
11347 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
11348 + DAILINK_COMP_ARRAY(COMP_CODEC("wm5102-codec", "wm5102-aif1")),
11349 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
11350 +
11351 +SND_SOC_DAILINK_DEFS(wm8804,
11352 + DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif2")),
11353 + DAILINK_COMP_ARRAY(COMP_CODEC("wm8804.1-003b", "wm8804-spdif")));
11354 +
11355 +static struct snd_soc_dai_link rpi_cirrus_dai[] = {
11356 + [DAI_WM5102] = {
11357 + .name = "WM5102",
11358 + .stream_name = "WM5102 AiFi",
11359 + .dai_fmt = SND_SOC_DAIFMT_I2S
11360 + | SND_SOC_DAIFMT_NB_NF
11361 + | SND_SOC_DAIFMT_CBM_CFM,
11362 + .ops = &rpi_cirrus_ops,
11363 + .init = rpi_cirrus_init_wm5102,
11364 + SND_SOC_DAILINK_REG(wm5102),
11365 + },
11366 + [DAI_WM8804] = {
11367 + .name = "WM5102 SPDIF",
11368 + .stream_name = "SPDIF Tx/Rx",
11369 + .dai_fmt = SND_SOC_DAIFMT_I2S
11370 + | SND_SOC_DAIFMT_NB_NF
11371 + | SND_SOC_DAIFMT_CBM_CFM,
11372 + .ignore_suspend = 1,
11373 + .params = &rpi_cirrus_dai_link2_params,
11374 + .init = rpi_cirrus_init_wm8804,
11375 + SND_SOC_DAILINK_REG(wm8804),
11376 + },
11377 +};
11378 +
11379 +
11380 +static int rpi_cirrus_late_probe(struct snd_soc_card *card)
11381 +{
11382 + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
11383 + struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card);
11384 + struct snd_soc_pcm_runtime *wm8804_runtime = get_wm8804_runtime(card);
11385 + int ret;
11386 +
11387 + dev_dbg(card->dev, "iec958_bits: %02x %02x %02x %02x\n",
11388 + priv->iec958_status[0],
11389 + priv->iec958_status[1],
11390 + priv->iec958_status[2],
11391 + priv->iec958_status[3]);
11392 +
11393 + ret = snd_soc_dai_set_sysclk(
11394 + asoc_rtd_to_codec(wm5102_runtime, 0), ARIZONA_CLK_SYSCLK, 0, 0);
11395 + if (ret) {
11396 + dev_err(card->dev,
11397 + "Failed to set WM5102 codec dai clk domain: %d\n", ret);
11398 + return ret;
11399 + }
11400 +
11401 + ret = snd_soc_dai_set_sysclk(
11402 + asoc_rtd_to_cpu(wm8804_runtime, 0), ARIZONA_CLK_SYSCLK, 0, 0);
11403 + if (ret)
11404 + dev_err(card->dev,
11405 + "Failed to set WM8804 codec dai clk domain: %d\n", ret);
11406 +
11407 + return ret;
11408 +}
11409 +
11410 +/* audio machine driver */
11411 +static struct snd_soc_card rpi_cirrus_card = {
11412 + .name = "RPi-Cirrus",
11413 + .driver_name = "RPiCirrus",
11414 + .owner = THIS_MODULE,
11415 + .dai_link = rpi_cirrus_dai,
11416 + .num_links = ARRAY_SIZE(rpi_cirrus_dai),
11417 + .late_probe = rpi_cirrus_late_probe,
11418 + .controls = rpi_cirrus_controls,
11419 + .num_controls = ARRAY_SIZE(rpi_cirrus_controls),
11420 + .dapm_widgets = rpi_cirrus_dapm_widgets,
11421 + .num_dapm_widgets = ARRAY_SIZE(rpi_cirrus_dapm_widgets),
11422 + .dapm_routes = rpi_cirrus_dapm_routes,
11423 + .num_dapm_routes = ARRAY_SIZE(rpi_cirrus_dapm_routes),
11424 + .set_bias_level = rpi_cirrus_set_bias_level,
11425 + .set_bias_level_post = rpi_cirrus_set_bias_level_post,
11426 +};
11427 +
11428 +static int rpi_cirrus_probe(struct platform_device *pdev)
11429 +{
11430 + int ret = 0;
11431 + struct rpi_cirrus_priv *priv;
11432 + struct device_node *i2s_node;
11433 +
11434 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
11435 + if (!priv)
11436 + return -ENOMEM;
11437 +
11438 + priv->min_rate_idx = 1; /* min samplerate 32kHz */
11439 + priv->card_rate = RPI_CIRRUS_DEFAULT_RATE;
11440 +
11441 + mutex_init(&priv->lock);
11442 +
11443 + snd_soc_card_set_drvdata(&rpi_cirrus_card, priv);
11444 +
11445 + if (!pdev->dev.of_node)
11446 + return -ENODEV;
11447 +
11448 + i2s_node = of_parse_phandle(
11449 + pdev->dev.of_node, "i2s-controller", 0);
11450 + if (!i2s_node) {
11451 + dev_err(&pdev->dev, "i2s-controller missing in DT\n");
11452 + return -ENODEV;
11453 + }
11454 +
11455 + rpi_cirrus_dai[DAI_WM5102].cpus->of_node = i2s_node;
11456 + rpi_cirrus_dai[DAI_WM5102].platforms->of_node = i2s_node;
11457 +
11458 + rpi_cirrus_card.dev = &pdev->dev;
11459 +
11460 + ret = devm_snd_soc_register_card(&pdev->dev, &rpi_cirrus_card);
11461 + if (ret) {
11462 + if (ret == -EPROBE_DEFER)
11463 + dev_dbg(&pdev->dev,
11464 + "register card requested probe deferral\n");
11465 + else
11466 + dev_err(&pdev->dev,
11467 + "Failed to register card: %d\n", ret);
11468 + }
11469 +
11470 + return ret;
11471 +}
11472 +
11473 +static const struct of_device_id rpi_cirrus_of_match[] = {
11474 + { .compatible = "wlf,rpi-cirrus", },
11475 + {},
11476 +};
11477 +MODULE_DEVICE_TABLE(of, rpi_cirrus_of_match);
11478 +
11479 +static struct platform_driver rpi_cirrus_driver = {
11480 + .driver = {
11481 + .name = "snd-rpi-cirrus",
11482 + .of_match_table = of_match_ptr(rpi_cirrus_of_match),
11483 + },
11484 + .probe = rpi_cirrus_probe,
11485 +};
11486 +
11487 +module_platform_driver(rpi_cirrus_driver);
11488 +
11489 +MODULE_AUTHOR("Matthias Reichl <hias@horus.com>");
11490 +MODULE_DESCRIPTION("ASoC driver for Cirrus Logic Audio Card");
11491 +MODULE_LICENSE("GPL");
11492 --- /dev/null
11493 +++ b/sound/soc/bcm/rpi-proto.c
11494 @@ -0,0 +1,147 @@
11495 +/*
11496 + * ASoC driver for PROTO AudioCODEC (with a WM8731)
11497 + * connected to a Raspberry Pi
11498 + *
11499 + * Author: Florian Meier, <koalo@koalo.de>
11500 + * Copyright 2013
11501 + *
11502 + * This program is free software; you can redistribute it and/or modify
11503 + * it under the terms of the GNU General Public License version 2 as
11504 + * published by the Free Software Foundation.
11505 + */
11506 +
11507 +#include <linux/module.h>
11508 +#include <linux/platform_device.h>
11509 +
11510 +#include <sound/core.h>
11511 +#include <sound/pcm.h>
11512 +#include <sound/soc.h>
11513 +#include <sound/jack.h>
11514 +
11515 +#include "../codecs/wm8731.h"
11516 +
11517 +static const unsigned int wm8731_rates_12288000[] = {
11518 + 8000, 32000, 48000, 96000,
11519 +};
11520 +
11521 +static struct snd_pcm_hw_constraint_list wm8731_constraints_12288000 = {
11522 + .list = wm8731_rates_12288000,
11523 + .count = ARRAY_SIZE(wm8731_rates_12288000),
11524 +};
11525 +
11526 +static int snd_rpi_proto_startup(struct snd_pcm_substream *substream)
11527 +{
11528 + /* Setup constraints, because there is a 12.288 MHz XTAL on the board */
11529 + snd_pcm_hw_constraint_list(substream->runtime, 0,
11530 + SNDRV_PCM_HW_PARAM_RATE,
11531 + &wm8731_constraints_12288000);
11532 + return 0;
11533 +}
11534 +
11535 +static int snd_rpi_proto_hw_params(struct snd_pcm_substream *substream,
11536 + struct snd_pcm_hw_params *params)
11537 +{
11538 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
11539 + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
11540 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
11541 + int sysclk = 12288000; /* This is fixed on this board */
11542 +
11543 + /* Set proto bclk */
11544 + int ret = snd_soc_dai_set_bclk_ratio(cpu_dai,32*2);
11545 + if (ret < 0){
11546 + dev_err(rtd->card->dev,
11547 + "Failed to set BCLK ratio %d\n", ret);
11548 + return ret;
11549 + }
11550 +
11551 + /* Set proto sysclk */
11552 + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
11553 + sysclk, SND_SOC_CLOCK_IN);
11554 + if (ret < 0) {
11555 + dev_err(rtd->card->dev,
11556 + "Failed to set WM8731 SYSCLK: %d\n", ret);
11557 + return ret;
11558 + }
11559 +
11560 + return 0;
11561 +}
11562 +
11563 +/* machine stream operations */
11564 +static struct snd_soc_ops snd_rpi_proto_ops = {
11565 + .startup = snd_rpi_proto_startup,
11566 + .hw_params = snd_rpi_proto_hw_params,
11567 +};
11568 +
11569 +SND_SOC_DAILINK_DEFS(rpi_proto,
11570 + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
11571 + DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.1-001a", "wm8731-hifi")),
11572 + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
11573 +
11574 +static struct snd_soc_dai_link snd_rpi_proto_dai[] = {
11575 +{
11576 + .name = "WM8731",
11577 + .stream_name = "WM8731 HiFi",
11578 + .dai_fmt = SND_SOC_DAIFMT_I2S
11579 + | SND_SOC_DAIFMT_NB_NF
11580 + | SND_SOC_DAIFMT_CBM_CFM,
11581 + .ops = &snd_rpi_proto_ops,
11582 + SND_SOC_DAILINK_REG(rpi_proto),
11583 +},
11584 +};
11585 +
11586 +/* audio machine driver */
11587 +static struct snd_soc_card snd_rpi_proto = {
11588 + .name = "snd_rpi_proto",
11589 + .owner = THIS_MODULE,
11590 + .dai_link = snd_rpi_proto_dai,
11591 + .num_links = ARRAY_SIZE(snd_rpi_proto_dai),
11592 +};
11593 +
11594 +static int snd_rpi_proto_probe(struct platform_device *pdev)
11595 +{
11596 + int ret = 0;
11597 +
11598 + snd_rpi_proto.dev = &pdev->dev;
11599 +
11600 + if (pdev->dev.of_node) {
11601 + struct device_node *i2s_node;
11602 + struct snd_soc_dai_link *dai = &snd_rpi_proto_dai[0];
11603 + i2s_node = of_parse_phandle(pdev->dev.of_node,
11604 + "i2s-controller", 0);
11605 +
11606 + if (i2s_node) {
11607 + dai->cpus->dai_name = NULL;
11608 + dai->cpus->of_node = i2s_node;
11609 + dai->platforms->name = NULL;
11610 + dai->platforms->of_node = i2s_node;
11611 + }
11612 + }
11613 +
11614 + ret = devm_snd_soc_register_card(&pdev->dev, &snd_rpi_proto);
11615 + if (ret && ret != -EPROBE_DEFER)
11616 + dev_err(&pdev->dev,
11617 + "snd_soc_register_card() failed: %d\n", ret);
11618 +
11619 + return ret;
11620 +}
11621 +
11622 +static const struct of_device_id snd_rpi_proto_of_match[] = {
11623 + { .compatible = "rpi,rpi-proto", },
11624 + {},
11625 +};
11626 +MODULE_DEVICE_TABLE(of, snd_rpi_proto_of_match);
11627 +
11628 +static struct platform_driver snd_rpi_proto_driver = {
11629 + .driver = {
11630 + .name = "snd-rpi-proto",
11631 + .owner = THIS_MODULE,
11632 + .of_match_table = snd_rpi_proto_of_match,
11633 + },
11634 + .probe = snd_rpi_proto_probe,
11635 +};
11636 +
11637 +module_platform_driver(snd_rpi_proto_driver);
11638 +
11639 +MODULE_AUTHOR("Florian Meier");
11640 +MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)");
11641 +MODULE_LICENSE("GPL");
11642 --- /dev/null
11643 +++ b/sound/soc/bcm/rpi-simple-soundcard.c
11644 @@ -0,0 +1,339 @@
11645 +// SPDX-License-Identifier: GPL-2.0
11646 +/*
11647 + * rpi-simple-soundcard.c -- ALSA SoC Raspberry Pi soundcard.
11648 + *
11649 + * Copyright (C) 2018 Raspberry Pi.
11650 + *
11651 + * Authors: Tim Gover <tim.gover@raspberrypi.org>
11652 + *
11653 + * Based on code:
11654 + * hifiberry_amp.c, hifiberry_dac.c, rpi-dac.c
11655 + * by Florian Meier <florian.meier@koalo.de>
11656 + *
11657 + * googlevoicehat-soundcard.c
11658 + * by Peter Malkin <petermalkin@google.com>
11659 + *
11660 + * adau1977-adc.c
11661 + * by Andrey Grodzovsky <andrey2805@gmail.com>
11662 + *
11663 + * merus-amp.c
11664 + * by Ariel Muszkat <ariel.muszkat@gmail.com>
11665 + * Jorgen Kragh Jakobsen <jorgen.kraghjakobsen@infineon.com>
11666 + *
11667 + * This program is free software; you can redistribute it and/or
11668 + * modify it under the terms of the GNU General Public License
11669 + * version 2 as published by the Free Software Foundation.
11670 + *
11671 + * This program is distributed in the hope that it will be useful, but
11672 + * WITHOUT ANY WARRANTY; without even the implied warranty of
11673 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11674 + * General Public License for more details.
11675 + */
11676 +
11677 +#include <linux/module.h>
11678 +#include <linux/platform_device.h>
11679 +
11680 +#include <sound/core.h>
11681 +#include <sound/pcm.h>
11682 +#include <sound/pcm_params.h>
11683 +#include <sound/soc.h>
11684 +
11685 +/* Parameters for generic RPI functions */
11686 +struct snd_rpi_simple_drvdata {
11687 + struct snd_soc_dai_link *dai;
11688 + const char* card_name;
11689 + unsigned int fixed_bclk_ratio;
11690 +};
11691 +
11692 +static int snd_rpi_simple_init(struct snd_soc_pcm_runtime *rtd)
11693 +{
11694 + struct snd_rpi_simple_drvdata *drvdata =
11695 + snd_soc_card_get_drvdata(rtd->card);
11696 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
11697 +
11698 + if (drvdata->fixed_bclk_ratio > 0)
11699 + return snd_soc_dai_set_bclk_ratio(cpu_dai,
11700 + drvdata->fixed_bclk_ratio);
11701 +
11702 + return 0;
11703 +}
11704 +
11705 +static int snd_rpi_simple_hw_params(struct snd_pcm_substream *substream,
11706 + struct snd_pcm_hw_params *params)
11707 +{
11708 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
11709 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
11710 + struct snd_rpi_simple_drvdata *drvdata;
11711 + unsigned int sample_bits;
11712 +
11713 + drvdata = snd_soc_card_get_drvdata(rtd->card);
11714 +
11715 + if (drvdata->fixed_bclk_ratio > 0)
11716 + return 0; // BCLK is configured in .init
11717 +
11718 + /* The simple drivers just set the bclk_ratio to sample_bits * 2 so
11719 + * hard-code this for now. More complex drivers could just replace
11720 + * the hw_params routine.
11721 + */
11722 + sample_bits = snd_pcm_format_physical_width(params_format(params));
11723 + return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2);
11724 +}
11725 +
11726 +static struct snd_soc_ops snd_rpi_simple_ops = {
11727 + .hw_params = snd_rpi_simple_hw_params,
11728 +};
11729 +
11730 +enum adau1977_clk_id {
11731 + ADAU1977_SYSCLK,
11732 +};
11733 +
11734 +enum adau1977_sysclk_src {
11735 + ADAU1977_SYSCLK_SRC_MCLK,
11736 + ADAU1977_SYSCLK_SRC_LRCLK,
11737 +};
11738 +
11739 +static int adau1977_init(struct snd_soc_pcm_runtime *rtd)
11740 +{
11741 + int ret;
11742 + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
11743 +
11744 + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0, 0, 0, 0);
11745 + if (ret < 0)
11746 + return ret;
11747 +
11748 + return snd_soc_component_set_sysclk(codec_dai->component,
11749 + ADAU1977_SYSCLK, ADAU1977_SYSCLK_SRC_MCLK,
11750 + 11289600, SND_SOC_CLOCK_IN);
11751 +}
11752 +
11753 +SND_SOC_DAILINK_DEFS(adau1977,
11754 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
11755 + DAILINK_COMP_ARRAY(COMP_CODEC("adau1977.1-0011", "adau1977-hifi")),
11756 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
11757 +
11758 +static struct snd_soc_dai_link snd_rpi_adau1977_dai[] = {
11759 + {
11760 + .name = "adau1977",
11761 + .stream_name = "ADAU1977",
11762 + .init = adau1977_init,
11763 + .dai_fmt = SND_SOC_DAIFMT_I2S |
11764 + SND_SOC_DAIFMT_NB_NF |
11765 + SND_SOC_DAIFMT_CBM_CFM,
11766 + SND_SOC_DAILINK_REG(adau1977),
11767 + },
11768 +};
11769 +
11770 +static struct snd_rpi_simple_drvdata drvdata_adau1977 = {
11771 + .card_name = "snd_rpi_adau1977_adc",
11772 + .dai = snd_rpi_adau1977_dai,
11773 +};
11774 +
11775 +SND_SOC_DAILINK_DEFS(gvchat,
11776 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
11777 + DAILINK_COMP_ARRAY(COMP_CODEC("voicehat-codec", "voicehat-hifi")),
11778 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
11779 +
11780 +static struct snd_soc_dai_link snd_googlevoicehat_soundcard_dai[] = {
11781 +{
11782 + .name = "Google voiceHAT SoundCard",
11783 + .stream_name = "Google voiceHAT SoundCard HiFi",
11784 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
11785 + SND_SOC_DAIFMT_CBS_CFS,
11786 + SND_SOC_DAILINK_REG(gvchat),
11787 +},
11788 +};
11789 +
11790 +static struct snd_rpi_simple_drvdata drvdata_googlevoicehat = {
11791 + .card_name = "snd_rpi_googlevoicehat_soundcard",
11792 + .dai = snd_googlevoicehat_soundcard_dai,
11793 +};
11794 +
11795 +SND_SOC_DAILINK_DEFS(hifiberry_dacplusdsp,
11796 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
11797 + DAILINK_COMP_ARRAY(COMP_CODEC("dacplusdsp-codec", "dacplusdsp-hifi")),
11798 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
11799 +
11800 +static struct snd_soc_dai_link snd_hifiberrydacplusdsp_soundcard_dai[] = {
11801 +{
11802 + .name = "Hifiberry DAC+DSP SoundCard",
11803 + .stream_name = "Hifiberry DAC+DSP SoundCard HiFi",
11804 + .dai_fmt = SND_SOC_DAIFMT_I2S |
11805 + SND_SOC_DAIFMT_NB_NF |
11806 + SND_SOC_DAIFMT_CBS_CFS,
11807 + SND_SOC_DAILINK_REG(hifiberry_dacplusdsp),
11808 +},
11809 +};
11810 +
11811 +static struct snd_rpi_simple_drvdata drvdata_hifiberrydacplusdsp = {
11812 + .card_name = "snd_rpi_hifiberrydacplusdsp_soundcard",
11813 + .dai = snd_hifiberrydacplusdsp_soundcard_dai,
11814 +};
11815 +
11816 +SND_SOC_DAILINK_DEFS(hifiberry_amp,
11817 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
11818 + DAILINK_COMP_ARRAY(COMP_CODEC("tas5713.1-001b", "tas5713-hifi")),
11819 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
11820 +
11821 +static struct snd_soc_dai_link snd_hifiberry_amp_dai[] = {
11822 + {
11823 + .name = "HifiBerry AMP",
11824 + .stream_name = "HifiBerry AMP HiFi",
11825 + .dai_fmt = SND_SOC_DAIFMT_I2S |
11826 + SND_SOC_DAIFMT_NB_NF |
11827 + SND_SOC_DAIFMT_CBS_CFS,
11828 + SND_SOC_DAILINK_REG(hifiberry_amp),
11829 + },
11830 +};
11831 +
11832 +static struct snd_rpi_simple_drvdata drvdata_hifiberry_amp = {
11833 + .card_name = "snd_rpi_hifiberry_amp",
11834 + .dai = snd_hifiberry_amp_dai,
11835 + .fixed_bclk_ratio = 64,
11836 +};
11837 +
11838 +SND_SOC_DAILINK_DEFS(hifiberry_dac,
11839 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
11840 + DAILINK_COMP_ARRAY(COMP_CODEC("pcm5102a-codec", "pcm5102a-hifi")),
11841 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
11842 +
11843 +static struct snd_soc_dai_link snd_hifiberry_dac_dai[] = {
11844 + {
11845 + .name = "HifiBerry DAC",
11846 + .stream_name = "HifiBerry DAC HiFi",
11847 + .dai_fmt = SND_SOC_DAIFMT_I2S |
11848 + SND_SOC_DAIFMT_NB_NF |
11849 + SND_SOC_DAIFMT_CBS_CFS,
11850 + SND_SOC_DAILINK_REG(hifiberry_dac),
11851 + },
11852 +};
11853 +
11854 +static struct snd_rpi_simple_drvdata drvdata_hifiberry_dac = {
11855 + .card_name = "snd_rpi_hifiberry_dac",
11856 + .dai = snd_hifiberry_dac_dai,
11857 +};
11858 +
11859 +SND_SOC_DAILINK_DEFS(rpi_dac,
11860 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
11861 + DAILINK_COMP_ARRAY(COMP_CODEC("pcm1794a-codec", "pcm1794a-hifi")),
11862 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
11863 +
11864 +static struct snd_soc_dai_link snd_rpi_dac_dai[] = {
11865 +{
11866 + .name = "RPi-DAC",
11867 + .stream_name = "RPi-DAC HiFi",
11868 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
11869 + SND_SOC_DAIFMT_CBS_CFS,
11870 + SND_SOC_DAILINK_REG(rpi_dac),
11871 +},
11872 +};
11873 +
11874 +static struct snd_rpi_simple_drvdata drvdata_rpi_dac = {
11875 + .card_name = "snd_rpi_rpi_dac",
11876 + .dai = snd_rpi_dac_dai,
11877 + .fixed_bclk_ratio = 64,
11878 +};
11879 +
11880 +SND_SOC_DAILINK_DEFS(merus_amp,
11881 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
11882 + DAILINK_COMP_ARRAY(COMP_CODEC("ma120x0p.1-0020","ma120x0p-amp")),
11883 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
11884 +
11885 +static struct snd_soc_dai_link snd_merus_amp_dai[] = {
11886 + {
11887 + .name = "MerusAmp",
11888 + .stream_name = "Merus Audio Amp",
11889 + .dai_fmt = SND_SOC_DAIFMT_I2S |
11890 + SND_SOC_DAIFMT_NB_NF |
11891 + SND_SOC_DAIFMT_CBS_CFS,
11892 + SND_SOC_DAILINK_REG(merus_amp),
11893 + },
11894 +};
11895 +
11896 +static struct snd_rpi_simple_drvdata drvdata_merus_amp = {
11897 + .card_name = "snd_rpi_merus_amp",
11898 + .dai = snd_merus_amp_dai,
11899 + .fixed_bclk_ratio = 64,
11900 +};
11901 +
11902 +static const struct of_device_id snd_rpi_simple_of_match[] = {
11903 + { .compatible = "adi,adau1977-adc",
11904 + .data = (void *) &drvdata_adau1977 },
11905 + { .compatible = "googlevoicehat,googlevoicehat-soundcard",
11906 + .data = (void *) &drvdata_googlevoicehat },
11907 + { .compatible = "hifiberrydacplusdsp,hifiberrydacplusdsp-soundcard",
11908 + .data = (void *) &drvdata_hifiberrydacplusdsp },
11909 + { .compatible = "hifiberry,hifiberry-amp",
11910 + .data = (void *) &drvdata_hifiberry_amp },
11911 + { .compatible = "hifiberry,hifiberry-dac",
11912 + .data = (void *) &drvdata_hifiberry_dac },
11913 + { .compatible = "rpi,rpi-dac", &drvdata_rpi_dac},
11914 + { .compatible = "merus,merus-amp",
11915 + .data = (void *) &drvdata_merus_amp },
11916 + {},
11917 +};
11918 +
11919 +static struct snd_soc_card snd_rpi_simple = {
11920 + .driver_name = "RPi-simple",
11921 + .owner = THIS_MODULE,
11922 + .dai_link = NULL,
11923 + .num_links = 1, /* Only a single DAI supported at the moment */
11924 +};
11925 +
11926 +static int snd_rpi_simple_probe(struct platform_device *pdev)
11927 +{
11928 + int ret = 0;
11929 + const struct of_device_id *of_id;
11930 +
11931 + snd_rpi_simple.dev = &pdev->dev;
11932 + of_id = of_match_node(snd_rpi_simple_of_match, pdev->dev.of_node);
11933 +
11934 + if (pdev->dev.of_node && of_id->data) {
11935 + struct device_node *i2s_node;
11936 + struct snd_rpi_simple_drvdata *drvdata =
11937 + (struct snd_rpi_simple_drvdata *) of_id->data;
11938 + struct snd_soc_dai_link *dai = drvdata->dai;
11939 +
11940 + snd_soc_card_set_drvdata(&snd_rpi_simple, drvdata);
11941 +
11942 + /* More complex drivers might override individual functions */
11943 + if (!dai->init)
11944 + dai->init = snd_rpi_simple_init;
11945 + if (!dai->ops)
11946 + dai->ops = &snd_rpi_simple_ops;
11947 +
11948 + snd_rpi_simple.name = drvdata->card_name;
11949 +
11950 + snd_rpi_simple.dai_link = dai;
11951 + i2s_node = of_parse_phandle(pdev->dev.of_node,
11952 + "i2s-controller", 0);
11953 + if (!i2s_node) {
11954 + pr_err("Failed to find i2s-controller DT node\n");
11955 + return -ENODEV;
11956 + }
11957 +
11958 + dai->cpus->of_node = i2s_node;
11959 + dai->platforms->of_node = i2s_node;
11960 + }
11961 +
11962 + ret = devm_snd_soc_register_card(&pdev->dev, &snd_rpi_simple);
11963 + if (ret && ret != -EPROBE_DEFER)
11964 + dev_err(&pdev->dev, "Failed to register card %d\n", ret);
11965 +
11966 + return ret;
11967 +}
11968 +
11969 +static struct platform_driver snd_rpi_simple_driver = {
11970 + .driver = {
11971 + .name = "snd-rpi-simple",
11972 + .owner = THIS_MODULE,
11973 + .of_match_table = snd_rpi_simple_of_match,
11974 + },
11975 + .probe = snd_rpi_simple_probe,
11976 +};
11977 +MODULE_DEVICE_TABLE(of, snd_rpi_simple_of_match);
11978 +
11979 +module_platform_driver(snd_rpi_simple_driver);
11980 +
11981 +MODULE_AUTHOR("Tim Gover <tim.gover@raspberrypi.org>");
11982 +MODULE_DESCRIPTION("ASoC Raspberry Pi simple soundcard driver ");
11983 +MODULE_LICENSE("GPL v2");
11984 --- /dev/null
11985 +++ b/sound/soc/bcm/rpi-wm8804-soundcard.c
11986 @@ -0,0 +1,410 @@
11987 +// SPDX-License-Identifier: GPL-2.0
11988 +/*
11989 + * rpi--wm8804.c -- ALSA SoC Raspberry Pi soundcard.
11990 + *
11991 + * Copyright (C) 2018 Raspberry Pi.
11992 + *
11993 + * Authors: Tim Gover <tim.gover@raspberrypi.org>
11994 + *
11995 + * Generic driver for Pi Hat WM8804 digi sounds cards
11996 + *
11997 + * Based upon code from:
11998 + * justboom-digi.c
11999 + * by Milan Neskovic <info@justboom.co>
12000 + *
12001 + * iqaudio_digi.c
12002 + * by Daniel Matuschek <info@crazy-audio.com>
12003 + *
12004 + * allo-digione.c
12005 + * by Baswaraj <jaikumar@cem-solutions.net>
12006 + *
12007 + * hifiberry-digi.c
12008 + * Daniel Matuschek <info@crazy-audio.com>
12009 + *
12010 + * This program is free software; you can redistribute it and/or
12011 + * modify it under the terms of the GNU General Public License
12012 + * version 2 as published by the Free Software Foundation.
12013 + *
12014 + * This program is distributed in the hope that it will be useful, but
12015 + * WITHOUT ANY WARRANTY; without even the implied warranty of
12016 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12017 + * General Public License for more details.
12018 + */
12019 +
12020 +#include <linux/gpio/consumer.h>
12021 +#include <linux/platform_device.h>
12022 +#include <linux/module.h>
12023 +
12024 +#include <sound/core.h>
12025 +#include <sound/pcm.h>
12026 +#include <sound/pcm_params.h>
12027 +#include <sound/soc.h>
12028 +
12029 +#include "../codecs/wm8804.h"
12030 +
12031 +struct wm8804_clk_cfg {
12032 + unsigned int sysclk_freq;
12033 + unsigned int mclk_freq;
12034 + unsigned int mclk_div;
12035 +};
12036 +
12037 +/* Parameters for generic functions */
12038 +struct snd_rpi_wm8804_drvdata {
12039 + /* Required - pointer to the DAI structure */
12040 + struct snd_soc_dai_link *dai;
12041 + /* Required - snd_soc_card name */
12042 + const char *card_name;
12043 + /* Optional DT node names if card info is defined in DT */
12044 + const char *card_name_dt;
12045 + const char *dai_name_dt;
12046 + const char *dai_stream_name_dt;
12047 + /* Optional probe extension - called prior to register_card */
12048 + int (*probe)(struct platform_device *pdev);
12049 +};
12050 +
12051 +static struct gpio_desc *snd_clk44gpio;
12052 +static struct gpio_desc *snd_clk48gpio;
12053 +static int wm8804_samplerate = 0;
12054 +
12055 +/* Forward declarations */
12056 +static struct snd_soc_dai_link snd_allo_digione_dai[];
12057 +static struct snd_soc_card snd_rpi_wm8804;
12058 +
12059 +
12060 +#define CLK_44EN_RATE 22579200UL
12061 +#define CLK_48EN_RATE 24576000UL
12062 +
12063 +static unsigned int snd_rpi_wm8804_enable_clock(unsigned int samplerate)
12064 +{
12065 + switch (samplerate) {
12066 + case 11025:
12067 + case 22050:
12068 + case 44100:
12069 + case 88200:
12070 + case 176400:
12071 + gpiod_set_value_cansleep(snd_clk44gpio, 1);
12072 + gpiod_set_value_cansleep(snd_clk48gpio, 0);
12073 + return CLK_44EN_RATE;
12074 + default:
12075 + gpiod_set_value_cansleep(snd_clk48gpio, 1);
12076 + gpiod_set_value_cansleep(snd_clk44gpio, 0);
12077 + return CLK_48EN_RATE;
12078 + }
12079 +}
12080 +
12081 +static void snd_rpi_wm8804_clk_cfg(unsigned int samplerate,
12082 + struct wm8804_clk_cfg *clk_cfg)
12083 +{
12084 + clk_cfg->sysclk_freq = 27000000;
12085 +
12086 + if (samplerate <= 96000 ||
12087 + snd_rpi_wm8804.dai_link == snd_allo_digione_dai) {
12088 + clk_cfg->mclk_freq = samplerate * 256;
12089 + clk_cfg->mclk_div = WM8804_MCLKDIV_256FS;
12090 + } else {
12091 + clk_cfg->mclk_freq = samplerate * 128;
12092 + clk_cfg->mclk_div = WM8804_MCLKDIV_128FS;
12093 + }
12094 +
12095 + if (!(IS_ERR(snd_clk44gpio) || IS_ERR(snd_clk48gpio)))
12096 + clk_cfg->sysclk_freq = snd_rpi_wm8804_enable_clock(samplerate);
12097 +}
12098 +
12099 +static int snd_rpi_wm8804_hw_params(struct snd_pcm_substream *substream,
12100 + struct snd_pcm_hw_params *params)
12101 +{
12102 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
12103 + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
12104 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
12105 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
12106 + int sampling_freq = 1;
12107 + int ret;
12108 + struct wm8804_clk_cfg clk_cfg;
12109 + int samplerate = params_rate(params);
12110 +
12111 + if (samplerate == wm8804_samplerate)
12112 + return 0;
12113 +
12114 + /* clear until all clocks are setup properly */
12115 + wm8804_samplerate = 0;
12116 +
12117 + snd_rpi_wm8804_clk_cfg(samplerate, &clk_cfg);
12118 +
12119 + pr_debug("%s samplerate: %d mclk_freq: %u mclk_div: %u sysclk: %u\n",
12120 + __func__, samplerate, clk_cfg.mclk_freq,
12121 + clk_cfg.mclk_div, clk_cfg.sysclk_freq);
12122 +
12123 + switch (samplerate) {
12124 + case 32000:
12125 + sampling_freq = 0x03;
12126 + break;
12127 + case 44100:
12128 + sampling_freq = 0x00;
12129 + break;
12130 + case 48000:
12131 + sampling_freq = 0x02;
12132 + break;
12133 + case 88200:
12134 + sampling_freq = 0x08;
12135 + break;
12136 + case 96000:
12137 + sampling_freq = 0x0a;
12138 + break;
12139 + case 176400:
12140 + sampling_freq = 0x0c;
12141 + break;
12142 + case 192000:
12143 + sampling_freq = 0x0e;
12144 + break;
12145 + default:
12146 + dev_err(rtd->card->dev,
12147 + "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n",
12148 + samplerate);
12149 + }
12150 +
12151 + snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, clk_cfg.mclk_div);
12152 + snd_soc_dai_set_pll(codec_dai, 0, 0,
12153 + clk_cfg.sysclk_freq, clk_cfg.mclk_freq);
12154 +
12155 + ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL,
12156 + clk_cfg.sysclk_freq, SND_SOC_CLOCK_OUT);
12157 + if (ret < 0) {
12158 + dev_err(rtd->card->dev,
12159 + "Failed to set WM8804 SYSCLK: %d\n", ret);
12160 + return ret;
12161 + }
12162 +
12163 + wm8804_samplerate = samplerate;
12164 +
12165 + /* set sampling frequency status bits */
12166 + snd_soc_component_update_bits(component, WM8804_SPDTX4, 0x0f,
12167 + sampling_freq);
12168 +
12169 + return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
12170 +}
12171 +
12172 +static struct snd_soc_ops snd_rpi_wm8804_ops = {
12173 + .hw_params = snd_rpi_wm8804_hw_params,
12174 +};
12175 +
12176 +SND_SOC_DAILINK_DEFS(justboom_digi,
12177 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
12178 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
12179 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
12180 +
12181 +static struct snd_soc_dai_link snd_justboom_digi_dai[] = {
12182 +{
12183 + .name = "JustBoom Digi",
12184 + .stream_name = "JustBoom Digi HiFi",
12185 + SND_SOC_DAILINK_REG(justboom_digi),
12186 +},
12187 +};
12188 +
12189 +static struct snd_rpi_wm8804_drvdata drvdata_justboom_digi = {
12190 + .card_name = "snd_rpi_justboom_digi",
12191 + .dai = snd_justboom_digi_dai,
12192 +};
12193 +
12194 +SND_SOC_DAILINK_DEFS(iqaudio_digi,
12195 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
12196 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
12197 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
12198 +
12199 +static struct snd_soc_dai_link snd_iqaudio_digi_dai[] = {
12200 +{
12201 + .name = "IQAudIO Digi",
12202 + .stream_name = "IQAudIO Digi HiFi",
12203 + SND_SOC_DAILINK_REG(iqaudio_digi),
12204 +},
12205 +};
12206 +
12207 +static struct snd_rpi_wm8804_drvdata drvdata_iqaudio_digi = {
12208 + .card_name = "IQAudIODigi",
12209 + .dai = snd_iqaudio_digi_dai,
12210 + .card_name_dt = "wm8804-digi,card-name",
12211 + .dai_name_dt = "wm8804-digi,dai-name",
12212 + .dai_stream_name_dt = "wm8804-digi,dai-stream-name",
12213 +};
12214 +
12215 +static int snd_allo_digione_probe(struct platform_device *pdev)
12216 +{
12217 + pr_debug("%s\n", __func__);
12218 +
12219 + if (IS_ERR(snd_clk44gpio) || IS_ERR(snd_clk48gpio)) {
12220 + dev_err(&pdev->dev, "devm_gpiod_get() failed\n");
12221 + return -EINVAL;
12222 + }
12223 + return 0;
12224 +}
12225 +
12226 +SND_SOC_DAILINK_DEFS(allo_digione,
12227 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
12228 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
12229 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
12230 +
12231 +static struct snd_soc_dai_link snd_allo_digione_dai[] = {
12232 +{
12233 + .name = "Allo DigiOne",
12234 + .stream_name = "Allo DigiOne HiFi",
12235 + SND_SOC_DAILINK_REG(allo_digione),
12236 +},
12237 +};
12238 +
12239 +static struct snd_rpi_wm8804_drvdata drvdata_allo_digione = {
12240 + .card_name = "snd_allo_digione",
12241 + .dai = snd_allo_digione_dai,
12242 + .probe = snd_allo_digione_probe,
12243 +};
12244 +
12245 +SND_SOC_DAILINK_DEFS(hifiberry_digi,
12246 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
12247 + DAILINK_COMP_ARRAY(COMP_EMPTY()),
12248 + DAILINK_COMP_ARRAY(COMP_EMPTY()));
12249 +
12250 +static struct snd_soc_dai_link snd_hifiberry_digi_dai[] = {
12251 +{
12252 + .name = "HifiBerry Digi",
12253 + .stream_name = "HifiBerry Digi HiFi",
12254 + SND_SOC_DAILINK_REG(hifiberry_digi),
12255 +},
12256 +};
12257 +
12258 +static int snd_hifiberry_digi_probe(struct platform_device *pdev)
12259 +{
12260 + pr_debug("%s\n", __func__);
12261 +
12262 + if (IS_ERR(snd_clk44gpio) || IS_ERR(snd_clk48gpio))
12263 + return 0;
12264 +
12265 + snd_hifiberry_digi_dai->name = "HiFiBerry Digi+ Pro";
12266 + snd_hifiberry_digi_dai->stream_name = "HiFiBerry Digi+ Pro HiFi";
12267 + return 0;
12268 +}
12269 +
12270 +static struct snd_rpi_wm8804_drvdata drvdata_hifiberry_digi = {
12271 + .card_name = "snd_rpi_hifiberry_digi",
12272 + .dai = snd_hifiberry_digi_dai,
12273 + .probe = snd_hifiberry_digi_probe,
12274 +};
12275 +
12276 +static const struct of_device_id snd_rpi_wm8804_of_match[] = {
12277 + { .compatible = "justboom,justboom-digi",
12278 + .data = (void *) &drvdata_justboom_digi },
12279 + { .compatible = "iqaudio,wm8804-digi",
12280 + .data = (void *) &drvdata_iqaudio_digi },
12281 + { .compatible = "allo,allo-digione",
12282 + .data = (void *) &drvdata_allo_digione },
12283 + { .compatible = "hifiberry,hifiberry-digi",
12284 + .data = (void *) &drvdata_hifiberry_digi },
12285 + {},
12286 +};
12287 +
12288 +static struct snd_soc_card snd_rpi_wm8804 = {
12289 + .driver_name = "RPi-WM8804",
12290 + .owner = THIS_MODULE,
12291 + .dai_link = NULL,
12292 + .num_links = 1,
12293 +};
12294 +
12295 +static int snd_rpi_wm8804_probe(struct platform_device *pdev)
12296 +{
12297 + int ret = 0;
12298 + const struct of_device_id *of_id;
12299 +
12300 + snd_rpi_wm8804.dev = &pdev->dev;
12301 + of_id = of_match_node(snd_rpi_wm8804_of_match, pdev->dev.of_node);
12302 +
12303 + if (pdev->dev.of_node && of_id->data) {
12304 + struct device_node *i2s_node;
12305 + struct snd_rpi_wm8804_drvdata *drvdata =
12306 + (struct snd_rpi_wm8804_drvdata *) of_id->data;
12307 + struct snd_soc_dai_link *dai = drvdata->dai;
12308 +
12309 + snd_soc_card_set_drvdata(&snd_rpi_wm8804, drvdata);
12310 +
12311 + if (!dai->ops)
12312 + dai->ops = &snd_rpi_wm8804_ops;
12313 + if (!dai->codecs->dai_name)
12314 + dai->codecs->dai_name = "wm8804-spdif";
12315 + if (!dai->codecs->name)
12316 + dai->codecs->name = "wm8804.1-003b";
12317 + if (!dai->dai_fmt)
12318 + dai->dai_fmt = SND_SOC_DAIFMT_I2S |
12319 + SND_SOC_DAIFMT_NB_NF |
12320 + SND_SOC_DAIFMT_CBM_CFM;
12321 +
12322 + snd_rpi_wm8804.dai_link = dai;
12323 + i2s_node = of_parse_phandle(pdev->dev.of_node,
12324 + "i2s-controller", 0);
12325 + if (!i2s_node) {
12326 + pr_err("Failed to find i2s-controller DT node\n");
12327 + return -ENODEV;
12328 + }
12329 +
12330 + snd_rpi_wm8804.name = drvdata->card_name;
12331 +
12332 + /* If requested by in drvdata get card & DAI names from DT */
12333 + if (drvdata->card_name_dt)
12334 + of_property_read_string(i2s_node,
12335 + drvdata->card_name_dt,
12336 + &snd_rpi_wm8804.name);
12337 +
12338 + if (drvdata->dai_name_dt)
12339 + of_property_read_string(i2s_node,
12340 + drvdata->dai_name_dt,
12341 + &dai->name);
12342 +
12343 + if (drvdata->dai_stream_name_dt)
12344 + of_property_read_string(i2s_node,
12345 + drvdata->dai_stream_name_dt,
12346 + &dai->stream_name);
12347 +
12348 + dai->cpus->of_node = i2s_node;
12349 + dai->platforms->of_node = i2s_node;
12350 +
12351 + /*
12352 + * clk44gpio and clk48gpio are not required by all cards so
12353 + * don't check the error status.
12354 + */
12355 + snd_clk44gpio =
12356 + devm_gpiod_get(&pdev->dev, "clock44", GPIOD_OUT_LOW);
12357 +
12358 + snd_clk48gpio =
12359 + devm_gpiod_get(&pdev->dev, "clock48", GPIOD_OUT_LOW);
12360 +
12361 + if (drvdata->probe) {
12362 + ret = drvdata->probe(pdev);
12363 + if (ret < 0) {
12364 + dev_err(&pdev->dev, "Custom probe failed %d\n",
12365 + ret);
12366 + return ret;
12367 + }
12368 + }
12369 +
12370 + pr_debug("%s card: %s dai: %s stream: %s\n", __func__,
12371 + snd_rpi_wm8804.name,
12372 + dai->name, dai->stream_name);
12373 + }
12374 +
12375 + ret = devm_snd_soc_register_card(&pdev->dev, &snd_rpi_wm8804);
12376 + if (ret && ret != -EPROBE_DEFER)
12377 + dev_err(&pdev->dev, "Failed to register card %d\n", ret);
12378 +
12379 + return ret;
12380 +}
12381 +
12382 +static struct platform_driver snd_rpi_wm8804_driver = {
12383 + .driver = {
12384 + .name = "snd-rpi-wm8804",
12385 + .owner = THIS_MODULE,
12386 + .of_match_table = snd_rpi_wm8804_of_match,
12387 + },
12388 + .probe = snd_rpi_wm8804_probe,
12389 +};
12390 +MODULE_DEVICE_TABLE(of, snd_rpi_wm8804_of_match);
12391 +
12392 +module_platform_driver(snd_rpi_wm8804_driver);
12393 +
12394 +MODULE_AUTHOR("Tim Gover <tim.gover@raspberrypi.org>");
12395 +MODULE_DESCRIPTION("ASoC Raspberry Pi Hat generic digi driver for WM8804 based cards");
12396 +MODULE_LICENSE("GPL v2");
12397 --- a/sound/soc/codecs/Kconfig
12398 +++ b/sound/soc/codecs/Kconfig
12399 @@ -100,12 +100,14 @@ config SND_SOC_ALL_CODECS
12400 imply SND_SOC_ICS43432
12401 imply SND_SOC_INNO_RK3036
12402 imply SND_SOC_ISABELLE
12403 + imply SND_SOC_I_SABRE_CODEC
12404 imply SND_SOC_JZ4740_CODEC
12405 imply SND_SOC_JZ4725B_CODEC
12406 imply SND_SOC_JZ4770_CODEC
12407 imply SND_SOC_LM4857
12408 imply SND_SOC_LM49453
12409 imply SND_SOC_LOCHNAGAR_SC
12410 + imply SND_SOC_MA120X0P
12411 imply SND_SOC_MAX98088
12412 imply SND_SOC_MAX98090
12413 imply SND_SOC_MAX98095
12414 @@ -142,6 +144,7 @@ config SND_SOC_ALL_CODECS
12415 imply SND_SOC_PCM179X_SPI
12416 imply SND_SOC_PCM186X_I2C
12417 imply SND_SOC_PCM186X_SPI
12418 + imply SND_SOC_PCM1794A
12419 imply SND_SOC_PCM3008
12420 imply SND_SOC_PCM3060_I2C
12421 imply SND_SOC_PCM3060_SPI
12422 @@ -206,6 +209,7 @@ config SND_SOC_ALL_CODECS
12423 imply SND_SOC_TLV320ADCX140
12424 imply SND_SOC_TLV320AIC23_I2C
12425 imply SND_SOC_TLV320AIC23_SPI
12426 + imply SND_SOC_TAS5713
12427 imply SND_SOC_TLV320AIC26
12428 imply SND_SOC_TLV320AIC31XX
12429 imply SND_SOC_TLV320AIC32X4_I2C
12430 @@ -343,12 +347,12 @@ config SND_SOC_AD193X
12431 tristate
12432
12433 config SND_SOC_AD193X_SPI
12434 - tristate
12435 + tristate "Analog Devices AU193X CODEC - SPI"
12436 depends on SPI_MASTER
12437 select SND_SOC_AD193X
12438
12439 config SND_SOC_AD193X_I2C
12440 - tristate
12441 + tristate "Analog Devices AU193X CODEC - I2C"
12442 depends on I2C
12443 select SND_SOC_AD193X
12444
12445 @@ -809,7 +813,7 @@ config SND_SOC_HDAC_HDA
12446 select SND_HDA
12447
12448 config SND_SOC_ICS43432
12449 - tristate
12450 + tristate "InvenSense ICS43432 I2S microphone codec"
12451
12452 config SND_SOC_INNO_RK3036
12453 tristate "Inno codec driver for RK3036 SoC"
12454 @@ -830,6 +834,13 @@ config SND_SOC_LOCHNAGAR_SC
12455 This driver support the sound card functionality of the Cirrus
12456 Logic Lochnagar audio development board.
12457
12458 +config SND_SOC_MA120X0P
12459 + tristate "Infineon Merus(TM) MA120X0P Multilevel Class-D Audio amplifiers"
12460 + depends on I2C
12461 + help
12462 + Enable support for Infineon MA120X0P Multilevel Class-D audio power
12463 + amplifiers.
12464 +
12465 config SND_SOC_MADERA
12466 tristate
12467 default y if SND_SOC_CS47L15=y
12468 @@ -1130,6 +1141,10 @@ config SND_SOC_RT5616
12469 tristate "Realtek RT5616 CODEC"
12470 depends on I2C
12471
12472 +config SND_SOC_PCM1794A
12473 + tristate
12474 + depends on I2C
12475 +
12476 config SND_SOC_RT5631
12477 tristate "Realtek ALC5631/RT5631 CODEC"
12478 depends on I2C
12479 @@ -1351,6 +1366,9 @@ config SND_SOC_TFA9879
12480 tristate "NXP Semiconductors TFA9879 amplifier"
12481 depends on I2C
12482
12483 +config SND_SOC_TAS5713
12484 + tristate
12485 +
12486 config SND_SOC_TLV320AIC23
12487 tristate
12488
12489 @@ -1789,4 +1807,8 @@ config SND_SOC_TPA6130A2
12490 tristate "Texas Instruments TPA6130A2 headphone amplifier"
12491 depends on I2C
12492
12493 +config SND_SOC_I_SABRE_CODEC
12494 + tristate "Audiophonics I-SABRE Codec"
12495 + depends on I2C
12496 +
12497 endmenu
12498 --- a/sound/soc/codecs/Makefile
12499 +++ b/sound/soc/codecs/Makefile
12500 @@ -96,6 +96,7 @@ snd-soc-hdac-hda-objs := hdac_hda.o
12501 snd-soc-ics43432-objs := ics43432.o
12502 snd-soc-inno-rk3036-objs := inno_rk3036.o
12503 snd-soc-isabelle-objs := isabelle.o
12504 +snd-soc-i-sabre-codec-objs := i-sabre-codec.o
12505 snd-soc-jz4740-codec-objs := jz4740.o
12506 snd-soc-jz4725b-codec-objs := jz4725b.o
12507 snd-soc-jz4770-codec-objs := jz4770.o
12508 @@ -103,6 +104,7 @@ snd-soc-l3-objs := l3.o
12509 snd-soc-lm4857-objs := lm4857.o
12510 snd-soc-lm49453-objs := lm49453.o
12511 snd-soc-lochnagar-sc-objs := lochnagar-sc.o
12512 +snd-soc-ma120x0p-objs := ma120x0p.o
12513 snd-soc-madera-objs := madera.o
12514 snd-soc-max9759-objs := max9759.o
12515 snd-soc-max9768-objs := max9768.o
12516 @@ -144,6 +146,7 @@ snd-soc-pcm179x-spi-objs := pcm179x-spi.
12517 snd-soc-pcm186x-objs := pcm186x.o
12518 snd-soc-pcm186x-i2c-objs := pcm186x-i2c.o
12519 snd-soc-pcm186x-spi-objs := pcm186x-spi.o
12520 +snd-soc-pcm1794a-objs := pcm1794a.o
12521 snd-soc-pcm3008-objs := pcm3008.o
12522 snd-soc-pcm3060-objs := pcm3060.o
12523 snd-soc-pcm3060-i2c-objs := pcm3060-i2c.o
12524 @@ -216,6 +219,7 @@ snd-soc-tas6424-objs := tas6424.o
12525 snd-soc-tda7419-objs := tda7419.o
12526 snd-soc-tas2770-objs := tas2770.o
12527 snd-soc-tfa9879-objs := tfa9879.o
12528 +snd-soc-tas5713-objs := tas5713.o
12529 snd-soc-tlv320aic23-objs := tlv320aic23.o
12530 snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
12531 snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o
12532 @@ -405,6 +409,7 @@ obj-$(CONFIG_SND_SOC_HDAC_HDA) += snd-so
12533 obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o
12534 obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o
12535 obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
12536 +obj-$(CONFIG_SND_SOC_I_SABRE_CODEC) += snd-soc-i-sabre-codec.o
12537 obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
12538 obj-$(CONFIG_SND_SOC_JZ4725B_CODEC) += snd-soc-jz4725b-codec.o
12539 obj-$(CONFIG_SND_SOC_JZ4770_CODEC) += snd-soc-jz4770-codec.o
12540 @@ -412,6 +417,7 @@ obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
12541 obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
12542 obj-$(CONFIG_SND_SOC_LM49453) += snd-soc-lm49453.o
12543 obj-$(CONFIG_SND_SOC_LOCHNAGAR_SC) += snd-soc-lochnagar-sc.o
12544 +obj-$(CONFIG_SND_SOC_MA120X0P) += snd-soc-ma120x0p.o
12545 obj-$(CONFIG_SND_SOC_MADERA) += snd-soc-madera.o
12546 obj-$(CONFIG_SND_SOC_MAX9759) += snd-soc-max9759.o
12547 obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o
12548 @@ -465,6 +471,7 @@ obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc
12549 obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
12550 obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
12551 obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o
12552 +obj-$(CONFIG_SND_SOC_PCM1794A) += snd-soc-pcm1794a.o
12553 obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
12554 obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o
12555 obj-$(CONFIG_SND_SOC_RT1011) += snd-soc-rt1011.o
12556 @@ -526,6 +533,7 @@ obj-$(CONFIG_SND_SOC_TAS6424) += snd-soc
12557 obj-$(CONFIG_SND_SOC_TDA7419) += snd-soc-tda7419.o
12558 obj-$(CONFIG_SND_SOC_TAS2770) += snd-soc-tas2770.o
12559 obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o
12560 +obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o
12561 obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
12562 obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o
12563 obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o
12564 --- a/sound/soc/codecs/cs42xx8-i2c.c
12565 +++ b/sound/soc/codecs/cs42xx8-i2c.c
12566 @@ -45,11 +45,18 @@ static struct i2c_device_id cs42xx8_i2c_
12567 };
12568 MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id);
12569
12570 +const struct of_device_id cs42xx8_i2c_of_match[] = {
12571 + { .compatible = "cirrus,cs42448", .data = &cs42448_data, },
12572 + { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
12573 + { /* sentinel */ }
12574 +};
12575 +MODULE_DEVICE_TABLE(of, cs42xx8_i2c_of_match);
12576 +
12577 static struct i2c_driver cs42xx8_i2c_driver = {
12578 .driver = {
12579 .name = "cs42xx8",
12580 .pm = &cs42xx8_pm,
12581 - .of_match_table = cs42xx8_of_match,
12582 + .of_match_table = cs42xx8_i2c_of_match,
12583 },
12584 .probe = cs42xx8_i2c_probe,
12585 .remove = cs42xx8_i2c_remove,
12586 --- a/sound/soc/codecs/cs42xx8.c
12587 +++ b/sound/soc/codecs/cs42xx8.c
12588 @@ -517,8 +517,10 @@ const struct of_device_id cs42xx8_of_mat
12589 { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
12590 { /* sentinel */ }
12591 };
12592 +#if !IS_ENABLED(CONFIG_SND_SOC_CS42XX8_I2C)
12593 MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
12594 EXPORT_SYMBOL_GPL(cs42xx8_of_match);
12595 +#endif
12596
12597 int cs42xx8_probe(struct device *dev, struct regmap *regmap)
12598 {
12599 --- /dev/null
12600 +++ b/sound/soc/codecs/i-sabre-codec.c
12601 @@ -0,0 +1,392 @@
12602 +/*
12603 + * Driver for I-Sabre Q2M
12604 + *
12605 + * Author: Satoru Kawase
12606 + * Modified by: Xiao Qingyong
12607 + * Modified by: JC BARBAUD (Mute)
12608 + * Update kernel v4.18+ by : Audiophonics
12609 + * Copyright 2018 Audiophonics
12610 + *
12611 + * This program is free software; you can redistribute it and/or
12612 + * modify it under the terms of the GNU General Public License
12613 + * version 2 as published by the Free Software Foundation.
12614 + *
12615 + * This program is distributed in the hope that it will be useful, but
12616 + * WITHOUT ANY WARRANTY; without even the implied warranty of
12617 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12618 + * General Public License for more details.
12619 + */
12620 +
12621 +
12622 +#include <linux/init.h>
12623 +#include <linux/module.h>
12624 +#include <linux/regmap.h>
12625 +#include <linux/i2c.h>
12626 +#include <sound/soc.h>
12627 +#include <sound/pcm_params.h>
12628 +#include <sound/tlv.h>
12629 +
12630 +#include "i-sabre-codec.h"
12631 +
12632 +
12633 +/* I-Sabre Q2M Codec Private Data */
12634 +struct i_sabre_codec_priv {
12635 + struct regmap *regmap;
12636 + unsigned int fmt;
12637 +};
12638 +
12639 +
12640 +/* I-Sabre Q2M Codec Default Register Value */
12641 +static const struct reg_default i_sabre_codec_reg_defaults[] = {
12642 + { ISABRECODEC_REG_10, 0x00 },
12643 + { ISABRECODEC_REG_20, 0x00 },
12644 + { ISABRECODEC_REG_21, 0x00 },
12645 + { ISABRECODEC_REG_22, 0x00 },
12646 + { ISABRECODEC_REG_24, 0x00 },
12647 +};
12648 +
12649 +
12650 +static bool i_sabre_codec_writeable(struct device *dev, unsigned int reg)
12651 +{
12652 + switch (reg) {
12653 + case ISABRECODEC_REG_10:
12654 + case ISABRECODEC_REG_20:
12655 + case ISABRECODEC_REG_21:
12656 + case ISABRECODEC_REG_22:
12657 + case ISABRECODEC_REG_24:
12658 + return true;
12659 +
12660 + default:
12661 + return false;
12662 + }
12663 +}
12664 +
12665 +static bool i_sabre_codec_readable(struct device *dev, unsigned int reg)
12666 +{
12667 + switch (reg) {
12668 + case ISABRECODEC_REG_01:
12669 + case ISABRECODEC_REG_02:
12670 + case ISABRECODEC_REG_10:
12671 + case ISABRECODEC_REG_20:
12672 + case ISABRECODEC_REG_21:
12673 + case ISABRECODEC_REG_22:
12674 + case ISABRECODEC_REG_24:
12675 + return true;
12676 +
12677 + default:
12678 + return false;
12679 + }
12680 +}
12681 +
12682 +static bool i_sabre_codec_volatile(struct device *dev, unsigned int reg)
12683 +{
12684 + switch (reg) {
12685 + case ISABRECODEC_REG_01:
12686 + case ISABRECODEC_REG_02:
12687 + return true;
12688 +
12689 + default:
12690 + return false;
12691 + }
12692 +}
12693 +
12694 +
12695 +/* Volume Scale */
12696 +static const DECLARE_TLV_DB_SCALE(volume_tlv, -10000, 100, 0);
12697 +
12698 +
12699 +/* Filter Type */
12700 +static const char * const fir_filter_type_texts[] = {
12701 + "brick wall",
12702 + "corrected minimum phase fast",
12703 + "minimum phase slow",
12704 + "minimum phase fast",
12705 + "linear phase slow",
12706 + "linear phase fast",
12707 + "apodizing fast",
12708 +};
12709 +
12710 +static SOC_ENUM_SINGLE_DECL(i_sabre_fir_filter_type_enum,
12711 + ISABRECODEC_REG_22, 0, fir_filter_type_texts);
12712 +
12713 +
12714 +/* I2S / SPDIF Select */
12715 +static const char * const iis_spdif_sel_texts[] = {
12716 + "I2S",
12717 + "SPDIF",
12718 +};
12719 +
12720 +static SOC_ENUM_SINGLE_DECL(i_sabre_iis_spdif_sel_enum,
12721 + ISABRECODEC_REG_24, 0, iis_spdif_sel_texts);
12722 +
12723 +
12724 +/* Control */
12725 +static const struct snd_kcontrol_new i_sabre_codec_controls[] = {
12726 +SOC_SINGLE_RANGE_TLV("Digital Playback Volume", ISABRECODEC_REG_20, 0, 0, 100, 1, volume_tlv),
12727 +SOC_SINGLE("Digital Playback Switch", ISABRECODEC_REG_21, 0, 1, 1),
12728 +SOC_ENUM("FIR Filter Type", i_sabre_fir_filter_type_enum),
12729 +SOC_ENUM("I2S/SPDIF Select", i_sabre_iis_spdif_sel_enum),
12730 +};
12731 +
12732 +
12733 +static const u32 i_sabre_codec_dai_rates_slave[] = {
12734 + 8000, 11025, 16000, 22050, 32000,
12735 + 44100, 48000, 64000, 88200, 96000,
12736 + 176400, 192000, 352800, 384000,
12737 + 705600, 768000, 1411200, 1536000
12738 +};
12739 +
12740 +static const struct snd_pcm_hw_constraint_list constraints_slave = {
12741 + .list = i_sabre_codec_dai_rates_slave,
12742 + .count = ARRAY_SIZE(i_sabre_codec_dai_rates_slave),
12743 +};
12744 +
12745 +static int i_sabre_codec_dai_startup_slave(
12746 + struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
12747 +{
12748 + struct snd_soc_component *component = dai->component;
12749 + int ret;
12750 +
12751 + ret = snd_pcm_hw_constraint_list(substream->runtime,
12752 + 0, SNDRV_PCM_HW_PARAM_RATE, &constraints_slave);
12753 + if (ret != 0) {
12754 + dev_err(component->card->dev, "Failed to setup rates constraints: %d\n", ret);
12755 + }
12756 +
12757 + return ret;
12758 +}
12759 +
12760 +static int i_sabre_codec_dai_startup(
12761 + struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
12762 +{
12763 + struct snd_soc_component *component = dai->component;
12764 + struct i_sabre_codec_priv *i_sabre_codec
12765 + = snd_soc_component_get_drvdata(component);
12766 +
12767 + switch (i_sabre_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
12768 + case SND_SOC_DAIFMT_CBS_CFS:
12769 + return i_sabre_codec_dai_startup_slave(substream, dai);
12770 +
12771 + default:
12772 + return (-EINVAL);
12773 + }
12774 +}
12775 +
12776 +static int i_sabre_codec_hw_params(
12777 + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
12778 + struct snd_soc_dai *dai)
12779 +{
12780 + struct snd_soc_component *component = dai->component;
12781 + struct i_sabre_codec_priv *i_sabre_codec
12782 + = snd_soc_component_get_drvdata(component);
12783 + unsigned int daifmt;
12784 + int format_width;
12785 +
12786 + dev_dbg(component->card->dev, "hw_params %u Hz, %u channels\n",
12787 + params_rate(params), params_channels(params));
12788 +
12789 + /* Check I2S Format (Bit Size) */
12790 + format_width = snd_pcm_format_width(params_format(params));
12791 + if ((format_width != 32) && (format_width != 16)) {
12792 + dev_err(component->card->dev, "Bad frame size: %d\n",
12793 + snd_pcm_format_width(params_format(params)));
12794 + return (-EINVAL);
12795 + }
12796 +
12797 + /* Check Slave Mode */
12798 + daifmt = i_sabre_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK;
12799 + if (daifmt != SND_SOC_DAIFMT_CBS_CFS) {
12800 + return (-EINVAL);
12801 + }
12802 +
12803 + /* Notify Sampling Frequency */
12804 + switch (params_rate(params))
12805 + {
12806 + case 44100:
12807 + case 48000:
12808 + case 88200:
12809 + case 96000:
12810 + case 176400:
12811 + case 192000:
12812 + snd_soc_component_update_bits(component, ISABRECODEC_REG_10, 0x01, 0x00);
12813 + break;
12814 +
12815 + case 352800:
12816 + case 384000:
12817 + case 705600:
12818 + case 768000:
12819 + case 1411200:
12820 + case 1536000:
12821 + snd_soc_component_update_bits(component, ISABRECODEC_REG_10, 0x01, 0x01);
12822 + break;
12823 + }
12824 +
12825 + return 0;
12826 +}
12827 +
12828 +static int i_sabre_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
12829 +{
12830 + struct snd_soc_component *component = dai->component;
12831 + struct i_sabre_codec_priv *i_sabre_codec
12832 + = snd_soc_component_get_drvdata(component);
12833 +
12834 + /* interface format */
12835 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
12836 + case SND_SOC_DAIFMT_I2S:
12837 + break;
12838 +
12839 + case SND_SOC_DAIFMT_RIGHT_J:
12840 + case SND_SOC_DAIFMT_LEFT_J:
12841 + default:
12842 + return (-EINVAL);
12843 + }
12844 +
12845 + /* clock inversion */
12846 + if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
12847 + return (-EINVAL);
12848 + }
12849 +
12850 + /* Set Audio Data Format */
12851 + i_sabre_codec->fmt = fmt;
12852 +
12853 + return 0;
12854 +}
12855 +
12856 +static int i_sabre_codec_dac_mute(struct snd_soc_dai *dai, int mute, int direction)
12857 +{
12858 + struct snd_soc_component *component = dai->component;
12859 +
12860 + if (mute) {
12861 + snd_soc_component_update_bits(component, ISABRECODEC_REG_21, 0x01, 0x01);
12862 + } else {
12863 + snd_soc_component_update_bits(component, ISABRECODEC_REG_21, 0x01, 0x00);
12864 + }
12865 +
12866 + return 0;
12867 +}
12868 +
12869 +
12870 +static const struct snd_soc_dai_ops i_sabre_codec_dai_ops = {
12871 + .startup = i_sabre_codec_dai_startup,
12872 + .hw_params = i_sabre_codec_hw_params,
12873 + .set_fmt = i_sabre_codec_set_fmt,
12874 + .mute_stream = i_sabre_codec_dac_mute,
12875 +};
12876 +
12877 +static struct snd_soc_dai_driver i_sabre_codec_dai = {
12878 + .name = "i-sabre-codec-dai",
12879 + .playback = {
12880 + .stream_name = "Playback",
12881 + .channels_min = 2,
12882 + .channels_max = 2,
12883 + .rates = SNDRV_PCM_RATE_CONTINUOUS,
12884 + .rate_min = 8000,
12885 + .rate_max = 1536000,
12886 + .formats = SNDRV_PCM_FMTBIT_S16_LE
12887 + | SNDRV_PCM_FMTBIT_S32_LE,
12888 + },
12889 + .ops = &i_sabre_codec_dai_ops,
12890 +};
12891 +
12892 +static struct snd_soc_component_driver i_sabre_codec_codec_driver = {
12893 + .controls = i_sabre_codec_controls,
12894 + .num_controls = ARRAY_SIZE(i_sabre_codec_controls),
12895 +};
12896 +
12897 +
12898 +static const struct regmap_config i_sabre_codec_regmap = {
12899 + .reg_bits = 8,
12900 + .val_bits = 8,
12901 + .max_register = ISABRECODEC_MAX_REG,
12902 +
12903 + .reg_defaults = i_sabre_codec_reg_defaults,
12904 + .num_reg_defaults = ARRAY_SIZE(i_sabre_codec_reg_defaults),
12905 +
12906 + .writeable_reg = i_sabre_codec_writeable,
12907 + .readable_reg = i_sabre_codec_readable,
12908 + .volatile_reg = i_sabre_codec_volatile,
12909 +
12910 + .cache_type = REGCACHE_RBTREE,
12911 +};
12912 +
12913 +
12914 +static int i_sabre_codec_probe(struct device *dev, struct regmap *regmap)
12915 +{
12916 + struct i_sabre_codec_priv *i_sabre_codec;
12917 + int ret;
12918 +
12919 + i_sabre_codec = devm_kzalloc(dev, sizeof(*i_sabre_codec), GFP_KERNEL);
12920 + if (!i_sabre_codec) {
12921 + dev_err(dev, "devm_kzalloc");
12922 + return (-ENOMEM);
12923 + }
12924 +
12925 + i_sabre_codec->regmap = regmap;
12926 +
12927 + dev_set_drvdata(dev, i_sabre_codec);
12928 +
12929 + ret = snd_soc_register_component(dev,
12930 + &i_sabre_codec_codec_driver, &i_sabre_codec_dai, 1);
12931 + if (ret != 0) {
12932 + dev_err(dev, "Failed to register CODEC: %d\n", ret);
12933 + return ret;
12934 + }
12935 +
12936 + return 0;
12937 +}
12938 +
12939 +static void i_sabre_codec_remove(struct device *dev)
12940 +{
12941 + snd_soc_unregister_component(dev);
12942 +}
12943 +
12944 +
12945 +static int i_sabre_codec_i2c_probe(
12946 + struct i2c_client *i2c, const struct i2c_device_id *id)
12947 +{
12948 + struct regmap *regmap;
12949 +
12950 + regmap = devm_regmap_init_i2c(i2c, &i_sabre_codec_regmap);
12951 + if (IS_ERR(regmap)) {
12952 + return PTR_ERR(regmap);
12953 + }
12954 +
12955 + return i_sabre_codec_probe(&i2c->dev, regmap);
12956 +}
12957 +
12958 +static int i_sabre_codec_i2c_remove(struct i2c_client *i2c)
12959 +{
12960 + i_sabre_codec_remove(&i2c->dev);
12961 +
12962 + return 0;
12963 +}
12964 +
12965 +
12966 +static const struct i2c_device_id i_sabre_codec_i2c_id[] = {
12967 + { "i-sabre-codec", },
12968 + { }
12969 +};
12970 +MODULE_DEVICE_TABLE(i2c, i_sabre_codec_i2c_id);
12971 +
12972 +static const struct of_device_id i_sabre_codec_of_match[] = {
12973 + { .compatible = "audiophonics,i-sabre-codec", },
12974 + { }
12975 +};
12976 +MODULE_DEVICE_TABLE(of, i_sabre_codec_of_match);
12977 +
12978 +static struct i2c_driver i_sabre_codec_i2c_driver = {
12979 + .driver = {
12980 + .name = "i-sabre-codec-i2c",
12981 + .owner = THIS_MODULE,
12982 + .of_match_table = of_match_ptr(i_sabre_codec_of_match),
12983 + },
12984 + .probe = i_sabre_codec_i2c_probe,
12985 + .remove = i_sabre_codec_i2c_remove,
12986 + .id_table = i_sabre_codec_i2c_id,
12987 +};
12988 +module_i2c_driver(i_sabre_codec_i2c_driver);
12989 +
12990 +
12991 +MODULE_DESCRIPTION("ASoC I-Sabre Q2M codec driver");
12992 +MODULE_AUTHOR("Audiophonics <http://www.audiophonics.fr>");
12993 +MODULE_LICENSE("GPL");
12994 --- /dev/null
12995 +++ b/sound/soc/codecs/i-sabre-codec.h
12996 @@ -0,0 +1,42 @@
12997 +/*
12998 + * Driver for I-Sabre Q2M
12999 + *
13000 + * Author: Satoru Kawase
13001 + * Modified by: Xiao Qingyong
13002 + * Copyright 2018 Audiophonics
13003 + *
13004 + * This program is free software; you can redistribute it and/or
13005 + * modify it under the terms of the GNU General Public License
13006 + * version 2 as published by the Free Software Foundation.
13007 + *
13008 + * This program is distributed in the hope that it will be useful, but
13009 + * WITHOUT ANY WARRANTY; without even the implied warranty of
13010 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13011 + * General Public License for more details.
13012 + */
13013 +
13014 +#ifndef _SND_SOC_ISABRECODEC
13015 +#define _SND_SOC_ISABRECODEC
13016 +
13017 +
13018 +/* ISABRECODEC Register Address */
13019 +#define ISABRECODEC_REG_01 0x01 /* Virtual Device ID : 0x01 = es9038q2m */
13020 +#define ISABRECODEC_REG_02 0x02 /* API revision : 0x01 = Revision 01 */
13021 +#define ISABRECODEC_REG_10 0x10 /* 0x01 = above 192kHz, 0x00 = otherwise */
13022 +#define ISABRECODEC_REG_20 0x20 /* 0 - 100 (decimal value, 0 = min., 100 = max.) */
13023 +#define ISABRECODEC_REG_21 0x21 /* 0x00 = Mute OFF, 0x01 = Mute ON */
13024 +#define ISABRECODEC_REG_22 0x22
13025 +/*
13026 + 0x00 = brick wall,
13027 + 0x01 = corrected minimum phase fast,
13028 + 0x02 = minimum phase slow,
13029 + 0x03 = minimum phase fast,
13030 + 0x04 = linear phase slow,
13031 + 0x05 = linear phase fast,
13032 + 0x06 = apodizing fast,
13033 +*/
13034 +//#define ISABRECODEC_REG_23 0x23 /* reserved */
13035 +#define ISABRECODEC_REG_24 0x24 /* 0x00 = I2S, 0x01 = SPDIF */
13036 +#define ISABRECODEC_MAX_REG 0x24 /* Maximum Register Number */
13037 +
13038 +#endif /* _SND_SOC_ISABRECODEC */
13039 --- /dev/null
13040 +++ b/sound/soc/codecs/ma120x0p.c
13041 @@ -0,0 +1,1384 @@
13042 +// SPDX-License-Identifier: GPL-2.0-or-later
13043 +/*
13044 + * ASoC Driver for Infineon Merus(TM) ma120x0p multi-level class-D amplifier
13045 + *
13046 + * Authors: Ariel Muszkat <ariel.muszkat@gmail.com>
13047 + * Jorgen Kragh Jakobsen <jorgen.kraghjakobsen@infineon.com>
13048 + *
13049 + * Copyright (C) 2019 Infineon Technologies AG
13050 + *
13051 + */
13052 +#include <linux/module.h>
13053 +#include <linux/moduleparam.h>
13054 +#include <linux/init.h>
13055 +#include <linux/delay.h>
13056 +#include <linux/pm_runtime.h>
13057 +#include <linux/i2c.h>
13058 +#include <linux/of_device.h>
13059 +#include <linux/spi/spi.h>
13060 +#include <linux/regmap.h>
13061 +#include <linux/regulator/consumer.h>
13062 +#include <linux/slab.h>
13063 +#include <linux/gpio/consumer.h>
13064 +#include <linux/gpio.h>
13065 +#include <sound/core.h>
13066 +#include <sound/pcm.h>
13067 +#include <sound/pcm_params.h>
13068 +#include <sound/soc.h>
13069 +#include <sound/soc-dapm.h>
13070 +#include <sound/initval.h>
13071 +#include <sound/tlv.h>
13072 +#include <linux/interrupt.h>
13073 +
13074 +#include <linux/kernel.h>
13075 +#include <linux/string.h>
13076 +#include <linux/fs.h>
13077 +#include <linux/uaccess.h>
13078 +
13079 +#ifndef _MA120X0P_
13080 +#define _MA120X0P_
13081 +//------------------------------------------------------------------manualPM---
13082 +// Select Manual PowerMode control
13083 +#define ma_manualpm__a 0
13084 +#define ma_manualpm__len 1
13085 +#define ma_manualpm__mask 0x40
13086 +#define ma_manualpm__shift 0x06
13087 +#define ma_manualpm__reset 0x00
13088 +//--------------------------------------------------------------------pm_man---
13089 +// manual selected power mode
13090 +#define ma_pm_man__a 0
13091 +#define ma_pm_man__len 2
13092 +#define ma_pm_man__mask 0x30
13093 +#define ma_pm_man__shift 0x04
13094 +#define ma_pm_man__reset 0x03
13095 +//------------------------------------------ ----------------------mthr_1to2---
13096 +// mod. index threshold value for pm1=>pm2 change.
13097 +#define ma_mthr_1to2__a 1
13098 +#define ma_mthr_1to2__len 8
13099 +#define ma_mthr_1to2__mask 0xff
13100 +#define ma_mthr_1to2__shift 0x00
13101 +#define ma_mthr_1to2__reset 0x3c
13102 +//-----------------------------------------------------------------mthr_2to1---
13103 +// mod. index threshold value for pm2=>pm1 change.
13104 +#define ma_mthr_2to1__a 2
13105 +#define ma_mthr_2to1__len 8
13106 +#define ma_mthr_2to1__mask 0xff
13107 +#define ma_mthr_2to1__shift 0x00
13108 +#define ma_mthr_2to1__reset 0x32
13109 +//-----------------------------------------------------------------mthr_2to3---
13110 +// mod. index threshold value for pm2=>pm3 change.
13111 +#define ma_mthr_2to3__a 3
13112 +#define ma_mthr_2to3__len 8
13113 +#define ma_mthr_2to3__mask 0xff
13114 +#define ma_mthr_2to3__shift 0x00
13115 +#define ma_mthr_2to3__reset 0x5a
13116 +//-----------------------------------------------------------------mthr_3to2---
13117 +// mod. index threshold value for pm3=>pm2 change.
13118 +#define ma_mthr_3to2__a 4
13119 +#define ma_mthr_3to2__len 8
13120 +#define ma_mthr_3to2__mask 0xff
13121 +#define ma_mthr_3to2__shift 0x00
13122 +#define ma_mthr_3to2__reset 0x50
13123 +//-------------------------------------------------------------pwmclkdiv_nom---
13124 +// pwm default clock divider value
13125 +#define ma_pwmclkdiv_nom__a 8
13126 +#define ma_pwmclkdiv_nom__len 8
13127 +#define ma_pwmclkdiv_nom__mask 0xff
13128 +#define ma_pwmclkdiv_nom__shift 0x00
13129 +#define ma_pwmclkdiv_nom__reset 0x26
13130 +//--------- ----------------------------------------------------ocp_latch_en---
13131 +// high to use permanently latching level-2 ocp
13132 +#define ma_ocp_latch_en__a 10
13133 +#define ma_ocp_latch_en__len 1
13134 +#define ma_ocp_latch_en__mask 0x02
13135 +#define ma_ocp_latch_en__shift 0x01
13136 +#define ma_ocp_latch_en__reset 0x00
13137 +//---------------------------------------------------------------lf_clamp_en---
13138 +// high (default) to enable lf int2+3 clamping on clip
13139 +#define ma_lf_clamp_en__a 10
13140 +#define ma_lf_clamp_en__len 1
13141 +#define ma_lf_clamp_en__mask 0x80
13142 +#define ma_lf_clamp_en__shift 0x07
13143 +#define ma_lf_clamp_en__reset 0x00
13144 +//-------------------------------------------------------pmcfg_btl_b.modtype---
13145 +//
13146 +#define ma_pmcfg_btl_b__modtype__a 18
13147 +#define ma_pmcfg_btl_b__modtype__len 2
13148 +#define ma_pmcfg_btl_b__modtype__mask 0x18
13149 +#define ma_pmcfg_btl_b__modtype__shift 0x03
13150 +#define ma_pmcfg_btl_b__modtype__reset 0x02
13151 +//-------------------------------------------------------pmcfg_btl_b.freqdiv---
13152 +#define ma_pmcfg_btl_b__freqdiv__a 18
13153 +#define ma_pmcfg_btl_b__freqdiv__len 2
13154 +#define ma_pmcfg_btl_b__freqdiv__mask 0x06
13155 +#define ma_pmcfg_btl_b__freqdiv__shift 0x01
13156 +#define ma_pmcfg_btl_b__freqdiv__reset 0x01
13157 +//----------------------------------------------------pmcfg_btl_b.lf_gain_ol---
13158 +//
13159 +#define ma_pmcfg_btl_b__lf_gain_ol__a 18
13160 +#define ma_pmcfg_btl_b__lf_gain_ol__len 1
13161 +#define ma_pmcfg_btl_b__lf_gain_ol__mask 0x01
13162 +#define ma_pmcfg_btl_b__lf_gain_ol__shift 0x00
13163 +#define ma_pmcfg_btl_b__lf_gain_ol__reset 0x01
13164 +//-------------------------------------------------------pmcfg_btl_c.freqdiv---
13165 +//
13166 +#define ma_pmcfg_btl_c__freqdiv__a 19
13167 +#define ma_pmcfg_btl_c__freqdiv__len 2
13168 +#define ma_pmcfg_btl_c__freqdiv__mask 0x06
13169 +#define ma_pmcfg_btl_c__freqdiv__shift 0x01
13170 +#define ma_pmcfg_btl_c__freqdiv__reset 0x01
13171 +//-------------------------------------------------------pmcfg_btl_c.modtype---
13172 +//
13173 +#define ma_pmcfg_btl_c__modtype__a 19
13174 +#define ma_pmcfg_btl_c__modtype__len 2
13175 +#define ma_pmcfg_btl_c__modtype__mask 0x18
13176 +#define ma_pmcfg_btl_c__modtype__shift 0x03
13177 +#define ma_pmcfg_btl_c__modtype__reset 0x01
13178 +//----------------------------------------------------pmcfg_btl_c.lf_gain_ol---
13179 +//
13180 +#define ma_pmcfg_btl_c__lf_gain_ol__a 19
13181 +#define ma_pmcfg_btl_c__lf_gain_ol__len 1
13182 +#define ma_pmcfg_btl_c__lf_gain_ol__mask 0x01
13183 +#define ma_pmcfg_btl_c__lf_gain_ol__shift 0x00
13184 +#define ma_pmcfg_btl_c__lf_gain_ol__reset 0x00
13185 +//-------------------------------------------------------pmcfg_btl_d.modtype---
13186 +//
13187 +#define ma_pmcfg_btl_d__modtype__a 20
13188 +#define ma_pmcfg_btl_d__modtype__len 2
13189 +#define ma_pmcfg_btl_d__modtype__mask 0x18
13190 +#define ma_pmcfg_btl_d__modtype__shift 0x03
13191 +#define ma_pmcfg_btl_d__modtype__reset 0x02
13192 +//-------------------------------------------------------pmcfg_btl_d.freqdiv---
13193 +//
13194 +#define ma_pmcfg_btl_d__freqdiv__a 20
13195 +#define ma_pmcfg_btl_d__freqdiv__len 2
13196 +#define ma_pmcfg_btl_d__freqdiv__mask 0x06
13197 +#define ma_pmcfg_btl_d__freqdiv__shift 0x01
13198 +#define ma_pmcfg_btl_d__freqdiv__reset 0x02
13199 +//----------------------------------------------------pmcfg_btl_d.lf_gain_ol---
13200 +//
13201 +#define ma_pmcfg_btl_d__lf_gain_ol__a 20
13202 +#define ma_pmcfg_btl_d__lf_gain_ol__len 1
13203 +#define ma_pmcfg_btl_d__lf_gain_ol__mask 0x01
13204 +#define ma_pmcfg_btl_d__lf_gain_ol__shift 0x00
13205 +#define ma_pmcfg_btl_d__lf_gain_ol__reset 0x00
13206 +//------------ -------------------------------------------pmcfg_se_a.modtype---
13207 +//
13208 +#define ma_pmcfg_se_a__modtype__a 21
13209 +#define ma_pmcfg_se_a__modtype__len 2
13210 +#define ma_pmcfg_se_a__modtype__mask 0x18
13211 +#define ma_pmcfg_se_a__modtype__shift 0x03
13212 +#define ma_pmcfg_se_a__modtype__reset 0x01
13213 +//--------------------------------------------------------pmcfg_se_a.freqdiv---
13214 +//
13215 +#define ma_pmcfg_se_a__freqdiv__a 21
13216 +#define ma_pmcfg_se_a__freqdiv__len 2
13217 +#define ma_pmcfg_se_a__freqdiv__mask 0x06
13218 +#define ma_pmcfg_se_a__freqdiv__shift 0x01
13219 +#define ma_pmcfg_se_a__freqdiv__reset 0x00
13220 +//-----------------------------------------------------pmcfg_se_a.lf_gain_ol---
13221 +//
13222 +#define ma_pmcfg_se_a__lf_gain_ol__a 21
13223 +#define ma_pmcfg_se_a__lf_gain_ol__len 1
13224 +#define ma_pmcfg_se_a__lf_gain_ol__mask 0x01
13225 +#define ma_pmcfg_se_a__lf_gain_ol__shift 0x00
13226 +#define ma_pmcfg_se_a__lf_gain_ol__reset 0x01
13227 +//-----------------------------------------------------pmcfg_se_b.lf_gain_ol---
13228 +//
13229 +#define ma_pmcfg_se_b__lf_gain_ol__a 22
13230 +#define ma_pmcfg_se_b__lf_gain_ol__len 1
13231 +#define ma_pmcfg_se_b__lf_gain_ol__mask 0x01
13232 +#define ma_pmcfg_se_b__lf_gain_ol__shift 0x00
13233 +#define ma_pmcfg_se_b__lf_gain_ol__reset 0x00
13234 +//--------------------------------------------------------pmcfg_se_b.freqdiv---
13235 +//
13236 +#define ma_pmcfg_se_b__freqdiv__a 22
13237 +#define ma_pmcfg_se_b__freqdiv__len 2
13238 +#define ma_pmcfg_se_b__freqdiv__mask 0x06
13239 +#define ma_pmcfg_se_b__freqdiv__shift 0x01
13240 +#define ma_pmcfg_se_b__freqdiv__reset 0x01
13241 +//--------------------------------------------------------pmcfg_se_b.modtype---
13242 +//
13243 +#define ma_pmcfg_se_b__modtype__a 22
13244 +#define ma_pmcfg_se_b__modtype__len 2
13245 +#define ma_pmcfg_se_b__modtype__mask 0x18
13246 +#define ma_pmcfg_se_b__modtype__shift 0x03
13247 +#define ma_pmcfg_se_b__modtype__reset 0x01
13248 +//----------------------------------------------------------balwaitcount_pm1---
13249 +// pm1 balancing period.
13250 +#define ma_balwaitcount_pm1__a 23
13251 +#define ma_balwaitcount_pm1__len 8
13252 +#define ma_balwaitcount_pm1__mask 0xff
13253 +#define ma_balwaitcount_pm1__shift 0x00
13254 +#define ma_balwaitcount_pm1__reset 0x14
13255 +//----------------------------------------------------------balwaitcount_pm2---
13256 +// pm2 balancing period.
13257 +#define ma_balwaitcount_pm2__a 24
13258 +#define ma_balwaitcount_pm2__len 8
13259 +#define ma_balwaitcount_pm2__mask 0xff
13260 +#define ma_balwaitcount_pm2__shift 0x00
13261 +#define ma_balwaitcount_pm2__reset 0x14
13262 +//----------------------------------------------------------balwaitcount_pm3---
13263 +// pm3 balancing period.
13264 +#define ma_balwaitcount_pm3__a 25
13265 +#define ma_balwaitcount_pm3__len 8
13266 +#define ma_balwaitcount_pm3__mask 0xff
13267 +#define ma_balwaitcount_pm3__shift 0x00
13268 +#define ma_balwaitcount_pm3__reset 0x1a
13269 +//-------------------------------------------------------------usespread_pm1---
13270 +// pm1 pwm spread-spectrum mode on/off.
13271 +#define ma_usespread_pm1__a 26
13272 +#define ma_usespread_pm1__len 1
13273 +#define ma_usespread_pm1__mask 0x40
13274 +#define ma_usespread_pm1__shift 0x06
13275 +#define ma_usespread_pm1__reset 0x00
13276 +//---------------------------------------------------------------dtsteps_pm1---
13277 +// pm1 dead time setting [10ns steps].
13278 +#define ma_dtsteps_pm1__a 26
13279 +#define ma_dtsteps_pm1__len 3
13280 +#define ma_dtsteps_pm1__mask 0x38
13281 +#define ma_dtsteps_pm1__shift 0x03
13282 +#define ma_dtsteps_pm1__reset 0x04
13283 +//---------------------------------------------------------------baltype_pm1---
13284 +// pm1 balancing sensor scheme.
13285 +#define ma_baltype_pm1__a 26
13286 +#define ma_baltype_pm1__len 3
13287 +#define ma_baltype_pm1__mask 0x07
13288 +#define ma_baltype_pm1__shift 0x00
13289 +#define ma_baltype_pm1__reset 0x00
13290 +//-------------------------------------------------------------usespread_pm2---
13291 +// pm2 pwm spread-spectrum mode on/off.
13292 +#define ma_usespread_pm2__a 27
13293 +#define ma_usespread_pm2__len 1
13294 +#define ma_usespread_pm2__mask 0x40
13295 +#define ma_usespread_pm2__shift 0x06
13296 +#define ma_usespread_pm2__reset 0x00
13297 +//---------------------------------------------------------------dtsteps_pm2---
13298 +// pm2 dead time setting [10ns steps].
13299 +#define ma_dtsteps_pm2__a 27
13300 +#define ma_dtsteps_pm2__len 3
13301 +#define ma_dtsteps_pm2__mask 0x38
13302 +#define ma_dtsteps_pm2__shift 0x03
13303 +#define ma_dtsteps_pm2__reset 0x03
13304 +//---------------------------------------------------------------baltype_pm2---
13305 +// pm2 balancing sensor scheme.
13306 +#define ma_baltype_pm2__a 27
13307 +#define ma_baltype_pm2__len 3
13308 +#define ma_baltype_pm2__mask 0x07
13309 +#define ma_baltype_pm2__shift 0x00
13310 +#define ma_baltype_pm2__reset 0x01
13311 +//-------------------------------------------------------------usespread_pm3---
13312 +// pm3 pwm spread-spectrum mode on/off.
13313 +#define ma_usespread_pm3__a 28
13314 +#define ma_usespread_pm3__len 1
13315 +#define ma_usespread_pm3__mask 0x40
13316 +#define ma_usespread_pm3__shift 0x06
13317 +#define ma_usespread_pm3__reset 0x00
13318 +//---------------------------------------------------------------dtsteps_pm3---
13319 +// pm3 dead time setting [10ns steps].
13320 +#define ma_dtsteps_pm3__a 28
13321 +#define ma_dtsteps_pm3__len 3
13322 +#define ma_dtsteps_pm3__mask 0x38
13323 +#define ma_dtsteps_pm3__shift 0x03
13324 +#define ma_dtsteps_pm3__reset 0x01
13325 +//---------------------------------------------------------------baltype_pm3---
13326 +// pm3 balancing sensor scheme.
13327 +#define ma_baltype_pm3__a 28
13328 +#define ma_baltype_pm3__len 3
13329 +#define ma_baltype_pm3__mask 0x07
13330 +#define ma_baltype_pm3__shift 0x00
13331 +#define ma_baltype_pm3__reset 0x03
13332 +//-----------------------------------------------------------------pmprofile---
13333 +// pm profile select. valid presets: 0-1-2-3-4. 5=> custom profile.
13334 +#define ma_pmprofile__a 29
13335 +#define ma_pmprofile__len 3
13336 +#define ma_pmprofile__mask 0x07
13337 +#define ma_pmprofile__shift 0x00
13338 +#define ma_pmprofile__reset 0x00
13339 +//-------------------------------------------------------------------pm3_man---
13340 +// custom profile pm3 contents. 0=>a, 1=>b, 2=>c, 3=>d
13341 +#define ma_pm3_man__a 30
13342 +#define ma_pm3_man__len 2
13343 +#define ma_pm3_man__mask 0x30
13344 +#define ma_pm3_man__shift 0x04
13345 +#define ma_pm3_man__reset 0x02
13346 +//-------------------------------------------------------------------pm2_man---
13347 +// custom profile pm2 contents. 0=>a, 1=>b, 2=>c, 3=>d
13348 +#define ma_pm2_man__a 30
13349 +#define ma_pm2_man__len 2
13350 +#define ma_pm2_man__mask 0x0c
13351 +#define ma_pm2_man__shift 0x02
13352 +#define ma_pm2_man__reset 0x03
13353 +//-------------------------------------------------------------------pm1_man---
13354 +// custom profile pm1 contents. 0=>a, 1=>b, 2=>c, 3=>d
13355 +#define ma_pm1_man__a 30
13356 +#define ma_pm1_man__len 2
13357 +#define ma_pm1_man__mask 0x03
13358 +#define ma_pm1_man__shift 0x00
13359 +#define ma_pm1_man__reset 0x03
13360 +//-----------------------------------------------------------ocp_latch_clear---
13361 +// low-high clears current ocp latched condition.
13362 +#define ma_ocp_latch_clear__a 32
13363 +#define ma_ocp_latch_clear__len 1
13364 +#define ma_ocp_latch_clear__mask 0x80
13365 +#define ma_ocp_latch_clear__shift 0x07
13366 +#define ma_ocp_latch_clear__reset 0x00
13367 +//-------------------------------------------------------------audio_in_mode---
13368 +// audio input mode; 0-1-2-3-4-5
13369 +#define ma_audio_in_mode__a 37
13370 +#define ma_audio_in_mode__len 3
13371 +#define ma_audio_in_mode__mask 0xe0
13372 +#define ma_audio_in_mode__shift 0x05
13373 +#define ma_audio_in_mode__reset 0x00
13374 +//-----------------------------------------------------------------eh_dcshdn---
13375 +// high to enable dc protection
13376 +#define ma_eh_dcshdn__a 38
13377 +#define ma_eh_dcshdn__len 1
13378 +#define ma_eh_dcshdn__mask 0x04
13379 +#define ma_eh_dcshdn__shift 0x02
13380 +#define ma_eh_dcshdn__reset 0x01
13381 +//---------------------------------------------------------audio_in_mode_ext---
13382 +// if set, audio_in_mode is controlled from audio_in_mode register. if not set
13383 +//audio_in_mode is set from fuse bank setting
13384 +#define ma_audio_in_mode_ext__a 39
13385 +#define ma_audio_in_mode_ext__len 1
13386 +#define ma_audio_in_mode_ext__mask 0x20
13387 +#define ma_audio_in_mode_ext__shift 0x05
13388 +#define ma_audio_in_mode_ext__reset 0x00
13389 +//------------------------------------------------------------------eh_clear---
13390 +// flip to clear error registers
13391 +#define ma_eh_clear__a 45
13392 +#define ma_eh_clear__len 1
13393 +#define ma_eh_clear__mask 0x04
13394 +#define ma_eh_clear__shift 0x02
13395 +#define ma_eh_clear__reset 0x00
13396 +//----------------------------------------------------------thermal_compr_en---
13397 +// enable otw-contr. input compression?
13398 +#define ma_thermal_compr_en__a 45
13399 +#define ma_thermal_compr_en__len 1
13400 +#define ma_thermal_compr_en__mask 0x20
13401 +#define ma_thermal_compr_en__shift 0x05
13402 +#define ma_thermal_compr_en__reset 0x01
13403 +//---------------------------------------------------------------system_mute---
13404 +// 1 = mute system, 0 = normal operation
13405 +#define ma_system_mute__a 45
13406 +#define ma_system_mute__len 1
13407 +#define ma_system_mute__mask 0x40
13408 +#define ma_system_mute__shift 0x06
13409 +#define ma_system_mute__reset 0x00
13410 +//------------------------------------------------------thermal_compr_max_db---
13411 +// audio limiter max thermal reduction
13412 +#define ma_thermal_compr_max_db__a 46
13413 +#define ma_thermal_compr_max_db__len 3
13414 +#define ma_thermal_compr_max_db__mask 0x07
13415 +#define ma_thermal_compr_max_db__shift 0x00
13416 +#define ma_thermal_compr_max_db__reset 0x04
13417 +//---------------------------------------------------------audio_proc_enable---
13418 +// enable audio proc, bypass if not enabled
13419 +#define ma_audio_proc_enable__a 53
13420 +#define ma_audio_proc_enable__len 1
13421 +#define ma_audio_proc_enable__mask 0x08
13422 +#define ma_audio_proc_enable__shift 0x03
13423 +#define ma_audio_proc_enable__reset 0x00
13424 +//--------------------------------------------------------audio_proc_release---
13425 +// 00:slow, 01:normal, 10:fast
13426 +#define ma_audio_proc_release__a 53
13427 +#define ma_audio_proc_release__len 2
13428 +#define ma_audio_proc_release__mask 0x30
13429 +#define ma_audio_proc_release__shift 0x04
13430 +#define ma_audio_proc_release__reset 0x00
13431 +//---------------------------------------------------------audio_proc_attack---
13432 +// 00:slow, 01:normal, 10:fast
13433 +#define ma_audio_proc_attack__a 53
13434 +#define ma_audio_proc_attack__len 2
13435 +#define ma_audio_proc_attack__mask 0xc0
13436 +#define ma_audio_proc_attack__shift 0x06
13437 +#define ma_audio_proc_attack__reset 0x00
13438 +//----------------------------------------------------------------i2s_format---
13439 +// i2s basic data format, 000 = std. i2s, 001 = left justified (default)
13440 +#define ma_i2s_format__a 53
13441 +#define ma_i2s_format__len 3
13442 +#define ma_i2s_format__mask 0x07
13443 +#define ma_i2s_format__shift 0x00
13444 +#define ma_i2s_format__reset 0x01
13445 +//--------------------------------------------------audio_proc_limiterenable---
13446 +// 1: enable limiter, 0: disable limiter
13447 +#define ma_audio_proc_limiterenable__a 54
13448 +#define ma_audio_proc_limiterenable__len 1
13449 +#define ma_audio_proc_limiterenable__mask 0x40
13450 +#define ma_audio_proc_limiterenable__shift 0x06
13451 +#define ma_audio_proc_limiterenable__reset 0x00
13452 +//-----------------------------------------------------------audio_proc_mute---
13453 +// 1: mute, 0: unmute
13454 +#define ma_audio_proc_mute__a 54
13455 +#define ma_audio_proc_mute__len 1
13456 +#define ma_audio_proc_mute__mask 0x80
13457 +#define ma_audio_proc_mute__shift 0x07
13458 +#define ma_audio_proc_mute__reset 0x00
13459 +//---------------------------------------------------------------i2s_sck_pol---
13460 +// i2s sck polarity cfg. 0 = rising edge data change
13461 +#define ma_i2s_sck_pol__a 54
13462 +#define ma_i2s_sck_pol__len 1
13463 +#define ma_i2s_sck_pol__mask 0x01
13464 +#define ma_i2s_sck_pol__shift 0x00
13465 +#define ma_i2s_sck_pol__reset 0x01
13466 +//-------------------------------------------------------------i2s_framesize---
13467 +// i2s word length. 00 = 32bit, 01 = 24bit
13468 +#define ma_i2s_framesize__a 54
13469 +#define ma_i2s_framesize__len 2
13470 +#define ma_i2s_framesize__mask 0x18
13471 +#define ma_i2s_framesize__shift 0x03
13472 +#define ma_i2s_framesize__reset 0x00
13473 +//----------------------------------------------------------------i2s_ws_pol---
13474 +// i2s ws polarity. 0 = low first
13475 +#define ma_i2s_ws_pol__a 54
13476 +#define ma_i2s_ws_pol__len 1
13477 +#define ma_i2s_ws_pol__mask 0x02
13478 +#define ma_i2s_ws_pol__shift 0x01
13479 +#define ma_i2s_ws_pol__reset 0x00
13480 +//-----------------------------------------------------------------i2s_order---
13481 +// i2s word bit order. 0 = msb first
13482 +#define ma_i2s_order__a 54
13483 +#define ma_i2s_order__len 1
13484 +#define ma_i2s_order__mask 0x04
13485 +#define ma_i2s_order__shift 0x02
13486 +#define ma_i2s_order__reset 0x00
13487 +//------------------------------------------------------------i2s_rightfirst---
13488 +// i2s l/r word order; 0 = left first
13489 +#define ma_i2s_rightfirst__a 54
13490 +#define ma_i2s_rightfirst__len 1
13491 +#define ma_i2s_rightfirst__mask 0x20
13492 +#define ma_i2s_rightfirst__shift 0x05
13493 +#define ma_i2s_rightfirst__reset 0x00
13494 +//-------------------------------------------------------------vol_db_master---
13495 +// master volume db
13496 +#define ma_vol_db_master__a 64
13497 +#define ma_vol_db_master__len 8
13498 +#define ma_vol_db_master__mask 0xff
13499 +#define ma_vol_db_master__shift 0x00
13500 +#define ma_vol_db_master__reset 0x18
13501 +//------------------------------------------------------------vol_lsb_master---
13502 +// master volume lsb 1/4 steps
13503 +#define ma_vol_lsb_master__a 65
13504 +#define ma_vol_lsb_master__len 2
13505 +#define ma_vol_lsb_master__mask 0x03
13506 +#define ma_vol_lsb_master__shift 0x00
13507 +#define ma_vol_lsb_master__reset 0x00
13508 +//----------------------------------------------------------------vol_db_ch0---
13509 +// volume channel 0
13510 +#define ma_vol_db_ch0__a 66
13511 +#define ma_vol_db_ch0__len 8
13512 +#define ma_vol_db_ch0__mask 0xff
13513 +#define ma_vol_db_ch0__shift 0x00
13514 +#define ma_vol_db_ch0__reset 0x18
13515 +//----------------------------------------------------------------vol_db_ch1---
13516 +// volume channel 1
13517 +#define ma_vol_db_ch1__a 67
13518 +#define ma_vol_db_ch1__len 8
13519 +#define ma_vol_db_ch1__mask 0xff
13520 +#define ma_vol_db_ch1__shift 0x00
13521 +#define ma_vol_db_ch1__reset 0x18
13522 +//----------------------------------------------------------------vol_db_ch2---
13523 +// volume channel 2
13524 +#define ma_vol_db_ch2__a 68
13525 +#define ma_vol_db_ch2__len 8
13526 +#define ma_vol_db_ch2__mask 0xff
13527 +#define ma_vol_db_ch2__shift 0x00
13528 +#define ma_vol_db_ch2__reset 0x18
13529 +//----------------------------------------------------------------vol_db_ch3---
13530 +// volume channel 3
13531 +#define ma_vol_db_ch3__a 69
13532 +#define ma_vol_db_ch3__len 8
13533 +#define ma_vol_db_ch3__mask 0xff
13534 +#define ma_vol_db_ch3__shift 0x00
13535 +#define ma_vol_db_ch3__reset 0x18
13536 +//---------------------------------------------------------------vol_lsb_ch0---
13537 +// volume channel 1 - 1/4 steps
13538 +#define ma_vol_lsb_ch0__a 70
13539 +#define ma_vol_lsb_ch0__len 2
13540 +#define ma_vol_lsb_ch0__mask 0x03
13541 +#define ma_vol_lsb_ch0__shift 0x00
13542 +#define ma_vol_lsb_ch0__reset 0x00
13543 +//---------------------------------------------------------------vol_lsb_ch1---
13544 +// volume channel 3 - 1/4 steps
13545 +#define ma_vol_lsb_ch1__a 70
13546 +#define ma_vol_lsb_ch1__len 2
13547 +#define ma_vol_lsb_ch1__mask 0x0c
13548 +#define ma_vol_lsb_ch1__shift 0x02
13549 +#define ma_vol_lsb_ch1__reset 0x00
13550 +//---------------------------------------------------------------vol_lsb_ch2---
13551 +// volume channel 2 - 1/4 steps
13552 +#define ma_vol_lsb_ch2__a 70
13553 +#define ma_vol_lsb_ch2__len 2
13554 +#define ma_vol_lsb_ch2__mask 0x30
13555 +#define ma_vol_lsb_ch2__shift 0x04
13556 +#define ma_vol_lsb_ch2__reset 0x00
13557 +//---------------------------------------------------------------vol_lsb_ch3---
13558 +// volume channel 3 - 1/4 steps
13559 +#define ma_vol_lsb_ch3__a 70
13560 +#define ma_vol_lsb_ch3__len 2
13561 +#define ma_vol_lsb_ch3__mask 0xc0
13562 +#define ma_vol_lsb_ch3__shift 0x06
13563 +#define ma_vol_lsb_ch3__reset 0x00
13564 +//----------------------------------------------------------------thr_db_ch0---
13565 +// thr_db channel 0
13566 +#define ma_thr_db_ch0__a 71
13567 +#define ma_thr_db_ch0__len 8
13568 +#define ma_thr_db_ch0__mask 0xff
13569 +#define ma_thr_db_ch0__shift 0x00
13570 +#define ma_thr_db_ch0__reset 0x18
13571 +//----------------------------------------------------------------thr_db_ch1---
13572 +// thr db ch1
13573 +#define ma_thr_db_ch1__a 72
13574 +#define ma_thr_db_ch1__len 8
13575 +#define ma_thr_db_ch1__mask 0xff
13576 +#define ma_thr_db_ch1__shift 0x00
13577 +#define ma_thr_db_ch1__reset 0x18
13578 +//----------------------------------------------------------------thr_db_ch2---
13579 +// thr db ch2
13580 +#define ma_thr_db_ch2__a 73
13581 +#define ma_thr_db_ch2__len 8
13582 +#define ma_thr_db_ch2__mask 0xff
13583 +#define ma_thr_db_ch2__shift 0x00
13584 +#define ma_thr_db_ch2__reset 0x18
13585 +//----------------------------------------------------------------thr_db_ch3---
13586 +// threshold db ch3
13587 +#define ma_thr_db_ch3__a 74
13588 +#define ma_thr_db_ch3__len 8
13589 +#define ma_thr_db_ch3__mask 0xff
13590 +#define ma_thr_db_ch3__shift 0x00
13591 +#define ma_thr_db_ch3__reset 0x18
13592 +//---------------------------------------------------------------thr_lsb_ch0---
13593 +// thr lsb ch0
13594 +#define ma_thr_lsb_ch0__a 75
13595 +#define ma_thr_lsb_ch0__len 2
13596 +#define ma_thr_lsb_ch0__mask 0x03
13597 +#define ma_thr_lsb_ch0__shift 0x00
13598 +#define ma_thr_lsb_ch0__reset 0x00
13599 +//---------------------------------------------------------------thr_lsb_ch1---
13600 +// thr lsb ch1
13601 +#define ma_thr_lsb_ch1__a 75
13602 +#define ma_thr_lsb_ch1__len 2
13603 +#define ma_thr_lsb_ch1__mask 0x0c
13604 +#define ma_thr_lsb_ch1__shift 0x02
13605 +#define ma_thr_lsb_ch1__reset 0x00
13606 +//---------------------------------------------------------------thr_lsb_ch2---
13607 +// thr lsb ch2 1/4 db step
13608 +#define ma_thr_lsb_ch2__a 75
13609 +#define ma_thr_lsb_ch2__len 2
13610 +#define ma_thr_lsb_ch2__mask 0x30
13611 +#define ma_thr_lsb_ch2__shift 0x04
13612 +#define ma_thr_lsb_ch2__reset 0x00
13613 +//---------------------------------------------------------------thr_lsb_ch3---
13614 +// threshold lsb ch3
13615 +#define ma_thr_lsb_ch3__a 75
13616 +#define ma_thr_lsb_ch3__len 2
13617 +#define ma_thr_lsb_ch3__mask 0xc0
13618 +#define ma_thr_lsb_ch3__shift 0x06
13619 +#define ma_thr_lsb_ch3__reset 0x00
13620 +//-----------------------------------------------------------dcu_mon0.pm_mon---
13621 +// power mode monitor channel 0
13622 +#define ma_dcu_mon0__pm_mon__a 96
13623 +#define ma_dcu_mon0__pm_mon__len 2
13624 +#define ma_dcu_mon0__pm_mon__mask 0x03
13625 +#define ma_dcu_mon0__pm_mon__shift 0x00
13626 +#define ma_dcu_mon0__pm_mon__reset 0x00
13627 +//-----------------------------------------------------dcu_mon0.freqmode_mon---
13628 +// frequence mode monitor channel 0
13629 +#define ma_dcu_mon0__freqmode_mon__a 96
13630 +#define ma_dcu_mon0__freqmode_mon__len 3
13631 +#define ma_dcu_mon0__freqmode_mon__mask 0x70
13632 +#define ma_dcu_mon0__freqmode_mon__shift 0x04
13633 +#define ma_dcu_mon0__freqmode_mon__reset 0x00
13634 +//-------------------------------------------------------dcu_mon0.pps_passed---
13635 +// dcu0 pps completion indicator
13636 +#define ma_dcu_mon0__pps_passed__a 96
13637 +#define ma_dcu_mon0__pps_passed__len 1
13638 +#define ma_dcu_mon0__pps_passed__mask 0x80
13639 +#define ma_dcu_mon0__pps_passed__shift 0x07
13640 +#define ma_dcu_mon0__pps_passed__reset 0x00
13641 +//----------------------------------------------------------dcu_mon0.ocp_mon---
13642 +// ocp monitor channel 0
13643 +#define ma_dcu_mon0__ocp_mon__a 97
13644 +#define ma_dcu_mon0__ocp_mon__len 1
13645 +#define ma_dcu_mon0__ocp_mon__mask 0x01
13646 +#define ma_dcu_mon0__ocp_mon__shift 0x00
13647 +#define ma_dcu_mon0__ocp_mon__reset 0x00
13648 +//--------------------------------------------------------dcu_mon0.vcfly1_ok---
13649 +// cfly1 protection monitor channel 0.
13650 +#define ma_dcu_mon0__vcfly1_ok__a 97
13651 +#define ma_dcu_mon0__vcfly1_ok__len 1
13652 +#define ma_dcu_mon0__vcfly1_ok__mask 0x02
13653 +#define ma_dcu_mon0__vcfly1_ok__shift 0x01
13654 +#define ma_dcu_mon0__vcfly1_ok__reset 0x00
13655 +//--------------------------------------------------------dcu_mon0.vcfly2_ok---
13656 +// cfly2 protection monitor channel 0.
13657 +#define ma_dcu_mon0__vcfly2_ok__a 97
13658 +#define ma_dcu_mon0__vcfly2_ok__len 1
13659 +#define ma_dcu_mon0__vcfly2_ok__mask 0x04
13660 +#define ma_dcu_mon0__vcfly2_ok__shift 0x02
13661 +#define ma_dcu_mon0__vcfly2_ok__reset 0x00
13662 +//----------------------------------------------------------dcu_mon0.pvdd_ok---
13663 +// dcu0 pvdd monitor
13664 +#define ma_dcu_mon0__pvdd_ok__a 97
13665 +#define ma_dcu_mon0__pvdd_ok__len 1
13666 +#define ma_dcu_mon0__pvdd_ok__mask 0x08
13667 +#define ma_dcu_mon0__pvdd_ok__shift 0x03
13668 +#define ma_dcu_mon0__pvdd_ok__reset 0x00
13669 +//-----------------------------------------------------------dcu_mon0.vdd_ok---
13670 +// dcu0 vdd monitor
13671 +#define ma_dcu_mon0__vdd_ok__a 97
13672 +#define ma_dcu_mon0__vdd_ok__len 1
13673 +#define ma_dcu_mon0__vdd_ok__mask 0x10
13674 +#define ma_dcu_mon0__vdd_ok__shift 0x04
13675 +#define ma_dcu_mon0__vdd_ok__reset 0x00
13676 +//-------------------------------------------------------------dcu_mon0.mute---
13677 +// dcu0 mute monitor
13678 +#define ma_dcu_mon0__mute__a 97
13679 +#define ma_dcu_mon0__mute__len 1
13680 +#define ma_dcu_mon0__mute__mask 0x20
13681 +#define ma_dcu_mon0__mute__shift 0x05
13682 +#define ma_dcu_mon0__mute__reset 0x00
13683 +//------------------------------------------------------------dcu_mon0.m_mon---
13684 +// m sense monitor channel 0
13685 +#define ma_dcu_mon0__m_mon__a 98
13686 +#define ma_dcu_mon0__m_mon__len 8
13687 +#define ma_dcu_mon0__m_mon__mask 0xff
13688 +#define ma_dcu_mon0__m_mon__shift 0x00
13689 +#define ma_dcu_mon0__m_mon__reset 0x00
13690 +//-----------------------------------------------------------dcu_mon1.pm_mon---
13691 +// power mode monitor channel 1
13692 +#define ma_dcu_mon1__pm_mon__a 100
13693 +#define ma_dcu_mon1__pm_mon__len 2
13694 +#define ma_dcu_mon1__pm_mon__mask 0x03
13695 +#define ma_dcu_mon1__pm_mon__shift 0x00
13696 +#define ma_dcu_mon1__pm_mon__reset 0x00
13697 +//-----------------------------------------------------dcu_mon1.freqmode_mon---
13698 +// frequence mode monitor channel 1
13699 +#define ma_dcu_mon1__freqmode_mon__a 100
13700 +#define ma_dcu_mon1__freqmode_mon__len 3
13701 +#define ma_dcu_mon1__freqmode_mon__mask 0x70
13702 +#define ma_dcu_mon1__freqmode_mon__shift 0x04
13703 +#define ma_dcu_mon1__freqmode_mon__reset 0x00
13704 +//-------------------------------------------------------dcu_mon1.pps_passed---
13705 +// dcu1 pps completion indicator
13706 +#define ma_dcu_mon1__pps_passed__a 100
13707 +#define ma_dcu_mon1__pps_passed__len 1
13708 +#define ma_dcu_mon1__pps_passed__mask 0x80
13709 +#define ma_dcu_mon1__pps_passed__shift 0x07
13710 +#define ma_dcu_mon1__pps_passed__reset 0x00
13711 +//----------------------------------------------------------dcu_mon1.ocp_mon---
13712 +// ocp monitor channel 1
13713 +#define ma_dcu_mon1__ocp_mon__a 101
13714 +#define ma_dcu_mon1__ocp_mon__len 1
13715 +#define ma_dcu_mon1__ocp_mon__mask 0x01
13716 +#define ma_dcu_mon1__ocp_mon__shift 0x00
13717 +#define ma_dcu_mon1__ocp_mon__reset 0x00
13718 +//--------------------------------------------------------dcu_mon1.vcfly1_ok---
13719 +// cfly1 protcetion monitor channel 1
13720 +#define ma_dcu_mon1__vcfly1_ok__a 101
13721 +#define ma_dcu_mon1__vcfly1_ok__len 1
13722 +#define ma_dcu_mon1__vcfly1_ok__mask 0x02
13723 +#define ma_dcu_mon1__vcfly1_ok__shift 0x01
13724 +#define ma_dcu_mon1__vcfly1_ok__reset 0x00
13725 +//--------------------------------------------------------dcu_mon1.vcfly2_ok---
13726 +// cfly2 protection monitor channel 1
13727 +#define ma_dcu_mon1__vcfly2_ok__a 101
13728 +#define ma_dcu_mon1__vcfly2_ok__len 1
13729 +#define ma_dcu_mon1__vcfly2_ok__mask 0x04
13730 +#define ma_dcu_mon1__vcfly2_ok__shift 0x02
13731 +#define ma_dcu_mon1__vcfly2_ok__reset 0x00
13732 +//----------------------------------------------------------dcu_mon1.pvdd_ok---
13733 +// dcu1 pvdd monitor
13734 +#define ma_dcu_mon1__pvdd_ok__a 101
13735 +#define ma_dcu_mon1__pvdd_ok__len 1
13736 +#define ma_dcu_mon1__pvdd_ok__mask 0x08
13737 +#define ma_dcu_mon1__pvdd_ok__shift 0x03
13738 +#define ma_dcu_mon1__pvdd_ok__reset 0x00
13739 +//-----------------------------------------------------------dcu_mon1.vdd_ok---
13740 +// dcu1 vdd monitor
13741 +#define ma_dcu_mon1__vdd_ok__a 101
13742 +#define ma_dcu_mon1__vdd_ok__len 1
13743 +#define ma_dcu_mon1__vdd_ok__mask 0x10
13744 +#define ma_dcu_mon1__vdd_ok__shift 0x04
13745 +#define ma_dcu_mon1__vdd_ok__reset 0x00
13746 +//-------------------------------------------------------------dcu_mon1.mute---
13747 +// dcu1 mute monitor
13748 +#define ma_dcu_mon1__mute__a 101
13749 +#define ma_dcu_mon1__mute__len 1
13750 +#define ma_dcu_mon1__mute__mask 0x20
13751 +#define ma_dcu_mon1__mute__shift 0x05
13752 +#define ma_dcu_mon1__mute__reset 0x00
13753 +//------------------------------------------------------------dcu_mon1.m_mon---
13754 +// m sense monitor channel 1
13755 +#define ma_dcu_mon1__m_mon__a 102
13756 +#define ma_dcu_mon1__m_mon__len 8
13757 +#define ma_dcu_mon1__m_mon__mask 0xff
13758 +#define ma_dcu_mon1__m_mon__shift 0x00
13759 +#define ma_dcu_mon1__m_mon__reset 0x00
13760 +//--------------------------------------------------------dcu_mon0.sw_enable---
13761 +// dcu0 switch enable monitor
13762 +#define ma_dcu_mon0__sw_enable__a 104
13763 +#define ma_dcu_mon0__sw_enable__len 1
13764 +#define ma_dcu_mon0__sw_enable__mask 0x40
13765 +#define ma_dcu_mon0__sw_enable__shift 0x06
13766 +#define ma_dcu_mon0__sw_enable__reset 0x00
13767 +//--------------------------------------------------------dcu_mon1.sw_enable---
13768 +// dcu1 switch enable monitor
13769 +#define ma_dcu_mon1__sw_enable__a 104
13770 +#define ma_dcu_mon1__sw_enable__len 1
13771 +#define ma_dcu_mon1__sw_enable__mask 0x80
13772 +#define ma_dcu_mon1__sw_enable__shift 0x07
13773 +#define ma_dcu_mon1__sw_enable__reset 0x00
13774 +//------------------------------------------------------------hvboot0_ok_mon---
13775 +// hvboot0_ok for test/debug
13776 +#define ma_hvboot0_ok_mon__a 105
13777 +#define ma_hvboot0_ok_mon__len 1
13778 +#define ma_hvboot0_ok_mon__mask 0x40
13779 +#define ma_hvboot0_ok_mon__shift 0x06
13780 +#define ma_hvboot0_ok_mon__reset 0x00
13781 +//------------------------------------------------------------hvboot1_ok_mon---
13782 +// hvboot1_ok for test/debug
13783 +#define ma_hvboot1_ok_mon__a 105
13784 +#define ma_hvboot1_ok_mon__len 1
13785 +#define ma_hvboot1_ok_mon__mask 0x80
13786 +#define ma_hvboot1_ok_mon__shift 0x07
13787 +#define ma_hvboot1_ok_mon__reset 0x00
13788 +//-----------------------------------------------------------------error_acc---
13789 +// accumulated errors, at and after triggering
13790 +#define ma_error_acc__a 109
13791 +#define ma_error_acc__len 8
13792 +#define ma_error_acc__mask 0xff
13793 +#define ma_error_acc__shift 0x00
13794 +#define ma_error_acc__reset 0x00
13795 +//-------------------------------------------------------------i2s_data_rate---
13796 +// detected i2s data rate: 00/01/10 = x1/x2/x4
13797 +#define ma_i2s_data_rate__a 116
13798 +#define ma_i2s_data_rate__len 2
13799 +#define ma_i2s_data_rate__mask 0x03
13800 +#define ma_i2s_data_rate__shift 0x00
13801 +#define ma_i2s_data_rate__reset 0x00
13802 +//---------------------------------------------------------audio_in_mode_mon---
13803 +// audio input mode monitor
13804 +#define ma_audio_in_mode_mon__a 116
13805 +#define ma_audio_in_mode_mon__len 3
13806 +#define ma_audio_in_mode_mon__mask 0x1c
13807 +#define ma_audio_in_mode_mon__shift 0x02
13808 +#define ma_audio_in_mode_mon__reset 0x00
13809 +//------------------------------------------------------------------msel_mon---
13810 +// msel[2:0] monitor register
13811 +#define ma_msel_mon__a 117
13812 +#define ma_msel_mon__len 3
13813 +#define ma_msel_mon__mask 0x07
13814 +#define ma_msel_mon__shift 0x00
13815 +#define ma_msel_mon__reset 0x00
13816 +//---------------------------------------------------------------------error---
13817 +// current error flag monitor reg - for app. ctrl.
13818 +#define ma_error__a 124
13819 +#define ma_error__len 8
13820 +#define ma_error__mask 0xff
13821 +#define ma_error__shift 0x00
13822 +#define ma_error__reset 0x00
13823 +//----------------------------------------------------audio_proc_limiter_mon---
13824 +// b7-b4: channel 3-0 limiter active
13825 +#define ma_audio_proc_limiter_mon__a 126
13826 +#define ma_audio_proc_limiter_mon__len 4
13827 +#define ma_audio_proc_limiter_mon__mask 0xf0
13828 +#define ma_audio_proc_limiter_mon__shift 0x04
13829 +#define ma_audio_proc_limiter_mon__reset 0x00
13830 +//-------------------------------------------------------audio_proc_clip_mon---
13831 +// b3-b0: channel 3-0 clipping monitor
13832 +#define ma_audio_proc_clip_mon__a 126
13833 +#define ma_audio_proc_clip_mon__len 4
13834 +#define ma_audio_proc_clip_mon__mask 0x0f
13835 +#define ma_audio_proc_clip_mon__shift 0x00
13836 +#define ma_audio_proc_clip_mon__reset 0x00
13837 +#endif
13838 +
13839 +#define SOC_ENUM_ERR(xname, xenum)\
13840 +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
13841 + .access = SNDRV_CTL_ELEM_ACCESS_READ,\
13842 + .info = snd_soc_info_enum_double,\
13843 + .get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double,\
13844 + .private_value = (unsigned long)&(xenum) }
13845 +
13846 +static struct i2c_client *i2c;
13847 +
13848 +struct ma120x0p_priv {
13849 + struct regmap *regmap;
13850 + int mclk_div;
13851 + struct snd_soc_component *component;
13852 + struct gpio_desc *enable_gpio;
13853 + struct gpio_desc *mute_gpio;
13854 + struct gpio_desc *booster_gpio;
13855 + struct gpio_desc *error_gpio;
13856 +};
13857 +
13858 +static struct ma120x0p_priv *priv_data;
13859 +
13860 +//Used to share the IRQ number within this file
13861 +static unsigned int irqNumber;
13862 +
13863 +// Function prototype for the custom IRQ handler function
13864 +static irqreturn_t ma120x0p_irq_handler(int irq, void *data);
13865 +
13866 +//Alsa Controls
13867 +static const char * const limenable_text[] = {"Bypassed", "Enabled"};
13868 +static const char * const limatack_text[] = {"Slow", "Normal", "Fast"};
13869 +static const char * const limrelease_text[] = {"Slow", "Normal", "Fast"};
13870 +
13871 +static const char * const err_flycap_text[] = {"Ok", "Error"};
13872 +static const char * const err_overcurr_text[] = {"Ok", "Error"};
13873 +static const char * const err_pllerr_text[] = {"Ok", "Error"};
13874 +static const char * const err_pvddunder_text[] = {"Ok", "Error"};
13875 +static const char * const err_overtempw_text[] = {"Ok", "Error"};
13876 +static const char * const err_overtempe_text[] = {"Ok", "Error"};
13877 +static const char * const err_pinlowimp_text[] = {"Ok", "Error"};
13878 +static const char * const err_dcprot_text[] = {"Ok", "Error"};
13879 +
13880 +static const char * const pwr_mode_prof_text[] = {"PMF0", "PMF1", "PMF2",
13881 +"PMF3", "PMF4"};
13882 +
13883 +static const struct soc_enum lim_enable_ctrl =
13884 + SOC_ENUM_SINGLE(ma_audio_proc_limiterenable__a,
13885 + ma_audio_proc_limiterenable__shift,
13886 + ma_audio_proc_limiterenable__len + 1,
13887 + limenable_text);
13888 +static const struct soc_enum limatack_ctrl =
13889 + SOC_ENUM_SINGLE(ma_audio_proc_attack__a,
13890 + ma_audio_proc_attack__shift,
13891 + ma_audio_proc_attack__len + 1,
13892 + limatack_text);
13893 +static const struct soc_enum limrelease_ctrl =
13894 + SOC_ENUM_SINGLE(ma_audio_proc_release__a,
13895 + ma_audio_proc_release__shift,
13896 + ma_audio_proc_release__len + 1,
13897 + limrelease_text);
13898 +static const struct soc_enum err_flycap_ctrl =
13899 + SOC_ENUM_SINGLE(ma_error__a, 0, 3, err_flycap_text);
13900 +static const struct soc_enum err_overcurr_ctrl =
13901 + SOC_ENUM_SINGLE(ma_error__a, 1, 3, err_overcurr_text);
13902 +static const struct soc_enum err_pllerr_ctrl =
13903 + SOC_ENUM_SINGLE(ma_error__a, 2, 3, err_pllerr_text);
13904 +static const struct soc_enum err_pvddunder_ctrl =
13905 + SOC_ENUM_SINGLE(ma_error__a, 3, 3, err_pvddunder_text);
13906 +static const struct soc_enum err_overtempw_ctrl =
13907 + SOC_ENUM_SINGLE(ma_error__a, 4, 3, err_overtempw_text);
13908 +static const struct soc_enum err_overtempe_ctrl =
13909 + SOC_ENUM_SINGLE(ma_error__a, 5, 3, err_overtempe_text);
13910 +static const struct soc_enum err_pinlowimp_ctrl =
13911 + SOC_ENUM_SINGLE(ma_error__a, 6, 3, err_pinlowimp_text);
13912 +static const struct soc_enum err_dcprot_ctrl =
13913 + SOC_ENUM_SINGLE(ma_error__a, 7, 3, err_dcprot_text);
13914 +static const struct soc_enum pwr_mode_prof_ctrl =
13915 + SOC_ENUM_SINGLE(ma_pmprofile__a, ma_pmprofile__shift, 5,
13916 + pwr_mode_prof_text);
13917 +
13918 +static const char * const pwr_mode_texts[] = {
13919 + "Dynamic power mode",
13920 + "Power mode 1",
13921 + "Power mode 2",
13922 + "Power mode 3",
13923 + };
13924 +
13925 +static const int pwr_mode_values[] = {
13926 + 0x10,
13927 + 0x50,
13928 + 0x60,
13929 + 0x70,
13930 + };
13931 +
13932 +static const SOC_VALUE_ENUM_SINGLE_DECL(pwr_mode_ctrl,
13933 + ma_pm_man__a, 0, 0x70,
13934 + pwr_mode_texts,
13935 + pwr_mode_values);
13936 +
13937 +static const DECLARE_TLV_DB_SCALE(ma120x0p_vol_tlv, -5000, 100, 0);
13938 +static const DECLARE_TLV_DB_SCALE(ma120x0p_lim_tlv, -5000, 100, 0);
13939 +static const DECLARE_TLV_DB_SCALE(ma120x0p_lr_tlv, -5000, 100, 0);
13940 +
13941 +static const struct snd_kcontrol_new ma120x0p_snd_controls[] = {
13942 + //Master Volume
13943 + SOC_SINGLE_RANGE_TLV("A.Mstr Vol Volume",
13944 + ma_vol_db_master__a, 0, 0x18, 0x4a, 1, ma120x0p_vol_tlv),
13945 +
13946 + //L-R Volume ch0
13947 + SOC_SINGLE_RANGE_TLV("B.L Vol Volume",
13948 + ma_vol_db_ch0__a, 0, 0x18, 0x4a, 1, ma120x0p_lr_tlv),
13949 + SOC_SINGLE_RANGE_TLV("C.R Vol Volume",
13950 + ma_vol_db_ch1__a, 0, 0x18, 0x4a, 1, ma120x0p_lr_tlv),
13951 +
13952 + //L-R Limiter Threshold ch0-ch1
13953 + SOC_DOUBLE_R_RANGE_TLV("D.Lim thresh Volume",
13954 + ma_thr_db_ch0__a, ma_thr_db_ch1__a, 0, 0x0e, 0x4a, 1,
13955 + ma120x0p_lim_tlv),
13956 +
13957 + //Enum Switches/Selectors
13958 + //SOC_ENUM("E.AudioProc Mute", audioproc_mute_ctrl),
13959 + SOC_ENUM("F.Limiter Enable", lim_enable_ctrl),
13960 + SOC_ENUM("G.Limiter Attck", limatack_ctrl),
13961 + SOC_ENUM("H.Limiter Rls", limrelease_ctrl),
13962 +
13963 + //Enum Error Monitor (read-only)
13964 + SOC_ENUM_ERR("I.Err flycap", err_flycap_ctrl),
13965 + SOC_ENUM_ERR("J.Err overcurr", err_overcurr_ctrl),
13966 + SOC_ENUM_ERR("K.Err pllerr", err_pllerr_ctrl),
13967 + SOC_ENUM_ERR("L.Err pvddunder", err_pvddunder_ctrl),
13968 + SOC_ENUM_ERR("M.Err overtempw", err_overtempw_ctrl),
13969 + SOC_ENUM_ERR("N.Err overtempe", err_overtempe_ctrl),
13970 + SOC_ENUM_ERR("O.Err pinlowimp", err_pinlowimp_ctrl),
13971 + SOC_ENUM_ERR("P.Err dcprot", err_dcprot_ctrl),
13972 +
13973 + //Power modes profiles
13974 + SOC_ENUM("Q.PM Prof", pwr_mode_prof_ctrl),
13975 +
13976 + // Power mode selection (Dynamic,1,2,3)
13977 + SOC_ENUM("R.Power Mode", pwr_mode_ctrl),
13978 +};
13979 +
13980 +//Machine Driver
13981 +static int ma120x0p_hw_params(struct snd_pcm_substream *substream,
13982 + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
13983 +{
13984 + u16 blen = 0x00;
13985 +
13986 + struct snd_soc_component *component = dai->component;
13987 +
13988 + priv_data->component = component;
13989 +
13990 + switch (params_format(params)) {
13991 + case SNDRV_PCM_FORMAT_S16_LE:
13992 + blen = 0x10;
13993 + break;
13994 + case SNDRV_PCM_FORMAT_S24_LE:
13995 + blen = 0x00;
13996 + break;
13997 + case SNDRV_PCM_FORMAT_S32_LE:
13998 + blen = 0x00;
13999 + break;
14000 + default:
14001 + dev_err(dai->dev, "Unsupported word length: %u\n",
14002 + params_format(params));
14003 + return -EINVAL;
14004 + }
14005 +
14006 + // set word length
14007 + snd_soc_component_update_bits(component, ma_i2s_framesize__a,
14008 + ma_i2s_framesize__mask, blen);
14009 +
14010 + return 0;
14011 +}
14012 +
14013 +static int ma120x0p_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
14014 +{
14015 + int val = 0;
14016 +
14017 + struct ma120x0p_priv *ma120x0p;
14018 +
14019 + struct snd_soc_component *component = dai->component;
14020 +
14021 + ma120x0p = snd_soc_component_get_drvdata(component);
14022 +
14023 + if (mute)
14024 + val = 0;
14025 + else
14026 + val = 1;
14027 +
14028 + gpiod_set_value_cansleep(priv_data->mute_gpio, val);
14029 +
14030 + return 0;
14031 +}
14032 +
14033 +static const struct snd_soc_dai_ops ma120x0p_dai_ops = {
14034 + .hw_params = ma120x0p_hw_params,
14035 + .mute_stream = ma120x0p_mute_stream,
14036 +};
14037 +
14038 +static struct snd_soc_dai_driver ma120x0p_dai = {
14039 + .name = "ma120x0p-amp",
14040 + .playback = {
14041 + .stream_name = "Playback",
14042 + .channels_min = 2,
14043 + .channels_max = 2,
14044 + .rates = SNDRV_PCM_RATE_CONTINUOUS,
14045 + .rate_min = 44100,
14046 + .rate_max = 96000,
14047 + .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE
14048 + },
14049 + .ops = &ma120x0p_dai_ops,
14050 +};
14051 +
14052 +//Codec Driver
14053 +static int ma120x0p_clear_err(struct snd_soc_component *component)
14054 +{
14055 + int ret = 0;
14056 +
14057 + struct ma120x0p_priv *ma120x0p;
14058 +
14059 + ma120x0p = snd_soc_component_get_drvdata(component);
14060 +
14061 + ret = snd_soc_component_update_bits(component,
14062 + ma_eh_clear__a, ma_eh_clear__mask, 0x00);
14063 + if (ret < 0)
14064 + return ret;
14065 +
14066 + ret = snd_soc_component_update_bits(component,
14067 + ma_eh_clear__a, ma_eh_clear__mask, 0x04);
14068 + if (ret < 0)
14069 + return ret;
14070 +
14071 + ret = snd_soc_component_update_bits(component,
14072 + ma_eh_clear__a, ma_eh_clear__mask, 0x00);
14073 + if (ret < 0)
14074 + return ret;
14075 +
14076 + return 0;
14077 +}
14078 +
14079 +static void ma120x0p_remove(struct snd_soc_component *component)
14080 +{
14081 + struct ma120x0p_priv *ma120x0p;
14082 +
14083 + ma120x0p = snd_soc_component_get_drvdata(component);
14084 +}
14085 +
14086 +static int ma120x0p_probe(struct snd_soc_component *component)
14087 +{
14088 + struct ma120x0p_priv *ma120x0p;
14089 +
14090 + int ret = 0;
14091 +
14092 + i2c = container_of(component->dev, struct i2c_client, dev);
14093 +
14094 + ma120x0p = snd_soc_component_get_drvdata(component);
14095 +
14096 + //Reset error
14097 + ma120x0p_clear_err(component);
14098 + if (ret < 0)
14099 + return ret;
14100 +
14101 + // set serial audio format I2S and enable audio processor
14102 + ret = snd_soc_component_write(component, ma_i2s_format__a, 0x08);
14103 + if (ret < 0)
14104 + return ret;
14105 +
14106 + // Enable audio limiter
14107 + ret = snd_soc_component_update_bits(component,
14108 + ma_audio_proc_limiterenable__a,
14109 + ma_audio_proc_limiterenable__mask, 0x40);
14110 + if (ret < 0)
14111 + return ret;
14112 +
14113 + // Set lim attack to fast
14114 + ret = snd_soc_component_update_bits(component,
14115 + ma_audio_proc_attack__a, ma_audio_proc_attack__mask, 0x80);
14116 + if (ret < 0)
14117 + return ret;
14118 +
14119 + // Set lim attack to low
14120 + ret = snd_soc_component_update_bits(component,
14121 + ma_audio_proc_release__a, ma_audio_proc_release__mask, 0x00);
14122 + if (ret < 0)
14123 + return ret;
14124 +
14125 + // set volume to 0dB
14126 + ret = snd_soc_component_write(component, ma_vol_db_master__a, 0x18);
14127 + if (ret < 0)
14128 + return ret;
14129 +
14130 + // set ch0 lim thresh to -15dB
14131 + ret = snd_soc_component_write(component, ma_thr_db_ch0__a, 0x27);
14132 + if (ret < 0)
14133 + return ret;
14134 +
14135 + // set ch1 lim thresh to -15dB
14136 + ret = snd_soc_component_write(component, ma_thr_db_ch1__a, 0x27);
14137 + if (ret < 0)
14138 + return ret;
14139 +
14140 + //Check for errors
14141 + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x00, 0);
14142 + if (ret < 0)
14143 + return ret;
14144 + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x01, 0);
14145 + if (ret < 0)
14146 + return ret;
14147 + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x02, 0);
14148 + if (ret < 0)
14149 + return ret;
14150 + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x08, 0);
14151 + if (ret < 0)
14152 + return ret;
14153 + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x10, 0);
14154 + if (ret < 0)
14155 + return ret;
14156 + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x20, 0);
14157 + if (ret < 0)
14158 + return ret;
14159 + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x40, 0);
14160 + if (ret < 0)
14161 + return ret;
14162 + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x80, 0);
14163 + if (ret < 0)
14164 + return ret;
14165 +
14166 + return 0;
14167 +}
14168 +
14169 +static int ma120x0p_set_bias_level(struct snd_soc_component *component,
14170 + enum snd_soc_bias_level level)
14171 +{
14172 + int ret = 0;
14173 +
14174 + struct ma120x0p_priv *ma120x0p;
14175 +
14176 + ma120x0p = snd_soc_component_get_drvdata(component);
14177 +
14178 + switch (level) {
14179 + case SND_SOC_BIAS_ON:
14180 + break;
14181 +
14182 + case SND_SOC_BIAS_PREPARE:
14183 + break;
14184 +
14185 + case SND_SOC_BIAS_STANDBY:
14186 + ret = gpiod_get_value_cansleep(priv_data->enable_gpio);
14187 + if (ret != 0) {
14188 + dev_err(component->dev, "Device ma120x0p disabled in STANDBY BIAS: %d\n",
14189 + ret);
14190 + return ret;
14191 + }
14192 + break;
14193 +
14194 + case SND_SOC_BIAS_OFF:
14195 + break;
14196 + }
14197 +
14198 + return 0;
14199 +}
14200 +
14201 +static const struct snd_soc_dapm_widget ma120x0p_dapm_widgets[] = {
14202 + SND_SOC_DAPM_OUTPUT("OUT_A"),
14203 + SND_SOC_DAPM_OUTPUT("OUT_B"),
14204 +};
14205 +
14206 +static const struct snd_soc_dapm_route ma120x0p_dapm_routes[] = {
14207 + { "OUT_B", NULL, "Playback" },
14208 + { "OUT_A", NULL, "Playback" },
14209 +};
14210 +
14211 +static const struct snd_soc_component_driver ma120x0p_component_driver = {
14212 + .probe = ma120x0p_probe,
14213 + .remove = ma120x0p_remove,
14214 + .set_bias_level = ma120x0p_set_bias_level,
14215 + .dapm_widgets = ma120x0p_dapm_widgets,
14216 + .num_dapm_widgets = ARRAY_SIZE(ma120x0p_dapm_widgets),
14217 + .dapm_routes = ma120x0p_dapm_routes,
14218 + .num_dapm_routes = ARRAY_SIZE(ma120x0p_dapm_routes),
14219 + .controls = ma120x0p_snd_controls,
14220 + .num_controls = ARRAY_SIZE(ma120x0p_snd_controls),
14221 + .use_pmdown_time = 1,
14222 + .endianness = 1,
14223 + .non_legacy_dai_naming = 1,
14224 +};
14225 +
14226 +//I2C Driver
14227 +static const struct reg_default ma120x0p_reg_defaults[] = {
14228 + { 0x01, 0x3c },
14229 +};
14230 +
14231 +static bool ma120x0p_reg_volatile(struct device *dev, unsigned int reg)
14232 +{
14233 + switch (reg) {
14234 + case ma_error__a:
14235 + return true;
14236 + default:
14237 + return false;
14238 + }
14239 +}
14240 +
14241 +static const struct of_device_id ma120x0p_of_match[] = {
14242 + { .compatible = "ma,ma120x0p", },
14243 + { }
14244 +};
14245 +
14246 +MODULE_DEVICE_TABLE(of, ma120x0p_of_match);
14247 +
14248 +static struct regmap_config ma120x0p_regmap_config = {
14249 + .reg_bits = 8,
14250 + .val_bits = 8,
14251 +
14252 + .max_register = 255,
14253 + .volatile_reg = ma120x0p_reg_volatile,
14254 +
14255 + .cache_type = REGCACHE_RBTREE,
14256 + .reg_defaults = ma120x0p_reg_defaults,
14257 + .num_reg_defaults = ARRAY_SIZE(ma120x0p_reg_defaults),
14258 +};
14259 +
14260 +static int ma120x0p_i2c_probe(struct i2c_client *i2c,
14261 + const struct i2c_device_id *id)
14262 +{
14263 + int ret;
14264 +
14265 + priv_data = devm_kzalloc(&i2c->dev, sizeof(*priv_data), GFP_KERNEL);
14266 + if (!priv_data)
14267 + return -ENOMEM;
14268 + i2c_set_clientdata(i2c, priv_data);
14269 +
14270 + priv_data->regmap = devm_regmap_init_i2c(i2c, &ma120x0p_regmap_config);
14271 + if (IS_ERR(priv_data->regmap)) {
14272 + ret = PTR_ERR(priv_data->regmap);
14273 + return ret;
14274 + }
14275 +
14276 + //Startup sequence
14277 +
14278 + //Make sure the device is muted
14279 + priv_data->mute_gpio = devm_gpiod_get_optional(&i2c->dev, "mute_gp",
14280 + GPIOD_OUT_LOW);
14281 + if (IS_ERR(priv_data->mute_gpio)) {
14282 + ret = PTR_ERR(priv_data->mute_gpio);
14283 + dev_err(&i2c->dev, "Failed to get mute gpio line: %d\n", ret);
14284 + return ret;
14285 + }
14286 + msleep(50);
14287 +
14288 +// MA120xx0P devices are usually powered by an integrated boost converter.
14289 +// An option GPIO control line is provided to enable the booster properly and
14290 +// in sync with the enable and mute GPIO lines.
14291 + priv_data->booster_gpio = devm_gpiod_get_optional(&i2c->dev,
14292 + "booster_gp", GPIOD_OUT_LOW);
14293 + if (IS_ERR(priv_data->booster_gpio)) {
14294 + ret = PTR_ERR(priv_data->booster_gpio);
14295 + dev_err(&i2c->dev,
14296 + "Failed to get booster enable gpio line: %d\n", ret);
14297 + return ret;
14298 + }
14299 + msleep(50);
14300 +
14301 + //Enable booster and wait 200ms until stable PVDD
14302 + gpiod_set_value_cansleep(priv_data->booster_gpio, 1);
14303 + msleep(200);
14304 +
14305 + //Enable ma120x0pp
14306 + priv_data->enable_gpio = devm_gpiod_get_optional(&i2c->dev,
14307 + "enable_gp", GPIOD_OUT_LOW);
14308 + if (IS_ERR(priv_data->enable_gpio)) {
14309 + ret = PTR_ERR(priv_data->enable_gpio);
14310 + dev_err(&i2c->dev,
14311 + "Failed to get ma120x0p enable gpio line: %d\n", ret);
14312 + return ret;
14313 + }
14314 + msleep(50);
14315 +
14316 + //Optional use of ma120x0pp error line as an interrupt trigger to
14317 + //platform GPIO.
14318 + //Get error input gpio ma120x0p
14319 + priv_data->error_gpio = devm_gpiod_get_optional(&i2c->dev,
14320 + "error_gp", GPIOD_IN);
14321 + if (IS_ERR(priv_data->error_gpio)) {
14322 + ret = PTR_ERR(priv_data->error_gpio);
14323 + dev_err(&i2c->dev,
14324 + "Failed to get ma120x0p error gpio line: %d\n", ret);
14325 + return ret;
14326 + }
14327 +
14328 + if (priv_data->error_gpio != NULL) {
14329 + irqNumber = gpiod_to_irq(priv_data->error_gpio);
14330 +
14331 + ret = devm_request_threaded_irq(&i2c->dev,
14332 + irqNumber, ma120x0p_irq_handler,
14333 + NULL, IRQF_TRIGGER_FALLING,
14334 + "ma120x0p", priv_data);
14335 + if (ret != 0)
14336 + dev_warn(&i2c->dev, "Failed to request IRQ: %d\n",
14337 + ret);
14338 + }
14339 +
14340 + ret = devm_snd_soc_register_component(&i2c->dev,
14341 + &ma120x0p_component_driver, &ma120x0p_dai, 1);
14342 +
14343 + return ret;
14344 +}
14345 +
14346 +static irqreturn_t ma120x0p_irq_handler(int irq, void *data)
14347 +{
14348 + gpiod_set_value_cansleep(priv_data->mute_gpio, 0);
14349 + gpiod_set_value_cansleep(priv_data->enable_gpio, 1);
14350 + return IRQ_HANDLED;
14351 +}
14352 +
14353 +static int ma120x0p_i2c_remove(struct i2c_client *i2c)
14354 +{
14355 + snd_soc_unregister_component(&i2c->dev);
14356 + i2c_set_clientdata(i2c, NULL);
14357 +
14358 + gpiod_set_value_cansleep(priv_data->mute_gpio, 0);
14359 + msleep(30);
14360 + gpiod_set_value_cansleep(priv_data->enable_gpio, 1);
14361 + msleep(200);
14362 + gpiod_set_value_cansleep(priv_data->booster_gpio, 0);
14363 + msleep(200);
14364 +
14365 + kfree(priv_data);
14366 +
14367 + return 0;
14368 +}
14369 +
14370 +static void ma120x0p_i2c_shutdown(struct i2c_client *i2c)
14371 +{
14372 + snd_soc_unregister_component(&i2c->dev);
14373 + i2c_set_clientdata(i2c, NULL);
14374 +
14375 + gpiod_set_value_cansleep(priv_data->mute_gpio, 0);
14376 + msleep(30);
14377 + gpiod_set_value_cansleep(priv_data->enable_gpio, 1);
14378 + msleep(200);
14379 + gpiod_set_value_cansleep(priv_data->booster_gpio, 0);
14380 + msleep(200);
14381 +
14382 + kfree(priv_data);
14383 +}
14384 +
14385 +static const struct i2c_device_id ma120x0p_i2c_id[] = {
14386 + { "ma120x0p", 0 },
14387 + { }
14388 +};
14389 +
14390 +MODULE_DEVICE_TABLE(i2c, ma120x0p_i2c_id);
14391 +
14392 +static struct i2c_driver ma120x0p_i2c_driver = {
14393 + .driver = {
14394 + .name = "ma120x0p",
14395 + .owner = THIS_MODULE,
14396 + .of_match_table = ma120x0p_of_match,
14397 + },
14398 + .probe = ma120x0p_i2c_probe,
14399 + .remove = ma120x0p_i2c_remove,
14400 + .shutdown = ma120x0p_i2c_shutdown,
14401 + .id_table = ma120x0p_i2c_id
14402 +};
14403 +
14404 +static int __init ma120x0p_modinit(void)
14405 +{
14406 + int ret = 0;
14407 +
14408 + ret = i2c_add_driver(&ma120x0p_i2c_driver);
14409 + if (ret != 0) {
14410 + pr_err("Failed to register MA120X0P I2C driver: %d\n", ret);
14411 + return ret;
14412 + }
14413 + return ret;
14414 +}
14415 +module_init(ma120x0p_modinit);
14416 +
14417 +static void __exit ma120x0p_exit(void)
14418 +{
14419 + i2c_del_driver(&ma120x0p_i2c_driver);
14420 +}
14421 +module_exit(ma120x0p_exit);
14422 +
14423 +MODULE_AUTHOR("Ariel Muszkat ariel.muszkat@gmail.com>");
14424 +MODULE_DESCRIPTION("ASoC driver for ma120x0p");
14425 +MODULE_LICENSE("GPL v2");
14426 --- /dev/null
14427 +++ b/sound/soc/codecs/pcm1794a.c
14428 @@ -0,0 +1,69 @@
14429 +/*
14430 + * Driver for the PCM1794A codec
14431 + *
14432 + * Author: Florian Meier <florian.meier@koalo.de>
14433 + * Copyright 2013
14434 + *
14435 + * This program is free software; you can redistribute it and/or
14436 + * modify it under the terms of the GNU General Public License
14437 + * version 2 as published by the Free Software Foundation.
14438 + *
14439 + * This program is distributed in the hope that it will be useful, but
14440 + * WITHOUT ANY WARRANTY; without even the implied warranty of
14441 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14442 + * General Public License for more details.
14443 + */
14444 +
14445 +
14446 +#include <linux/init.h>
14447 +#include <linux/module.h>
14448 +#include <linux/platform_device.h>
14449 +
14450 +#include <sound/soc.h>
14451 +
14452 +static struct snd_soc_dai_driver pcm1794a_dai = {
14453 + .name = "pcm1794a-hifi",
14454 + .playback = {
14455 + .channels_min = 2,
14456 + .channels_max = 2,
14457 + .rates = SNDRV_PCM_RATE_8000_192000,
14458 + .formats = SNDRV_PCM_FMTBIT_S16_LE |
14459 + SNDRV_PCM_FMTBIT_S24_LE
14460 + },
14461 +};
14462 +
14463 +static struct snd_soc_component_driver soc_component_dev_pcm1794a;
14464 +
14465 +static int pcm1794a_probe(struct platform_device *pdev)
14466 +{
14467 + return snd_soc_register_component(&pdev->dev, &soc_component_dev_pcm1794a,
14468 + &pcm1794a_dai, 1);
14469 +}
14470 +
14471 +static int pcm1794a_remove(struct platform_device *pdev)
14472 +{
14473 + snd_soc_unregister_component(&pdev->dev);
14474 + return 0;
14475 +}
14476 +
14477 +static const struct of_device_id pcm1794a_of_match[] = {
14478 + { .compatible = "ti,pcm1794a", },
14479 + { }
14480 +};
14481 +MODULE_DEVICE_TABLE(of, pcm1794a_of_match);
14482 +
14483 +static struct platform_driver pcm1794a_component_driver = {
14484 + .probe = pcm1794a_probe,
14485 + .remove = pcm1794a_remove,
14486 + .driver = {
14487 + .name = "pcm1794a-codec",
14488 + .owner = THIS_MODULE,
14489 + .of_match_table = of_match_ptr(pcm1794a_of_match),
14490 + },
14491 +};
14492 +
14493 +module_platform_driver(pcm1794a_component_driver);
14494 +
14495 +MODULE_DESCRIPTION("ASoC PCM1794A codec driver");
14496 +MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
14497 +MODULE_LICENSE("GPL v2");
14498 --- a/sound/soc/codecs/pcm512x.c
14499 +++ b/sound/soc/codecs/pcm512x.c
14500 @@ -534,7 +534,7 @@ static unsigned long pcm512x_ncp_target(
14501
14502 static const u32 pcm512x_dai_rates[] = {
14503 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
14504 - 88200, 96000, 176400, 192000, 384000,
14505 + 88200, 96000, 176400, 192000, 352800, 384000,
14506 };
14507
14508 static const struct snd_pcm_hw_constraint_list constraints_slave = {
14509 --- /dev/null
14510 +++ b/sound/soc/codecs/tas5713.c
14511 @@ -0,0 +1,363 @@
14512 +/*
14513 + * ASoC Driver for TAS5713
14514 + *
14515 + * Author: Sebastian Eickhoff <basti.eickhoff@googlemail.com>
14516 + * Copyright 2014
14517 + *
14518 + * This program is free software; you can redistribute it and/or
14519 + * modify it under the terms of the GNU General Public License
14520 + * version 2 as published by the Free Software Foundation.
14521 + *
14522 + * This program is distributed in the hope that it will be useful, but
14523 + * WITHOUT ANY WARRANTY; without even the implied warranty of
14524 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14525 + * General Public License for more details.
14526 + */
14527 +
14528 +#include <linux/module.h>
14529 +#include <linux/moduleparam.h>
14530 +#include <linux/init.h>
14531 +#include <linux/delay.h>
14532 +#include <linux/pm.h>
14533 +#include <linux/i2c.h>
14534 +#include <linux/of_device.h>
14535 +#include <linux/spi/spi.h>
14536 +#include <linux/regmap.h>
14537 +#include <linux/regulator/consumer.h>
14538 +#include <linux/slab.h>
14539 +#include <sound/core.h>
14540 +#include <sound/pcm.h>
14541 +#include <sound/pcm_params.h>
14542 +#include <sound/soc.h>
14543 +#include <sound/initval.h>
14544 +#include <sound/tlv.h>
14545 +
14546 +#include <linux/kernel.h>
14547 +#include <linux/string.h>
14548 +#include <linux/fs.h>
14549 +#include <asm/uaccess.h>
14550 +
14551 +#include "tas5713.h"
14552 +
14553 +
14554 +static struct i2c_client *i2c;
14555 +
14556 +struct tas5713_priv {
14557 + struct regmap *regmap;
14558 + int mclk_div;
14559 + struct snd_soc_component *component;
14560 +};
14561 +
14562 +static struct tas5713_priv *priv_data;
14563 +
14564 +
14565 +
14566 +
14567 +/*
14568 + * _ _ ___ _ ___ _ _
14569 + * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___
14570 + * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-<
14571 + * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/
14572 + *
14573 + */
14574 +
14575 +static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1);
14576 +
14577 +
14578 +static const struct snd_kcontrol_new tas5713_snd_controls[] = {
14579 + SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv),
14580 + SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv)
14581 +};
14582 +
14583 +
14584 +
14585 +
14586 +/*
14587 + * __ __ _ _ ___ _
14588 + * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _
14589 + * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_|
14590 + * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_|
14591 + *
14592 + */
14593 +
14594 +static int tas5713_hw_params(struct snd_pcm_substream *substream,
14595 + struct snd_pcm_hw_params *params,
14596 + struct snd_soc_dai *dai)
14597 +{
14598 + u16 blen = 0x00;
14599 +
14600 + struct snd_soc_component *component = dai->component;
14601 + priv_data->component = component;
14602 +
14603 + switch (params_format(params)) {
14604 + case SNDRV_PCM_FORMAT_S16_LE:
14605 + blen = 0x03;
14606 + break;
14607 + case SNDRV_PCM_FORMAT_S20_3LE:
14608 + blen = 0x1;
14609 + break;
14610 + case SNDRV_PCM_FORMAT_S24_LE:
14611 + blen = 0x04;
14612 + break;
14613 + case SNDRV_PCM_FORMAT_S32_LE:
14614 + blen = 0x05;
14615 + break;
14616 + default:
14617 + dev_err(dai->dev, "Unsupported word length: %u\n",
14618 + params_format(params));
14619 + return -EINVAL;
14620 + }
14621 +
14622 + // set word length
14623 + snd_soc_component_update_bits(component, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen);
14624 +
14625 + return 0;
14626 +}
14627 +
14628 +
14629 +static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
14630 +{
14631 + unsigned int val = 0;
14632 +
14633 + struct tas5713_priv *tas5713;
14634 + struct snd_soc_component *component = dai->component;
14635 + tas5713 = snd_soc_component_get_drvdata(component);
14636 +
14637 + if (mute) {
14638 + val = TAS5713_SOFT_MUTE_ALL;
14639 + }
14640 +
14641 + return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val);
14642 +}
14643 +
14644 +
14645 +static const struct snd_soc_dai_ops tas5713_dai_ops = {
14646 + .hw_params = tas5713_hw_params,
14647 + .mute_stream = tas5713_mute_stream,
14648 +};
14649 +
14650 +
14651 +static struct snd_soc_dai_driver tas5713_dai = {
14652 + .name = "tas5713-hifi",
14653 + .playback = {
14654 + .stream_name = "Playback",
14655 + .channels_min = 2,
14656 + .channels_max = 2,
14657 + .rates = SNDRV_PCM_RATE_8000_48000,
14658 + .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ),
14659 + },
14660 + .ops = &tas5713_dai_ops,
14661 +};
14662 +
14663 +
14664 +
14665 +
14666 +/*
14667 + * ___ _ ___ _
14668 + * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _
14669 + * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_|
14670 + * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_|
14671 + *
14672 + */
14673 +
14674 +static void tas5713_remove(struct snd_soc_component *component)
14675 +{
14676 + struct tas5713_priv *tas5713;
14677 +
14678 + tas5713 = snd_soc_component_get_drvdata(component);
14679 +}
14680 +
14681 +
14682 +static int tas5713_probe(struct snd_soc_component *component)
14683 +{
14684 + struct tas5713_priv *tas5713;
14685 + int i, ret;
14686 +
14687 + i2c = container_of(component->dev, struct i2c_client, dev);
14688 +
14689 + tas5713 = snd_soc_component_get_drvdata(component);
14690 +
14691 + // Reset error
14692 + ret = snd_soc_component_write(component, TAS5713_ERROR_STATUS, 0x00);
14693 + if (ret < 0) return ret;
14694 +
14695 + // Trim oscillator
14696 + ret = snd_soc_component_write(component, TAS5713_OSC_TRIM, 0x00);
14697 + if (ret < 0) return ret;
14698 + msleep(1000);
14699 +
14700 + // Reset error
14701 + ret = snd_soc_component_write(component, TAS5713_ERROR_STATUS, 0x00);
14702 + if (ret < 0) return ret;
14703 +
14704 + // I2S 24bit
14705 + ret = snd_soc_component_write(component, TAS5713_SERIAL_DATA_INTERFACE, 0x05);
14706 + if (ret < 0) return ret;
14707 +
14708 + // Unmute
14709 + ret = snd_soc_component_write(component, TAS5713_SYSTEM_CTRL2, 0x00);
14710 + if (ret < 0) return ret;
14711 + ret = snd_soc_component_write(component, TAS5713_SOFT_MUTE, 0x00);
14712 + if (ret < 0) return ret;
14713 +
14714 + // Set volume to 0db
14715 + ret = snd_soc_component_write(component, TAS5713_VOL_MASTER, 0x00);
14716 + if (ret < 0) return ret;
14717 +
14718 + // Now start programming the default initialization sequence
14719 + for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) {
14720 + ret = i2c_master_send(i2c,
14721 + tas5713_init_sequence[i].data,
14722 + tas5713_init_sequence[i].size);
14723 + if (ret < 0) {
14724 + printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret);
14725 + }
14726 + }
14727 +
14728 + // Unmute
14729 + ret = snd_soc_component_write(component, TAS5713_SYSTEM_CTRL2, 0x00);
14730 + if (ret < 0) return ret;
14731 +
14732 + return 0;
14733 +}
14734 +
14735 +
14736 +static struct snd_soc_component_driver soc_codec_dev_tas5713 = {
14737 + .probe = tas5713_probe,
14738 + .remove = tas5713_remove,
14739 + .controls = tas5713_snd_controls,
14740 + .num_controls = ARRAY_SIZE(tas5713_snd_controls),
14741 +};
14742 +
14743 +
14744 +
14745 +
14746 +/*
14747 + * ___ ___ ___ ___ _
14748 + * |_ _|_ ) __| | \ _ _(_)_ _____ _ _
14749 + * | | / / (__ | |) | '_| \ V / -_) '_|
14750 + * |___/___\___| |___/|_| |_|\_/\___|_|
14751 + *
14752 + */
14753 +
14754 +static const struct reg_default tas5713_reg_defaults[] = {
14755 + { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB
14756 + { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB
14757 + { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB
14758 + { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB
14759 +};
14760 +
14761 +
14762 +static bool tas5713_reg_volatile(struct device *dev, unsigned int reg)
14763 +{
14764 + switch (reg) {
14765 + case TAS5713_DEVICE_ID:
14766 + case TAS5713_ERROR_STATUS:
14767 + case TAS5713_CLOCK_CTRL:
14768 + return true;
14769 + default:
14770 + return false;
14771 + }
14772 +}
14773 +
14774 +
14775 +static const struct of_device_id tas5713_of_match[] = {
14776 + { .compatible = "ti,tas5713", },
14777 + { }
14778 +};
14779 +MODULE_DEVICE_TABLE(of, tas5713_of_match);
14780 +
14781 +
14782 +static struct regmap_config tas5713_regmap_config = {
14783 + .reg_bits = 8,
14784 + .val_bits = 8,
14785 +
14786 + .max_register = TAS5713_MAX_REGISTER,
14787 + .volatile_reg = tas5713_reg_volatile,
14788 +
14789 + .cache_type = REGCACHE_RBTREE,
14790 + .reg_defaults = tas5713_reg_defaults,
14791 + .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults),
14792 +};
14793 +
14794 +
14795 +static int tas5713_i2c_probe(struct i2c_client *i2c,
14796 + const struct i2c_device_id *id)
14797 +{
14798 + int ret;
14799 +
14800 + priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL);
14801 + if (!priv_data)
14802 + return -ENOMEM;
14803 +
14804 + priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config);
14805 + if (IS_ERR(priv_data->regmap)) {
14806 + ret = PTR_ERR(priv_data->regmap);
14807 + return ret;
14808 + }
14809 +
14810 + i2c_set_clientdata(i2c, priv_data);
14811 +
14812 + ret = snd_soc_register_component(&i2c->dev,
14813 + &soc_codec_dev_tas5713, &tas5713_dai, 1);
14814 +
14815 + return ret;
14816 +}
14817 +
14818 +
14819 +static int tas5713_i2c_remove(struct i2c_client *i2c)
14820 +{
14821 + snd_soc_unregister_component(&i2c->dev);
14822 + i2c_set_clientdata(i2c, NULL);
14823 +
14824 + kfree(priv_data);
14825 +
14826 + return 0;
14827 +}
14828 +
14829 +
14830 +static const struct i2c_device_id tas5713_i2c_id[] = {
14831 + { "tas5713", 0 },
14832 + { }
14833 +};
14834 +
14835 +MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id);
14836 +
14837 +
14838 +static struct i2c_driver tas5713_i2c_driver = {
14839 + .driver = {
14840 + .name = "tas5713",
14841 + .owner = THIS_MODULE,
14842 + .of_match_table = tas5713_of_match,
14843 + },
14844 + .probe = tas5713_i2c_probe,
14845 + .remove = tas5713_i2c_remove,
14846 + .id_table = tas5713_i2c_id
14847 +};
14848 +
14849 +
14850 +static int __init tas5713_modinit(void)
14851 +{
14852 + int ret = 0;
14853 +
14854 + ret = i2c_add_driver(&tas5713_i2c_driver);
14855 + if (ret) {
14856 + printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n",
14857 + ret);
14858 + }
14859 +
14860 + return ret;
14861 +}
14862 +module_init(tas5713_modinit);
14863 +
14864 +
14865 +static void __exit tas5713_exit(void)
14866 +{
14867 + i2c_del_driver(&tas5713_i2c_driver);
14868 +}
14869 +module_exit(tas5713_exit);
14870 +
14871 +
14872 +MODULE_AUTHOR("Sebastian Eickhoff <basti.eickhoff@googlemail.com>");
14873 +MODULE_DESCRIPTION("ASoC driver for TAS5713");
14874 +MODULE_LICENSE("GPL v2");
14875 --- /dev/null
14876 +++ b/sound/soc/codecs/tas5713.h
14877 @@ -0,0 +1,210 @@
14878 +/*
14879 + * ASoC Driver for TAS5713
14880 + *
14881 + * Author: Sebastian Eickhoff <basti.eickhoff@googlemail.com>
14882 + * Copyright 2014
14883 + *
14884 + * This program is free software; you can redistribute it and/or
14885 + * modify it under the terms of the GNU General Public License
14886 + * version 2 as published by the Free Software Foundation.
14887 + *
14888 + * This program is distributed in the hope that it will be useful, but
14889 + * WITHOUT ANY WARRANTY; without even the implied warranty of
14890 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14891 + * General Public License for more details.
14892 + */
14893 +
14894 +#ifndef _TAS5713_H
14895 +#define _TAS5713_H
14896 +
14897 +
14898 +// TAS5713 I2C-bus register addresses
14899 +
14900 +#define TAS5713_CLOCK_CTRL 0x00
14901 +#define TAS5713_DEVICE_ID 0x01
14902 +#define TAS5713_ERROR_STATUS 0x02
14903 +#define TAS5713_SYSTEM_CTRL1 0x03
14904 +#define TAS5713_SERIAL_DATA_INTERFACE 0x04
14905 +#define TAS5713_SYSTEM_CTRL2 0x05
14906 +#define TAS5713_SOFT_MUTE 0x06
14907 +#define TAS5713_VOL_MASTER 0x07
14908 +#define TAS5713_VOL_CH1 0x08
14909 +#define TAS5713_VOL_CH2 0x09
14910 +#define TAS5713_VOL_HEADPHONE 0x0A
14911 +#define TAS5713_VOL_CONFIG 0x0E
14912 +#define TAS5713_MODULATION_LIMIT 0x10
14913 +#define TAS5713_IC_DLY_CH1 0x11
14914 +#define TAS5713_IC_DLY_CH2 0x12
14915 +#define TAS5713_IC_DLY_CH3 0x13
14916 +#define TAS5713_IC_DLY_CH4 0x14
14917 +
14918 +#define TAS5713_START_STOP_PERIOD 0x1A
14919 +#define TAS5713_OSC_TRIM 0x1B
14920 +#define TAS5713_BKND_ERR 0x1C
14921 +
14922 +#define TAS5713_INPUT_MUX 0x20
14923 +#define TAS5713_SRC_SELECT_CH4 0x21
14924 +#define TAS5713_PWM_MUX 0x25
14925 +
14926 +#define TAS5713_CH1_BQ0 0x29
14927 +#define TAS5713_CH1_BQ1 0x2A
14928 +#define TAS5713_CH1_BQ2 0x2B
14929 +#define TAS5713_CH1_BQ3 0x2C
14930 +#define TAS5713_CH1_BQ4 0x2D
14931 +#define TAS5713_CH1_BQ5 0x2E
14932 +#define TAS5713_CH1_BQ6 0x2F
14933 +#define TAS5713_CH1_BQ7 0x58
14934 +#define TAS5713_CH1_BQ8 0x59
14935 +
14936 +#define TAS5713_CH2_BQ0 0x30
14937 +#define TAS5713_CH2_BQ1 0x31
14938 +#define TAS5713_CH2_BQ2 0x32
14939 +#define TAS5713_CH2_BQ3 0x33
14940 +#define TAS5713_CH2_BQ4 0x34
14941 +#define TAS5713_CH2_BQ5 0x35
14942 +#define TAS5713_CH2_BQ6 0x36
14943 +#define TAS5713_CH2_BQ7 0x5C
14944 +#define TAS5713_CH2_BQ8 0x5D
14945 +
14946 +#define TAS5713_CH4_BQ0 0x5A
14947 +#define TAS5713_CH4_BQ1 0x5B
14948 +#define TAS5713_CH3_BQ0 0x5E
14949 +#define TAS5713_CH3_BQ1 0x5F
14950 +
14951 +#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B
14952 +#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C
14953 +#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E
14954 +#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F
14955 +#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40
14956 +#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43
14957 +#define TAS5713_DRC_CTRL 0x46
14958 +
14959 +#define TAS5713_BANK_SW_CTRL 0x50
14960 +#define TAS5713_CH1_OUTPUT_MIXER 0x51
14961 +#define TAS5713_CH2_OUTPUT_MIXER 0x52
14962 +#define TAS5713_CH1_INPUT_MIXER 0x53
14963 +#define TAS5713_CH2_INPUT_MIXER 0x54
14964 +#define TAS5713_OUTPUT_POST_SCALE 0x56
14965 +#define TAS5713_OUTPUT_PRESCALE 0x57
14966 +
14967 +#define TAS5713_IDF_POST_SCALE 0x62
14968 +
14969 +#define TAS5713_CH1_INLINE_MIXER 0x70
14970 +#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71
14971 +#define TAS5713_CH1_R_CHANNEL_MIXER 0x72
14972 +#define TAS5713_CH1_L_CHANNEL_MIXER 0x73
14973 +#define TAS5713_CH2_INLINE_MIXER 0x74
14974 +#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75
14975 +#define TAS5713_CH2_L_CHANNEL_MIXER 0x76
14976 +#define TAS5713_CH2_R_CHANNEL_MIXER 0x77
14977 +
14978 +#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8
14979 +#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9
14980 +
14981 +#define TAS5713_REGISTER_COUNT 0x46
14982 +#define TAS5713_MAX_REGISTER 0xF9
14983 +
14984 +
14985 +// Bitmasks for registers
14986 +#define TAS5713_SOFT_MUTE_ALL 0x07
14987 +
14988 +
14989 +
14990 +struct tas5713_init_command {
14991 + const int size;
14992 + const char *const data;
14993 +};
14994 +
14995 +static const struct tas5713_init_command tas5713_init_sequence[] = {
14996 +
14997 + // Trim oscillator
14998 + { .size = 2, .data = "\x1B\x00" },
14999 + // System control register 1 (0x03): block DC
15000 + { .size = 2, .data = "\x03\x80" },
15001 + // Mute everything
15002 + { .size = 2, .data = "\x05\x40" },
15003 + // Modulation limit register (0x10): 97.7%
15004 + { .size = 2, .data = "\x10\x02" },
15005 + // Interchannel delay registers
15006 + // (0x11, 0x12, 0x13, and 0x14): BD mode
15007 + { .size = 2, .data = "\x11\xB8" },
15008 + { .size = 2, .data = "\x12\x60" },
15009 + { .size = 2, .data = "\x13\xA0" },
15010 + { .size = 2, .data = "\x14\x48" },
15011 + // PWM shutdown group register (0x19): no shutdown
15012 + { .size = 2, .data = "\x19\x00" },
15013 + // Input multiplexer register (0x20): BD mode
15014 + { .size = 2, .data = "\x20\x00\x89\x77\x72" },
15015 + // PWM output mux register (0x25)
15016 + // Channel 1 --> OUTA, channel 1 neg --> OUTB
15017 + // Channel 2 --> OUTC, channel 2 neg --> OUTD
15018 + { .size = 5, .data = "\x25\x01\x02\x13\x45" },
15019 + // DRC control (0x46): DRC off
15020 + { .size = 5, .data = "\x46\x00\x00\x00\x00" },
15021 + // BKND_ERR register (0x1C): 299ms reset period
15022 + { .size = 2, .data = "\x1C\x07" },
15023 + // Mute channel 3
15024 + { .size = 2, .data = "\x0A\xFF" },
15025 + // Volume configuration register (0x0E): volume slew 512 steps
15026 + { .size = 2, .data = "\x0E\x90" },
15027 + // Clock control register (0x00): 44/48kHz, MCLK=64xfs
15028 + { .size = 2, .data = "\x00\x60" },
15029 + // Bank switch and eq control (0x50): no bank switching
15030 + { .size = 5, .data = "\x50\x00\x00\x00\x00" },
15031 + // Volume registers (0x07, 0x08, 0x09, 0x0A)
15032 + { .size = 2, .data = "\x07\x20" },
15033 + { .size = 2, .data = "\x08\x30" },
15034 + { .size = 2, .data = "\x09\x30" },
15035 + { .size = 2, .data = "\x0A\xFF" },
15036 + // 0x72, 0x73, 0x76, 0x77 input mixer:
15037 + // no intermix between channels
15038 + { .size = 5, .data = "\x72\x00\x00\x00\x00" },
15039 + { .size = 5, .data = "\x73\x00\x80\x00\x00" },
15040 + { .size = 5, .data = "\x76\x00\x00\x00\x00" },
15041 + { .size = 5, .data = "\x77\x00\x80\x00\x00" },
15042 + // 0x70, 0x71, 0x74, 0x75 inline DRC mixer:
15043 + // no inline DRC inmix
15044 + { .size = 5, .data = "\x70\x00\x80\x00\x00" },
15045 + { .size = 5, .data = "\x71\x00\x00\x00\x00" },
15046 + { .size = 5, .data = "\x74\x00\x80\x00\x00" },
15047 + { .size = 5, .data = "\x75\x00\x00\x00\x00" },
15048 + // 0x56, 0x57 Output scale
15049 + { .size = 5, .data = "\x56\x00\x80\x00\x00" },
15050 + { .size = 5, .data = "\x57\x00\x02\x00\x00" },
15051 + // 0x3B, 0x3c
15052 + { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" },
15053 + { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
15054 + { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" },
15055 + { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
15056 + { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
15057 + { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
15058 + // 0x51, 0x52: output mixer
15059 + { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" },
15060 + { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" },
15061 + // PEQ defaults
15062 + { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15063 + { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15064 + { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15065 + { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15066 + { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15067 + { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15068 + { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15069 + { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15070 + { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15071 + { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15072 + { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15073 + { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15074 + { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15075 + { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15076 + { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15077 + { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15078 + { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15079 + { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15080 + { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15081 + { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15082 + { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15083 + { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
15084 +};
15085 +
15086 +
15087 +#endif /* _TAS5713_H */
15088 --- a/sound/soc/soc-core.c
15089 +++ b/sound/soc/soc-core.c
15090 @@ -1429,7 +1429,15 @@ int snd_soc_runtime_set_dai_fmt(struct s
15091 int ret;
15092
15093 for_each_rtd_codec_dais(rtd, i, codec_dai) {
15094 - ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
15095 + unsigned int codec_dai_fmt = dai_fmt;
15096 +
15097 + // there can only be one master when using multiple codecs
15098 + if (i && (codec_dai_fmt & SND_SOC_DAIFMT_MASTER_MASK)) {
15099 + codec_dai_fmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
15100 + codec_dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
15101 + }
15102 +
15103 + ret = snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
15104 if (ret != 0 && ret != -ENOTSUPP) {
15105 dev_warn(codec_dai->dev,
15106 "ASoC: Failed to set DAI format: %d\n", ret);