aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/adi,adau17x1.txt8
-rw-r--r--Documentation/devicetree/bindings/sound/adi,adau7002.txt19
-rw-r--r--include/linux/mfd/arizona/core.h10
-rw-r--r--include/sound/compress_driver.h5
-rw-r--r--sound/core/compress_offload.c67
-rw-r--r--sound/soc/codecs/Kconfig9
-rw-r--r--sound/soc/codecs/Makefile4
-rw-r--r--sound/soc/codecs/adau-utils.c61
-rw-r--r--sound/soc/codecs/adau-utils.h7
-rw-r--r--sound/soc/codecs/adau1373.c38
-rw-r--r--sound/soc/codecs/adau1761-i2c.c2
-rw-r--r--sound/soc/codecs/adau1761-spi.c2
-rw-r--r--sound/soc/codecs/adau1781-i2c.c2
-rw-r--r--sound/soc/codecs/adau1781-spi.c2
-rw-r--r--sound/soc/codecs/adau17x1.c251
-rw-r--r--sound/soc/codecs/adau17x1.h6
-rw-r--r--sound/soc/codecs/adau7002.c80
-rw-r--r--sound/soc/codecs/ak4613.c12
-rw-r--r--sound/soc/codecs/ak4642.c13
-rw-r--r--sound/soc/codecs/arizona.c35
-rw-r--r--sound/soc/codecs/arizona.h17
-rw-r--r--sound/soc/codecs/cs47l24.c8
-rw-r--r--sound/soc/codecs/wm5110.c8
-rw-r--r--sound/soc/codecs/wm_adsp.c29
24 files changed, 555 insertions, 140 deletions
diff --git a/Documentation/devicetree/bindings/sound/adi,adau17x1.txt b/Documentation/devicetree/bindings/sound/adi,adau17x1.txt
index 8dbce0e18dda..1447dec28125 100644
--- a/Documentation/devicetree/bindings/sound/adi,adau17x1.txt
+++ b/Documentation/devicetree/bindings/sound/adi,adau17x1.txt
@@ -13,6 +13,11 @@ Required properties:
13 - reg: The i2c address. Value depends on the state of ADDR0 13 - reg: The i2c address. Value depends on the state of ADDR0
14 and ADDR1, as wired in hardware. 14 and ADDR1, as wired in hardware.
15 15
16Optional properties:
17 - clock-names: If provided must be "mclk".
18 - clocks: phandle + clock-specifiers for the clock that provides
19 the audio master clock for the device.
20
16Examples: 21Examples:
17#include <dt-bindings/sound/adau17x1.h> 22#include <dt-bindings/sound/adau17x1.h>
18 23
@@ -20,5 +25,8 @@ Examples:
20 adau1361@38 { 25 adau1361@38 {
21 compatible = "adi,adau1761"; 26 compatible = "adi,adau1761";
22 reg = <0x38>; 27 reg = <0x38>;
28
29 clock-names = "mclk";
30 clocks = <&audio_clock>;
23 }; 31 };
24 }; 32 };
diff --git a/Documentation/devicetree/bindings/sound/adi,adau7002.txt b/Documentation/devicetree/bindings/sound/adi,adau7002.txt
new file mode 100644
index 000000000000..f144ee1abf85
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/adi,adau7002.txt
@@ -0,0 +1,19 @@
1Analog Devices ADAU7002 Stereo PDM-to-I2S/TDM Converter
2
3Required properties:
4
5 - compatible: Must be "adi,adau7002"
6
7Optional properties:
8
9 - IOVDD-supply: Phandle and specifier for the power supply providing the IOVDD
10 supply as covered in Documentation/devicetree/bindings/regulator/regulator.txt
11
12 If this property is not present it is assumed that the supply pin is
13 hardwired to always on.
14
15Example:
16 adau7002: pdm-to-i2s {
17 compatible = "adi,adau7002";
18 IOVDD-supply = <&supply>;
19 };
diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h
index d55a42297d49..58ab4c0fe761 100644
--- a/include/linux/mfd/arizona/core.h
+++ b/include/linux/mfd/arizona/core.h
@@ -14,6 +14,7 @@
14#define _WM_ARIZONA_CORE_H 14#define _WM_ARIZONA_CORE_H
15 15
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/notifier.h>
17#include <linux/regmap.h> 18#include <linux/regmap.h>
18#include <linux/regulator/consumer.h> 19#include <linux/regulator/consumer.h>
19#include <linux/mfd/arizona/pdata.h> 20#include <linux/mfd/arizona/pdata.h>
@@ -148,8 +149,17 @@ struct arizona {
148 uint16_t dac_comp_coeff; 149 uint16_t dac_comp_coeff;
149 uint8_t dac_comp_enabled; 150 uint8_t dac_comp_enabled;
150 struct mutex dac_comp_lock; 151 struct mutex dac_comp_lock;
152
153 struct blocking_notifier_head notifier;
151}; 154};
152 155
156static inline int arizona_call_notifiers(struct arizona *arizona,
157 unsigned long event,
158 void *data)
159{
160 return blocking_notifier_call_chain(&arizona->notifier, event, data);
161}
162
153int arizona_clk32k_enable(struct arizona *arizona); 163int arizona_clk32k_enable(struct arizona *arizona);
154int arizona_clk32k_disable(struct arizona *arizona); 164int arizona_clk32k_disable(struct arizona *arizona);
155 165
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
index c0abcdc11470..cee8c00f3d3e 100644
--- a/include/sound/compress_driver.h
+++ b/include/sound/compress_driver.h
@@ -68,6 +68,7 @@ struct snd_compr_runtime {
68 * @ops: pointer to DSP callbacks 68 * @ops: pointer to DSP callbacks
69 * @runtime: pointer to runtime structure 69 * @runtime: pointer to runtime structure
70 * @device: device pointer 70 * @device: device pointer
71 * @error_work: delayed work used when closing the stream due to an error
71 * @direction: stream direction, playback/recording 72 * @direction: stream direction, playback/recording
72 * @metadata_set: metadata set flag, true when set 73 * @metadata_set: metadata set flag, true when set
73 * @next_track: has userspace signal next track transition, true when set 74 * @next_track: has userspace signal next track transition, true when set
@@ -78,6 +79,7 @@ struct snd_compr_stream {
78 struct snd_compr_ops *ops; 79 struct snd_compr_ops *ops;
79 struct snd_compr_runtime *runtime; 80 struct snd_compr_runtime *runtime;
80 struct snd_compr *device; 81 struct snd_compr *device;
82 struct delayed_work error_work;
81 enum snd_compr_direction direction; 83 enum snd_compr_direction direction;
82 bool metadata_set; 84 bool metadata_set;
83 bool next_track; 85 bool next_track;
@@ -187,4 +189,7 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
187 wake_up(&stream->runtime->sleep); 189 wake_up(&stream->runtime->sleep);
188} 190}
189 191
192int snd_compr_stop_error(struct snd_compr_stream *stream,
193 snd_pcm_state_t state);
194
190#endif 195#endif
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 9b3334be9df2..2c498488af6c 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -67,6 +67,8 @@ struct snd_compr_file {
67 struct snd_compr_stream stream; 67 struct snd_compr_stream stream;
68}; 68};
69 69
70static void error_delayed_work(struct work_struct *work);
71
70/* 72/*
71 * a note on stream states used: 73 * a note on stream states used:
72 * we use following states in the compressed core 74 * we use following states in the compressed core
@@ -123,6 +125,9 @@ static int snd_compr_open(struct inode *inode, struct file *f)
123 snd_card_unref(compr->card); 125 snd_card_unref(compr->card);
124 return -ENOMEM; 126 return -ENOMEM;
125 } 127 }
128
129 INIT_DELAYED_WORK(&data->stream.error_work, error_delayed_work);
130
126 data->stream.ops = compr->ops; 131 data->stream.ops = compr->ops;
127 data->stream.direction = dirn; 132 data->stream.direction = dirn;
128 data->stream.private_data = compr->private_data; 133 data->stream.private_data = compr->private_data;
@@ -153,6 +158,8 @@ static int snd_compr_free(struct inode *inode, struct file *f)
153 struct snd_compr_file *data = f->private_data; 158 struct snd_compr_file *data = f->private_data;
154 struct snd_compr_runtime *runtime = data->stream.runtime; 159 struct snd_compr_runtime *runtime = data->stream.runtime;
155 160
161 cancel_delayed_work_sync(&data->stream.error_work);
162
156 switch (runtime->state) { 163 switch (runtime->state) {
157 case SNDRV_PCM_STATE_RUNNING: 164 case SNDRV_PCM_STATE_RUNNING:
158 case SNDRV_PCM_STATE_DRAINING: 165 case SNDRV_PCM_STATE_DRAINING:
@@ -237,6 +244,15 @@ snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
237 avail = snd_compr_calc_avail(stream, &ioctl_avail); 244 avail = snd_compr_calc_avail(stream, &ioctl_avail);
238 ioctl_avail.avail = avail; 245 ioctl_avail.avail = avail;
239 246
247 switch (stream->runtime->state) {
248 case SNDRV_PCM_STATE_OPEN:
249 return -EBADFD;
250 case SNDRV_PCM_STATE_XRUN:
251 return -EPIPE;
252 default:
253 break;
254 }
255
240 if (copy_to_user((__u64 __user *)arg, 256 if (copy_to_user((__u64 __user *)arg,
241 &ioctl_avail, sizeof(ioctl_avail))) 257 &ioctl_avail, sizeof(ioctl_avail)))
242 return -EFAULT; 258 return -EFAULT;
@@ -346,11 +362,13 @@ static ssize_t snd_compr_read(struct file *f, char __user *buf,
346 switch (stream->runtime->state) { 362 switch (stream->runtime->state) {
347 case SNDRV_PCM_STATE_OPEN: 363 case SNDRV_PCM_STATE_OPEN:
348 case SNDRV_PCM_STATE_PREPARED: 364 case SNDRV_PCM_STATE_PREPARED:
349 case SNDRV_PCM_STATE_XRUN:
350 case SNDRV_PCM_STATE_SUSPENDED: 365 case SNDRV_PCM_STATE_SUSPENDED:
351 case SNDRV_PCM_STATE_DISCONNECTED: 366 case SNDRV_PCM_STATE_DISCONNECTED:
352 retval = -EBADFD; 367 retval = -EBADFD;
353 goto out; 368 goto out;
369 case SNDRV_PCM_STATE_XRUN:
370 retval = -EPIPE;
371 goto out;
354 } 372 }
355 373
356 avail = snd_compr_get_avail(stream); 374 avail = snd_compr_get_avail(stream);
@@ -399,10 +417,16 @@ static unsigned int snd_compr_poll(struct file *f, poll_table *wait)
399 stream = &data->stream; 417 stream = &data->stream;
400 418
401 mutex_lock(&stream->device->lock); 419 mutex_lock(&stream->device->lock);
402 if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) { 420
421 switch (stream->runtime->state) {
422 case SNDRV_PCM_STATE_OPEN:
423 case SNDRV_PCM_STATE_XRUN:
403 retval = snd_compr_get_poll(stream) | POLLERR; 424 retval = snd_compr_get_poll(stream) | POLLERR;
404 goto out; 425 goto out;
426 default:
427 break;
405 } 428 }
429
406 poll_wait(f, &stream->runtime->sleep, wait); 430 poll_wait(f, &stream->runtime->sleep, wait);
407 431
408 avail = snd_compr_get_avail(stream); 432 avail = snd_compr_get_avail(stream);
@@ -697,6 +721,45 @@ static int snd_compr_stop(struct snd_compr_stream *stream)
697 return retval; 721 return retval;
698} 722}
699 723
724static void error_delayed_work(struct work_struct *work)
725{
726 struct snd_compr_stream *stream;
727
728 stream = container_of(work, struct snd_compr_stream, error_work.work);
729
730 mutex_lock(&stream->device->lock);
731
732 stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
733 wake_up(&stream->runtime->sleep);
734
735 mutex_unlock(&stream->device->lock);
736}
737
738/*
739 * snd_compr_stop_error: Report a fatal error on a stream
740 * @stream: pointer to stream
741 * @state: state to transition the stream to
742 *
743 * Stop the stream and set its state.
744 *
745 * Should be called with compressed device lock held.
746 */
747int snd_compr_stop_error(struct snd_compr_stream *stream,
748 snd_pcm_state_t state)
749{
750 if (stream->runtime->state == state)
751 return 0;
752
753 stream->runtime->state = state;
754
755 pr_debug("Changing state to: %d\n", state);
756
757 queue_delayed_work(system_power_efficient_wq, &stream->error_work, 0);
758
759 return 0;
760}
761EXPORT_SYMBOL_GPL(snd_compr_stop_error);
762
700static int snd_compress_wait_for_drain(struct snd_compr_stream *stream) 763static int snd_compress_wait_for_drain(struct snd_compr_stream *stream)
701{ 764{
702 int ret; 765 int ret;
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index f3fb98f0a995..a9faf3711064 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -32,6 +32,7 @@ config SND_SOC_ALL_CODECS
32 select SND_SOC_ADAU1977_SPI if SPI_MASTER 32 select SND_SOC_ADAU1977_SPI if SPI_MASTER
33 select SND_SOC_ADAU1977_I2C if I2C 33 select SND_SOC_ADAU1977_I2C if I2C
34 select SND_SOC_ADAU1701 if I2C 34 select SND_SOC_ADAU1701 if I2C
35 select SND_SOC_ADAU7002
35 select SND_SOC_ADS117X 36 select SND_SOC_ADS117X
36 select SND_SOC_AK4104 if SPI_MASTER 37 select SND_SOC_AK4104 if SPI_MASTER
37 select SND_SOC_AK4535 if I2C 38 select SND_SOC_AK4535 if I2C
@@ -269,8 +270,12 @@ config SND_SOC_AD1980
269config SND_SOC_AD73311 270config SND_SOC_AD73311
270 tristate 271 tristate
271 272
273config SND_SOC_ADAU_UTILS
274 tristate
275
272config SND_SOC_ADAU1373 276config SND_SOC_ADAU1373
273 tristate 277 tristate
278 select SND_SOC_ADAU_UTILS
274 279
275config SND_SOC_ADAU1701 280config SND_SOC_ADAU1701
276 tristate "Analog Devices ADAU1701 CODEC" 281 tristate "Analog Devices ADAU1701 CODEC"
@@ -280,6 +285,7 @@ config SND_SOC_ADAU1701
280config SND_SOC_ADAU17X1 285config SND_SOC_ADAU17X1
281 tristate 286 tristate
282 select SND_SOC_SIGMADSP_REGMAP 287 select SND_SOC_SIGMADSP_REGMAP
288 select SND_SOC_ADAU_UTILS
283 289
284config SND_SOC_ADAU1761 290config SND_SOC_ADAU1761
285 tristate 291 tristate
@@ -322,6 +328,9 @@ config SND_SOC_ADAU1977_I2C
322 select SND_SOC_ADAU1977 328 select SND_SOC_ADAU1977
323 select REGMAP_I2C 329 select REGMAP_I2C
324 330
331config SND_SOC_ADAU7002
332 tristate "Analog Devices ADAU7002 Stereo PDM-to-I2S/TDM Converter"
333
325config SND_SOC_ADAV80X 334config SND_SOC_ADAV80X
326 tristate 335 tristate
327 336
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 0f548fd34ca3..e37815d55c10 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -7,6 +7,7 @@ snd-soc-ad193x-spi-objs := ad193x-spi.o
7snd-soc-ad193x-i2c-objs := ad193x-i2c.o 7snd-soc-ad193x-i2c-objs := ad193x-i2c.o
8snd-soc-ad1980-objs := ad1980.o 8snd-soc-ad1980-objs := ad1980.o
9snd-soc-ad73311-objs := ad73311.o 9snd-soc-ad73311-objs := ad73311.o
10snd-soc-adau-utils-objs := adau-utils.o
10snd-soc-adau1373-objs := adau1373.o 11snd-soc-adau1373-objs := adau1373.o
11snd-soc-adau1701-objs := adau1701.o 12snd-soc-adau1701-objs := adau1701.o
12snd-soc-adau17x1-objs := adau17x1.o 13snd-soc-adau17x1-objs := adau17x1.o
@@ -19,6 +20,7 @@ snd-soc-adau1781-spi-objs := adau1781-spi.o
19snd-soc-adau1977-objs := adau1977.o 20snd-soc-adau1977-objs := adau1977.o
20snd-soc-adau1977-spi-objs := adau1977-spi.o 21snd-soc-adau1977-spi-objs := adau1977-spi.o
21snd-soc-adau1977-i2c-objs := adau1977-i2c.o 22snd-soc-adau1977-i2c-objs := adau1977-i2c.o
23snd-soc-adau7002-objs := adau7002.o
22snd-soc-adav80x-objs := adav80x.o 24snd-soc-adav80x-objs := adav80x.o
23snd-soc-adav801-objs := adav801.o 25snd-soc-adav801-objs := adav801.o
24snd-soc-adav803-objs := adav803.o 26snd-soc-adav803-objs := adav803.o
@@ -220,6 +222,7 @@ obj-$(CONFIG_SND_SOC_AD193X_SPI) += snd-soc-ad193x-spi.o
220obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o 222obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o
221obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o 223obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
222obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o 224obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
225obj-$(CONFIG_SND_SOC_ADAU_UTILS) += snd-soc-adau-utils.o
223obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o 226obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o
224obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o 227obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o
225obj-$(CONFIG_SND_SOC_ADAU17X1) += snd-soc-adau17x1.o 228obj-$(CONFIG_SND_SOC_ADAU17X1) += snd-soc-adau17x1.o
@@ -232,6 +235,7 @@ obj-$(CONFIG_SND_SOC_ADAU1781_SPI) += snd-soc-adau1781-spi.o
232obj-$(CONFIG_SND_SOC_ADAU1977) += snd-soc-adau1977.o 235obj-$(CONFIG_SND_SOC_ADAU1977) += snd-soc-adau1977.o
233obj-$(CONFIG_SND_SOC_ADAU1977_SPI) += snd-soc-adau1977-spi.o 236obj-$(CONFIG_SND_SOC_ADAU1977_SPI) += snd-soc-adau1977-spi.o
234obj-$(CONFIG_SND_SOC_ADAU1977_I2C) += snd-soc-adau1977-i2c.o 237obj-$(CONFIG_SND_SOC_ADAU1977_I2C) += snd-soc-adau1977-i2c.o
238obj-$(CONFIG_SND_SOC_ADAU7002) += snd-soc-adau7002.o
235obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o 239obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o
236obj-$(CONFIG_SND_SOC_ADAV801) += snd-soc-adav801.o 240obj-$(CONFIG_SND_SOC_ADAV801) += snd-soc-adav801.o
237obj-$(CONFIG_SND_SOC_ADAV803) += snd-soc-adav803.o 241obj-$(CONFIG_SND_SOC_ADAV803) += snd-soc-adav803.o
diff --git a/sound/soc/codecs/adau-utils.c b/sound/soc/codecs/adau-utils.c
new file mode 100644
index 000000000000..19d6a6f41b12
--- /dev/null
+++ b/sound/soc/codecs/adau-utils.c
@@ -0,0 +1,61 @@
1/*
2 * Shared helper functions for devices from the ADAU family
3 *
4 * Copyright 2011-2016 Analog Devices Inc.
5 * Author: Lars-Peter Clausen <lars@metafoo.de>
6 *
7 * Licensed under the GPL-2 or later.
8 */
9
10#include <linux/gcd.h>
11#include <linux/kernel.h>
12#include <linux/module.h>
13
14#include "adau-utils.h"
15
16int adau_calc_pll_cfg(unsigned int freq_in, unsigned int freq_out,
17 uint8_t regs[5])
18{
19 unsigned int r, n, m, i, j;
20 unsigned int div;
21
22 if (!freq_out) {
23 r = 0;
24 n = 0;
25 m = 0;
26 div = 0;
27 } else {
28 if (freq_out % freq_in != 0) {
29 div = DIV_ROUND_UP(freq_in, 13500000);
30 freq_in /= div;
31 r = freq_out / freq_in;
32 i = freq_out % freq_in;
33 j = gcd(i, freq_in);
34 n = i / j;
35 m = freq_in / j;
36 div--;
37 } else {
38 r = freq_out / freq_in;
39 n = 0;
40 m = 0;
41 div = 0;
42 }
43 if (n > 0xffff || m > 0xffff || div > 3 || r > 8 || r < 2)
44 return -EINVAL;
45 }
46
47 regs[0] = m >> 8;
48 regs[1] = m & 0xff;
49 regs[2] = n >> 8;
50 regs[3] = n & 0xff;
51 regs[4] = (r << 3) | (div << 1);
52 if (m != 0)
53 regs[4] |= 1; /* Fractional mode */
54
55 return 0;
56}
57EXPORT_SYMBOL_GPL(adau_calc_pll_cfg);
58
59MODULE_DESCRIPTION("ASoC ADAU audio CODECs shared helper functions");
60MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
61MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/adau-utils.h b/sound/soc/codecs/adau-utils.h
new file mode 100644
index 000000000000..939b5f37762f
--- /dev/null
+++ b/sound/soc/codecs/adau-utils.h
@@ -0,0 +1,7 @@
1#ifndef SOUND_SOC_CODECS_ADAU_PLL_H
2#define SOUND_SOC_CODECS_ADAU_PLL_H
3
4int adau_calc_pll_cfg(unsigned int freq_in, unsigned int freq_out,
5 uint8_t regs[5]);
6
7#endif
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index fe1353a797b9..1556b360fa15 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -23,6 +23,7 @@
23#include <sound/adau1373.h> 23#include <sound/adau1373.h>
24 24
25#include "adau1373.h" 25#include "adau1373.h"
26#include "adau-utils.h"
26 27
27struct adau1373_dai { 28struct adau1373_dai {
28 unsigned int clk_src; 29 unsigned int clk_src;
@@ -1254,7 +1255,8 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id,
1254{ 1255{
1255 struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); 1256 struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
1256 unsigned int dpll_div = 0; 1257 unsigned int dpll_div = 0;
1257 unsigned int x, r, n, m, i, j, mode; 1258 uint8_t pll_regs[5];
1259 int ret;
1258 1260
1259 switch (pll_id) { 1261 switch (pll_id) {
1260 case ADAU1373_PLL1: 1262 case ADAU1373_PLL1:
@@ -1295,27 +1297,8 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id,
1295 dpll_div++; 1297 dpll_div++;
1296 } 1298 }
1297 1299
1298 if (freq_out % freq_in != 0) { 1300 ret = adau_calc_pll_cfg(freq_in, freq_out, pll_regs);
1299 /* fout = fin * (r + (n/m)) / x */ 1301 if (ret)
1300 x = DIV_ROUND_UP(freq_in, 13500000);
1301 freq_in /= x;
1302 r = freq_out / freq_in;
1303 i = freq_out % freq_in;
1304 j = gcd(i, freq_in);
1305 n = i / j;
1306 m = freq_in / j;
1307 x--;
1308 mode = 1;
1309 } else {
1310 /* fout = fin / r */
1311 r = freq_out / freq_in;
1312 n = 0;
1313 m = 0;
1314 x = 0;
1315 mode = 0;
1316 }
1317
1318 if (r < 2 || r > 8 || x > 3 || m > 0xffff || n > 0xffff)
1319 return -EINVAL; 1302 return -EINVAL;
1320 1303
1321 if (dpll_div) { 1304 if (dpll_div) {
@@ -1330,12 +1313,11 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id,
1330 1313
1331 regmap_write(adau1373->regmap, ADAU1373_DPLL_CTRL(pll_id), 1314 regmap_write(adau1373->regmap, ADAU1373_DPLL_CTRL(pll_id),
1332 (source << 4) | dpll_div); 1315 (source << 4) | dpll_div);
1333 regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff); 1316 regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL1(pll_id), pll_regs[0]);
1334 regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL2(pll_id), m & 0xff); 1317 regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL2(pll_id), pll_regs[1]);
1335 regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff); 1318 regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL3(pll_id), pll_regs[2]);
1336 regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL4(pll_id), n & 0xff); 1319 regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL4(pll_id), pll_regs[3]);
1337 regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL5(pll_id), 1320 regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL5(pll_id), pll_regs[4]);
1338 (r << 3) | (x << 1) | mode);
1339 1321
1340 /* Set sysclk to pll_rate / 4 */ 1322 /* Set sysclk to pll_rate / 4 */
1341 regmap_update_bits(adau1373->regmap, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09); 1323 regmap_update_bits(adau1373->regmap, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09);
diff --git a/sound/soc/codecs/adau1761-i2c.c b/sound/soc/codecs/adau1761-i2c.c
index 8de010f758cd..9e7f257f17f8 100644
--- a/sound/soc/codecs/adau1761-i2c.c
+++ b/sound/soc/codecs/adau1761-i2c.c
@@ -31,7 +31,7 @@ static int adau1761_i2c_probe(struct i2c_client *client,
31 31
32static int adau1761_i2c_remove(struct i2c_client *client) 32static int adau1761_i2c_remove(struct i2c_client *client)
33{ 33{
34 snd_soc_unregister_codec(&client->dev); 34 adau17x1_remove(&client->dev);
35 return 0; 35 return 0;
36} 36}
37 37
diff --git a/sound/soc/codecs/adau1761-spi.c b/sound/soc/codecs/adau1761-spi.c
index d9171245bd9f..a0b214be759a 100644
--- a/sound/soc/codecs/adau1761-spi.c
+++ b/sound/soc/codecs/adau1761-spi.c
@@ -48,7 +48,7 @@ static int adau1761_spi_probe(struct spi_device *spi)
48 48
49static int adau1761_spi_remove(struct spi_device *spi) 49static int adau1761_spi_remove(struct spi_device *spi)
50{ 50{
51 snd_soc_unregister_codec(&spi->dev); 51 adau17x1_remove(&spi->dev);
52 return 0; 52 return 0;
53} 53}
54 54
diff --git a/sound/soc/codecs/adau1781-i2c.c b/sound/soc/codecs/adau1781-i2c.c
index 06cbca84cf02..7b9d1802d159 100644
--- a/sound/soc/codecs/adau1781-i2c.c
+++ b/sound/soc/codecs/adau1781-i2c.c
@@ -31,7 +31,7 @@ static int adau1781_i2c_probe(struct i2c_client *client,
31 31
32static int adau1781_i2c_remove(struct i2c_client *client) 32static int adau1781_i2c_remove(struct i2c_client *client)
33{ 33{
34 snd_soc_unregister_codec(&client->dev); 34 adau17x1_remove(&client->dev);
35 return 0; 35 return 0;
36} 36}
37 37
diff --git a/sound/soc/codecs/adau1781-spi.c b/sound/soc/codecs/adau1781-spi.c
index 3d965a01b99c..9b233544d2e8 100644
--- a/sound/soc/codecs/adau1781-spi.c
+++ b/sound/soc/codecs/adau1781-spi.c
@@ -48,7 +48,7 @@ static int adau1781_spi_probe(struct spi_device *spi)
48 48
49static int adau1781_spi_remove(struct spi_device *spi) 49static int adau1781_spi_remove(struct spi_device *spi)
50{ 50{
51 snd_soc_unregister_codec(&spi->dev); 51 adau17x1_remove(&spi->dev);
52 return 0; 52 return 0;
53} 53}
54 54
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c
index fcf05b254ecd..439aa3ff1f99 100644
--- a/sound/soc/codecs/adau17x1.c
+++ b/sound/soc/codecs/adau17x1.c
@@ -9,6 +9,7 @@
9 9
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/clk.h>
12#include <linux/delay.h> 13#include <linux/delay.h>
13#include <linux/slab.h> 14#include <linux/slab.h>
14#include <sound/core.h> 15#include <sound/core.h>
@@ -23,6 +24,7 @@
23 24
24#include "sigmadsp.h" 25#include "sigmadsp.h"
25#include "adau17x1.h" 26#include "adau17x1.h"
27#include "adau-utils.h"
26 28
27static const char * const adau17x1_capture_mixer_boost_text[] = { 29static const char * const adau17x1_capture_mixer_boost_text[] = {
28 "Normal operation", "Boost Level 1", "Boost Level 2", "Boost Level 3", 30 "Normal operation", "Boost Level 1", "Boost Level 2", "Boost Level 3",
@@ -302,6 +304,116 @@ bool adau17x1_has_dsp(struct adau *adau)
302} 304}
303EXPORT_SYMBOL_GPL(adau17x1_has_dsp); 305EXPORT_SYMBOL_GPL(adau17x1_has_dsp);
304 306
307static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id,
308 int source, unsigned int freq_in, unsigned int freq_out)
309{
310 struct snd_soc_codec *codec = dai->codec;
311 struct adau *adau = snd_soc_codec_get_drvdata(codec);
312 int ret;
313
314 if (freq_in < 8000000 || freq_in > 27000000)
315 return -EINVAL;
316
317 ret = adau_calc_pll_cfg(freq_in, freq_out, adau->pll_regs);
318 if (ret < 0)
319 return ret;
320
321 /* The PLL register is 6 bytes long and can only be written at once. */
322 ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL,
323 adau->pll_regs, ARRAY_SIZE(adau->pll_regs));
324 if (ret)
325 return ret;
326
327 adau->pll_freq = freq_out;
328
329 return 0;
330}
331
332static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai,
333 int clk_id, unsigned int freq, int dir)
334{
335 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(dai->codec);
336 struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
337 bool is_pll;
338 bool was_pll;
339
340 switch (clk_id) {
341 case ADAU17X1_CLK_SRC_MCLK:
342 is_pll = false;
343 break;
344 case ADAU17X1_CLK_SRC_PLL_AUTO:
345 if (!adau->mclk)
346 return -EINVAL;
347 /* Fall-through */
348 case ADAU17X1_CLK_SRC_PLL:
349 is_pll = true;
350 break;
351 default:
352 return -EINVAL;
353 }
354
355 switch (adau->clk_src) {
356 case ADAU17X1_CLK_SRC_MCLK:
357 was_pll = false;
358 break;
359 case ADAU17X1_CLK_SRC_PLL:
360 case ADAU17X1_CLK_SRC_PLL_AUTO:
361 was_pll = true;
362 break;
363 default:
364 return -EINVAL;
365 }
366
367 adau->sysclk = freq;
368
369 if (is_pll != was_pll) {
370 if (is_pll) {
371 snd_soc_dapm_add_routes(dapm,
372 &adau17x1_dapm_pll_route, 1);
373 } else {
374 snd_soc_dapm_del_routes(dapm,
375 &adau17x1_dapm_pll_route, 1);
376 }
377 }
378
379 adau->clk_src = clk_id;
380
381 return 0;
382}
383
384static int adau17x1_auto_pll(struct snd_soc_dai *dai,
385 struct snd_pcm_hw_params *params)
386{
387 struct adau *adau = snd_soc_dai_get_drvdata(dai);
388 unsigned int pll_rate;
389
390 switch (params_rate(params)) {
391 case 48000:
392 case 8000:
393 case 12000:
394 case 16000:
395 case 24000:
396 case 32000:
397 case 96000:
398 pll_rate = 48000 * 1024;
399 break;
400 case 44100:
401 case 7350:
402 case 11025:
403 case 14700:
404 case 22050:
405 case 29400:
406 case 88200:
407 pll_rate = 44100 * 1024;
408 break;
409 default:
410 return -EINVAL;
411 }
412
413 return adau17x1_set_dai_pll(dai, ADAU17X1_PLL, ADAU17X1_PLL_SRC_MCLK,
414 clk_get_rate(adau->mclk), pll_rate);
415}
416
305static int adau17x1_hw_params(struct snd_pcm_substream *substream, 417static int adau17x1_hw_params(struct snd_pcm_substream *substream,
306 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 418 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
307{ 419{
@@ -311,10 +423,19 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
311 unsigned int freq; 423 unsigned int freq;
312 int ret; 424 int ret;
313 425
314 if (adau->clk_src == ADAU17X1_CLK_SRC_PLL) 426 switch (adau->clk_src) {
427 case ADAU17X1_CLK_SRC_PLL_AUTO:
428 ret = adau17x1_auto_pll(dai, params);
429 if (ret)
430 return ret;
431 /* Fall-through */
432 case ADAU17X1_CLK_SRC_PLL:
315 freq = adau->pll_freq; 433 freq = adau->pll_freq;
316 else 434 break;
435 default:
317 freq = adau->sysclk; 436 freq = adau->sysclk;
437 break;
438 }
318 439
319 if (freq % params_rate(params) != 0) 440 if (freq % params_rate(params) != 0)
320 return -EINVAL; 441 return -EINVAL;
@@ -386,93 +507,6 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
386 ADAU17X1_SERIAL_PORT1_DELAY_MASK, val); 507 ADAU17X1_SERIAL_PORT1_DELAY_MASK, val);
387} 508}
388 509
389static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id,
390 int source, unsigned int freq_in, unsigned int freq_out)
391{
392 struct snd_soc_codec *codec = dai->codec;
393 struct adau *adau = snd_soc_codec_get_drvdata(codec);
394 unsigned int r, n, m, i, j;
395 unsigned int div;
396 int ret;
397
398 if (freq_in < 8000000 || freq_in > 27000000)
399 return -EINVAL;
400
401 if (!freq_out) {
402 r = 0;
403 n = 0;
404 m = 0;
405 div = 0;
406 } else {
407 if (freq_out % freq_in != 0) {
408 div = DIV_ROUND_UP(freq_in, 13500000);
409 freq_in /= div;
410 r = freq_out / freq_in;
411 i = freq_out % freq_in;
412 j = gcd(i, freq_in);
413 n = i / j;
414 m = freq_in / j;
415 div--;
416 } else {
417 r = freq_out / freq_in;
418 n = 0;
419 m = 0;
420 div = 0;
421 }
422 if (n > 0xffff || m > 0xffff || div > 3 || r > 8 || r < 2)
423 return -EINVAL;
424 }
425
426 adau->pll_regs[0] = m >> 8;
427 adau->pll_regs[1] = m & 0xff;
428 adau->pll_regs[2] = n >> 8;
429 adau->pll_regs[3] = n & 0xff;
430 adau->pll_regs[4] = (r << 3) | (div << 1);
431 if (m != 0)
432 adau->pll_regs[4] |= 1; /* Fractional mode */
433
434 /* The PLL register is 6 bytes long and can only be written at once. */
435 ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL,
436 adau->pll_regs, ARRAY_SIZE(adau->pll_regs));
437 if (ret)
438 return ret;
439
440 adau->pll_freq = freq_out;
441
442 return 0;
443}
444
445static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai,
446 int clk_id, unsigned int freq, int dir)
447{
448 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(dai->codec);
449 struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
450
451 switch (clk_id) {
452 case ADAU17X1_CLK_SRC_MCLK:
453 case ADAU17X1_CLK_SRC_PLL:
454 break;
455 default:
456 return -EINVAL;
457 }
458
459 adau->sysclk = freq;
460
461 if (adau->clk_src != clk_id) {
462 if (clk_id == ADAU17X1_CLK_SRC_PLL) {
463 snd_soc_dapm_add_routes(dapm,
464 &adau17x1_dapm_pll_route, 1);
465 } else {
466 snd_soc_dapm_del_routes(dapm,
467 &adau17x1_dapm_pll_route, 1);
468 }
469 }
470
471 adau->clk_src = clk_id;
472
473 return 0;
474}
475
476static int adau17x1_set_dai_fmt(struct snd_soc_dai *dai, 510static int adau17x1_set_dai_fmt(struct snd_soc_dai *dai,
477 unsigned int fmt) 511 unsigned int fmt)
478{ 512{
@@ -857,6 +891,10 @@ int adau17x1_add_routes(struct snd_soc_codec *codec)
857 ret = snd_soc_dapm_add_routes(dapm, adau17x1_no_dsp_dapm_routes, 891 ret = snd_soc_dapm_add_routes(dapm, adau17x1_no_dsp_dapm_routes,
858 ARRAY_SIZE(adau17x1_no_dsp_dapm_routes)); 892 ARRAY_SIZE(adau17x1_no_dsp_dapm_routes));
859 } 893 }
894
895 if (adau->clk_src != ADAU17X1_CLK_SRC_MCLK)
896 snd_soc_dapm_add_routes(dapm, &adau17x1_dapm_pll_route, 1);
897
860 return ret; 898 return ret;
861} 899}
862EXPORT_SYMBOL_GPL(adau17x1_add_routes); 900EXPORT_SYMBOL_GPL(adau17x1_add_routes);
@@ -879,6 +917,7 @@ int adau17x1_probe(struct device *dev, struct regmap *regmap,
879 const char *firmware_name) 917 const char *firmware_name)
880{ 918{
881 struct adau *adau; 919 struct adau *adau;
920 int ret;
882 921
883 if (IS_ERR(regmap)) 922 if (IS_ERR(regmap))
884 return PTR_ERR(regmap); 923 return PTR_ERR(regmap);
@@ -887,6 +926,30 @@ int adau17x1_probe(struct device *dev, struct regmap *regmap,
887 if (!adau) 926 if (!adau)
888 return -ENOMEM; 927 return -ENOMEM;
889 928
929 adau->mclk = devm_clk_get(dev, "mclk");
930 if (IS_ERR(adau->mclk)) {
931 if (PTR_ERR(adau->mclk) != -ENOENT)
932 return PTR_ERR(adau->mclk);
933 /* Clock is optional (for the driver) */
934 adau->mclk = NULL;
935 } else if (adau->mclk) {
936 adau->clk_src = ADAU17X1_CLK_SRC_PLL_AUTO;
937
938 /*
939 * Any valid PLL output rate will work at this point, use one
940 * that is likely to be chosen later as well. The register will
941 * be written when the PLL is powered up for the first time.
942 */
943 ret = adau_calc_pll_cfg(clk_get_rate(adau->mclk), 48000 * 1024,
944 adau->pll_regs);
945 if (ret < 0)
946 return ret;
947
948 ret = clk_prepare_enable(adau->mclk);
949 if (ret)
950 return ret;
951 }
952
890 adau->regmap = regmap; 953 adau->regmap = regmap;
891 adau->switch_mode = switch_mode; 954 adau->switch_mode = switch_mode;
892 adau->type = type; 955 adau->type = type;
@@ -910,6 +973,16 @@ int adau17x1_probe(struct device *dev, struct regmap *regmap,
910} 973}
911EXPORT_SYMBOL_GPL(adau17x1_probe); 974EXPORT_SYMBOL_GPL(adau17x1_probe);
912 975
976void adau17x1_remove(struct device *dev)
977{
978 struct adau *adau = dev_get_drvdata(dev);
979
980 snd_soc_unregister_codec(dev);
981 if (adau->mclk)
982 clk_disable_unprepare(adau->mclk);
983}
984EXPORT_SYMBOL_GPL(adau17x1_remove);
985
913MODULE_DESCRIPTION("ASoC ADAU1X61/ADAU1X81 common code"); 986MODULE_DESCRIPTION("ASoC ADAU1X61/ADAU1X81 common code");
914MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 987MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
915MODULE_LICENSE("GPL"); 988MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau17x1.h b/sound/soc/codecs/adau17x1.h
index 5ae87a084d97..bf04b7efee40 100644
--- a/sound/soc/codecs/adau17x1.h
+++ b/sound/soc/codecs/adau17x1.h
@@ -22,13 +22,18 @@ enum adau17x1_pll_src {
22}; 22};
23 23
24enum adau17x1_clk_src { 24enum adau17x1_clk_src {
25 /* Automatically configure PLL based on the sample rate */
26 ADAU17X1_CLK_SRC_PLL_AUTO,
25 ADAU17X1_CLK_SRC_MCLK, 27 ADAU17X1_CLK_SRC_MCLK,
26 ADAU17X1_CLK_SRC_PLL, 28 ADAU17X1_CLK_SRC_PLL,
27}; 29};
28 30
31struct clk;
32
29struct adau { 33struct adau {
30 unsigned int sysclk; 34 unsigned int sysclk;
31 unsigned int pll_freq; 35 unsigned int pll_freq;
36 struct clk *mclk;
32 37
33 enum adau17x1_clk_src clk_src; 38 enum adau17x1_clk_src clk_src;
34 enum adau17x1_type type; 39 enum adau17x1_type type;
@@ -52,6 +57,7 @@ int adau17x1_add_routes(struct snd_soc_codec *codec);
52int adau17x1_probe(struct device *dev, struct regmap *regmap, 57int adau17x1_probe(struct device *dev, struct regmap *regmap,
53 enum adau17x1_type type, void (*switch_mode)(struct device *dev), 58 enum adau17x1_type type, void (*switch_mode)(struct device *dev),
54 const char *firmware_name); 59 const char *firmware_name);
60void adau17x1_remove(struct device *dev);
55int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec, 61int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec,
56 enum adau17x1_micbias_voltage micbias); 62 enum adau17x1_micbias_voltage micbias);
57bool adau17x1_readable_register(struct device *dev, unsigned int reg); 63bool adau17x1_readable_register(struct device *dev, unsigned int reg);
diff --git a/sound/soc/codecs/adau7002.c b/sound/soc/codecs/adau7002.c
new file mode 100644
index 000000000000..9df72c6adcca
--- /dev/null
+++ b/sound/soc/codecs/adau7002.c
@@ -0,0 +1,80 @@
1/*
2 * ADAU7002 Stereo PDM-to-I2S/TDM converter driver
3 *
4 * Copyright 2014-2016 Analog Devices
5 * Author: Lars-Peter Clausen <lars@metafoo.de>
6 *
7 * Licensed under the GPL-2.
8 */
9
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/of.h>
13#include <linux/platform_device.h>
14
15#include <sound/soc.h>
16
17static const struct snd_soc_dapm_widget adau7002_widgets[] = {
18 SND_SOC_DAPM_INPUT("PDM_DAT"),
19 SND_SOC_DAPM_REGULATOR_SUPPLY("IOVDD", 0, 0),
20};
21
22static const struct snd_soc_dapm_route adau7002_routes[] = {
23 { "Capture", NULL, "PDM_DAT" },
24 { "Capture", NULL, "IOVDD" },
25};
26
27static struct snd_soc_dai_driver adau7002_dai = {
28 .name = "adau7002-hifi",
29 .capture = {
30 .stream_name = "Capture",
31 .channels_min = 2,
32 .channels_max = 2,
33 .rates = SNDRV_PCM_RATE_8000_96000,
34 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |
35 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |
36 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE,
37 .sig_bits = 20,
38 },
39};
40
41static const struct snd_soc_codec_driver adau7002_codec_driver = {
42 .dapm_widgets = adau7002_widgets,
43 .num_dapm_widgets = ARRAY_SIZE(adau7002_widgets),
44 .dapm_routes = adau7002_routes,
45 .num_dapm_routes = ARRAY_SIZE(adau7002_routes),
46};
47
48static int adau7002_probe(struct platform_device *pdev)
49{
50 return snd_soc_register_codec(&pdev->dev, &adau7002_codec_driver,
51 &adau7002_dai, 1);
52}
53
54static int adau7002_remove(struct platform_device *pdev)
55{
56 snd_soc_unregister_codec(&pdev->dev);
57 return 0;
58}
59
60#ifdef CONFIG_OF
61static const struct of_device_id adau7002_dt_ids[] = {
62 { .compatible = "adi,adau7002", },
63 { }
64};
65MODULE_DEVICE_TABLE(of, adau7002_dt_ids);
66#endif
67
68static struct platform_driver adau7002_driver = {
69 .driver = {
70 .name = "adau7002",
71 .of_match_table = of_match_ptr(adau7002_dt_ids),
72 },
73 .probe = adau7002_probe,
74 .remove = adau7002_remove,
75};
76module_platform_driver(adau7002_driver);
77
78MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
79MODULE_DESCRIPTION("ADAU7002 Stereo PDM-to-I2S/TDM Converter driver");
80MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c
index 5013d2ba0c10..97798d250f08 100644
--- a/sound/soc/codecs/ak4613.c
+++ b/sound/soc/codecs/ak4613.c
@@ -437,15 +437,25 @@ static struct snd_soc_dai_driver ak4613_dai = {
437 .symmetric_rates = 1, 437 .symmetric_rates = 1,
438}; 438};
439 439
440static int ak4613_resume(struct snd_soc_codec *codec) 440static int ak4613_suspend(struct snd_soc_codec *codec)
441{ 441{
442 struct regmap *regmap = dev_get_regmap(codec->dev, NULL); 442 struct regmap *regmap = dev_get_regmap(codec->dev, NULL);
443 443
444 regcache_cache_only(regmap, true);
444 regcache_mark_dirty(regmap); 445 regcache_mark_dirty(regmap);
446 return 0;
447}
448
449static int ak4613_resume(struct snd_soc_codec *codec)
450{
451 struct regmap *regmap = dev_get_regmap(codec->dev, NULL);
452
453 regcache_cache_only(regmap, false);
445 return regcache_sync(regmap); 454 return regcache_sync(regmap);
446} 455}
447 456
448static struct snd_soc_codec_driver soc_codec_dev_ak4613 = { 457static struct snd_soc_codec_driver soc_codec_dev_ak4613 = {
458 .suspend = ak4613_suspend,
449 .resume = ak4613_resume, 459 .resume = ak4613_resume,
450 .set_bias_level = ak4613_set_bias_level, 460 .set_bias_level = ak4613_set_bias_level,
451 .controls = ak4613_snd_controls, 461 .controls = ak4613_snd_controls,
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 4d8b9e49e8d6..cc941d66ec3d 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -523,15 +523,23 @@ static struct snd_soc_dai_driver ak4642_dai = {
523 .symmetric_rates = 1, 523 .symmetric_rates = 1,
524}; 524};
525 525
526static int ak4642_resume(struct snd_soc_codec *codec) 526static int ak4642_suspend(struct snd_soc_codec *codec)
527{ 527{
528 struct regmap *regmap = dev_get_regmap(codec->dev, NULL); 528 struct regmap *regmap = dev_get_regmap(codec->dev, NULL);
529 529
530 regcache_cache_only(regmap, true);
530 regcache_mark_dirty(regmap); 531 regcache_mark_dirty(regmap);
531 regcache_sync(regmap);
532 return 0; 532 return 0;
533} 533}
534 534
535static int ak4642_resume(struct snd_soc_codec *codec)
536{
537 struct regmap *regmap = dev_get_regmap(codec->dev, NULL);
538
539 regcache_cache_only(regmap, false);
540 regcache_sync(regmap);
541 return 0;
542}
535static int ak4642_probe(struct snd_soc_codec *codec) 543static int ak4642_probe(struct snd_soc_codec *codec)
536{ 544{
537 struct ak4642_priv *priv = snd_soc_codec_get_drvdata(codec); 545 struct ak4642_priv *priv = snd_soc_codec_get_drvdata(codec);
@@ -544,6 +552,7 @@ static int ak4642_probe(struct snd_soc_codec *codec)
544 552
545static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { 553static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
546 .probe = ak4642_probe, 554 .probe = ak4642_probe,
555 .suspend = ak4642_suspend,
547 .resume = ak4642_resume, 556 .resume = ak4642_resume,
548 .set_bias_level = ak4642_set_bias_level, 557 .set_bias_level = ak4642_set_bias_level,
549 .controls = ak4642_snd_controls, 558 .controls = ak4642_snd_controls,
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 664a8c044ffb..7f9ab92ffa91 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -324,6 +324,17 @@ int arizona_init_gpio(struct snd_soc_codec *codec)
324} 324}
325EXPORT_SYMBOL_GPL(arizona_init_gpio); 325EXPORT_SYMBOL_GPL(arizona_init_gpio);
326 326
327int arizona_init_notifiers(struct snd_soc_codec *codec)
328{
329 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
330 struct arizona *arizona = priv->arizona;
331
332 BLOCKING_INIT_NOTIFIER_HEAD(&arizona->notifier);
333
334 return 0;
335}
336EXPORT_SYMBOL_GPL(arizona_init_notifiers);
337
327const char * const arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { 338const char * const arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
328 "None", 339 "None",
329 "Tone Generator 1", 340 "Tone Generator 1",
@@ -2573,6 +2584,30 @@ int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
2573} 2584}
2574EXPORT_SYMBOL_GPL(arizona_lhpf_coeff_put); 2585EXPORT_SYMBOL_GPL(arizona_lhpf_coeff_put);
2575 2586
2587int arizona_register_notifier(struct snd_soc_codec *codec,
2588 struct notifier_block *nb,
2589 int (*notify)(struct notifier_block *nb,
2590 unsigned long action, void *data))
2591{
2592 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
2593 struct arizona *arizona = priv->arizona;
2594
2595 nb->notifier_call = notify;
2596
2597 return blocking_notifier_chain_register(&arizona->notifier, nb);
2598}
2599EXPORT_SYMBOL_GPL(arizona_register_notifier);
2600
2601int arizona_unregister_notifier(struct snd_soc_codec *codec,
2602 struct notifier_block *nb)
2603{
2604 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
2605 struct arizona *arizona = priv->arizona;
2606
2607 return blocking_notifier_chain_unregister(&arizona->notifier, nb);
2608}
2609EXPORT_SYMBOL_GPL(arizona_unregister_notifier);
2610
2576MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support"); 2611MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
2577MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 2612MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
2578MODULE_LICENSE("GPL"); 2613MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index ce0531b8c632..46862af7665e 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -63,6 +63,9 @@
63#define ARIZONA_DVFS_SR1_RQ 0x001 63#define ARIZONA_DVFS_SR1_RQ 0x001
64#define ARIZONA_DVFS_ADSP1_RQ 0x100 64#define ARIZONA_DVFS_ADSP1_RQ 0x100
65 65
66/* Notifier events */
67#define ARIZONA_NOTIFY_VOICE_TRIGGER 0x1
68
66struct arizona; 69struct arizona;
67struct wm_adsp; 70struct wm_adsp;
68 71
@@ -95,6 +98,10 @@ struct arizona_priv {
95 bool dvfs_cached; 98 bool dvfs_cached;
96}; 99};
97 100
101struct arizona_voice_trigger_info {
102 int core;
103};
104
98#define ARIZONA_NUM_MIXER_INPUTS 104 105#define ARIZONA_NUM_MIXER_INPUTS 104
99 106
100extern const unsigned int arizona_mixer_tlv[]; 107extern const unsigned int arizona_mixer_tlv[];
@@ -306,6 +313,7 @@ extern int arizona_set_fll(struct arizona_fll *fll, int source,
306extern int arizona_init_spk(struct snd_soc_codec *codec); 313extern int arizona_init_spk(struct snd_soc_codec *codec);
307extern int arizona_init_gpio(struct snd_soc_codec *codec); 314extern int arizona_init_gpio(struct snd_soc_codec *codec);
308extern int arizona_init_mono(struct snd_soc_codec *codec); 315extern int arizona_init_mono(struct snd_soc_codec *codec);
316extern int arizona_init_notifiers(struct snd_soc_codec *codec);
309 317
310extern int arizona_free_spk(struct snd_soc_codec *codec); 318extern int arizona_free_spk(struct snd_soc_codec *codec);
311 319
@@ -317,4 +325,13 @@ int arizona_set_output_mode(struct snd_soc_codec *codec, int output,
317extern bool arizona_input_analog(struct snd_soc_codec *codec, int shift); 325extern bool arizona_input_analog(struct snd_soc_codec *codec, int shift);
318 326
319extern const char *arizona_sample_rate_val_to_name(unsigned int rate_val); 327extern const char *arizona_sample_rate_val_to_name(unsigned int rate_val);
328
329extern int arizona_register_notifier(struct snd_soc_codec *codec,
330 struct notifier_block *nb,
331 int (*notify)(struct notifier_block *nb,
332 unsigned long action,
333 void *data));
334extern int arizona_unregister_notifier(struct snd_soc_codec *codec,
335 struct notifier_block *nb);
336
320#endif 337#endif
diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c
index 5ec5a682d186..bbc8cf18ded0 100644
--- a/sound/soc/codecs/cs47l24.c
+++ b/sound/soc/codecs/cs47l24.c
@@ -1067,6 +1067,7 @@ static irqreturn_t cs47l24_adsp2_irq(int irq, void *data)
1067{ 1067{
1068 struct cs47l24_priv *priv = data; 1068 struct cs47l24_priv *priv = data;
1069 struct arizona *arizona = priv->core.arizona; 1069 struct arizona *arizona = priv->core.arizona;
1070 struct arizona_voice_trigger_info info;
1070 int serviced = 0; 1071 int serviced = 0;
1071 int i, ret; 1072 int i, ret;
1072 1073
@@ -1074,6 +1075,12 @@ static irqreturn_t cs47l24_adsp2_irq(int irq, void *data)
1074 ret = wm_adsp_compr_handle_irq(&priv->core.adsp[i]); 1075 ret = wm_adsp_compr_handle_irq(&priv->core.adsp[i]);
1075 if (ret != -ENODEV) 1076 if (ret != -ENODEV)
1076 serviced++; 1077 serviced++;
1078 if (ret == WM_ADSP_COMPR_VOICE_TRIGGER) {
1079 info.core = i;
1080 arizona_call_notifiers(arizona,
1081 ARIZONA_NOTIFY_VOICE_TRIGGER,
1082 &info);
1083 }
1077 } 1084 }
1078 1085
1079 if (!serviced) { 1086 if (!serviced) {
@@ -1096,6 +1103,7 @@ static int cs47l24_codec_probe(struct snd_soc_codec *codec)
1096 arizona_init_spk(codec); 1103 arizona_init_spk(codec);
1097 arizona_init_gpio(codec); 1104 arizona_init_gpio(codec);
1098 arizona_init_mono(codec); 1105 arizona_init_mono(codec);
1106 arizona_init_notifiers(codec);
1099 1107
1100 ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, 1108 ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1,
1101 "ADSP2 Compressed IRQ", cs47l24_adsp2_irq, 1109 "ADSP2 Compressed IRQ", cs47l24_adsp2_irq,
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index d54f1b46c9ec..1aac0e1122cf 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -2223,6 +2223,7 @@ static irqreturn_t wm5110_adsp2_irq(int irq, void *data)
2223{ 2223{
2224 struct wm5110_priv *priv = data; 2224 struct wm5110_priv *priv = data;
2225 struct arizona *arizona = priv->core.arizona; 2225 struct arizona *arizona = priv->core.arizona;
2226 struct arizona_voice_trigger_info info;
2226 int serviced = 0; 2227 int serviced = 0;
2227 int i, ret; 2228 int i, ret;
2228 2229
@@ -2230,6 +2231,12 @@ static irqreturn_t wm5110_adsp2_irq(int irq, void *data)
2230 ret = wm_adsp_compr_handle_irq(&priv->core.adsp[i]); 2231 ret = wm_adsp_compr_handle_irq(&priv->core.adsp[i]);
2231 if (ret != -ENODEV) 2232 if (ret != -ENODEV)
2232 serviced++; 2233 serviced++;
2234 if (ret == WM_ADSP_COMPR_VOICE_TRIGGER) {
2235 info.core = i;
2236 arizona_call_notifiers(arizona,
2237 ARIZONA_NOTIFY_VOICE_TRIGGER,
2238 &info);
2239 }
2233 } 2240 }
2234 2241
2235 if (!serviced) { 2242 if (!serviced) {
@@ -2252,6 +2259,7 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
2252 arizona_init_spk(codec); 2259 arizona_init_spk(codec);
2253 arizona_init_gpio(codec); 2260 arizona_init_gpio(codec);
2254 arizona_init_mono(codec); 2261 arizona_init_mono(codec);
2262 arizona_init_notifiers(codec);
2255 2263
2256 ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, 2264 ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1,
2257 "ADSP2 Compressed IRQ", wm5110_adsp2_irq, 2265 "ADSP2 Compressed IRQ", wm5110_adsp2_irq,
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index a07bd7c2c587..f6eb2e5b2c07 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -2366,13 +2366,15 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
2366 dsp->running = false; 2366 dsp->running = false;
2367 2367
2368 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2368 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2369 ADSP2_SYS_ENA | ADSP2_CORE_ENA | 2369 ADSP2_CORE_ENA | ADSP2_START, 0);
2370 ADSP2_START, 0);
2371 2370
2372 /* Make sure DMAs are quiesced */ 2371 /* Make sure DMAs are quiesced */
2372 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
2373 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0); 2373 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
2374 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0); 2374 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0);
2375 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); 2375
2376 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2377 ADSP2_SYS_ENA, 0);
2376 2378
2377 list_for_each_entry(ctl, &dsp->ctl_list, list) 2379 list_for_each_entry(ctl, &dsp->ctl_list, list)
2378 ctl->enabled = 0; 2380 ctl->enabled = 0;
@@ -3037,12 +3039,8 @@ int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
3037 3039
3038 buf = compr->buf; 3040 buf = compr->buf;
3039 3041
3040 if (!compr->buf) { 3042 if (!compr->buf || compr->buf->error) {
3041 ret = -ENXIO; 3043 snd_compr_stop_error(stream, SNDRV_PCM_STATE_XRUN);
3042 goto out;
3043 }
3044
3045 if (compr->buf->error) {
3046 ret = -EIO; 3044 ret = -EIO;
3047 goto out; 3045 goto out;
3048 } 3046 }
@@ -3060,8 +3058,12 @@ int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
3060 */ 3058 */
3061 if (buf->avail < wm_adsp_compr_frag_words(compr)) { 3059 if (buf->avail < wm_adsp_compr_frag_words(compr)) {
3062 ret = wm_adsp_buffer_get_error(buf); 3060 ret = wm_adsp_buffer_get_error(buf);
3063 if (ret < 0) 3061 if (ret < 0) {
3062 if (compr->buf->error)
3063 snd_compr_stop_error(stream,
3064 SNDRV_PCM_STATE_XRUN);
3064 goto out; 3065 goto out;
3066 }
3065 3067
3066 ret = wm_adsp_buffer_reenable_irq(buf); 3068 ret = wm_adsp_buffer_reenable_irq(buf);
3067 if (ret < 0) { 3069 if (ret < 0) {
@@ -3156,11 +3158,10 @@ static int wm_adsp_compr_read(struct wm_adsp_compr *compr,
3156 3158
3157 adsp_dbg(dsp, "Requested read of %zu bytes\n", count); 3159 adsp_dbg(dsp, "Requested read of %zu bytes\n", count);
3158 3160
3159 if (!compr->buf) 3161 if (!compr->buf || compr->buf->error) {
3160 return -ENXIO; 3162 snd_compr_stop_error(compr->stream, SNDRV_PCM_STATE_XRUN);
3161
3162 if (compr->buf->error)
3163 return -EIO; 3163 return -EIO;
3164 }
3164 3165
3165 count /= WM_ADSP_DATA_WORD_SIZE; 3166 count /= WM_ADSP_DATA_WORD_SIZE;
3166 3167